summaryrefslogtreecommitdiff
path: root/src/pal/tests
diff options
context:
space:
mode:
authorJiyoung Yun <jy910.yun@samsung.com>2016-11-23 19:09:09 +0900
committerJiyoung Yun <jy910.yun@samsung.com>2016-11-23 19:09:09 +0900
commit4b4aad7217d3292650e77eec2cf4c198ea9c3b4b (patch)
tree98110734c91668dfdbb126fcc0e15ddbd93738ca /src/pal/tests
parentfa45f57ed55137c75ac870356a1b8f76c84b229c (diff)
downloadcoreclr-4b4aad7217d3292650e77eec2cf4c198ea9c3b4b.tar.gz
coreclr-4b4aad7217d3292650e77eec2cf4c198ea9c3b4b.tar.bz2
coreclr-4b4aad7217d3292650e77eec2cf4c198ea9c3b4b.zip
Imported Upstream version 1.1.0upstream/1.1.0
Diffstat (limited to 'src/pal/tests')
-rw-r--r--src/pal/tests/CMakeLists.txt32
-rw-r--r--src/pal/tests/palsuite/CMakeLists.txt24
-rw-r--r--src/pal/tests/palsuite/DisabledTests.txt123
-rw-r--r--src/pal/tests/palsuite/README.txt140
-rw-r--r--src/pal/tests/palsuite/c_runtime/CMakeLists.txt162
-rw-r--r--src/pal/tests/palsuite/c_runtime/__iscsym/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/__iscsym/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/__iscsym/test1/__iscsym.c93
-rw-r--r--src/pal/tests/palsuite/c_runtime/__iscsym/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_alloca/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/_alloca/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_alloca/test1/test1.c62
-rw-r--r--src/pal/tests/palsuite/c_runtime/_alloca/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/_ecvt/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/_ecvt/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_ecvt/test1/test1.c135
-rw-r--r--src/pal/tests/palsuite/c_runtime/_ecvt/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_fdopen/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/_fdopen/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_fdopen/test1/test1.c112
-rw-r--r--src/pal/tests/palsuite/c_runtime/_fdopen/test1/testinfo.dat23
-rw-r--r--src/pal/tests/palsuite/c_runtime/_finite/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/_finite/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_finite/test1/test1.c119
-rw-r--r--src/pal/tests/palsuite/c_runtime/_finite/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/_fullpath/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/_fullpath/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_fullpath/test1/test1.c181
-rw-r--r--src/pal/tests/palsuite/c_runtime/_fullpath/test1/testinfo.dat23
-rw-r--r--src/pal/tests/palsuite/c_runtime/_gcvt/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/c_runtime/_gcvt/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_gcvt/test1/_gcvt.c58
-rw-r--r--src/pal/tests/palsuite/c_runtime/_gcvt/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/_gcvt/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_gcvt/test2/test2.c83
-rw-r--r--src/pal/tests/palsuite/c_runtime/_gcvt/test2/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/_getw/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/_getw/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_getw/test1/test.datbin0 -> 28 bytes
-rw-r--r--src/pal/tests/palsuite/c_runtime/_getw/test1/test1.c96
-rw-r--r--src/pal/tests/palsuite/c_runtime/_getw/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/_isnan/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/_isnan/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_isnan/test1/test1.c115
-rw-r--r--src/pal/tests/palsuite/c_runtime/_isnan/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/c_runtime/_itow/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/_itow/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_itow/test1/test1.c102
-rw-r--r--src/pal/tests/palsuite/c_runtime/_itow/test1/testinfo.dat18
-rw-r--r--src/pal/tests/palsuite/c_runtime/_makepath/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/_makepath/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_makepath/test1/test1.c65
-rw-r--r--src/pal/tests/palsuite/c_runtime/_makepath/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_mbsdec/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/_mbsdec/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_mbsdec/test1/test1.c77
-rw-r--r--src/pal/tests/palsuite/c_runtime/_mbsdec/test1/testinfo.dat18
-rw-r--r--src/pal/tests/palsuite/c_runtime/_mbsinc/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/_mbsinc/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_mbsinc/test1/test1.c62
-rw-r--r--src/pal/tests/palsuite/c_runtime/_mbsinc/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/_mbslen/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/_mbslen/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_mbslen/test1/test1.c66
-rw-r--r--src/pal/tests/palsuite/c_runtime/_mbslen/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/_mbsninc/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/_mbsninc/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_mbsninc/test1/test1.c65
-rw-r--r--src/pal/tests/palsuite/c_runtime/_mbsninc/test1/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/c_runtime/_open_osfhandle/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/c_runtime/_open_osfhandle/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_open_osfhandle/test1/test1.c132
-rw-r--r--src/pal/tests/palsuite/c_runtime/_open_osfhandle/test1/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/c_runtime/_open_osfhandle/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_open_osfhandle/test2/test2.c86
-rw-r--r--src/pal/tests/palsuite/c_runtime/_open_osfhandle/test2/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/c_runtime/_putenv/CMakeLists.txt7
-rw-r--r--src/pal/tests/palsuite/c_runtime/_putenv/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_putenv/test1/test1.c99
-rw-r--r--src/pal/tests/palsuite/c_runtime/_putenv/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/_putenv/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_putenv/test2/test2.c76
-rw-r--r--src/pal/tests/palsuite/c_runtime/_putenv/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/_putenv/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_putenv/test3/test3.c102
-rw-r--r--src/pal/tests/palsuite/c_runtime/_putenv/test3/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_putenv/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_putenv/test4/test4.c75
-rw-r--r--src/pal/tests/palsuite/c_runtime/_putenv/test4/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_putw/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/_putw/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_putw/test1/test1.c112
-rw-r--r--src/pal/tests/palsuite/c_runtime/_putw/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/_rotl/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/_rotl/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_rotl/test1/test1.cpp55
-rw-r--r--src/pal/tests/palsuite/c_runtime/_rotl/test1/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/c_runtime/_rotr/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/_rotr/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_rotr/test1/test1.cpp60
-rw-r--r--src/pal/tests/palsuite/c_runtime/_rotr/test1/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/CMakeLists.txt22
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/_snprintf.h194
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test1/test1.c58
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test10/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test10/test10.c55
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test10/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test11/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test11/test11.c54
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test11/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test12/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test12/test12.c55
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test12/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test13/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test13/test13.c55
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test13/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test14/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test14/test14.c57
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test14/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test15/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test15/test15.c56
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test15/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test16/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test16/test16.c52
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test16/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test17/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test17/test17.c53
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test17/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test18/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test18/test18.c53
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test18/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test19/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test19/test19.c76
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test19/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test2/test2.c44
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test2/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test3/test3.c45
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test3/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test4/test4.c69
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test4/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test5/test5.c61
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test5/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test6/test6.c47
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test6/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test7/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test7/test7.c47
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test7/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test8/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test8/test8.c56
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test8/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test9/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test9/test9.c55
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snprintf/test9/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/CMakeLists.txt22
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/_snwprintf.h199
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test1/test1.c62
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test10/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test10/test10.c54
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test10/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test11/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test11/test11.c54
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test11/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test12/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test12/test12.c54
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test12/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test13/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test13/test13.c54
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test13/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test14/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test14/test14.c66
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test14/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test15/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test15/test15.c67
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test15/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test16/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test16/test16.c65
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test16/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test17/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test17/test17.c68
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test17/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test18/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test18/test18.c69
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test18/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test19/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test19/test19.c90
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test19/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test2/test2.c44
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test2/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test3/test3.c44
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test3/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test4/test4.c71
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test4/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test5/test5.c63
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test5/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test6/test6.c46
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test6/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test7/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test7/test7.c46
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test7/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test8/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test8/test8.c53
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test8/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test9/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test9/test9.c53
-rw-r--r--src/pal/tests/palsuite/c_runtime/_snwprintf/test9/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_splitpath/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/_splitpath/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_splitpath/test1/test1.c108
-rw-r--r--src/pal/tests/palsuite/c_runtime/_splitpath/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/_stricmp/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/_stricmp/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_stricmp/test1/test1.c70
-rw-r--r--src/pal/tests/palsuite/c_runtime/_stricmp/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/_strlwr/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/_strlwr/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_strlwr/test1/test1.c42
-rw-r--r--src/pal/tests/palsuite/c_runtime/_strlwr/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/_strnicmp/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/_strnicmp/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_strnicmp/test1/test1.c85
-rw-r--r--src/pal/tests/palsuite/c_runtime/_strnicmp/test1/testinfo.dat18
-rw-r--r--src/pal/tests/palsuite/c_runtime/_swab/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/_swab/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_swab/test1/test1.c45
-rw-r--r--src/pal/tests/palsuite/c_runtime/_swab/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/CMakeLists.txt22
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/_vsnprintf.h124
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test1/test1.c55
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test10/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test10/test10.c50
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test10/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test11/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test11/test11.c50
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test11/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test12/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test12/test12.c52
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test12/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test13/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test13/test13.c52
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test13/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test14/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test14/test14.c50
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test14/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test15/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test15/test15.c49
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test15/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test16/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test16/test16.c49
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test16/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test17/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test17/test17.c50
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test17/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test18/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test18/test18.c50
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test18/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test19/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test19/test19.c103
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test19/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test2/test2.c44
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test2/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test3/test3.c43
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test3/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test4/test4.c98
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test4/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test5/test5.c78
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test5/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test6/test6.c44
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test6/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test7/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test7/test7.c44
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test7/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test8/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test8/test8.c52
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test8/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test9/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test9/test9.c51
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnprintf/test9/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/CMakeLists.txt22
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/_vsnwprintf.h133
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test1/test1.c60
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test10/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test10/test10.c50
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test10/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test11/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test11/test11.c50
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test11/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test12/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test12/test12.c50
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test12/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test13/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test13/test13.c50
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test13/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test14/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test14/test14.c63
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test14/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test15/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test15/test15.c64
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test15/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test16/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test16/test16.c63
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test16/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test17/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test17/test17.c65
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test17/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test18/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test18/test18.c65
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test18/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test19/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test19/test19.c139
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test19/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test2/test2.c40
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test2/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test3/test3.c40
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test3/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test4/test4.c121
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test4/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test5/test5.c81
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test5/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test6/test6.c43
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test6/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test7/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test7/test7.c43
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test7/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test8/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test8/test8.c49
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test8/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test9/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test9/test9.c49
-rw-r--r--src/pal/tests/palsuite/c_runtime/_vsnwprintf/test9/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wcsicmp/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/test1.c68
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wcslwr/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wcslwr/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wcslwr/test1/test1.c50
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wcslwr/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wcsnicmp/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/test1.c95
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/testinfo.dat18
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wfopen/CMakeLists.txt10
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wfopen/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wfopen/test1/test1.c79
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wfopen/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wfopen/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wfopen/test2/test2.c68
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wfopen/test2/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wfopen/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wfopen/test3/test3.c70
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wfopen/test3/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wfopen/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wfopen/test4/test4.c87
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wfopen/test4/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wfopen/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wfopen/test5/test5.c82
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wfopen/test5/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wfopen/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wfopen/test6/test6.c152
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wfopen/test6/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wfopen/test7/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wfopen/test7/test7.c119
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wfopen/test7/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wmakepath/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wmakepath/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wmakepath/test1/test1.c76
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wmakepath/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wsplitpath/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wsplitpath/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wsplitpath/test1/test1.c151
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wsplitpath/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wtoi/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wtoi/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wtoi/test1/test1.c79
-rw-r--r--src/pal/tests/palsuite/c_runtime/_wtoi/test1/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/c_runtime/abs/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/abs/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/abs/test1/abs.c54
-rw-r--r--src/pal/tests/palsuite/c_runtime/abs/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/acos/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/acos/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/acos/test1/test1.c130
-rw-r--r--src/pal/tests/palsuite/c_runtime/acos/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/asin/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/asin/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/asin/test1/test1.c146
-rw-r--r--src/pal/tests/palsuite/c_runtime/asin/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/atan/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/atan/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/atan/test1/test1.c128
-rw-r--r--src/pal/tests/palsuite/c_runtime/atan/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/atan2/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/atan2/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/atan2/test1/test1.c148
-rw-r--r--src/pal/tests/palsuite/c_runtime/atan2/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/atof/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/atof/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/atof/test1/test1.c75
-rw-r--r--src/pal/tests/palsuite/c_runtime/atof/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/c_runtime/atoi/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/atoi/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/atoi/test1/test1.c86
-rw-r--r--src/pal/tests/palsuite/c_runtime/atoi/test1/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/c_runtime/atol/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/atol/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/atol/test1/test1.c88
-rw-r--r--src/pal/tests/palsuite/c_runtime/atol/test1/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/c_runtime/bsearch/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/c_runtime/bsearch/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/bsearch/test1/test1.c48
-rw-r--r--src/pal/tests/palsuite/c_runtime/bsearch/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/bsearch/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/bsearch/test2/test2.c57
-rw-r--r--src/pal/tests/palsuite/c_runtime/bsearch/test2/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/ceil/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/ceil/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/ceil/test1/test1.c132
-rw-r--r--src/pal/tests/palsuite/c_runtime/ceil/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/cos/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/cos/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/cos/test1/test1.c131
-rw-r--r--src/pal/tests/palsuite/c_runtime/cos/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/cosh/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/cosh/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/cosh/test1/test1.c130
-rw-r--r--src/pal/tests/palsuite/c_runtime/cosh/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/ctime/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/ctime/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/ctime/test1/test1.c154
-rw-r--r--src/pal/tests/palsuite/c_runtime/ctime/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/errno/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/c_runtime/errno/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/errno/test1/test1.c43
-rw-r--r--src/pal/tests/palsuite/c_runtime/errno/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/errno/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/errno/test2/test2.c76
-rw-r--r--src/pal/tests/palsuite/c_runtime/errno/test2/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/exit/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/c_runtime/exit/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/exit/test1/test1.c37
-rw-r--r--src/pal/tests/palsuite/c_runtime/exit/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/exit/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/exit/test2/test2.c38
-rw-r--r--src/pal/tests/palsuite/c_runtime/exit/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/exp/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/exp/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/exp/test1/test1.c138
-rw-r--r--src/pal/tests/palsuite/c_runtime/exp/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/fabs/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/fabs/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fabs/test1/test1.c130
-rw-r--r--src/pal/tests/palsuite/c_runtime/fabs/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fabsf/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/fabsf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fabsf/test1/test1.c130
-rw-r--r--src/pal/tests/palsuite/c_runtime/fabsf/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fclose/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/c_runtime/fclose/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fclose/test1/test1.c79
-rw-r--r--src/pal/tests/palsuite/c_runtime/fclose/test1/testinfo.dat18
-rw-r--r--src/pal/tests/palsuite/c_runtime/fclose/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fclose/test2/test2.c77
-rw-r--r--src/pal/tests/palsuite/c_runtime/fclose/test2/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/feof/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/feof/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/feof/test1/test1.c88
-rw-r--r--src/pal/tests/palsuite/c_runtime/feof/test1/testfile1
-rw-r--r--src/pal/tests/palsuite/c_runtime/feof/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/c_runtime/ferror/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/c_runtime/ferror/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/ferror/test1/test1.c74
-rw-r--r--src/pal/tests/palsuite/c_runtime/ferror/test1/testfile1
-rw-r--r--src/pal/tests/palsuite/c_runtime/ferror/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/c_runtime/ferror/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/ferror/test2/test2.c69
-rw-r--r--src/pal/tests/palsuite/c_runtime/ferror/test2/testfile1
-rw-r--r--src/pal/tests/palsuite/c_runtime/ferror/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fflush/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/fflush/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fflush/test1/test1.c80
-rw-r--r--src/pal/tests/palsuite/c_runtime/fflush/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/fgets/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/c_runtime/fgets/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fgets/test1/test1.c102
-rw-r--r--src/pal/tests/palsuite/c_runtime/fgets/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/fgets/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fgets/test2/test2.c97
-rw-r--r--src/pal/tests/palsuite/c_runtime/fgets/test2/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/fgets/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fgets/test3/test3.c73
-rw-r--r--src/pal/tests/palsuite/c_runtime/fgets/test3/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/floor/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/floor/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/floor/test1/test1.c132
-rw-r--r--src/pal/tests/palsuite/c_runtime/floor/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fmod/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/fmod/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fmod/test1/test1.c157
-rw-r--r--src/pal/tests/palsuite/c_runtime/fmod/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fmodf/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/fmodf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fmodf/test1/test1.c156
-rw-r--r--src/pal/tests/palsuite/c_runtime/fmodf/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fopen/CMakeLists.txt10
-rw-r--r--src/pal/tests/palsuite/c_runtime/fopen/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fopen/test1/test1.c82
-rw-r--r--src/pal/tests/palsuite/c_runtime/fopen/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/fopen/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fopen/test2/test2.c65
-rw-r--r--src/pal/tests/palsuite/c_runtime/fopen/test2/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/fopen/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fopen/test3/test3.c66
-rw-r--r--src/pal/tests/palsuite/c_runtime/fopen/test3/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/fopen/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fopen/test4/test4.c82
-rw-r--r--src/pal/tests/palsuite/c_runtime/fopen/test4/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/fopen/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fopen/test5/test5.c78
-rw-r--r--src/pal/tests/palsuite/c_runtime/fopen/test5/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/fopen/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fopen/test6/test6.c131
-rw-r--r--src/pal/tests/palsuite/c_runtime/fopen/test6/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/fopen/test7/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fopen/test7/test7.c117
-rw-r--r--src/pal/tests/palsuite/c_runtime/fopen/test7/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/CMakeLists.txt22
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/fprintf.h177
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test1/test1.c80
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test10/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test10/test10.c49
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test10/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test11/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test11/test11.c49
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test11/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test12/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test12/test12.c50
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test12/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test13/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test13/test13.c50
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test13/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test14/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test14/test14.c49
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test14/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test15/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test15/test15.c49
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test15/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test16/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test16/test16.c48
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test16/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test17/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test17/test17.c49
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test17/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test18/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test18/test18.c49
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test18/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test19/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test19/test19.c153
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test19/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test2/test2.c43
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test3/test3.c43
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test3/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test4/test4.c110
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test4/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test5/test5.c131
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test5/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test6/test6.c46
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test6/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test7/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test7/test7.c44
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test7/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test8/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test8/test8.c49
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test8/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test9/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test9/test9.c49
-rw-r--r--src/pal/tests/palsuite/c_runtime/fprintf/test9/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fputs/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/c_runtime/fputs/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fputs/test1/test1.c100
-rw-r--r--src/pal/tests/palsuite/c_runtime/fputs/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/fputs/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fputs/test2/test2.c88
-rw-r--r--src/pal/tests/palsuite/c_runtime/fputs/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fread/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/c_runtime/fread/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fread/test1/test1.c135
-rw-r--r--src/pal/tests/palsuite/c_runtime/fread/test1/testfile1
-rw-r--r--src/pal/tests/palsuite/c_runtime/fread/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/fread/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fread/test2/test2.c143
-rw-r--r--src/pal/tests/palsuite/c_runtime/fread/test2/testfile1
-rw-r--r--src/pal/tests/palsuite/c_runtime/fread/test2/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/c_runtime/fread/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fread/test3/test3.c131
-rw-r--r--src/pal/tests/palsuite/c_runtime/fread/test3/testfile1
-rw-r--r--src/pal/tests/palsuite/c_runtime/fread/test3/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/free/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/free/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/free/test1/test1.c62
-rw-r--r--src/pal/tests/palsuite/c_runtime/free/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/fseek/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/fseek/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fseek/test1/test1.c193
-rw-r--r--src/pal/tests/palsuite/c_runtime/fseek/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/ftell/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/ftell/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/ftell/test1/ftell.c145
-rw-r--r--src/pal/tests/palsuite/c_runtime/ftell/test1/testfile.txt1
-rw-r--r--src/pal/tests/palsuite/c_runtime/ftell/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/CMakeLists.txt22
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/fwprintf.h453
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test1/test1.c71
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test10/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test10/test10.c51
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test10/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test11/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test11/test11.c51
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test11/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test12/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test12/test12.c52
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test12/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test13/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test13/test13.c52
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test13/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test14/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test14/test14.c66
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test14/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test15/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test15/test15.c66
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test15/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test16/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test16/test16.c65
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test16/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test17/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test17/test17.c51
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test17/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test18/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test18/test18.c51
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test18/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test19/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test19/test19.c81
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test19/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test2/test2.c45
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test3/test3.c45
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test3/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test4/test4.c85
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test4/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test5/test5.c63
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test5/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test6/test6.c48
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test6/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test7/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test7/test7.c47
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test7/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test8/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test8/test8.c51
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test8/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test9/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test9/test9.c51
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwprintf/test9/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwrite/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwrite/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwrite/test1/test1.c104
-rw-r--r--src/pal/tests/palsuite/c_runtime/fwrite/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/getc/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/getc/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/getc/test1/getc.c152
-rw-r--r--src/pal/tests/palsuite/c_runtime/getc/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/getenv/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/c_runtime/getenv/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/getenv/test1/test1.c78
-rw-r--r--src/pal/tests/palsuite/c_runtime/getenv/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/c_runtime/getenv/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/getenv/test2/test2.c101
-rw-r--r--src/pal/tests/palsuite/c_runtime/getenv/test2/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/getenv/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/getenv/test3/test3.c75
-rw-r--r--src/pal/tests/palsuite/c_runtime/getenv/test3/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/isalnum/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/isalnum/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/isalnum/test1/test1.c88
-rw-r--r--src/pal/tests/palsuite/c_runtime/isalnum/test1/testinfo.dat19
-rw-r--r--src/pal/tests/palsuite/c_runtime/isalpha/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/isalpha/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/isalpha/test1/test1.c86
-rw-r--r--src/pal/tests/palsuite/c_runtime/isalpha/test1/testinfo.dat19
-rw-r--r--src/pal/tests/palsuite/c_runtime/isdigit/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/isdigit/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/isdigit/test1/test1.c47
-rw-r--r--src/pal/tests/palsuite/c_runtime/isdigit/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/islower/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/islower/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/islower/test1/test1.c85
-rw-r--r--src/pal/tests/palsuite/c_runtime/islower/test1/testinfo.dat19
-rw-r--r--src/pal/tests/palsuite/c_runtime/isprint/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/c_runtime/isprint/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/isprint/test1/isprint.c42
-rw-r--r--src/pal/tests/palsuite/c_runtime/isprint/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/isprint/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/isprint/test2/test2.c59
-rw-r--r--src/pal/tests/palsuite/c_runtime/isprint/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/isspace/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/isspace/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/isspace/test1/test1.c82
-rw-r--r--src/pal/tests/palsuite/c_runtime/isspace/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/isupper/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/isupper/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/isupper/test1/test1.c88
-rw-r--r--src/pal/tests/palsuite/c_runtime/isupper/test1/testinfo.dat19
-rw-r--r--src/pal/tests/palsuite/c_runtime/iswdigit/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/iswdigit/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/iswdigit/test1/test1.c69
-rw-r--r--src/pal/tests/palsuite/c_runtime/iswdigit/test1/testinfo.dat19
-rw-r--r--src/pal/tests/palsuite/c_runtime/iswprint/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/iswprint/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/iswprint/test1/test1.c59
-rw-r--r--src/pal/tests/palsuite/c_runtime/iswprint/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/iswspace/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/iswspace/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/iswspace/test1/test1.c78
-rw-r--r--src/pal/tests/palsuite/c_runtime/iswspace/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/iswupper/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/iswupper/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/iswupper/test1/test1.c91
-rw-r--r--src/pal/tests/palsuite/c_runtime/iswupper/test1/testinfo.dat19
-rw-r--r--src/pal/tests/palsuite/c_runtime/iswxdigit/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/iswxdigit/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/iswxdigit/test1/test1.c61
-rw-r--r--src/pal/tests/palsuite/c_runtime/iswxdigit/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/isxdigit/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/isxdigit/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/isxdigit/test1/test1.c58
-rw-r--r--src/pal/tests/palsuite/c_runtime/isxdigit/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/labs/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/labs/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/labs/test1/test1.c65
-rw-r--r--src/pal/tests/palsuite/c_runtime/labs/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/llabs/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/llabs/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/llabs/test1/test1.c65
-rw-r--r--src/pal/tests/palsuite/c_runtime/llabs/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/localtime/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/localtime/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/localtime/test1/test1.c69
-rw-r--r--src/pal/tests/palsuite/c_runtime/localtime/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/log/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/log/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/log/test1/test1.c140
-rw-r--r--src/pal/tests/palsuite/c_runtime/log/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/log10/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/log10/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/log10/test1/test1.c146
-rw-r--r--src/pal/tests/palsuite/c_runtime/log10/test1/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/c_runtime/malloc/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/c_runtime/malloc/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/malloc/test1/test1.c52
-rw-r--r--src/pal/tests/palsuite/c_runtime/malloc/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/malloc/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/malloc/test2/test2.c41
-rw-r--r--src/pal/tests/palsuite/c_runtime/malloc/test2/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/memchr/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/memchr/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/memchr/test1/test1.c122
-rw-r--r--src/pal/tests/palsuite/c_runtime/memchr/test1/testinfo.dat19
-rw-r--r--src/pal/tests/palsuite/c_runtime/memcmp/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/memcmp/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/memcmp/test1/test1.c57
-rw-r--r--src/pal/tests/palsuite/c_runtime/memcmp/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/memcpy/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/memcpy/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/memcpy/test1/test1.c87
-rw-r--r--src/pal/tests/palsuite/c_runtime/memcpy/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/memmove/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/memmove/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/memmove/test1/test1.c116
-rw-r--r--src/pal/tests/palsuite/c_runtime/memmove/test1/testinfo.dat19
-rw-r--r--src/pal/tests/palsuite/c_runtime/memset/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/memset/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/memset/test1/test1.c60
-rw-r--r--src/pal/tests/palsuite/c_runtime/memset/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/modf/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/modf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/modf/test1/test1.c136
-rw-r--r--src/pal/tests/palsuite/c_runtime/modf/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/c_runtime/modff/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/modff/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/modff/test1/test1.c135
-rw-r--r--src/pal/tests/palsuite/c_runtime/modff/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/pow/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/pow/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/pow/test1/test1.c230
-rw-r--r--src/pal/tests/palsuite/c_runtime/pow/test1/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/CMakeLists.txt22
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/printf.h182
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test1/test1.c43
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test10/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test10/test10.c52
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test10/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test11/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test11/test11.c51
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test11/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test12/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test12/test12.c53
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test12/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test13/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test13/test13.c54
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test13/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test14/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test14/test14.c54
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test14/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test15/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test15/test15.c54
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test15/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test16/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test16/test16.c50
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test16/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test17/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test17/test17.c52
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test17/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test18/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test18/test18.c51
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test18/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test19/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test19/test19.c76
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test19/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test2/test2.c45
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test2/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test3/test3.c45
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test3/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test4/test4.c66
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test4/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test5/test5.c60
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test5/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test6/test6.c48
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test6/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test7/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test7/test7.c47
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test7/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test8/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test8/test8.c53
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test8/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test9/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test9/test9.c53
-rw-r--r--src/pal/tests/palsuite/c_runtime/printf/test9/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/qsort/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/c_runtime/qsort/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/qsort/test1/test1.c48
-rw-r--r--src/pal/tests/palsuite/c_runtime/qsort/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/qsort/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/qsort/test2/test2.c49
-rw-r--r--src/pal/tests/palsuite/c_runtime/qsort/test2/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/rand_srand/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/rand_srand/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/rand_srand/test1/test1.c100
-rw-r--r--src/pal/tests/palsuite/c_runtime/rand_srand/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/c_runtime/realloc/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/realloc/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/realloc/test1/test1.c66
-rw-r--r--src/pal/tests/palsuite/c_runtime/realloc/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/sin/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/sin/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sin/test1/test1.c131
-rw-r--r--src/pal/tests/palsuite/c_runtime/sin/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/sinh/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/sinh/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sinh/test1/test1.c130
-rw-r--r--src/pal/tests/palsuite/c_runtime/sinh/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/CMakeLists.txt22
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/sprintf.h195
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test1/test1.c45
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test10/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test10/test10.c55
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test10/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test11/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test11/test11.c55
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test11/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test12/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test12/test12.c56
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test12/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test13/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test13/test13.c56
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test13/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test14/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test14/test14.c53
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test14/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test15/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test15/test15.c53
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test15/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test16/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test16/test16.c52
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test16/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test17/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test17/test17.c54
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test17/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test18/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test18/test18.c53
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test18/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test19/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test19/test19.c78
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test19/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test2/test2.c47
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test2/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test3/test3.c47
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test3/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test4/test4.c69
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test4/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test5/test5.c62
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test5/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test6/test6.c50
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test6/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test7/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test7/test7.c49
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test7/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test8/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test8/test8.c55
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test8/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test9/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test9/test9.c55
-rw-r--r--src/pal/tests/palsuite/c_runtime/sprintf/test9/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sqrt/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/sqrt/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sqrt/test1/test1.c123
-rw-r--r--src/pal/tests/palsuite/c_runtime/sqrt/test1/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/CMakeLists.txt20
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/sscanf.h246
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test1/test1.c53
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test10/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test10/test10.c37
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test10/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test11/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test11/test11.c36
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test11/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test12/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test12/test12.c35
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test12/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test13/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test13/test13.c37
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test13/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test14/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test14/test14.c36
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test14/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test15/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test15/test15.c36
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test15/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test16/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test16/test16.c37
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test16/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test17/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test17/test17.c37
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test17/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test2/test2.c44
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test2/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test3/test3.c35
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test3/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test4/test4.c44
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test4/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test5/test5.c43
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test5/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test6/test6.c43
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test6/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test7/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test7/test7.c43
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test7/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test8/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test8/test8.c43
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test8/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test9/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test9/test9.c38
-rw-r--r--src/pal/tests/palsuite/c_runtime/sscanf/test9/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/strcat/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/strcat/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/strcat/test1/test1.c66
-rw-r--r--src/pal/tests/palsuite/c_runtime/strcat/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/strchr/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/strchr/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/strchr/test1/test1.c86
-rw-r--r--src/pal/tests/palsuite/c_runtime/strchr/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/strcmp/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/strcmp/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/strcmp/test1/test1.c73
-rw-r--r--src/pal/tests/palsuite/c_runtime/strcmp/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/strcpy/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/strcpy/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/strcpy/test1/test1.c51
-rw-r--r--src/pal/tests/palsuite/c_runtime/strcpy/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/strcspn/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/strcspn/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/strcspn/test1/test1.c59
-rw-r--r--src/pal/tests/palsuite/c_runtime/strcspn/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/strlen/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/strlen/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/strlen/test1/test1.c33
-rw-r--r--src/pal/tests/palsuite/c_runtime/strlen/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/strncat/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/strncat/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/strncat/test1/test1.c77
-rw-r--r--src/pal/tests/palsuite/c_runtime/strncat/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/strncmp/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/strncmp/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/strncmp/test1/test1.c80
-rw-r--r--src/pal/tests/palsuite/c_runtime/strncmp/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/strncpy/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/strncpy/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/strncpy/test1/test1.c85
-rw-r--r--src/pal/tests/palsuite/c_runtime/strncpy/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/strpbrk/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/strpbrk/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/strpbrk/test1/test1.c85
-rw-r--r--src/pal/tests/palsuite/c_runtime/strpbrk/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/strrchr/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/strrchr/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/strrchr/test1/test1.c55
-rw-r--r--src/pal/tests/palsuite/c_runtime/strrchr/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/c_runtime/strspn/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/strspn/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/strspn/test1/test1.c60
-rw-r--r--src/pal/tests/palsuite/c_runtime/strspn/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/strstr/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/strstr/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/strstr/test1/test1.c83
-rw-r--r--src/pal/tests/palsuite/c_runtime/strstr/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/c_runtime/strtod/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/c_runtime/strtod/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/strtod/test1/test1.c93
-rw-r--r--src/pal/tests/palsuite/c_runtime/strtod/test1/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/c_runtime/strtod/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/strtod/test2/test2.c65
-rw-r--r--src/pal/tests/palsuite/c_runtime/strtod/test2/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/c_runtime/strtok/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/strtok/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/strtok/test1/test1.c78
-rw-r--r--src/pal/tests/palsuite/c_runtime/strtok/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/strtoul/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/strtoul/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/strtoul/test1/test1.c73
-rw-r--r--src/pal/tests/palsuite/c_runtime/strtoul/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/CMakeLists.txt22
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/swprintf.h202
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test1/test1.c44
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test10/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test10/test10.c55
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test10/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test11/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test11/test11.c55
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test11/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test12/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test12/test12.c56
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test12/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test13/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test13/test13.c55
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test13/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test14/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test14/test14.c67
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test14/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test15/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test15/test15.c67
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test15/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test16/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test16/test16.c67
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test16/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test17/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test17/test17.c69
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test17/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test18/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test18/test18.c69
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test18/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test19/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test19/test19.c109
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test19/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test2/test2.c46
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test2/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test3/test3.c43
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test3/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test4/test4.c71
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test4/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test5/test5.c67
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test5/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test6/test6.c47
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test6/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test7/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test7/test7.c48
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test7/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test8/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test8/test8.c55
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test8/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test9/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test9/test9.c55
-rw-r--r--src/pal/tests/palsuite/c_runtime/swprintf/test9/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/CMakeLists.txt20
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/swscanf.h262
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test1/test1.c53
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test10/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test10/test10.c36
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test10/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test11/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test11/test11.c35
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test11/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test12/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test12/test12.c35
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test12/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test13/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test13/test13.c37
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test13/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test14/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test14/test14.c38
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test14/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test15/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test15/test15.c37
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test15/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test16/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test16/test16.c37
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test16/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test17/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test17/test17.c37
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test17/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test2/test2.c43
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test2/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test3/test3.c36
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test3/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test4/test4.c44
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test4/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test5/test5.c44
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test5/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test6/test6.c44
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test6/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test7/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test7/test7.c44
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test7/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test8/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test8/test8.c44
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test8/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test9/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test9/test9.c37
-rw-r--r--src/pal/tests/palsuite/c_runtime/swscanf/test9/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/tan/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/tan/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/tan/test1/test1.c137
-rw-r--r--src/pal/tests/palsuite/c_runtime/tan/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/tanh/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/c_runtime/tanh/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/tanh/test1/test1.c130
-rw-r--r--src/pal/tests/palsuite/c_runtime/tanh/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/time/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/time/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/time/test1/test1.c51
-rw-r--r--src/pal/tests/palsuite/c_runtime/time/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/tolower/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/tolower/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/tolower/test1/test1.c79
-rw-r--r--src/pal/tests/palsuite/c_runtime/tolower/test1/testinfo.dat19
-rw-r--r--src/pal/tests/palsuite/c_runtime/toupper/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/toupper/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/toupper/test1/test1.c64
-rw-r--r--src/pal/tests/palsuite/c_runtime/toupper/test1/testinfo.dat19
-rw-r--r--src/pal/tests/palsuite/c_runtime/towlower/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/towlower/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/towlower/test1/test1.c79
-rw-r--r--src/pal/tests/palsuite/c_runtime/towlower/test1/testinfo.dat19
-rw-r--r--src/pal/tests/palsuite/c_runtime/towupper/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/towupper/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/towupper/test1/test1.c65
-rw-r--r--src/pal/tests/palsuite/c_runtime/towupper/test1/testinfo.dat19
-rw-r--r--src/pal/tests/palsuite/c_runtime/ungetc/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/c_runtime/ungetc/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/ungetc/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/ungetc/test1/ungetc.c130
-rw-r--r--src/pal/tests/palsuite/c_runtime/ungetc/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/ungetc/test2/test2.txt1
-rw-r--r--src/pal/tests/palsuite/c_runtime/ungetc/test2/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/ungetc/test2/ungetc.c188
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/CMakeLists.txt22
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test1/test1.c68
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test10/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test10/test10.c52
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test10/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test11/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test11/test11.c51
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test11/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test12/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test12/test12.c53
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test12/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test13/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test13/test13.c54
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test13/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test14/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test14/test14.c54
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test14/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test15/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test15/test15.c54
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test15/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test16/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test16/test16.c50
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test16/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test17/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test17/test17.c52
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test17/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test18/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test18/test18.c51
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test18/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test19/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test19/test19.c76
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test19/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test2/test2.c45
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test2/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test3/test3.c45
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test3/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test4/test4.c70
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test4/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test5/test5.c60
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test5/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test6/test6.c48
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test6/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test7/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test7/test7.c47
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test7/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test8/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test8/test8.c53
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test8/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test9/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test9/test9.c53
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/test9/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vfprintf/vfprintf.h463
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/CMakeLists.txt23
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test1/test1.c43
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test10/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test10/test10.c52
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test10/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test11/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test11/test11.c51
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test11/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test12/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test12/test12.c53
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test12/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test13/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test13/test13.c54
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test13/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test14/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test14/test14.c54
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test14/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test15/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test15/test15.c54
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test15/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test16/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test16/test16.c50
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test16/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test17/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test17/test17.c52
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test17/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test18/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test18/test18.c51
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test18/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test19/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test19/test19.c76
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test19/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test2/test2.c45
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test2/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test3/test3.c45
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test3/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test4/test4.c70
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test4/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test5/test5.c60
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test5/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test6/test6.c48
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test6/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test7/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test7/test7.c47
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test7/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test8/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test8/test8.c53
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test8/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test9/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test9/test9.c53
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/test9/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/vprintf/vprintf.h193
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/CMakeLists.txt22
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test1/test1.c55
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test10/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test10/test10.c50
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test10/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test11/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test11/test11.c50
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test11/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test12/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test12/test12.c52
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test12/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test13/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test13/test13.c52
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test13/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test14/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test14/test14.c50
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test14/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test15/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test15/test15.c64
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test15/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test16/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test16/test16.c49
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test16/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test17/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test17/test17.c50
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test17/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test18/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test18/test18.c50
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test18/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test19/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test19/test19.c67
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test19/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test2/test2.c42
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test2/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test3/test3.c43
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test3/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test4/test4.c72
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test4/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test5/test5.c43
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test5/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test6/test6.c44
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test6/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test7/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test7/test7.c44
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test7/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test8/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test8/test8.c52
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test8/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test9/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test9/test9.c51
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/test9/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vsprintf/vsprintf.h218
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/CMakeLists.txt22
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test1/test1.c41
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test10/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test10/test10.c48
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test10/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test11/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test11/test11.c48
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test11/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test12/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test12/test12.c48
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test12/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test13/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test13/test13.c48
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test13/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test14/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test14/test14.c61
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test14/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test15/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test15/test15.c62
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test15/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test16/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test16/test16.c61
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test16/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test17/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test17/test17.c63
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test17/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test18/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test18/test18.c63
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test18/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test19/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test19/test19.c137
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test19/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test2/test2.c40
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test2/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test3/test3.c40
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test3/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test4/test4.c118
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test4/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test5/test5.c79
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test5/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test6/test6.c41
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test6/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test7/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test7/test7.c41
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test7/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test8/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test8/test8.c47
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test8/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test9/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test9/test9.c47
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/test9/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/vswprintf/vswprintf.h132
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcscat/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcscat/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcscat/test1/test1.c71
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcscat/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcschr/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcschr/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcschr/test1/test1.c51
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcschr/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcscmp/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcscmp/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcscmp/test1/test1.c57
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcscmp/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcscpy/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcscpy/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcscpy/test1/test1.c47
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcscpy/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcslen/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcslen/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcslen/test1/test1.c49
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcslen/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcsncat/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcsncat/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcsncat/test1/test1.c77
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcsncat/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcsncmp/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcsncmp/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcsncmp/test1/test1.c73
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcsncmp/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcsncpy/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcsncpy/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcsncpy/test1/test1.c84
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcsncpy/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcspbrk/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcspbrk/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcspbrk/test1/test1.c61
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcspbrk/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcsrchr/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcsrchr/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcsrchr/test1/test1.c50
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcsrchr/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcsstr/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcsstr/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcsstr/test1/test1.c62
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcsstr/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstod/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstod/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstod/test1/test1.c79
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstod/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstod/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstod/test2/test2.c59
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstod/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstok/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstok/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstok/test1/test1.c114
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstok/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstol/CMakeLists.txt9
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstol/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstol/test1/test1.c53
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstol/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstol/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstol/test2/test2.c53
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstol/test2/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstol/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstol/test3/test3.c52
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstol/test3/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstol/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstol/test4/test4.c77
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstol/test4/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstol/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstol/test5/test5.c76
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstol/test5/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstol/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstol/test6/test6.c86
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstol/test6/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstoul/CMakeLists.txt9
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstoul/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstoul/test1/test1.c49
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstoul/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstoul/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstoul/test2/test2.c49
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstoul/test2/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstoul/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstoul/test3/test3.c49
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstoul/test3/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstoul/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstoul/test4/test4.c52
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstoul/test4/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstoul/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstoul/test5/test5.c69
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstoul/test5/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstoul/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstoul/test6/test6.c83
-rw-r--r--src/pal/tests/palsuite/c_runtime/wcstoul/test6/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/wprintf/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/c_runtime/wprintf/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/wprintf/test1/test1.c47
-rw-r--r--src/pal/tests/palsuite/c_runtime/wprintf/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/wprintf/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/c_runtime/wprintf/test2/test2.c45
-rw-r--r--src/pal/tests/palsuite/c_runtime/wprintf/test2/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/c_runtime/wprintf/wprintf.h171
-rw-r--r--src/pal/tests/palsuite/common/ResultBuffer.cpp69
-rw-r--r--src/pal/tests/palsuite/common/ResultBuffer.h43
-rw-r--r--src/pal/tests/palsuite/common/ResultTime.h103
-rw-r--r--src/pal/tests/palsuite/common/pal_stdclib.h24
-rw-r--r--src/pal/tests/palsuite/common/palsuite.h182
-rw-r--r--src/pal/tests/palsuite/composite/CMakeLists.txt7
-rw-r--r--src/pal/tests/palsuite/composite/object_management/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/composite/object_management/event/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/composite/object_management/event/nonshared/CMakeLists.txt21
-rw-r--r--src/pal/tests/palsuite/composite/object_management/event/nonshared/event.c358
-rw-r--r--src/pal/tests/palsuite/composite/object_management/event/nonshared/main.c228
-rw-r--r--src/pal/tests/palsuite/composite/object_management/event/shared/CMakeLists.txt21
-rw-r--r--src/pal/tests/palsuite/composite/object_management/event/shared/event.c373
-rw-r--r--src/pal/tests/palsuite/composite/object_management/event/shared/main.c265
-rw-r--r--src/pal/tests/palsuite/composite/object_management/mutex/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/composite/object_management/mutex/nonshared/CMakeLists.txt21
-rw-r--r--src/pal/tests/palsuite/composite/object_management/mutex/nonshared/main.c230
-rw-r--r--src/pal/tests/palsuite/composite/object_management/mutex/nonshared/mutex.c340
-rw-r--r--src/pal/tests/palsuite/composite/object_management/mutex/shared/CMakeLists.txt21
-rw-r--r--src/pal/tests/palsuite/composite/object_management/mutex/shared/main.c265
-rw-r--r--src/pal/tests/palsuite/composite/object_management/mutex/shared/mutex.c354
-rw-r--r--src/pal/tests/palsuite/composite/object_management/readme.txt29
-rw-r--r--src/pal/tests/palsuite/composite/object_management/semaphore/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/CMakeLists.txt21
-rw-r--r--src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/main.c228
-rw-r--r--src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/semaphore.c342
-rw-r--r--src/pal/tests/palsuite/composite/object_management/semaphore/shared/CMakeLists.txt21
-rw-r--r--src/pal/tests/palsuite/composite/object_management/semaphore/shared/main.c278
-rw-r--r--src/pal/tests/palsuite/composite/object_management/semaphore/shared/semaphore.c351
-rw-r--r--src/pal/tests/palsuite/composite/synchronization/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/composite/synchronization/criticalsection/CMakeLists.txt20
-rw-r--r--src/pal/tests/palsuite/composite/synchronization/criticalsection/criticalsection.c418
-rw-r--r--src/pal/tests/palsuite/composite/synchronization/criticalsection/mainWrapper.c255
-rw-r--r--src/pal/tests/palsuite/composite/synchronization/criticalsection/readme.txt11
-rw-r--r--src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/CMakeLists.txt21
-rw-r--r--src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/mtx_critsect.cpp111
-rw-r--r--src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/mtx_critsect.h51
-rw-r--r--src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/pal_composite_native_cs.c471
-rw-r--r--src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/readme.txt19
-rw-r--r--src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/resultbuffer.cpp69
-rw-r--r--src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/resultbuffer.h43
-rw-r--r--src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/CMakeLists.txt22
-rw-r--r--src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/hpitinterlock.s168
-rw-r--r--src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/interlocked.cpp27
-rw-r--r--src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/makefile70
-rw-r--r--src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/mtx_critsect.cpp112
-rw-r--r--src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/mtx_critsect.h67
-rw-r--r--src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/notes.txt15
-rw-r--r--src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/pal_composite_native_cs.c475
-rw-r--r--src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/readme.txt39
-rw-r--r--src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/resultbuffer.cpp69
-rw-r--r--src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/resultbuffer.h43
-rw-r--r--src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/sparcinterloc.s73
-rw-r--r--src/pal/tests/palsuite/composite/threading/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/composite/threading/threadsuspension/CMakeLists.txt20
-rw-r--r--src/pal/tests/palsuite/composite/threading/threadsuspension/mainWrapper.c274
-rw-r--r--src/pal/tests/palsuite/composite/threading/threadsuspension/readme.txt11
-rw-r--r--src/pal/tests/palsuite/composite/threading/threadsuspension/samplefile.dat5124
-rw-r--r--src/pal/tests/palsuite/composite/threading/threadsuspension/threadsuspension.c907
-rw-r--r--src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/CMakeLists.txt20
-rw-r--r--src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/mainWrapper.c274
-rw-r--r--src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/readme.txt11
-rw-r--r--src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/samplefile.dat5124
-rw-r--r--src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/threadsuspension.c914
-rw-r--r--src/pal/tests/palsuite/composite/wfmo/CMakeLists.txt21
-rw-r--r--src/pal/tests/palsuite/composite/wfmo/main.c239
-rw-r--r--src/pal/tests/palsuite/composite/wfmo/mutex.c365
-rw-r--r--src/pal/tests/palsuite/composite/wfmo/readme.txt22
-rw-r--r--src/pal/tests/palsuite/debug_api/CMakeLists.txt9
-rw-r--r--src/pal/tests/palsuite/debug_api/DebugBreak/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/debug_api/DebugBreak/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/debug_api/DebugBreak/test1/test1.c47
-rw-r--r--src/pal/tests/palsuite/debug_api/DebugBreak/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/debug_api/OutputDebugStringA/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/CMakeLists.txt38
-rw-r--r--src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/helper.c35
-rw-r--r--src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/test1.c94
-rw-r--r--src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/debug_api/OutputDebugStringW/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/test1.c41
-rw-r--r--src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/debug_api/WriteProcessMemory/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/CMakeLists.txt36
-rw-r--r--src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/commonconsts.h46
-rw-r--r--src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/helper.c243
-rw-r--r--src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/test1.c189
-rw-r--r--src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/CMakeLists.txt36
-rw-r--r--src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/commonconsts.h50
-rw-r--r--src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/helper.c256
-rw-r--r--src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/test3.c205
-rw-r--r--src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/CMakeLists.txt36
-rw-r--r--src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/helper.c67
-rw-r--r--src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/test4.c124
-rw-r--r--src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/exception_handling/CMakeLists.txt13
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/PAL_EXCEPT_FILTER.c118
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/pal_except_filter.c154
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/pal_except_filter.c206
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/testinfo.dat19
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/PAL_EXCEPT_FILTER_EX.c197
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/testinfo.dat18
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/pal_except_filter_ex.c142
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/pal_except_filter.c208
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/testinfo.dat18
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/PAL_TRY_EXCEPT.c82
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/PAL_TRY_EXCEPT.c68
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/PAL_TRY_EXCEPT_EX.c133
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/PAL_TRY_EXCEPT_EX.c123
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/PAL_TRY_EXCEPT_EX.c130
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/PAL_TRY_LEAVE_FINALLY.c77
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/exception_handling/RaiseException/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/exception_handling/RaiseException/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/RaiseException/test1/test1.cpp130
-rw-r--r--src/pal/tests/palsuite/exception_handling/RaiseException/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/exception_handling/RaiseException/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/RaiseException/test2/test2.cpp224
-rw-r--r--src/pal/tests/palsuite/exception_handling/RaiseException/test2/testinfo.dat28
-rw-r--r--src/pal/tests/palsuite/exception_handling/RaiseException/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/RaiseException/test3/test.cpp115
-rw-r--r--src/pal/tests/palsuite/exception_handling/RaiseException/test3/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/test1.c82
-rw-r--r--src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/CMakeLists.txt10
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test1/test1.c67
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test1/testinfo.dat23
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test2/test2.c111
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test2/testinfo.dat25
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test3/test3.c120
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test3/testinfo.dat27
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test4/test4.c105
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test4/testinfo.dat27
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test5/test5.c112
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test5/testinfo.dat27
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test6/test6.c160
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test6/testinfo.dat25
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test7/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test7/test7.c67
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test7/testinfo.dat24
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_finally/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_finally/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_finally/test1/pal_finally.c302
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_finally/test1/testinfo.dat19
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_sxs/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_sxs/test1/CMakeLists.txt97
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest1.cpp75
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest1.src3
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest2.cpp75
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest2.src3
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_sxs/test1/exceptionsxs.cpp117
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_sxs/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/AreFileApisANSI/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/file_io/AreFileApisANSI/test1/AreFileApisANSI.c40
-rw-r--r--src/pal/tests/palsuite/file_io/AreFileApisANSI/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/AreFileApisANSI/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/CMakeLists.txt61
-rw-r--r--src/pal/tests/palsuite/file_io/CompareFileTime/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/file_io/CompareFileTime/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/CompareFileTime/test1/CompareFileTime.c68
-rw-r--r--src/pal/tests/palsuite/file_io/CompareFileTime/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/file_io/CopyFileA/CMakeLists.txt7
-rw-r--r--src/pal/tests/palsuite/file_io/CopyFileA/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/CopyFileA/test1/CopyFileA.c159
-rw-r--r--src/pal/tests/palsuite/file_io/CopyFileA/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/file_io/CopyFileA/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/CopyFileA/test2/test2.c120
-rw-r--r--src/pal/tests/palsuite/file_io/CopyFileA/test2/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/file_io/CopyFileA/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/CopyFileA/test3/test3.c141
-rw-r--r--src/pal/tests/palsuite/file_io/CopyFileA/test3/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/file_io/CopyFileA/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/CopyFileA/test4/test4.c180
-rw-r--r--src/pal/tests/palsuite/file_io/CopyFileA/test4/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/file_io/CopyFileW/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/file_io/CopyFileW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/CopyFileW/test1/CopyFileW.c155
-rw-r--r--src/pal/tests/palsuite/file_io/CopyFileW/test1/ExpectedResults.txt1
-rw-r--r--src/pal/tests/palsuite/file_io/CopyFileW/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/CopyFileW/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/CopyFileW/test2/test2.c124
-rw-r--r--src/pal/tests/palsuite/file_io/CopyFileW/test2/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/file_io/CopyFileW/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/CopyFileW/test3/test3.c196
-rw-r--r--src/pal/tests/palsuite/file_io/CopyFileW/test3/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/file_io/CreateDirectoryA/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/file_io/CreateDirectoryA/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/CreateDirectoryA/test1/CreateDirectoryA.c296
-rw-r--r--src/pal/tests/palsuite/file_io/CreateDirectoryA/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/CreateDirectoryA/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/CreateDirectoryA/test2/createdirectorya.c335
-rw-r--r--src/pal/tests/palsuite/file_io/CreateDirectoryA/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/CreateDirectoryW/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/file_io/CreateDirectoryW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/CreateDirectoryW/test1/CreateDirectoryW.c347
-rw-r--r--src/pal/tests/palsuite/file_io/CreateDirectoryW/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/file_io/CreateDirectoryW/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/CreateDirectoryW/test2/createdirectoryw.c345
-rw-r--r--src/pal/tests/palsuite/file_io/CreateDirectoryW/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/CreateFileA/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/file_io/CreateFileA/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/CreateFileA/test1/CreateFileA.c145
-rw-r--r--src/pal/tests/palsuite/file_io/CreateFileA/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/CreateFileA/test1/winoutput1
-rw-r--r--src/pal/tests/palsuite/file_io/CreateFileW/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/file_io/CreateFileW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/CreateFileW/test1/CreateFileW.c152
-rw-r--r--src/pal/tests/palsuite/file_io/CreateFileW/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/CreateFileW/test1/winoutput1
-rw-r--r--src/pal/tests/palsuite/file_io/DeleteFileA/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/file_io/DeleteFileA/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/DeleteFileA/test1/DeleteFileA.cpp182
-rw-r--r--src/pal/tests/palsuite/file_io/DeleteFileA/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/DeleteFileW/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/file_io/DeleteFileW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/DeleteFileW/test1/DeleteFileW.c164
-rw-r--r--src/pal/tests/palsuite/file_io/DeleteFileW/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/FILECanonicalizePath/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/FILECanonicalizePath/FILECanonicalizePath.c83
-rw-r--r--src/pal/tests/palsuite/file_io/FILECanonicalizePath/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/file_io/FileTimeToDosDateTime/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/file_io/FileTimeToDosDateTime/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/FileTimeToDosDateTime/test1/test1.c116
-rw-r--r--src/pal/tests/palsuite/file_io/FileTimeToDosDateTime/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/file_io/FindClose/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/file_io/FindClose/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/FindClose/test1/FindClose.c275
-rw-r--r--src/pal/tests/palsuite/file_io/FindClose/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/FindFirstFileA/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/file_io/FindFirstFileA/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/FindFirstFileA/test1/FindFirstFileA.c206
-rw-r--r--src/pal/tests/palsuite/file_io/FindFirstFileA/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/FindFirstFileW/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/file_io/FindFirstFileW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/FindFirstFileW/test1/FindFirstFileW.c212
-rw-r--r--src/pal/tests/palsuite/file_io/FindFirstFileW/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/FindNextFileA/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/file_io/FindNextFileA/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/FindNextFileA/test1/FindNextFileA.c243
-rw-r--r--src/pal/tests/palsuite/file_io/FindNextFileA/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/FindNextFileA/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/FindNextFileA/test2/findnextfilea.c107
-rw-r--r--src/pal/tests/palsuite/file_io/FindNextFileA/test2/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/file_io/FindNextFileW/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/file_io/FindNextFileW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/FindNextFileW/test1/FindNextFileW.c249
-rw-r--r--src/pal/tests/palsuite/file_io/FindNextFileW/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/FindNextFileW/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/FindNextFileW/test2/findnextfilew.c107
-rw-r--r--src/pal/tests/palsuite/file_io/FindNextFileW/test2/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/file_io/FlushFileBuffers/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/FlushFileBuffers.c130
-rw-r--r--src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/file_io/GetConsoleCP/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/file_io/GetConsoleCP/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetConsoleCP/test1/GetConsoleCP.c35
-rw-r--r--src/pal/tests/palsuite/file_io/GetConsoleCP/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/GetConsoleOutputCP/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/GetConsoleOutputCP.c35
-rw-r--r--src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/GetCurrentDirectoryA.c97
-rw-r--r--src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/GetCurrentDirectoryW.c106
-rw-r--r--src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test1/GetDiskFreeSpaceW.c94
-rw-r--r--src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test2/getdiskfreespacew.c65
-rw-r--r--src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test2/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesA/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_directory/CMakeLists.txt2
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_directory/keepme1
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_file1
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_ro_directory/CMakeLists.txt2
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_ro_directory/keepme1
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_ro_file1
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/CMakeLists.txt26
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/GetFileAttributesA.c340
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/no_directory/CMakeLists.txt2
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/no_directory/keepme1
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/no_file1
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/normal_test_directory/CMakeLists.txt2
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/normal_test_directory/keepme1
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/normal_test_file6
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/ro_test_directory/CMakeLists.txt2
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/ro_test_directory/keepme1
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/ro_test_file6
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/rw_directory/CMakeLists.txt2
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/rw_directory/keepme1
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/rw_file1
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/testinfo.dat20
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesExW/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/.hidden_directory/CMakeLists.txt2
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/.hidden_directory/anchor.txt2
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/.hidden_file1
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/CMakeLists.txt23
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/normal_test_directory/CMakeLists.txt2
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/normal_test_directory/keepme1
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/normal_test_file6
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/ro_test_directory/CMakeLists.txt2
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/ro_test_directory/keepme1
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/ro_test_file6
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/test1.c227
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/test2.c170
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesW/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_directory/CMakeLists.txt2
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_directory/keepme1
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_file1
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_ro_directory/CMakeLists.txt2
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_ro_directory/keepme1
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_ro_file1
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/CMakeLists.txt26
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/GetFileAttributesW.c345
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/no_directory/CMakeLists.txt2
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/no_directory/keepme1
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/no_file1
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/normal_test_directory/CMakeLists.txt2
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/normal_test_directory/keepme1
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/normal_test_file6
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/ro_test_directory/CMakeLists.txt2
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/ro_test_directory/keepme1
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/ro_test_file6
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/rw_file1
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/rw_test_directory/CMakeLists.txt2
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/rw_test_directory/keepme1
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/testinfo.dat20
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileSize/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileSize/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileSize/test1/GetFileSize.c173
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileSize/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileSizeEx/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/GetFileSizeEx.c173
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileTime/CMakeLists.txt10
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileTime/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileTime/test1/GetFileTime.c180
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileTime/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileTime/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileTime/test2/GetFileTime.c195
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileTime/test2/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileTime/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileTime/test3/GetFileTime.c142
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileTime/test3/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileTime/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileTime/test4/GetFileTime.c98
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileTime/test4/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileTime/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileTime/test5/getfiletime.c224
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileTime/test5/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileTime/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileTime/test6/getfiletime.c281
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileTime/test6/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileTime/test7/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileTime/test7/getfiletime.c279
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileTime/test7/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileType/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileType/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileType/test1/GetFileType.c76
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileType/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileType/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileType/test2/getfiletype.c95
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileType/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileType/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileType/test3/getfiletype.c72
-rw-r--r--src/pal/tests/palsuite/file_io/GetFileType/test3/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/GetFullPathNameA/CMakeLists.txt7
-rw-r--r--src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/GetFullPathNameA.c122
-rw-r--r--src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/test2.c143
-rw-r--r--src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/testinfo.dat18
-rw-r--r--src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/test3.c241
-rw-r--r--src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/testinfo.dat19
-rw-r--r--src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/test4.c203
-rw-r--r--src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/testinfo.dat19
-rw-r--r--src/pal/tests/palsuite/file_io/GetFullPathNameW/CMakeLists.txt7
-rw-r--r--src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/GetFullPathNameW.c157
-rw-r--r--src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/test2.c159
-rw-r--r--src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/test3.c240
-rw-r--r--src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/testinfo.dat19
-rw-r--r--src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/test4.c201
-rw-r--r--src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/testinfo.dat19
-rw-r--r--src/pal/tests/palsuite/file_io/GetLongPathNameW/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/file_io/GetLongPathNameW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetLongPathNameW/test1/GetLongPathNameW.c280
-rw-r--r--src/pal/tests/palsuite/file_io/GetLongPathNameW/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/file_io/GetLongPathNameW/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetLongPathNameW/test2/getlongpathnamew.c266
-rw-r--r--src/pal/tests/palsuite/file_io/GetLongPathNameW/test2/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/file_io/GetStdHandle/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/file_io/GetStdHandle/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetStdHandle/test1/GetStdHandle.c132
-rw-r--r--src/pal/tests/palsuite/file_io/GetStdHandle/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/GetStdHandle/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetStdHandle/test2/GetStdHandle.c79
-rw-r--r--src/pal/tests/palsuite/file_io/GetStdHandle/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/GetSystemTime/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/file_io/GetSystemTime/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetSystemTime/test1/test.c124
-rw-r--r--src/pal/tests/palsuite/file_io/GetSystemTime/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/GetSystemTimeAsFileTime.c86
-rw-r--r--src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/file_io/GetTempFileNameA/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/GetTempFileNameA.c125
-rw-r--r--src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/GetTempFileNameA.c80
-rw-r--r--src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/gettempfilenamea.c159
-rw-r--r--src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/file_io/GetTempFileNameW/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/GetTempFileNameW.c129
-rw-r--r--src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/GetTempFileNameW.c84
-rw-r--r--src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/gettempfilenamew.c161
-rw-r--r--src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/file_io/GetTempPathW/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/file_io/GetTempPathW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/GetTempPathW/test1/GetTempPathW.c103
-rw-r--r--src/pal/tests/palsuite/file_io/GetTempPathW/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/file_io/MoveFileA/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/file_io/MoveFileA/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/MoveFileA/test1/ExpectedResults.txt1
-rw-r--r--src/pal/tests/palsuite/file_io/MoveFileA/test1/MoveFileA.c469
-rw-r--r--src/pal/tests/palsuite/file_io/MoveFileA/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/MoveFileExA/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/file_io/MoveFileExA/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/MoveFileExA/test1/ExpectedResults.txt1
-rw-r--r--src/pal/tests/palsuite/file_io/MoveFileExA/test1/MoveFileExA.c360
-rw-r--r--src/pal/tests/palsuite/file_io/MoveFileExA/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/MoveFileExW/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/file_io/MoveFileExW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/MoveFileExW/test1/ExpectedResults.txt1
-rw-r--r--src/pal/tests/palsuite/file_io/MoveFileExW/test1/MoveFileExW.c431
-rw-r--r--src/pal/tests/palsuite/file_io/MoveFileExW/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/MoveFileW/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/file_io/MoveFileW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/MoveFileW/test1/ExpectedResults.txt1
-rw-r--r--src/pal/tests/palsuite/file_io/MoveFileW/test1/MoveFileW.c478
-rw-r--r--src/pal/tests/palsuite/file_io/MoveFileW/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/ReadFile/CMakeLists.txt7
-rw-r--r--src/pal/tests/palsuite/file_io/ReadFile/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/ReadFile/test1/NonReadableFile.txt1
-rw-r--r--src/pal/tests/palsuite/file_io/ReadFile/test1/ReadFile.c82
-rw-r--r--src/pal/tests/palsuite/file_io/ReadFile/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/ReadFile/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/ReadFile/test2/ReadFile.c198
-rw-r--r--src/pal/tests/palsuite/file_io/ReadFile/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/ReadFile/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/ReadFile/test3/ReadFile.c184
-rw-r--r--src/pal/tests/palsuite/file_io/ReadFile/test3/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/ReadFile/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/ReadFile/test4/readfile.c147
-rw-r--r--src/pal/tests/palsuite/file_io/ReadFile/test4/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/file_io/RemoveDirectoryA/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/file_io/RemoveDirectoryA/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/RemoveDirectoryA/test1/RemoveDirectoryA.cpp315
-rw-r--r--src/pal/tests/palsuite/file_io/RemoveDirectoryA/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/RemoveDirectoryW/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/file_io/RemoveDirectoryW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/RemoveDirectoryW/test1/RemoveDirectoryW.c282
-rw-r--r--src/pal/tests/palsuite/file_io/RemoveDirectoryW/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/SearchPathA/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/file_io/SearchPathA/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/SearchPathA/test1/SearchPathA.c144
-rw-r--r--src/pal/tests/palsuite/file_io/SearchPathA/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/file_io/SearchPathW/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/file_io/SearchPathW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/SearchPathW/test1/SearchPathW.c198
-rw-r--r--src/pal/tests/palsuite/file_io/SearchPathW/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test1/SetCurrentDirectoryA.c215
-rw-r--r--src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test2/setcurrentdirectorya.c142
-rw-r--r--src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test2/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test3/setcurrentdirectorya.c56
-rw-r--r--src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test3/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test1/SetCurrentDirectoryW.c178
-rw-r--r--src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test2/setcurrentdirectoryw.c147
-rw-r--r--src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test2/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test3/setcurrentdirectoryw.c64
-rw-r--r--src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test3/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/SetEndOfFile/CMakeLists.txt8
-rw-r--r--src/pal/tests/palsuite/file_io/SetEndOfFile/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/SetEndOfFile/test1/SetEndOfFile.c85
-rw-r--r--src/pal/tests/palsuite/file_io/SetEndOfFile/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/SetEndOfFile/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/SetEndOfFile/test2/SetEndOfFile.c154
-rw-r--r--src/pal/tests/palsuite/file_io/SetEndOfFile/test2/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/file_io/SetEndOfFile/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/SetEndOfFile/test3/SetEndOfFile.c109
-rw-r--r--src/pal/tests/palsuite/file_io/SetEndOfFile/test3/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/file_io/SetEndOfFile/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/SetEndOfFile/test4/setendoffile.c138
-rw-r--r--src/pal/tests/palsuite/file_io/SetEndOfFile/test4/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/file_io/SetEndOfFile/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/SetEndOfFile/test5/test5.c183
-rw-r--r--src/pal/tests/palsuite/file_io/SetEndOfFile/test5/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileAttributesA/CMakeLists.txt7
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileAttributesA/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileAttributesA/test1/SetFileAttributesA.c168
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileAttributesA/test1/test_file1
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileAttributesA/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileAttributesA/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileAttributesA/test2/SetFileAttributesA.c114
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileAttributesA/test2/test_file1
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileAttributesA/test2/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileAttributesA/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileAttributesA/test3/SetFileAttributesA.c48
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileAttributesA/test3/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileAttributesA/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileAttributesA/test4/SetFileAttributesA.c128
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileAttributesA/test4/test_file1
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileAttributesA/test4/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileAttributesW/CMakeLists.txt7
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileAttributesW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileAttributesW/test1/SetFileAttributesW.c167
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileAttributesW/test1/test_file1
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileAttributesW/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileAttributesW/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileAttributesW/test2/SetFileAttributesW.c121
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileAttributesW/test2/test_file1
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileAttributesW/test2/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileAttributesW/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileAttributesW/test3/SetFileAttributesW.c57
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileAttributesW/test3/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileAttributesW/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileAttributesW/test4/SetFileAttributesW.c133
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileAttributesW/test4/test_file1
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileAttributesW/test4/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/file_io/SetFilePointer/CMakeLists.txt10
-rw-r--r--src/pal/tests/palsuite/file_io/SetFilePointer/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/SetFilePointer/test1/SetFilePointer.c123
-rw-r--r--src/pal/tests/palsuite/file_io/SetFilePointer/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/SetFilePointer/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/SetFilePointer/test2/SetFilePointer.c356
-rw-r--r--src/pal/tests/palsuite/file_io/SetFilePointer/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/SetFilePointer/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/SetFilePointer/test3/SetFilePointer.c350
-rw-r--r--src/pal/tests/palsuite/file_io/SetFilePointer/test3/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/SetFilePointer/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/SetFilePointer/test4/SetFilePointer.c242
-rw-r--r--src/pal/tests/palsuite/file_io/SetFilePointer/test4/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/SetFilePointer/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/SetFilePointer/test5/SetFilePointer.c182
-rw-r--r--src/pal/tests/palsuite/file_io/SetFilePointer/test5/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/file_io/SetFilePointer/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/SetFilePointer/test6/SetFilePointer.c213
-rw-r--r--src/pal/tests/palsuite/file_io/SetFilePointer/test6/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/file_io/SetFilePointer/test7/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/SetFilePointer/test7/SetFilePointer.c213
-rw-r--r--src/pal/tests/palsuite/file_io/SetFilePointer/test7/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileTime/CMakeLists.txt7
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileTime/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileTime/test1/SetFileTime.c129
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileTime/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileTime/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileTime/test2/SetFileTime.c101
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileTime/test2/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileTime/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileTime/test3/SetFileTime.c66
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileTime/test3/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileTime/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileTime/test4/SetFileTime.c108
-rw-r--r--src/pal/tests/palsuite/file_io/SetFileTime/test4/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/file_io/WriteFile/CMakeLists.txt8
-rw-r--r--src/pal/tests/palsuite/file_io/WriteFile/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/WriteFile/test1/WriteFile.c114
-rw-r--r--src/pal/tests/palsuite/file_io/WriteFile/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/WriteFile/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/WriteFile/test2/Results.txt1
-rw-r--r--src/pal/tests/palsuite/file_io/WriteFile/test2/WriteFile.c109
-rw-r--r--src/pal/tests/palsuite/file_io/WriteFile/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/WriteFile/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/WriteFile/test3/WriteFile.c136
-rw-r--r--src/pal/tests/palsuite/file_io/WriteFile/test3/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/WriteFile/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/WriteFile/test4/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/file_io/WriteFile/test4/writefile.c155
-rw-r--r--src/pal/tests/palsuite/file_io/WriteFile/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/WriteFile/test5/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/file_io/WriteFile/test5/writefile.c117
-rw-r--r--src/pal/tests/palsuite/file_io/errorpathnotfound/CMakeLists.txt7
-rw-r--r--src/pal/tests/palsuite/file_io/errorpathnotfound/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/errorpathnotfound/test1/test1.c783
-rw-r--r--src/pal/tests/palsuite/file_io/errorpathnotfound/test1/testinfo.dat31
-rw-r--r--src/pal/tests/palsuite/file_io/errorpathnotfound/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/errorpathnotfound/test2/test2.c785
-rw-r--r--src/pal/tests/palsuite/file_io/errorpathnotfound/test2/testinfo.dat34
-rw-r--r--src/pal/tests/palsuite/file_io/errorpathnotfound/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/errorpathnotfound/test3/test3.c244
-rw-r--r--src/pal/tests/palsuite/file_io/errorpathnotfound/test3/testinfo.dat30
-rw-r--r--src/pal/tests/palsuite/file_io/errorpathnotfound/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/errorpathnotfound/test4/test4.c351
-rw-r--r--src/pal/tests/palsuite/file_io/errorpathnotfound/test4/testinfo.dat34
-rw-r--r--src/pal/tests/palsuite/file_io/gettemppatha/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/file_io/gettemppatha/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/file_io/gettemppatha/test1/gettemppatha.c103
-rw-r--r--src/pal/tests/palsuite/file_io/gettemppatha/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CMakeLists.txt28
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/CMakeLists.txt11
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/CreateFileMapping.c173
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/CreateFileMapping.c155
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/CreateFileMapping.c181
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/CreateFileMapping.c193
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/CreateFileMapping.c164
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/createfilemapping.c164
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/createfilemapping.c79
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/createfilemapping.c150
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CMakeLists.txt16
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/CreateFileMapping_neg.c93
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/CreateFileMappingW.c174
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test2/CreateFileMappingW.c124
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/CreateFileMappingW.c156
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/CreateFileMappingW.c182
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/CreateFileMappingW.c194
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/CreateFileMappingW.c165
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/createfilemapping.c165
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/createfilemapping.c82
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/createfilemapping.c151
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/CMakeLists.txt20
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/FreeLibrary.c128
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/dlltest.c32
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/test2.c52
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/CMakeLists.txt20
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/dlltest.c32
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/test1.c183
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/GetModuleFileNameA.c92
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/GetModuleFileNameA.c49
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/GetModuleFileNameW.c112
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/GetModuleFileNameW.c57
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/CMakeLists.txt20
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/test1.c111
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/testinfo.dat19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/testlib.c33
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/CMakeLists.txt20
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/test2.c152
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/testinfo.dat18
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/testlib.c33
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/GetProcessHeap/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/GetProcessHeap/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/GetProcessHeap/test1/GetProcessHeap.c39
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/GetProcessHeap/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test1/HeapAlloc.c100
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test2/HeapAlloc.c59
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test2/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test3/HeapAlloc.c62
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test3/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/HeapFree/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/HeapFree/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/HeapFree/test1/HeapFree.c62
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/HeapFree/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/CMakeLists.txt8
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test1/test1.c72
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test2/test2.c79
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test2/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test3/test3.c78
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test3/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test4/test4.c80
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test4/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test5/test5.c69
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test5/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/LocalAlloc.c49
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LocalFree/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/LocalFree.c49
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/LocalFree.c39
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LockFile/CMakeLists.txt10
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LockFile/LockFile.h152
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LockFile/test1/CMakeLists.txt36
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LockFile/test1/helper.c86
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LockFile/test1/test1.c140
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LockFile/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LockFile/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LockFile/test2/test2.c94
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LockFile/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LockFile/test3/CMakeLists.txt36
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LockFile/test3/helper.c102
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LockFile/test3/test3.c71
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LockFile/test3/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LockFile/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LockFile/test4/test4.c231
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LockFile/test4/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LockFile/test5/CMakeLists.txt36
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LockFile/test5/helper.c122
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LockFile/test5/test5.c161
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LockFile/test5/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LockFile/test6/CMakeLists.txt36
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LockFile/test6/helper.c71
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LockFile/test6/test6.c146
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LockFile/test6/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LockFile/test7/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LockFile/test7/test7.c135
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/LockFile/test7/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/CMakeLists.txt9
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/MapViewOfFile.c226
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/MapViewOfFile.c203
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/MapViewOfFile.c209
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/mapviewoffile.c166
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/mapviewoffile.c131
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test6/mapviewoffile.c85
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test6/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test1/OpenFileMappingA.c157
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/OpenFileMappingA.c214
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/OpenFileMappingA.c217
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/OpenFileMappingW.c155
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/OpenFileMappingW.c217
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/OpenFileMappingW.c210
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/ReadProcessMemory_neg.c127
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/ReadProcessMemory.c126
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/CMakeLists.txt36
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/commonconsts.h48
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/helper.c249
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/test2.c258
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/testinfo.dat18
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/CMakeLists.txt7
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test1/test1.c56
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test3/test3.c72
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test3/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test4/test4.c76
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test4/testinfo.dat18
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test5/test5.c63
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test5/testinfo.dat18
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/CMakeLists.txt7
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/UnlockFile.h112
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test1/CMakeLists.txt36
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test1/helper.c92
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test1/test1.c154
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test1/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test2/test2.c154
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test2/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test3/CMakeLists.txt36
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test3/helper.c103
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test3/test3.c142
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test3/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test4/test4.c187
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test4/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/UnmapViewOfFile.c184
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/unmapviewoffile.c42
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/CMakeLists.txt24
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/VirtualAlloc.c50
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/VirtualAlloc.c48
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/VirtualAlloc.c49
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/VirtualAlloc.c48
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/VirtualAlloc.c48
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/VirtualAlloc.c48
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/VirtualAlloc.c48
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/VirtualAlloc.c48
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/VirtualAlloc.c49
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/VirtualAlloc.c49
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/VirtualAlloc.c51
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/VirtualAlloc.c49
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/virtualalloc.c50
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/virtualalloc.c54
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/VirtualAlloc.c48
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/VirtualAlloc.c49
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/VirtualAlloc.c50
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/VirtualAlloc.c48
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/VirtualAlloc.c53
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/VirtualAlloc.c48
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/VirtualAlloc.c48
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/VirtualFree.c48
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/VirtualFree.c54
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/VirtualFree.c53
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/CMakeLists.txt9
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/VirtualProtect.c69
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/VirtualProtect.c69
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/VirtualProtect.c69
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/VirtualProtect.c68
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/VirtualProtect.c68
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/VirtualProtect.c69
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/VirtualQuery.c68
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/loader/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryA/CMakeLists.txt8
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryA/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryA/test1/LoadLibraryA.c53
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryA/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryA/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryA/test2/LoadLibraryA.c52
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryA/test2/MyModule.c19
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryA/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryA/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryA/test3/loadlibrarya.c40
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryA/test3/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryA/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryA/test5/loadlibrarya.c67
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryA/test5/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryA/test6/CMakeLists.txt36
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryA/test6/dlltest.c72
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryA/test6/loadlibrarya.c172
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryA/test6/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryA/test7/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryA/test7/LoadLibraryA.c83
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryA/test7/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryA/test8/CMakeLists.txt36
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryA/test8/dlltest.c72
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryA/test8/loadlibrarya.c235
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryA/test8/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryW/CMakeLists.txt7
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryW/test1/LoadLibraryW.c62
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryW/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryW/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryW/test2/loadlibraryw.c62
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryW/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryW/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryW/test3/loadlibraryw.c41
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryW/test3/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryW/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryW/test5/loadlibraryw.c71
-rw-r--r--src/pal/tests/palsuite/loader/LoadLibraryW/test5/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/locale_info/CMakeLists.txt26
-rw-r--r--src/pal/tests/palsuite/locale_info/CompareStringA/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/locale_info/CompareStringA/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/locale_info/CompareStringA/test1/test1.c99
-rw-r--r--src/pal/tests/palsuite/locale_info/CompareStringA/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/locale_info/CompareStringW/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/locale_info/CompareStringW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/locale_info/CompareStringW/test1/test1.c99
-rw-r--r--src/pal/tests/palsuite/locale_info/CompareStringW/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/locale_info/GetACP/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/locale_info/GetACP/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/locale_info/GetACP/test1/test1.c42
-rw-r--r--src/pal/tests/palsuite/locale_info/GetACP/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/locale_info/GetCPInfo/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/locale_info/GetCPInfo/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/locale_info/GetCPInfo/test1/test1.c54
-rw-r--r--src/pal/tests/palsuite/locale_info/GetCPInfo/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/locale_info/GetCPInfo/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/locale_info/GetCPInfo/test2/test2.c60
-rw-r--r--src/pal/tests/palsuite/locale_info/GetCPInfo/test2/testinfo.dat9
-rw-r--r--src/pal/tests/palsuite/locale_info/GetCPInfo/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/locale_info/GetCPInfo/test3/test3.c41
-rw-r--r--src/pal/tests/palsuite/locale_info/GetCPInfo/test3/testinfo.dat8
-rw-r--r--src/pal/tests/palsuite/locale_info/GetLocaleInfoW/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test1/test1.c89
-rw-r--r--src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test2/test2.c51
-rw-r--r--src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test2/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/locale_info/GetStringTypeExW/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/locale_info/GetStringTypeExW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/locale_info/GetStringTypeExW/test1/test1.c54
-rw-r--r--src/pal/tests/palsuite/locale_info/GetStringTypeExW/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/locale_info/GetStringTypeExW/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/locale_info/GetStringTypeExW/test2/test2.c78
-rw-r--r--src/pal/tests/palsuite/locale_info/GetStringTypeExW/test2/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/locale_info/GetSystemDefaultLangID/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/locale_info/GetSystemDefaultLangID/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/locale_info/GetSystemDefaultLangID/test1/test1.c59
-rw-r--r--src/pal/tests/palsuite/locale_info/GetSystemDefaultLangID/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/locale_info/GetThreadLocale/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/locale_info/GetThreadLocale/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/locale_info/GetThreadLocale/test1/test1.c36
-rw-r--r--src/pal/tests/palsuite/locale_info/GetThreadLocale/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/locale_info/GetTimeZoneInformation/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/locale_info/GetTimeZoneInformation/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/locale_info/GetTimeZoneInformation/test1/test1.c73
-rw-r--r--src/pal/tests/palsuite/locale_info/GetTimeZoneInformation/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/locale_info/GetUserDefaultLCID/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/locale_info/GetUserDefaultLCID/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/locale_info/GetUserDefaultLCID/test1/test1.c52
-rw-r--r--src/pal/tests/palsuite/locale_info/GetUserDefaultLCID/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/locale_info/GetUserDefaultLangID/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/locale_info/GetUserDefaultLangID/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/locale_info/GetUserDefaultLangID/test1/test1.c60
-rw-r--r--src/pal/tests/palsuite/locale_info/GetUserDefaultLangID/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/test1.c64
-rw-r--r--src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/test1.c72
-rw-r--r--src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/locale_info/IsValidCodePage/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/locale_info/IsValidCodePage/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/locale_info/IsValidCodePage/test1/test1.c50
-rw-r--r--src/pal/tests/palsuite/locale_info/IsValidCodePage/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/locale_info/IsValidCodePage/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/locale_info/IsValidCodePage/test2/test2.c51
-rw-r--r--src/pal/tests/palsuite/locale_info/IsValidCodePage/test2/testinfo.dat8
-rw-r--r--src/pal/tests/palsuite/locale_info/IsValidLocale/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/locale_info/IsValidLocale/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/locale_info/IsValidLocale/test1/test1.c76
-rw-r--r--src/pal/tests/palsuite/locale_info/IsValidLocale/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/locale_info/MultiByteToWideChar/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/test1.c81
-rw-r--r--src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/test2.c68
-rw-r--r--src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/test3.c73
-rw-r--r--src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/test4.c230
-rw-r--r--src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/locale_info/SetThreadLocale/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/locale_info/SetThreadLocale/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/locale_info/SetThreadLocale/test1/test1.c50
-rw-r--r--src/pal/tests/palsuite/locale_info/SetThreadLocale/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/locale_info/WideCharToMultiByte/CMakeLists.txt7
-rw-r--r--src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/test1.c102
-rw-r--r--src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/test2.c88
-rw-r--r--src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/test3.c100
-rw-r--r--src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/test4.c131
-rw-r--r--src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/test5.c154
-rw-r--r--src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/manual-inspect.dat17
-rw-r--r--src/pal/tests/palsuite/manual-unautomatable.dat35
-rw-r--r--src/pal/tests/palsuite/miscellaneous/CMakeLists.txt44
-rw-r--r--src/pal/tests/palsuite/miscellaneous/CharNextA/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/miscellaneous/CharNextA/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/CharNextA/test1/test.c62
-rw-r--r--src/pal/tests/palsuite/miscellaneous/CharNextA/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/miscellaneous/CharNextA/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/CharNextA/test2/test.c67
-rw-r--r--src/pal/tests/palsuite/miscellaneous/CharNextA/test2/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/miscellaneous/CharNextExA/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/miscellaneous/CharNextExA/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/CharNextExA/test1/test.c63
-rw-r--r--src/pal/tests/palsuite/miscellaneous/CharNextExA/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/miscellaneous/CharNextExA/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/CharNextExA/test2/test.c66
-rw-r--r--src/pal/tests/palsuite/miscellaneous/CharNextExA/test2/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/miscellaneous/CloseHandle/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/test.c64
-rw-r--r--src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/test.c46
-rw-r--r--src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/miscellaneous/CreatePipe/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/test1.c113
-rw-r--r--src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/test1.c66
-rw-r--r--src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/miscellaneous/FormatMessageW/CMakeLists.txt9
-rw-r--r--src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/test.c63
-rw-r--r--src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/test.c581
-rw-r--r--src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/test.c85
-rw-r--r--src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/test.c77
-rw-r--r--src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/test.c76
-rw-r--r--src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/test.c78
-rw-r--r--src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/test.c53
-rw-r--r--src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/test.c71
-rw-r--r--src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test1/GetCalendarInfoW.c57
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test2/GetCalendarInfoW.c79
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test2/testinfo.dat11
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetCommandLineW/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetCommandLineW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetCommandLineW/test1/test.c71
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetCommandLineW/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetComputerNameW/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetComputerNameW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetComputerNameW/test1/test.c53
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetComputerNameW/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetDateFormatW/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg1/GetDateFormatW_neg.c85
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg1/testinfo.dat8
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg2/GetDateFormatW_neg.c98
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg2/testinfo.dat9
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetDateFormatW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetDateFormatW/test1/GetDateFormatW.c100
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetDateFormatW/test1/testinfo.dat9
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/test1/test.c81
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/CMakeLists.txt9
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/test.c84
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/test.c56
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/test.c67
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/test.c75
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/test5.c145
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/test6.c99
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/CMakeLists.txt9
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/test.c79
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/test.c56
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/test.c71
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/test.c63
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/test5.c144
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/test6.c99
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetLastError/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetLastError/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetLastError/test1/test.c63
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetLastError/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetSystemInfo/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/test.c70
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetTickCount/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/test.c58
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetUserNameW/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetUserNameW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetUserNameW/test1/test.c52
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetUserNameW/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetVersionExA/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetVersionExA/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetVersionExA/test1/test.c83
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetVersionExA/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetVersionExW/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetVersionExW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetVersionExW/test1/test.c88
-rw-r--r--src/pal/tests/palsuite/miscellaneous/GetVersionExW/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterLockedExchangeAdd/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterLockedExchangeAdd/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterLockedExchangeAdd/test1/test.cpp102
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedBit/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedBit/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedBit/test1/test.cpp77
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedBit/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedBit/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedBit/test2/test.cpp77
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedBit/test2/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test1/test.cpp100
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test2/test.cpp168
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test1/test.cpp122
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test2/test.cpp104
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchangePointer/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchangePointer/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchangePointer/test1/test.cpp80
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchangePointer/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test1/test.cpp60
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test2/test.cpp94
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test1/test.cpp77
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test2/test.cpp99
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedExchange/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedExchange/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedExchange/test1/test.cpp69
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedExchange/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedExchange64/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedExchange64/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedExchange64/test1/test.cpp85
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedExchange64/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedExchangePointer/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedExchangePointer/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedExchangePointer/test1/InterlockedExchangePointer.cpp64
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedExchangePointer/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test1/test.cpp62
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test2/test.cpp95
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test1/test.cpp77
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test2/test.cpp101
-rw-r--r--src/pal/tests/palsuite/miscellaneous/IsBadCodePtr/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/miscellaneous/IsBadCodePtr/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/IsBadCodePtr/test1/test1.c60
-rw-r--r--src/pal/tests/palsuite/miscellaneous/IsBadCodePtr/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/test.c138
-rw-r--r--src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/test.c81
-rw-r--r--src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/test2.c128
-rw-r--r--src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/testinfo.dat19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/test3.c58
-rw-r--r--src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/miscellaneous/MessageBoxW/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/test.c81
-rw-r--r--src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/test.c76
-rw-r--r--src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/CMakeLists.txt7
-rw-r--r--src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/test1.c168
-rw-r--r--src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/testinfo.dat19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/test2.c85
-rw-r--r--src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/testinfo.dat19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/test3.c144
-rw-r--r--src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/testinfo.dat18
-rw-r--r--src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/test4.c100
-rw-r--r--src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/testinfo.dat18
-rw-r--r--src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/CMakeLists.txt7
-rw-r--r--src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/test.c142
-rw-r--r--src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/testinfo.dat18
-rw-r--r--src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/test.c88
-rw-r--r--src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/testinfo.dat18
-rw-r--r--src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/test3.c143
-rw-r--r--src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/test4.c99
-rw-r--r--src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/miscellaneous/SetLastError/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/miscellaneous/SetLastError/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/SetLastError/test1/test.c59
-rw-r--r--src/pal/tests/palsuite/miscellaneous/SetLastError/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/miscellaneous/_i64tow/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/miscellaneous/_i64tow/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/_i64tow/test1/test1.c76
-rw-r--r--src/pal/tests/palsuite/miscellaneous/_i64tow/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/miscellaneous/_ui64tow/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/miscellaneous/_ui64tow/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/_ui64tow/test1/_ui64tow.c101
-rw-r--r--src/pal/tests/palsuite/miscellaneous/_ui64tow/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/miscellaneous/_ui64tow/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/_ui64tow/test2/_ui64tow.c88
-rw-r--r--src/pal/tests/palsuite/miscellaneous/_ui64tow/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/miscellaneous/lstrcatW/CMakeLists.txt7
-rw-r--r--src/pal/tests/palsuite/miscellaneous/lstrcatW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/lstrcatW/test1/test.c59
-rw-r--r--src/pal/tests/palsuite/miscellaneous/lstrcatW/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/miscellaneous/lstrcatW/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/lstrcatW/test2/test2.c53
-rw-r--r--src/pal/tests/palsuite/miscellaneous/lstrcatW/test2/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/miscellaneous/lstrcatW/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/lstrcatW/test3/test3.c46
-rw-r--r--src/pal/tests/palsuite/miscellaneous/lstrcatW/test3/testinfo.dat26
-rw-r--r--src/pal/tests/palsuite/miscellaneous/lstrcatW/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/lstrcatW/test4/test4.c101
-rw-r--r--src/pal/tests/palsuite/miscellaneous/lstrcatW/test4/testinfo.dat28
-rw-r--r--src/pal/tests/palsuite/miscellaneous/lstrcpyW/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/miscellaneous/lstrcpyW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/lstrcpyW/test1/test.c66
-rw-r--r--src/pal/tests/palsuite/miscellaneous/lstrcpyW/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/miscellaneous/lstrcpynW/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/miscellaneous/lstrcpynW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/lstrcpynW/test1/test.c73
-rw-r--r--src/pal/tests/palsuite/miscellaneous/lstrcpynW/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/miscellaneous/lstrlenA/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/miscellaneous/lstrlenA/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/lstrlenA/test1/test.c49
-rw-r--r--src/pal/tests/palsuite/miscellaneous/lstrlenA/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/miscellaneous/lstrlenW/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/miscellaneous/lstrlenW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/lstrlenW/test1/test.c51
-rw-r--r--src/pal/tests/palsuite/miscellaneous/lstrlenW/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/miscellaneous/queryperformancecounter/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/miscellaneous/queryperformancecounter/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/queryperformancecounter/test1/test1.c107
-rw-r--r--src/pal/tests/palsuite/miscellaneous/queryperformancecounter/test1/testinfo.dat11
-rw-r--r--src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/test1.c59
-rw-r--r--src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfA/CMakeLists.txt13
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfA/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfA/test1/test.c58
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfA/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfA/test11/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfA/test11/test.c128
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfA/test11/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfA/test12/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfA/test12/test.c119
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfA/test12/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfA/test13/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfA/test13/test.c120
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfA/test13/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfA/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfA/test2/test.c123
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfA/test2/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfA/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfA/test3/test.c121
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfA/test3/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfA/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfA/test6/test.c114
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfA/test6/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfA/test7/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfA/test7/test.c112
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfA/test7/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfA/test8/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfA/test8/test.c120
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfA/test8/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfA/test9/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfA/test9/test.c122
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfA/test9/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfW/CMakeLists.txt13
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfW/test1/test.c64
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfW/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfW/test11/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfW/test11/test.c139
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfW/test11/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfW/test12/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfW/test12/test.c128
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfW/test12/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfW/test13/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfW/test13/test.c126
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfW/test13/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfW/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfW/test2/test.c108
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfW/test2/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfW/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfW/test3/test.c127
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfW/test3/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfW/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfW/test6/test.c115
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfW/test6/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfW/test7/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfW/test7/test.c117
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfW/test7/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfW/test8/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfW/test8/test.c128
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfW/test8/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfW/test9/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfW/test9/test.c128
-rw-r--r--src/pal/tests/palsuite/miscellaneous/wsprintfW/test9/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/pal_specific/CMakeLists.txt13
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/PAL_GetPALDirectoryW.c78
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/PAL_GetUserTempDirectoryW.c58
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/PAL_Initialize_Terminate.c33
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/pal_initialize_twice.c41
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/PAL_RegisterLibraryW_UnregisterLibraryW.c64
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/reg_unreg_libraryw_neg.c62
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_errno/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_errno/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_errno/test1/PAL_errno.c53
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_errno/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_get_stderr/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/PAL_get_stderr.c52
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_get_stdin/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/PAL_get_stdin.c68
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_get_stdout/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/PAL_get_stdout.c52
-rw-r--r--src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/pal_specific/pal_entrypoint/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/pal_specific/pal_entrypoint/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/pal_specific/pal_entrypoint/test1/pal_entrypoint.c54
-rw-r--r--src/pal/tests/palsuite/pal_specific/pal_entrypoint/test1/palstartup.h49
-rw-r--r--src/pal/tests/palsuite/pal_specific/pal_entrypoint/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/pal_specific/pal_initializedebug/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/pal_specific/pal_initializedebug/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/pal_specific/pal_initializedebug/test1/pal_initializedebug.c36
-rw-r--r--src/pal/tests/palsuite/pal_specific/pal_initializedebug/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/paltestlist.txt808
-rw-r--r--src/pal/tests/palsuite/paltestlist_to_be_reviewed.txt201
-rw-r--r--src/pal/tests/palsuite/palverify.dat889
-rwxr-xr-xsrc/pal/tests/palsuite/runpaltests.sh213
-rw-r--r--src/pal/tests/palsuite/samples/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/samples/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/samples/test1/test.c41
-rw-r--r--src/pal/tests/palsuite/samples/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/samples/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/samples/test2/test.c48
-rw-r--r--src/pal/tests/palsuite/samples/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/smoketest.script100
-rw-r--r--src/pal/tests/palsuite/tests-manual.dat12
-rw-r--r--src/pal/tests/palsuite/threading/CMakeLists.txt44
-rw-r--r--src/pal/tests/palsuite/threading/CreateEventA/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/threading/CreateEventA/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/CreateEventA/test1/test1.c95
-rw-r--r--src/pal/tests/palsuite/threading/CreateEventA/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/threading/CreateEventA/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/CreateEventA/test2/test2.c84
-rw-r--r--src/pal/tests/palsuite/threading/CreateEventA/test2/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/threading/CreateEventA/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/CreateEventA/test3/test3.c219
-rw-r--r--src/pal/tests/palsuite/threading/CreateEventA/test3/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/threading/CreateEventW/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/threading/CreateEventW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/CreateEventW/test1/test1.c93
-rw-r--r--src/pal/tests/palsuite/threading/CreateEventW/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/threading/CreateEventW/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/CreateEventW/test2/test2.c85
-rw-r--r--src/pal/tests/palsuite/threading/CreateEventW/test2/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/threading/CreateEventW/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/CreateEventW/test3/test3.c233
-rw-r--r--src/pal/tests/palsuite/threading/CreateEventW/test3/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test1/CreateMutexA.c345
-rw-r--r--src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test1/testinfo.dat33
-rw-r--r--src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test2/CreateMutexA.c331
-rw-r--r--src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test2/testinfo.dat24
-rw-r--r--src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test1/CreateMutexW.c345
-rw-r--r--src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test1/testinfo.dat33
-rw-r--r--src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test2/CreateMutexW.c340
-rw-r--r--src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test2/testinfo.dat24
-rw-r--r--src/pal/tests/palsuite/threading/CreateProcessA/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/threading/CreateProcessA/test1/CMakeLists.txt36
-rw-r--r--src/pal/tests/palsuite/threading/CreateProcessA/test1/childProcess.c131
-rw-r--r--src/pal/tests/palsuite/threading/CreateProcessA/test1/parentProcess.c201
-rw-r--r--src/pal/tests/palsuite/threading/CreateProcessA/test1/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/threading/CreateProcessA/test2/CMakeLists.txt36
-rw-r--r--src/pal/tests/palsuite/threading/CreateProcessA/test2/childprocess.c69
-rw-r--r--src/pal/tests/palsuite/threading/CreateProcessA/test2/parentprocess.c243
-rw-r--r--src/pal/tests/palsuite/threading/CreateProcessA/test2/test2.h72
-rw-r--r--src/pal/tests/palsuite/threading/CreateProcessA/test2/testinfo.dat20
-rw-r--r--src/pal/tests/palsuite/threading/CreateProcessW/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/threading/CreateProcessW/test1/CMakeLists.txt36
-rw-r--r--src/pal/tests/palsuite/threading/CreateProcessW/test1/childProcess.c150
-rw-r--r--src/pal/tests/palsuite/threading/CreateProcessW/test1/parentProcess.c210
-rw-r--r--src/pal/tests/palsuite/threading/CreateProcessW/test1/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/threading/CreateProcessW/test2/CMakeLists.txt36
-rw-r--r--src/pal/tests/palsuite/threading/CreateProcessW/test2/childprocess.c78
-rw-r--r--src/pal/tests/palsuite/threading/CreateProcessW/test2/parentprocess.c245
-rw-r--r--src/pal/tests/palsuite/threading/CreateProcessW/test2/test2.h31
-rw-r--r--src/pal/tests/palsuite/threading/CreateProcessW/test2/testinfo.dat20
-rw-r--r--src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/CreateSemaphore.c322
-rw-r--r--src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/testinfo.dat18
-rw-r--r--src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/CreateSemaphore.c313
-rw-r--r--src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/testinfo.dat18
-rw-r--r--src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/createsemaphore.c200
-rw-r--r--src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/testinfo.dat20
-rw-r--r--src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/CreateSemaphore.c323
-rw-r--r--src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/testinfo.dat18
-rw-r--r--src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/CreateSemaphore.c314
-rw-r--r--src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/testinfo.dat18
-rw-r--r--src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/createsemaphore.c201
-rw-r--r--src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/testinfo.dat20
-rw-r--r--src/pal/tests/palsuite/threading/CreateThread/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/threading/CreateThread/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/CreateThread/test1/test1.c119
-rw-r--r--src/pal/tests/palsuite/threading/CreateThread/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/threading/CreateThread/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/CreateThread/test2/test2.c184
-rw-r--r--src/pal/tests/palsuite/threading/CreateThread/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/threading/CreateThread/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/CreateThread/test3/test3.c101
-rw-r--r--src/pal/tests/palsuite/threading/CreateThread/test3/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/threading/CriticalSectionFunctions/CMakeLists.txt11
-rw-r--r--src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/InitializeCriticalSection.c235
-rw-r--r--src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/testinfo.dat21
-rw-r--r--src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/test2.c226
-rw-r--r--src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/testinfo.dat18
-rw-r--r--src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/test3.c376
-rw-r--r--src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/testinfo.dat29
-rw-r--r--src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/test4.c241
-rw-r--r--src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/test5.c187
-rw-r--r--src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/test6.c190
-rw-r--r--src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/test7.c188
-rw-r--r--src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/test8.c217
-rw-r--r--src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/thistest.dat2
-rw-r--r--src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test1/test1.c145
-rw-r--r--src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test1/testlib.c47
-rw-r--r--src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/dllmain1.c66
-rw-r--r--src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/dllmain2.c66
-rw-r--r--src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/test2.c237
-rw-r--r--src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/testinfo.dat18
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/CMakeLists.txt15
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test1/test1.c152
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test10/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test10/test10.c239
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test10/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test11/CMakeLists.txt36
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test11/childprocess.c74
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test11/myexitcode.h13
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test11/test11.c364
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test11/testinfo.dat19
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test12/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test12/test12.c129
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test12/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test2/test2.c96
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test2/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test3/test3.c123
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test3/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test4/test4.c239
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test4/testinfo.dat19
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test5/test5.c145
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test5/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test6/test6.c146
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test6/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test7/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test7/test7.c149
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test7/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test8/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test8/test8.c164
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test8/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test9/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test9/test9.c127
-rw-r--r--src/pal/tests/palsuite/threading/DuplicateHandle/test9/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/threading/ExitProcess/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/threading/ExitProcess/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/ExitProcess/test1/ExitProcess.c32
-rw-r--r--src/pal/tests/palsuite/threading/ExitProcess/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/threading/ExitProcess/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/ExitProcess/test2/test2.c30
-rw-r--r--src/pal/tests/palsuite/threading/ExitProcess/test2/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/threading/ExitProcess/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/ExitProcess/test3/test3.c40
-rw-r--r--src/pal/tests/palsuite/threading/ExitProcess/test3/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/threading/ExitThread/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/threading/ExitThread/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/ExitThread/test1/test1.c114
-rw-r--r--src/pal/tests/palsuite/threading/ExitThread/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/threading/ExitThread/test2/CMakeLists.txt36
-rw-r--r--src/pal/tests/palsuite/threading/ExitThread/test2/childprocess.c41
-rw-r--r--src/pal/tests/palsuite/threading/ExitThread/test2/myexitcode.h14
-rw-r--r--src/pal/tests/palsuite/threading/ExitThread/test2/test2.c168
-rw-r--r--src/pal/tests/palsuite/threading/ExitThread/test2/testinfo.dat19
-rw-r--r--src/pal/tests/palsuite/threading/ExitThread/test3/dllmain.c65
-rw-r--r--src/pal/tests/palsuite/threading/ExitThread/test3/test3.c162
-rw-r--r--src/pal/tests/palsuite/threading/ExitThread/test3/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/threading/GetCurrentProcess/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/threading/GetCurrentProcess/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/GetCurrentProcess/test1/process.c40
-rw-r--r--src/pal/tests/palsuite/threading/GetCurrentProcess/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/threading/GetCurrentProcessId/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/processId.c41
-rw-r--r--src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/threading/GetCurrentThread/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/threading/GetCurrentThread/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/GetCurrentThread/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/threading/GetCurrentThread/test1/thread.c93
-rw-r--r--src/pal/tests/palsuite/threading/GetCurrentThread/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/GetCurrentThread/test2/test2.c144
-rw-r--r--src/pal/tests/palsuite/threading/GetCurrentThread/test2/testinfo.dat18
-rw-r--r--src/pal/tests/palsuite/threading/GetCurrentThreadId/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/threadId.c82
-rw-r--r--src/pal/tests/palsuite/threading/GetExitCodeProcess/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/CMakeLists.txt36
-rw-r--r--src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/childProcess.c31
-rw-r--r--src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/myexitcode.h14
-rw-r--r--src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/test1.c163
-rw-r--r--src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/threading/GetProcessTimes/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/threading/GetProcessTimes/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/GetProcessTimes/test2/test2.c122
-rw-r--r--src/pal/tests/palsuite/threading/GetProcessTimes/test2/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/threading/GetThreadTimes/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/threading/GetThreadTimes/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/GetThreadTimes/test1/test1.c102
-rw-r--r--src/pal/tests/palsuite/threading/NamedMutex/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/threading/NamedMutex/test1/CMakeLists.txt20
-rw-r--r--src/pal/tests/palsuite/threading/NamedMutex/test1/namedmutex.cpp1058
-rw-r--r--src/pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp65
-rw-r--r--src/pal/tests/palsuite/threading/NamedMutex/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/threading/OpenEventW/CMakeLists.txt8
-rw-r--r--src/pal/tests/palsuite/threading/OpenEventW/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/OpenEventW/test1/test1.c134
-rw-r--r--src/pal/tests/palsuite/threading/OpenEventW/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/threading/OpenEventW/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/OpenEventW/test2/test2.c194
-rw-r--r--src/pal/tests/palsuite/threading/OpenEventW/test2/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/threading/OpenEventW/test3/CMakeLists.txt36
-rw-r--r--src/pal/tests/palsuite/threading/OpenEventW/test3/childprocess.c81
-rw-r--r--src/pal/tests/palsuite/threading/OpenEventW/test3/test3.c187
-rw-r--r--src/pal/tests/palsuite/threading/OpenEventW/test3/testinfo.dat21
-rw-r--r--src/pal/tests/palsuite/threading/OpenEventW/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/OpenEventW/test4/test4.c112
-rw-r--r--src/pal/tests/palsuite/threading/OpenEventW/test4/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/threading/OpenEventW/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/OpenEventW/test5/test5.c197
-rw-r--r--src/pal/tests/palsuite/threading/OpenEventW/test5/testinfo.dat19
-rw-r--r--src/pal/tests/palsuite/threading/OpenProcess/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/threading/OpenProcess/test1/CMakeLists.txt36
-rw-r--r--src/pal/tests/palsuite/threading/OpenProcess/test1/childProcess.c75
-rw-r--r--src/pal/tests/palsuite/threading/OpenProcess/test1/myexitcode.h14
-rw-r--r--src/pal/tests/palsuite/threading/OpenProcess/test1/test1.c282
-rw-r--r--src/pal/tests/palsuite/threading/OpenProcess/test1/testinfo.dat19
-rw-r--r--src/pal/tests/palsuite/threading/QueryThreadCycleTime/CMakeLists.txt3
-rw-r--r--src/pal/tests/palsuite/threading/QueryThreadCycleTime/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/QueryThreadCycleTime/test1/test1.c98
-rw-r--r--src/pal/tests/palsuite/threading/QueueUserAPC/CMakeLists.txt10
-rw-r--r--src/pal/tests/palsuite/threading/QueueUserAPC/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/QueueUserAPC/test1/test1.c313
-rw-r--r--src/pal/tests/palsuite/threading/QueueUserAPC/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/threading/QueueUserAPC/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/QueueUserAPC/test2/test2.c224
-rw-r--r--src/pal/tests/palsuite/threading/QueueUserAPC/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/threading/QueueUserAPC/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/QueueUserAPC/test3/test3.c33
-rw-r--r--src/pal/tests/palsuite/threading/QueueUserAPC/test3/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/threading/QueueUserAPC/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/QueueUserAPC/test4/test4.c72
-rw-r--r--src/pal/tests/palsuite/threading/QueueUserAPC/test4/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/threading/QueueUserAPC/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/QueueUserAPC/test5/test5.c200
-rw-r--r--src/pal/tests/palsuite/threading/QueueUserAPC/test5/testinfo.dat20
-rw-r--r--src/pal/tests/palsuite/threading/QueueUserAPC/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/QueueUserAPC/test6/test6.c129
-rw-r--r--src/pal/tests/palsuite/threading/QueueUserAPC/test6/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/threading/QueueUserAPC/test7/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/QueueUserAPC/test7/test7.c253
-rw-r--r--src/pal/tests/palsuite/threading/QueueUserAPC/test7/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/threading/ReleaseMutex/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/threading/ReleaseMutex/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/ReleaseMutex/test3/ReleaseMutex.c103
-rw-r--r--src/pal/tests/palsuite/threading/ReleaseMutex/test3/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/threading/ResetEvent/CMakeLists.txt7
-rw-r--r--src/pal/tests/palsuite/threading/ResetEvent/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/ResetEvent/test1/test1.c99
-rw-r--r--src/pal/tests/palsuite/threading/ResetEvent/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/threading/ResetEvent/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/ResetEvent/test2/test2.c89
-rw-r--r--src/pal/tests/palsuite/threading/ResetEvent/test2/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/threading/ResetEvent/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/ResetEvent/test3/test3.c86
-rw-r--r--src/pal/tests/palsuite/threading/ResetEvent/test3/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/threading/ResetEvent/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/ResetEvent/test4/test4.c161
-rw-r--r--src/pal/tests/palsuite/threading/ResetEvent/test4/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/threading/ResumeThread/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/threading/ResumeThread/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/ResumeThread/test1/test1.c141
-rw-r--r--src/pal/tests/palsuite/threading/ResumeThread/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/threading/SetErrorMode/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/threading/SetErrorMode/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/SetErrorMode/test1/test1.c50
-rw-r--r--src/pal/tests/palsuite/threading/SetErrorMode/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/threading/SetEvent/CMakeLists.txt7
-rw-r--r--src/pal/tests/palsuite/threading/SetEvent/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/SetEvent/test1/test1.c94
-rw-r--r--src/pal/tests/palsuite/threading/SetEvent/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/threading/SetEvent/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/SetEvent/test2/test2.c125
-rw-r--r--src/pal/tests/palsuite/threading/SetEvent/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/threading/SetEvent/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/SetEvent/test3/test3.c85
-rw-r--r--src/pal/tests/palsuite/threading/SetEvent/test3/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/threading/SetEvent/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/SetEvent/test4/test4.c161
-rw-r--r--src/pal/tests/palsuite/threading/SetEvent/test4/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/threading/Sleep/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/threading/Sleep/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/Sleep/test1/Sleep.c80
-rw-r--r--src/pal/tests/palsuite/threading/Sleep/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/threading/Sleep/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/Sleep/test2/sleep.c73
-rw-r--r--src/pal/tests/palsuite/threading/Sleep/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/threading/SleepEx/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/threading/SleepEx/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/SleepEx/test1/test1.c89
-rw-r--r--src/pal/tests/palsuite/threading/SleepEx/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/threading/SleepEx/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/SleepEx/test2/test2.c183
-rw-r--r--src/pal/tests/palsuite/threading/SleepEx/test2/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/threading/SwitchToThread/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/threading/SwitchToThread/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/SwitchToThread/test1/test1.c97
-rw-r--r--src/pal/tests/palsuite/threading/SwitchToThread/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/threading/TLS/CMakeLists.txt9
-rw-r--r--src/pal/tests/palsuite/threading/TLS/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/TLS/test1/TLS.c182
-rw-r--r--src/pal/tests/palsuite/threading/TLS/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/threading/TLS/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/TLS/test2/TLS.c66
-rw-r--r--src/pal/tests/palsuite/threading/TLS/test2/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/threading/TLS/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/TLS/test3/TLS.c90
-rw-r--r--src/pal/tests/palsuite/threading/TLS/test3/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/threading/TLS/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/TLS/test4/test4.c137
-rw-r--r--src/pal/tests/palsuite/threading/TLS/test4/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/threading/TLS/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/TLS/test5/test5.c108
-rw-r--r--src/pal/tests/palsuite/threading/TLS/test5/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/threading/TLS/test6_optimizedtls/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/TLS/test6_optimizedtls/test.c190
-rw-r--r--src/pal/tests/palsuite/threading/TLS/test6_optimizedtls/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/threading/TerminateProcess/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/threading/TerminateProcess/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/TerminateProcess/test1/TerminateProcess.c41
-rw-r--r--src/pal/tests/palsuite/threading/TerminateProcess/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/threading/ThreadPriority/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/threading/ThreadPriority/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/ThreadPriority/test1/ThreadPriority.c83
-rw-r--r--src/pal/tests/palsuite/threading/ThreadPriority/test1/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/threading/WaitForMultipleObjects/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/test1.c224
-rw-r--r--src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/CMakeLists.txt9
-rw-r--r--src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/test1.c226
-rw-r--r--src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/test2.c188
-rw-r--r--src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/test3.c106
-rw-r--r--src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/test4.c101
-rw-r--r--src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/CMakeLists.txt36
-rw-r--r--src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/commonconsts.h42
-rw-r--r--src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/helper.c122
-rw-r--r--src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/test5.c506
-rw-r--r--src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/testinfo.dat18
-rw-r--r--src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/CMakeLists.txt36
-rw-r--r--src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/child6.c211
-rw-r--r--src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/test6.c709
-rw-r--r--src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/thistest.dat2
-rw-r--r--src/pal/tests/palsuite/threading/WaitForSingleObject/CMakeLists.txt11
-rw-r--r--src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExMutexTest/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExMutexTest/WFSOExMutexTest.c214
-rw-r--r--src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExSemaphoreTest/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExSemaphoreTest/WFSOExSemaphoreTest.c184
-rw-r--r--src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExThreadTest/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExThreadTest/WFSOExThreadTest.c204
-rw-r--r--src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOMutexTest/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOMutexTest/WFSOMutexTest.c184
-rw-r--r--src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOProcessTest/CMakeLists.txt36
-rw-r--r--src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOProcessTest/ChildProcess.c50
-rw-r--r--src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOProcessTest/WFSOProcessTest.c119
-rw-r--r--src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOSemaphoreTest/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOSemaphoreTest/WFSOSemaphoreTest.c183
-rw-r--r--src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOThreadTest/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOThreadTest/WFSOThreadTest.c179
-rw-r--r--src/pal/tests/palsuite/threading/WaitForSingleObject/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/WaitForSingleObject/test1/test1.c121
-rw-r--r--src/pal/tests/palsuite/threading/WaitForSingleObject/test1/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/threading/YieldProcessor/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/threading/YieldProcessor/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/YieldProcessor/test1/test1.c92
-rw-r--r--src/pal/tests/palsuite/threading/YieldProcessor/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/threading/releasesemaphore/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/threading/releasesemaphore/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/threading/releasesemaphore/test1/test.c68
-rw-r--r--src/pal/tests/palsuite/threading/releasesemaphore/test1/testinfo.dat15
3589 files changed, 170276 insertions, 0 deletions
diff --git a/src/pal/tests/CMakeLists.txt b/src/pal/tests/CMakeLists.txt
new file mode 100644
index 0000000000..a6d1ba4d5b
--- /dev/null
+++ b/src/pal/tests/CMakeLists.txt
@@ -0,0 +1,32 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+if(CLR_CMAKE_PLATFORM_ARCH_AMD64)
+ set(PAL_CMAKE_PLATFORM_ARCH_AMD64 1)
+elseif(CLR_CMAKE_PLATFORM_ARCH_ARM)
+ set(PAL_CMAKE_PLATFORM_ARCH_ARM 1)
+elseif(CLR_CMAKE_PLATFORM_ARCH_ARM64)
+ set(PAL_CMAKE_PLATFORM_ARCH_ARM64 1)
+endif()
+
+# Compile options
+add_definitions(-DPLATFORM_UNIX=1)
+add_definitions(-DLP64COMPATIBLE=1)
+add_definitions(-DFEATURE_PAL=1)
+add_definitions(-DCORECLR=1)
+add_definitions(-DPIC=1)
+if(PAL_CMAKE_PLATFORM_ARCH_AMD64)
+ add_definitions(-DBIT64=1)
+ add_definitions(-D_WIN64=1)
+elseif(PAL_CMAKE_PLATFORM_ARCH_ARM)
+ add_definitions(-DBIT32=1)
+elseif(PAL_CMAKE_PLATFORM_ARCH_ARM64)
+ add_definitions(-DBIT64=1)
+ add_definitions(-D_WIN64=1)
+else()
+ message(FATAL_ERROR "Only ARM, ARM64 and AMD64 is supported")
+endif()
+
+add_compile_options(-Wno-empty-body)
+
+add_subdirectory(palsuite)
+
diff --git a/src/pal/tests/palsuite/CMakeLists.txt b/src/pal/tests/palsuite/CMakeLists.txt
new file mode 100644
index 0000000000..235b695961
--- /dev/null
+++ b/src/pal/tests/palsuite/CMakeLists.txt
@@ -0,0 +1,24 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+project(PALTESTSUITE)
+
+include_directories(${PALTESTSUITE_SOURCE_DIR}/common)
+
+add_compile_options(-Wno-incompatible-pointer-types-discards-qualifiers)
+add_compile_options(-Wno-int-to-void-pointer-cast)
+
+# TODO: make these tests compile
+# add_subdirectory(composite)
+add_subdirectory(exception_handling)
+
+add_subdirectory(c_runtime)
+add_subdirectory(debug_api)
+add_subdirectory(filemapping_memmgt)
+add_subdirectory(file_io)
+add_subdirectory(loader)
+add_subdirectory(locale_info)
+add_subdirectory(miscellaneous)
+add_subdirectory(pal_specific)
+add_subdirectory(samples)
+add_subdirectory(threading)
+add_subdirectory($ENV{__IntermediatesDir}/Generated/eventprovider/tests ${CMAKE_CURRENT_BINARY_DIR}/eventprovider )
diff --git a/src/pal/tests/palsuite/DisabledTests.txt b/src/pal/tests/palsuite/DisabledTests.txt
new file mode 100644
index 0000000000..b3ca370586
--- /dev/null
+++ b/src/pal/tests/palsuite/DisabledTests.txt
@@ -0,0 +1,123 @@
+Disabled Test Cases
+~~~~~~~~~~~~~~~~~~~
+
+Below is a list of all disabled test cases currently listed in
+testconfig.dat and an explanation as to why they are disabled.
+
+debug_api/debugbreak/test1
+debug_api/outputdebugstringa/test1
+debug_api/outputdebugstringw/test1
+debug_api/writeprocessmemory/test1
+debug_api/writeprocessmemory/test2
+debug_api/writeprocessmemory/test3
+debug_api/writeprocessmemory/test4
+=======================================
+The above testcases were disabled in the palsuite, because they depend heavily on
+WaitForDebugEvent,DebugActiveProcess and ContinueDebugEvent, where these api's have been removed from the PAL and listed in the rotor_pal.doc (6.0)
+
+
+file_io/gettempfilenamea/test2 :
+=======================================
+This test takes longer than 60 seconds to run. The test creates
+about 65000 files and then deletes them. The test that takes longer
+than 60 seconds will be flagged as an error and so in such a case
+the test will have to be run manually.
+
+file_io/gettempfilenamew/test2 :
+=======================================
+This test takes longer than 60 seconds to run. The test creates
+about 65000 files and then deletes them. The test that takes longer
+than 60 seconds will be flagged as an error and so in such a case
+the test will have to be run manually.
+
+locale_info/getcpinfo/test2:
+=======================================
+This test will be useful in future versions for testing various
+languages (code pages). Currently only U.S. English (tested by -
+test1) is supported.
+
+locale_info/getcpinfo/test3:
+=======================================
+This test will be useful in future versions for testing various
+languages (code pages). Currently only U.S. English (tested by -
+test1) is supported.
+
+locale_info/isvalidcodepage/test2:
+=======================================
+This test will be useful in future versions for testing various
+languages (code pages). Currently only U.S. English (tested by -
+test1) is supported.
+
+miscellaneous/getcalendarinfow/test2:
+=======================================
+Currently the only calendars that are supported are CAL_GREGORIAN
+and CAL_GREGORIAN_US, which are tested by test1. This test will
+be useful when full calendar support is implemented.
+
+miscellaneous/getdateformatw/test1:
+===================================
+Currently the only calendars that are supported are CAL_GREGORIAN
+and CAL_GREGORIAN_US. The GetDateFormatW function will only be
+called when the calendar is CAL_TAIWAN. Since this calendar is not
+currently supported in this release of the PAL, the GetDateFormatW
+function is not implemented except to return an error. This test
+will be useful when full calendar support is implemented.
+
+miscellaneous/getdateformatw/getdateformatw_neg1:
+================================================
+Currently the only calendars that are supported are CAL_GREGORIAN
+and CAL_GREGORIAN_US. The GetDateFormatW function will only be
+called when the calendar is CAL_TAIWAN. Since this calendar is not
+currently supported in this release of the PAL, the GetDateFormatW
+function is not implemented except to return an error. This test
+will be useful when full calendar support is implemented.
+
+miscellaneous/getdateformatw/getdateformatw_neg2:
+================================================
+Currently the only calendars that are supported are CAL_GREGORIAN
+and CAL_GREGORIAN_US. The GetDateFormatW function will only be
+called when the calendar is CAL_TAIWAN. Since this calendar is not
+currently supported in this release of the PAL, the GetDateFormatW
+function is not implemented except to return an error. This test
+will be useful when full calendar support is implemented.
+
+
+pal_specific/pal_get_stdin/test1 :
+=======================================
+This test case should be run manually. Requires user input.
+
+
+threading/setconsolectrlhandler/test1
+threading/setconsolectrlhandler/test2
+threading/setconsolectrlhandler/test3
+threading/setconsolectrlhandler/test4
+=======================================
+These tests cases should be run manually. Requires user input.
+
+threading/getprocesstimes/test1
+=======================================
+According to rotor_pal.doc, GetProcessTimes() should be supported for the current
+process only. I've removed this test because it tests GetProcessTimes() with
+invalid process handle value.
+
+threading/getthreadcontext/test1,1
+=======================================
+According to rotor_pal.doc, when GetThreadContext is call for a thread within
+the same process, it could only be called for te current thread. I've removed
+this test, because it tests GetThreadContext() with a non current thread handle
+belong the current procees.
+
+loader/loadlibrarya/test4
+loader/loadlibraryw/test4
+=======================================
+PAL BSD should not append the .so extension in LoadLibrary if the extension is
+omitted.
+file_io/deletefilea/test3
+file_io/deletefilew/test3
+=======================================
+No code in Rotor depends on DeleteFile[A/W] failing on readonly files so we
+don't need to exactly emulate this feature of the Win32 filesystems on FreeBSD.
+
+filemapping_memmgt\MapViewOfFile\test1
+=======================================
+Refer this github issue https://github.com/dotnet/coreclr/issues/5176 \ No newline at end of file
diff --git a/src/pal/tests/palsuite/README.txt b/src/pal/tests/palsuite/README.txt
new file mode 100644
index 0000000000..577fc543f0
--- /dev/null
+++ b/src/pal/tests/palsuite/README.txt
@@ -0,0 +1,140 @@
+; Licensed to the .NET Foundation under one or more agreements.
+; The .NET Foundation licenses this file to you under the MIT license.
+; See the LICENSE file in the project root for more information.
+
+===========================================================================
+
+
+1. ENVIRONMENT SETUP
+
+2. RUNNING THE SUITES
+
+3. ENVIRONMENT VARIABLES AND AUTOMATED TESTING SPECIFICS
+3.1 PAL_DISABLE_MESSAGEBOX
+3.2 Other Notes
+
+4. ADDITIONAL NOTES ON TESTING/SPECIFIC TEST CASE ISSUES
+ C_runtime: _fdopen testing issues
+ File_IO: getfiletime/test5
+ File_IO: getfilesize/test1, setfilepointer/test(5,6,7)
+ File_IO: gettempfilename(a,w)/test2
+ File_IO: setfileattributesa/test(1,4), setfileattributesw/test(1,4)
+ Miscellaneous: messageboxw/test(1,2)
+ Pal_specific:: pal_get_stdin/test1, pal_get_stdout/test1, pal_get_stderr/test1
+ Threading: setconsolectrlhandler/test(3,4)
+
+
+===========================================================================
+
+1. ENVIRONMENT SETUP
+~~~~~~~~~~~~~~~~~~~~~
+
+Within a Rotor build window (env.sh/env.csh/env.bat), no additional
+configuration needs to be done.
+
+
+2. RUNNING THE SUITES
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Run %ROTOR_DIR%\tests\pvtrun.pl to launch the test suites. It will
+display information about each test as it runs, then report a
+summary of the results upon completion.
+
+The results are logged to %ROTOR_DIR%\tests\pvtResults.log.
+
+
+3. ENVIRONMENT VARIABLES AND AUTOMATED TESTING SPECIFICS
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+3.1 PAL_DISABLE_MESSAGEBOX
+
+For automated testing on the WIN32 PAL, the following environment
+variable is useful to prevent pop-up message boxes from interupting the
+execution of the MessageBoxW test cases:
+
+set PAL_DISABLE_MESSAGEBOX=1
+
+
+3.2 Other Notes
+
+See notes in section 4 on the following test cases if running automated tests:
+
+ Miscellaneous: messageboxw/test(1,2)
+ Threading: setconsolectrlhandler/test(3,4)
+
+
+4. ADDITIONAL NOTES ON TESTING/SPECIFIC TEST CASE ISSUES
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+C Runtime: _fdopen testing issues
+
+There is a very specific manner in which _fdopen has been documented to work,
+this will determine how the function will be tested.
+
+_fdopen takes a parameter of a c run-time file handle, to open a stream to the
+file. This file handle can only be returned from the _open_osfhandle function.
+The Rotor documentation states that _open_osfhandle will only return a
+READ-ONLY file handle, from an operating-system file handle returned from
+CreatePipe().
+
+With these restrictions _fdopen will only be tested with a mode of read(r).
+The other modes are not possible to test. _open_osfhandle returns an error
+when attempting to open a write pipe handle in a mode of read-only. As well,
+it is not possible to read and write to the same handle that is returned from
+CreatePipe().
+
+The modes that will not be tested are as follows:
+
+ "w" - Opens an empty file for writing.
+ "a" - Opens for writing at the end of the file (appending).
+ "r+" - Opens for both reading and writing.
+ "w+" - Opens an empty file for both reading and writing.
+ "a+" - Opens for reading and appending.
+
+
+
+File_IO: getfiletime/test5
+
+This test case is NTFS specific.
+
+
+File_IO: getfilesize/test1, getfilesizeex/test1 setfilepointer/test(5,6,7)
+
+These tests cases create a large number of temporary files which require
+ample disk space. On systems with less than 6Gb free disk space expect
+these test cases to fail.
+
+
+File_IO: gettempfilename(a,w)/test2
+
+These test cases take longer than 60 seconds to run. Currently, the Test
+Harness will timeout any test case that exceeds 60 seconds.
+
+
+File_IO: setfileattributesa/test(1,4), SetFileAttributesW/test(1,4)
+
+These test cases ensure restricted file permissions are respected. Administrators
+or super users (root) are not affected by file permissions and, as a result, these
+test cases will fail for such users.
+
+
+Miscellaneous: messageboxw/test(1,2)
+
+Setting PAL_MESSAGEBOX_DISABLE=1 for these test cases prevents message box pop
+ups that occur during the tests' execution on Windows. For automated testing
+where user interaction is not desired/possible, setting this environment
+variable will prevent a pause in the automated test run.
+
+
+ic: pal_get_stdin/test1, pal_get_stdout/test1, pal_get_stderr/test1
+
+These test cases should be manually inspected to ensure the information being returned
+is correct. The pal_get_stdin test case requires user input. The pal_get_stdout and
+pal_get_stderr test cases do not require user input, but their output should be inspected
+to verify that correct messages are being displayed.
+
+
+Threading: setconsolectrlhandler/test(3,4)
+
+These test cases require user response in order to produce a meaningful results.
+For automated testing, this test case is disabled.
diff --git a/src/pal/tests/palsuite/c_runtime/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/CMakeLists.txt
new file mode 100644
index 0000000000..533454c285
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/CMakeLists.txt
@@ -0,0 +1,162 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(abs)
+add_subdirectory(acos)
+add_subdirectory(asin)
+add_subdirectory(atan)
+add_subdirectory(atan2)
+add_subdirectory(atof)
+add_subdirectory(atoi)
+add_subdirectory(atol)
+add_subdirectory(bsearch)
+add_subdirectory(ceil)
+add_subdirectory(cos)
+add_subdirectory(cosh)
+
+# TODO: make this test compile
+# add_subdirectory(ctime)
+
+add_subdirectory(errno)
+add_subdirectory(exit)
+add_subdirectory(exp)
+add_subdirectory(fabs)
+add_subdirectory(fabsf)
+add_subdirectory(fclose)
+add_subdirectory(feof)
+add_subdirectory(ferror)
+add_subdirectory(fflush)
+add_subdirectory(fgets)
+add_subdirectory(floor)
+add_subdirectory(fmod)
+add_subdirectory(fmodf)
+add_subdirectory(fopen)
+add_subdirectory(fprintf)
+add_subdirectory(fputs)
+add_subdirectory(fread)
+add_subdirectory(free)
+add_subdirectory(fseek)
+add_subdirectory(ftell)
+add_subdirectory(fwprintf)
+add_subdirectory(fwrite)
+add_subdirectory(getc)
+add_subdirectory(getenv)
+add_subdirectory(isalnum)
+add_subdirectory(isalpha)
+add_subdirectory(isdigit)
+add_subdirectory(islower)
+add_subdirectory(isprint)
+add_subdirectory(isspace)
+add_subdirectory(isupper)
+add_subdirectory(iswdigit)
+add_subdirectory(iswspace)
+add_subdirectory(iswupper)
+add_subdirectory(iswxdigit)
+add_subdirectory(isxdigit)
+add_subdirectory(labs)
+add_subdirectory(llabs)
+add_subdirectory(localtime)
+add_subdirectory(log)
+add_subdirectory(log10)
+add_subdirectory(malloc)
+add_subdirectory(memchr)
+add_subdirectory(memcmp)
+add_subdirectory(memcpy)
+add_subdirectory(memmove)
+add_subdirectory(memset)
+add_subdirectory(modf)
+add_subdirectory(modff)
+add_subdirectory(pow)
+add_subdirectory(printf)
+add_subdirectory(qsort)
+add_subdirectory(rand_srand)
+add_subdirectory(realloc)
+add_subdirectory(sin)
+add_subdirectory(sinh)
+add_subdirectory(sprintf)
+add_subdirectory(sqrt)
+add_subdirectory(sscanf)
+add_subdirectory(strcat)
+add_subdirectory(strchr)
+add_subdirectory(strcmp)
+add_subdirectory(strcpy)
+add_subdirectory(strcspn)
+add_subdirectory(strlen)
+add_subdirectory(strncat)
+add_subdirectory(strncmp)
+add_subdirectory(strncpy)
+add_subdirectory(strpbrk)
+add_subdirectory(strrchr)
+add_subdirectory(strspn)
+add_subdirectory(strstr)
+add_subdirectory(strtod)
+add_subdirectory(strtok)
+add_subdirectory(strtoul)
+add_subdirectory(swprintf)
+add_subdirectory(swscanf)
+add_subdirectory(tan)
+add_subdirectory(tanh)
+add_subdirectory(time)
+add_subdirectory(tolower)
+add_subdirectory(toupper)
+add_subdirectory(towlower)
+add_subdirectory(towupper)
+add_subdirectory(ungetc)
+add_subdirectory(vfprintf)
+add_subdirectory(vprintf)
+add_subdirectory(vsprintf)
+add_subdirectory(vswprintf)
+add_subdirectory(wcscat)
+add_subdirectory(wcschr)
+add_subdirectory(wcscmp)
+add_subdirectory(wcscpy)
+add_subdirectory(wcslen)
+add_subdirectory(wcsncat)
+add_subdirectory(wcsncmp)
+add_subdirectory(wcsncpy)
+add_subdirectory(wcspbrk)
+add_subdirectory(wcsrchr)
+add_subdirectory(wcsstr)
+add_subdirectory(wcstod)
+add_subdirectory(wcstok)
+add_subdirectory(wcstol)
+add_subdirectory(wcstoul)
+add_subdirectory(wprintf)
+add_subdirectory(_alloca)
+add_subdirectory(_ecvt)
+add_subdirectory(_fdopen)
+add_subdirectory(_finite)
+add_subdirectory(_fullpath)
+
+# TODO: make this test compile
+# add_subdirectory(_gcvt)
+
+add_subdirectory(_getw)
+add_subdirectory(_isnan)
+add_subdirectory(_itow)
+add_subdirectory(_makepath)
+add_subdirectory(_mbsdec)
+add_subdirectory(_mbsinc)
+add_subdirectory(_mbslen)
+add_subdirectory(_mbsninc)
+add_subdirectory(_open_osfhandle)
+add_subdirectory(_putenv)
+add_subdirectory(_putw)
+add_subdirectory(_rotl)
+add_subdirectory(_rotr)
+add_subdirectory(_snprintf)
+add_subdirectory(_snwprintf)
+add_subdirectory(_splitpath)
+add_subdirectory(_stricmp)
+add_subdirectory(_strlwr)
+add_subdirectory(_strnicmp)
+add_subdirectory(_swab)
+add_subdirectory(_vsnprintf)
+add_subdirectory(_vsnwprintf)
+add_subdirectory(_wcsicmp)
+add_subdirectory(_wcslwr)
+add_subdirectory(_wcsnicmp)
+add_subdirectory(_wfopen)
+add_subdirectory(_wmakepath)
+add_subdirectory(_wsplitpath)
+add_subdirectory(_wtoi)
+add_subdirectory(__iscsym)
diff --git a/src/pal/tests/palsuite/c_runtime/__iscsym/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/__iscsym/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/__iscsym/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/__iscsym/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/__iscsym/test1/CMakeLists.txt
new file mode 100644
index 0000000000..a283161f7d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/__iscsym/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ __iscsym.c
+)
+
+add_executable(paltest_iscsym_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_iscsym_test1 coreclrpal)
+
+target_link_libraries(paltest_iscsym_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/__iscsym/test1/__iscsym.c b/src/pal/tests/palsuite/c_runtime/__iscsym/test1/__iscsym.c
new file mode 100644
index 0000000000..9c8f1d0f25
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/__iscsym/test1/__iscsym.c
@@ -0,0 +1,93 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: __iscsym.c
+**
+** Purpose: Positive test the __iscsym API.
+** Call __iscsym to letter, digit and underscore
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ int index;
+ char non_letter_set[]=
+ {'~','`','!','@','#','$','%','^','&','*','(',')',')',
+ '-','+','=','|','\\',';',':','"','\'','<','>',
+ ',','.','?','/','\0'};
+ char errBuffer[200];
+
+ /*Initialize the PAL environment*/
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+ /*To check if the parameter passed in is a character*/
+ for(index = 'a'; index <= 'z'; index++)
+ {
+ err = __iscsym(index);
+ if(0 == err)
+ {
+ Fail("\n__iscsym failed to recognize a "
+ "lower-case letter:%c!\n", index);
+ }
+ }
+
+ /*To check if the parameter passed in is a character*/
+ for(index = 'A'; index <= 'Z'; index++)
+ {
+ err = __iscsym(index);
+ if(0 == err)
+ {
+ Fail("\n__iscsym failed to recognize an "
+ "upper-case letter: %c!\n", index);
+ }
+ }
+
+ /*To check if the parameter passed in is a digit*/
+ for(index = '0'; index <= '9'; index++)
+ {
+ err = __iscsym(index);
+ if(0 == err)
+ {
+ Fail("\n__iscsym failed to recognize a digit %c!\n",
+ index);
+ }
+ }
+
+ /*To check if the parameter passed in is a underscore*/
+ err = __iscsym('_');
+ if(0 == err)
+ {
+ Fail("\n__iscsym failed to recognize an underscore!\n");
+ }
+
+ memset(errBuffer, 0, 200);
+
+ for(index = 0; non_letter_set[index]; index++)
+ {
+ err = __iscsym(non_letter_set[index]);
+ if(0 != err)
+ {
+ strncat(errBuffer, &non_letter_set[index], 1);
+ strcat(errBuffer, ", ");
+ }
+ }
+
+ if(strlen(errBuffer) > 0)
+ {
+ Fail("\n__iscsym failed to identify the characters '%s' "
+ "as not letters, digits "
+ "or underscores\n", errBuffer);
+ }
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/__iscsym/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/__iscsym/test1/testinfo.dat
new file mode 100644
index 0000000000..e6668edccf
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/__iscsym/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = __iscsym
+Name = Positive test for __iscsym to test letter, digit and underscore
+TYPE = DEFAULT
+EXE1 = __iscsym
+Description
+=Test the __iscsym to test letter, digit and underscore
diff --git a/src/pal/tests/palsuite/c_runtime/_alloca/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_alloca/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_alloca/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_alloca/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_alloca/test1/CMakeLists.txt
new file mode 100644
index 0000000000..236b356185
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_alloca/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_alloca_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_alloca_test1 coreclrpal)
+
+target_link_libraries(paltest_alloca_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_alloca/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_alloca/test1/test1.c
new file mode 100644
index 0000000000..c533d84234
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_alloca/test1/test1.c
@@ -0,0 +1,62 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Checks that _alloca allocates memory, and that the memory is
+** readable and writeable.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+
+ char *testA = NULL;
+ int i = 0;
+
+ /*
+ * Initialize the PAL and return FAIL if this fails
+ */
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+
+ /* check that _alloca really gives us addressable memory */
+ testA = (char *)_alloca(20 * sizeof(char));
+ if (testA == NULL)
+ {
+ Fail ("The call to _alloca failed\n");
+ }
+
+ memset(testA, 'a', 20);
+
+ for (i = 0; i < 20; i++)
+ {
+ if (testA[i] != 'a')
+ {
+ Fail ("The memory returned by _alloca doesn't seem to be"
+ " properly allocated\n");
+ }
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/_alloca/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_alloca/test1/testinfo.dat
new file mode 100644
index 0000000000..e21562195e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_alloca/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _alloca
+Name = Positive Test for _alloca
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Checks that _alloca allocates memory, and that the memory is
+= readable and writeable.
diff --git a/src/pal/tests/palsuite/c_runtime/_ecvt/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_ecvt/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_ecvt/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_ecvt/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_ecvt/test1/CMakeLists.txt
new file mode 100644
index 0000000000..86f4547b2b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_ecvt/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_ecvt_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_ecvt_test1 coreclrpal)
+
+target_link_libraries(paltest_ecvt_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_ecvt/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_ecvt/test1/test1.c
new file mode 100644
index 0000000000..fbcf11ecfc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_ecvt/test1/test1.c
@@ -0,0 +1,135 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: c_runtime/_ecvt/test1/test1.c
+**
+** Purpose: Call the _ecvt function on a number of cases. Check that it
+** handles negatives, positives and double bounds correctly. Also check that
+** the 'digit' specification works.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+#define INT64_TO_DOUBLE(a) (*(double*)&a)
+
+INT64 NaN = 0x7ff8000000000000;
+INT64 NegativeInfinity = 0xfff0000000000000;
+INT64 NegativeSmall = 0x8000000000000001;
+INT64 PositiveInfinity = 0x7ff0000000000000;
+INT64 PositiveSmall = 0x0000000000000001;
+
+struct testCase
+{
+ double value; /* number to be converted */
+ int precision; /* number of digits to be stored */
+ int decimal; /* (expected) decimal point position for stored
+ * number */
+ int sign; /* (expected) return value */
+ char expResult[256]; /* (expected) character array to be returned
+ * NOTE: this necessarily limits precision
+ * to a value between 0 and 255 */
+ char bsdExpResult[256]; /* (expected) character array to be returned
+ * NOTE: this necessarily limits precision
+ * to a value between 0 and 255 */
+};
+
+int __cdecl main(int argc, char **argv)
+{
+ char *result;
+ int testDecimal;
+ int testSign;
+ int i=0;
+
+ struct testCase testCases[] =
+ {
+ /* odd ball values */
+ {INT64_TO_DOUBLE(NaN), 7, 1, 0, "1#QNAN0" },
+ /* positive values */
+ {0, 0, 0, 0, ""},
+ {INT64_TO_DOUBLE(PositiveSmall), 17, -323, 0,
+ "49406564584124654"},
+ {.00123, 3, -2, 0, "123"},
+ {.123, 3, 0, 0, "123"},
+ {123, 3, 3, 0, "123"},
+ {3.1415926535, 9, 1, 0, "314159265"},
+ {3.1415926535, 10, 1, 0, "3141592654"},
+ {3.1415926535, 11, 1, 0, "31415926535"},
+ {3.1415926535, 12, 1, 0, "314159265350"},
+ {184467444073709570000.0, 21, 21, 0, "184467444073709570000",
+ "184467444073709568000" },
+ {184467444073709570000.0, 22, 21, 0, "1844674440737095700000",
+ "1844674440737095680000" },
+ {INT64_TO_DOUBLE(PositiveInfinity), 7, 1, 0, "1#INF00" },
+ /* negative values */
+ {-0, 0, 0, 0, ""},
+ {INT64_TO_DOUBLE(NegativeSmall), 17, -323, 1,
+ "49406564584124654"},
+ {-.00123, 3, -2, 1, "123"},
+ {-.123, 3, 0, 1, "123"},
+ {-123, 3, 3, 1, "123"},
+ {-3.1415926535, 9, 1, 1, "314159265"},
+ {-3.1415926535, 10, 1, 1, "3141592654"},
+ {-3.1415926535, 11, 1, 1, "31415926535"},
+ {-3.1415926535, 12, 1, 1, "314159265350"},
+ {-184467444073709570000.0, 21, 21, 1, "184467444073709570000",
+ "184467444073709568000" },
+ {-184467444073709570000.0, 22, 21, 1, "1844674440737095700000",
+ "1844674440737095680000" },
+ {INT64_TO_DOUBLE(NegativeInfinity), 7, 1, 1, "1#INF00"}
+
+ };
+
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Loop through each case. Call _ecvt on each test case and check the
+ result.
+ */
+
+ for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++)
+ {
+ result = _ecvt(testCases[i].value,
+ testCases[i].precision,
+ &testDecimal,
+ &testSign);
+
+ if (( strcmp(testCases[i].expResult, result) != 0 &&
+ strcmp(testCases[i].bsdExpResult, result) != 0 ) ||
+
+ ( testCases[i].sign != testSign ) ||
+ ( testCases[i].decimal != testDecimal ))
+
+ {
+ Fail("PALSUITE ERROR: Test %d\n"
+ "-----------------------\n"
+ "testCases[i].value = '%f'\n"
+ "testCases[i].precision = '%d'\n"
+ "testCases[i].decimal = '%d'\n"
+ "testCases[i].sign = '%d'\n"
+ "testCases[i].expResult = '%s'\n"
+ "result = '%s'\n"
+ "testDecimal = '%d'\n"
+ "testSign = '%d'\n\n",
+ i,
+ testCases[i].value,
+ testCases[i].precision,
+ testCases[i].decimal,
+ testCases[i].sign,
+ testCases[i].expResult,
+ result,
+ testDecimal,
+ testSign);
+ }
+
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_ecvt/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_ecvt/test1/testinfo.dat
new file mode 100644
index 0000000000..12e7292ec7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_ecvt/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _ecvt
+Name = Call _ecvt on normal values, negatives, exponents and hex digits.
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Call the _ecvt function on a number of cases. Check that it
+= handles negatives, positives and double bounds correctly. Also check that
+= the 'digit' specification works.
diff --git a/src/pal/tests/palsuite/c_runtime/_fdopen/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_fdopen/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_fdopen/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_fdopen/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_fdopen/test1/CMakeLists.txt
new file mode 100644
index 0000000000..441d32bd5c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_fdopen/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_fdopen_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fdopen_test1 coreclrpal)
+
+target_link_libraries(paltest_fdopen_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_fdopen/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_fdopen/test1/test1.c
new file mode 100644
index 0000000000..b88267c6e4
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_fdopen/test1/test1.c
@@ -0,0 +1,112 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c (fdopen)
+**
+** Purpose: Tests the PAL implementation of the fdopen function.
+** This will test fdopen in r (read) mode. This test
+** creates and opens a test pipe, to write and read
+** from. fdopen requires a file handle(int), therefore
+** _open_osfhandle is used to get that handle.
+** _open_osfhandle is only used with CreatePipe. The
+** test will write and read from the pipe comparing
+** the results.
+**
+** See /tests/palsuite/README.txt for more information.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+const char* cTestString = "one fish, two fish, read fish, blue fish.";
+
+int __cdecl main(int argc, char **argv)
+{
+ HANDLE hReadPipe = NULL;
+ HANDLE hWritePipe = NULL;
+ BOOL bRetVal = FALSE;
+ int iFiledes = 0;
+ DWORD dwBytesWritten;
+ char buffer[45];
+ FILE *fp;
+
+ SECURITY_ATTRIBUTES lpPipeAttributes;
+
+ /*Initialize the PAL*/
+ if ((PAL_Initialize(argc, argv)) != 0)
+ {
+ return (FAIL);
+ }
+
+ /*Setup SECURITY_ATTRIBUTES structure for CreatePipe*/
+ lpPipeAttributes.nLength = sizeof(lpPipeAttributes);
+ lpPipeAttributes.lpSecurityDescriptor = NULL;
+ lpPipeAttributes.bInheritHandle = TRUE;
+
+ /*Create a Pipe*/
+ bRetVal = CreatePipe(&hReadPipe, // read handle
+ &hWritePipe, // write handle
+ &lpPipeAttributes, // security attributes
+ 0); // pipe size
+
+ if (bRetVal == FALSE)
+ {
+ Fail("ERROR: unable to create pipe");
+ }
+
+ /*Write to the write pipe handle*/
+ bRetVal = WriteFile(hWritePipe, // handle to file
+ cTestString, // data buffer
+ (DWORD)strlen(cTestString), // number of bytes to write
+ &dwBytesWritten, // number of bytes written
+ NULL); // overlapped buffer
+
+ if (bRetVal == FALSE)
+ {
+ Fail("ERROR: unable to write to pipe write handle "
+ "hWritePipe=0x%lx", hWritePipe);
+ }
+
+ /*Get a file descriptor for the read pipe handle*/
+ iFiledes = _open_osfhandle((long)hReadPipe, _O_RDONLY);
+
+ if (iFiledes == -1)
+ {
+ Fail("ERROR: _open_osfhandle failed to open "
+ " hReadPipe=0x%lx", hReadPipe);
+ }
+
+ /*Open read pipe handle in read mode*/
+ fp = _fdopen(iFiledes, "r");
+
+ if (fp == NULL)
+ {
+ Fail("ERROR: unable to fdopen file descriptor"
+ " iFiledes=%d", iFiledes);
+ }
+
+ /*Read from the read pipe handle*/
+ if((fread(buffer, sizeof(char), strlen(cTestString), fp)) == 0)
+ {
+ Fail("ERROR: Unable to read from file stream fp=0x%lx\n", fp);
+ }
+
+ /*Compare what was read with what was written.*/
+ if ((memcmp(cTestString, buffer, strlen(cTestString))) != 0)
+ {
+ Fail("ERROR: read \"%s\" expected \"%s\" \n", buffer, cTestString);
+ }
+
+ /*Close the file handle*/
+ if (_close(iFiledes) != 0)
+ {
+ Fail("ERROR: Unable to close file handle iFiledes=%d\n", iFiledes);
+ }
+
+ PAL_Terminate();
+ return (PASS);
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_fdopen/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_fdopen/test1/testinfo.dat
new file mode 100644
index 0000000000..89e48bb4c1
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_fdopen/test1/testinfo.dat
@@ -0,0 +1,23 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fdopen
+Name = test for fdopen and _close
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests the PAL implementation of the fdopen function.
+= This will test fdopen in r (read) mode. This test
+= creates and opens a test pipe, to write and read
+= from. fdopen requires a file handle(int), therefore
+= _open_osfhandle is used to get that handle.
+= _open_osfhandle is only used with CreatePipe. The
+= test will write and read from the pipe comparing
+= the results.
+= As a secondary test, _close is tested since it needs
+= the handle returned by _open_osfhandle. The handle is
+= closed, then a read is attempted on the handle which
+= should fail.
diff --git a/src/pal/tests/palsuite/c_runtime/_finite/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_finite/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_finite/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/_finite/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_finite/test1/CMakeLists.txt
new file mode 100644
index 0000000000..8aca58a8dc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_finite/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_finite_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_finite_test1 coreclrpal)
+
+target_link_libraries(paltest_finite_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_finite/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_finite/test1/test1.c
new file mode 100644
index 0000000000..c815055b38
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_finite/test1/test1.c
@@ -0,0 +1,119 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Checks that _finite correctly classifies all types
+** of floating point numbers (NaN, -Infinity, Infinity,
+** finite nonzero, unnormalized, 0, and -0)
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+/*
+The IEEE double precision floating point standard looks like this:
+
+ S EEEEEEEEEEE FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+ 0 1 11 12 63
+
+S is the sign bit. The E bits are the exponent, and the 52 F bits are
+the fraction. These represent a value, V.
+
+If E=2047 and F is nonzero, then V=NaN ("Not a number")
+If E=2047 and F is zero and S is 1, then V=-Infinity
+If E=2047 and F is zero and S is 0, then V=Infinity
+If 0<E<2047 then V=(-1)^S * 2^(E-1023) * (1.F) where "1.F" is the binary
+ number created by prefixing F with a leading 1 and a binary point.
+If E=0 and F is nonzero, then V=(-1)^S * 2^(-1022) * (0.F) These are
+ "unnormalized" values.
+If E=0 and F is zero and S is 1, then V=-0
+If E=0 and F is zero and S is 0, then V=0
+
+*/
+
+#define TO_DOUBLE(x) (*((double*)((void*)&x)))
+
+int __cdecl main(int argc, char **argv)
+{
+ /*non-finite numbers*/
+ UINT64 lsnan = UI64(0xffffffffffffffff);
+ UINT64 lqnan = UI64(0x7fffffffffffffff);
+ UINT64 lneginf = UI64(0xfff0000000000000);
+ UINT64 lposinf = UI64(0x7ff0000000000000);
+
+ double snan = TO_DOUBLE(lsnan);
+ double qnan = TO_DOUBLE(lqnan);
+ double neginf = TO_DOUBLE(lneginf);
+ double posinf = TO_DOUBLE(lposinf);
+
+ /*finite numbers*/
+ UINT64 lnegunnormalized = UI64(0x800fffffffffffff);
+ UINT64 lposunnormalized = UI64(0x000fffffffffffff);
+ UINT64 lnegzero = UI64(0x8000000000000000);
+
+ double negunnormalized = TO_DOUBLE(lnegunnormalized);
+ double posunnormalized = TO_DOUBLE(lposunnormalized);
+ double negzero = TO_DOUBLE(lnegzero);
+
+ /*
+ * Initialize the PAL and return FAIL if this fails
+ */
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ /*non-finite numbers*/
+ if (_finite(snan) || _finite(qnan))
+ {
+ Fail("_finite() found NAN to be finite.\n");
+ }
+
+ if (_finite(neginf))
+ {
+ Fail("_finite() found negative infinity to be finite.\n");
+ }
+
+ if (_finite(posinf))
+ {
+ Fail("_finite() found infinity to be finite.\n");
+ }
+
+ /*finite numbers*/
+ if (!_finite(negunnormalized))
+ {
+ Fail("_finite() found a negative unnormalized value to be infinite.\n");
+ }
+
+ if (!_finite(posunnormalized))
+ {
+ Fail("_finite() found an unnormalized value to be infinite.\n");
+ }
+
+ if (!_finite(negzero))
+ {
+ Fail("_finite() found negative zero to be infinite.\n");
+ }
+
+ if (!_finite(+0.0))
+ {
+ Fail("_finite() found zero to be infinite.\n");
+ }
+
+ if (!_finite(-123.456))
+ {
+ Fail("_finite() found %f to be infinite.\n", -123.456);
+ }
+
+ if (!_finite(+123.456))
+ {
+ Fail("_finite() found %f to be infinite.\n", +123.456);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_finite/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_finite/test1/testinfo.dat
new file mode 100644
index 0000000000..cec0f8ae4a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_finite/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _finite
+Name = Positive Test for _finite
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Checks that _finite correctly classifies all types of floating point
+= numbers (NaN, -Infinity, Infinity, finite nonzero, unnormalized, 0, and -0).
diff --git a/src/pal/tests/palsuite/c_runtime/_fullpath/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_fullpath/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_fullpath/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_fullpath/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_fullpath/test1/CMakeLists.txt
new file mode 100644
index 0000000000..9306efa700
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_fullpath/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_fullpath_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fullpath_test1 coreclrpal)
+
+target_link_libraries(paltest_fullpath_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_fullpath/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_fullpath/test1/test1.c
new file mode 100644
index 0000000000..f390f4309b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_fullpath/test1/test1.c
@@ -0,0 +1,181 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: _fullpath/test1/test1.c
+**
+** Purpose: Test to see if the _fullpath function returns the
+** proper values. A check is done to ensure NULL is returned
+** by _fullpath only for the condition where the length of the
+** created absolute path name (absPath) is greater than
+** maxLength.
+**
+** Dependencies: strlen
+** strncmp
+** SetCurrentDirectory
+** GetCurrentDirectory
+**
+
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+struct testcase
+{
+ char relPath[50]; /* relative path array */
+ int maxLength; /* pathlength to pass */
+ BOOL bRet; /* TRUE if testcase expects function to return NULL */
+};
+
+int __cdecl main( int argc, char **argv )
+{
+
+ DWORD dwOrigDirLength;
+ DWORD dwNewDirLength;
+ DWORD dwRetStrLength;
+ BOOL bRet;
+ char *retPath;
+ char szAbsPath[_MAX_PATH + 1];
+ char szDirNameOWD[_MAX_DIR];
+ char szDirNameNWD[_MAX_DIR];
+ int i;
+
+ struct testcase testcases[]=
+ {
+ {"." , _MAX_PATH, FALSE},
+ {".." , _MAX_PATH, FALSE},
+ {"..\\..", _MAX_PATH, FALSE},
+ {"..\\..\\..", _MAX_PATH, FALSE},
+ {"..", 1, TRUE}
+ };
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ for (i = 0; i < sizeof(testcases)/sizeof(struct testcase) ; i++)
+ {
+
+ /* reset variables */
+ memset(szAbsPath, 0, _MAX_PATH + 1);
+ memset(szDirNameOWD, 0, _MAX_DIR);
+ memset(szDirNameNWD, 0, _MAX_DIR);
+
+ dwOrigDirLength = 0;
+ dwNewDirLength = 0;
+ dwRetStrLength = 0;
+
+ /* Get the current directory name */
+ dwOrigDirLength = GetCurrentDirectory(_MAX_PATH, szDirNameOWD);
+ if (0 == dwOrigDirLength)
+ {
+ Fail ("PALSUITE ERROR: _fullpath (char *, %s, %d) test failed."
+ "\nGetCurrentDirectory (%d, %s) call failed. GetLastError"
+ " returned '%d'\n", testcases[i].relPath,
+ testcases[i].maxLength, _MAX_PATH, szDirNameOWD,
+ GetLastError());
+ }
+
+ /*
+ * Set the current directory to relPath.
+ */
+ bRet = SetCurrentDirectory(testcases[i].relPath);
+ if (0 == bRet)
+ {
+ Fail ("PALSUITE ERROR: _fullpath (char *, %s, %d) test failed."
+ "\nSetCurrentDirectory (%s) call failed. GetLastError"
+ " returned '%d'\n", testcases[i].relPath,
+ testcases[i].maxLength, testcases[i].relPath,
+ GetLastError());
+ }
+
+ /* Get the new current directory name */
+ dwNewDirLength = GetCurrentDirectory(_MAX_PATH, szDirNameNWD);
+ if (0 == dwNewDirLength)
+ {
+ Fail ("PALSUITE ERROR: _fullpath (char *, %s, %d) test failed."
+ "\nGetCurrentDirectory(%d, %s) call failed. GetLastError"
+ " returned '%d'\n", testcases[i].relPath,
+ testcases[i].maxLength, _MAX_PATH, szDirNameNWD,
+ GetLastError());
+ }
+
+ /* Set the current directory back to the original one */
+ bRet = SetCurrentDirectory(szDirNameOWD);
+ if (0 == bRet)
+ {
+ Fail ("PALSUITE ERROR: _fullpath (char *, %s, %d) test failed."
+ "\nSetCurrentDirectory(%s) call failed. GetLastError"
+ " returned '%d'\n", testcases[i].relPath,
+ testcases[i].maxLength, szDirNameOWD, GetLastError());
+ }
+
+ retPath = _fullpath( szAbsPath,
+ testcases[i].relPath,
+ testcases[i].maxLength );
+
+ if ( NULL == retPath )
+ {
+ /* The function returned NULL when a value was expected */
+ if ( FALSE == testcases[i].bRet )
+ {
+ Fail("PALSUITE ERROR: test failed.\n"
+ "_fullpath (char *, %s, %d) returned NULL\n"
+ "when '%s' was expected\n", testcases[i].relPath,
+ testcases[i].maxLength, szDirNameNWD );
+ }
+ }
+ else
+ {
+ dwRetStrLength = strlen ( szAbsPath );
+
+ /* Check that the path lengths are identical. */
+ if ( dwRetStrLength != dwNewDirLength )
+ {
+ Fail ("PALSUITE ERROR: _fullpath (char *, %s, %d) test failed."
+ "\ndwRetStringLength '%d' is not equal to "
+ "dwNewDirLength '%d'.\nszAbsPath is '%s' retPath is '%s'\n"
+ "szDirNameNWD is '%s'\n" , testcases[i].relPath,
+ testcases[i].maxLength, dwRetStrLength ,dwNewDirLength
+ ,szAbsPath ,retPath ,szDirNameNWD);
+ }
+
+ /*
+ * Perform a string comparison on the path provided by
+ * GetCurrentDirectory and the path provided by _fullpath
+ * to ensure they are identical.
+ */
+ if ( 0 != strncmp( szDirNameNWD, szAbsPath, dwNewDirLength ))
+ {
+ Fail ("PALSUITE ERROR: _fullpath (char *, %s, %d) test failed."
+ "strncmp ( %s, %s, %d ) call failed.\n",
+ testcases[i].relPath, testcases[i].maxLength,
+ szDirNameNWD, szAbsPath, dwNewDirLength );
+ }
+
+ /*
+ * Perform a string comparison on both paths provided by
+ * _fullpath to ensure they are identical.
+ */
+ if ( 0 != strncmp( retPath, szAbsPath, dwNewDirLength ))
+ {
+ Fail ("PALSUITE ERROR: _fullpath (char *, %s, %d) test failed."
+ "strncmp ( %s, %s, %d ) call failed.\n",
+ testcases[i].relPath, testcases[i].maxLength,
+ szDirNameNWD, szAbsPath, dwNewDirLength );
+ }
+ }
+ }
+
+ PAL_Terminate();
+ return ( PASS );
+}
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/_fullpath/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_fullpath/test1/testinfo.dat
new file mode 100644
index 0000000000..cd4db831a4
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_fullpath/test1/testinfo.dat
@@ -0,0 +1,23 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = c_runtime
+Function = _fullpath
+Name = Positive Test for _fullpath
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Test to see if the _fullpath function returns the
+= proper values. A check is done to ensure NULL is returned
+= by _fullpath only for the condition where the length of the
+= created absolute path name (absPath) is greater than
+= maxLength.
+
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/_gcvt/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_gcvt/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_gcvt/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_gcvt/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_gcvt/test1/CMakeLists.txt
new file mode 100644
index 0000000000..33eb5cf19c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_gcvt/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ _gcvt.c
+)
+
+add_executable(paltest_gcvt_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_gcvt_test1 coreclrpal)
+
+target_link_libraries(paltest_gcvt_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_gcvt/test1/_gcvt.c b/src/pal/tests/palsuite/c_runtime/_gcvt/test1/_gcvt.c
new file mode 100644
index 0000000000..ccfc286898
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_gcvt/test1/_gcvt.c
@@ -0,0 +1,58 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: _gcvt.c
+**
+** Purpose: Positive test the _gcvt API.
+** Call _gcvt to convert a floatable value to a string
+** with specified sigficant digits stored
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ double dValue = -3.1415926535;
+ char buffer[1024];
+ char *pChar7 = "-3.141593";
+
+ /*Initialize the PAL environment*/
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+
+ /* zero the buffer */
+ memset(buffer, 0, 1024);
+
+
+ /*
+
+ Testing
+ =======
+
+ To convert a floating-point value to
+ a string to save 7 significant digits
+ */
+ _gcvt(dValue, 7, buffer);
+ if(strcmp(pChar7, buffer))
+ {
+ Fail("\nFailed to call _gcvt to convert a floating-point value "
+ "to a string with 7 sigficants digits stored\n");
+ }
+
+
+ /*
+ Clean up and exit
+ */
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_gcvt/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_gcvt/test1/testinfo.dat
new file mode 100644
index 0000000000..d527418108
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_gcvt/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _gcvt
+Name = Positive test for _gcvt API to convert a floatable value to a string
+TYPE = DEFAULT
+EXE1 = _gcvt
+Description
+=Test the _gcvt to convert a floatable value to a string
+=with specified sigficant digits stored
diff --git a/src/pal/tests/palsuite/c_runtime/_gcvt/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_gcvt/test2/CMakeLists.txt
new file mode 100644
index 0000000000..05641b9b78
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_gcvt/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_gcvt_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_gcvt_test2 coreclrpal)
+
+target_link_libraries(paltest_gcvt_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_gcvt/test2/test2.c b/src/pal/tests/palsuite/c_runtime/_gcvt/test2/test2.c
new file mode 100644
index 0000000000..7ac9a4fcf0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_gcvt/test2/test2.c
@@ -0,0 +1,83 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test2.c
+**
+** Purpose: Call the _gcvt function on a number of cases. Check that it
+** handles negatives, exponents and hex digits properly. Also check that
+** the 'digit' specification works. (And that it doesn't truncate negative
+** signs or decimals)
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+struct testCase
+{
+ double Value;
+ int Digits;
+ char WinCorrectResult[128];
+ char BsdCorrectResult[128]; /* for the odd case where bsd sprintf
+ varies from windows sprintf */
+};
+
+int __cdecl main(int argc, char **argv)
+{
+ char result[128];
+ int i=0;
+
+ struct testCase testCases[] =
+ {
+ {1234567, 7, "1234567"},
+ {1234.123, 7, "1234.123"},
+ {1234.1234, 7, "1234.123"},
+ {12.325678e+2, 7, "1232.568"},
+ {-12.3233333, 8, "-12.323333"},
+ {-12.32, 8, "-12.32"},
+ {-12.32e+2, 8, "-1232.", "-1232" },
+ {0x21DDFABC, 8, "5.6819577e+008", "5.6819577e+08" },
+ {123456789012345.0, 15, "123456789012345" },
+ {12340000.0, 8, "12340000"},
+ {12340000000000000.0, 15, "1.234e+016", "1.234e+16" },
+ {12340000000000000.0, 17, "12340000000000000" },
+
+ };
+
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Loop through each case. Call _gcvt on each test case and check the
+ result.
+ */
+
+ for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++)
+ {
+ _gcvt(testCases[i].Value, testCases[i].Digits, result);
+
+ if (strcmp(testCases[i].WinCorrectResult, result) != 0 &&
+
+ ( testCases[i].BsdCorrectResult &&
+ strcmp(testCases[i].BsdCorrectResult, result) != 0 ) )
+ {
+ Fail("ERROR: _gcvt attempted to convert %f with %d digits "
+ "signifigant, which resulted in "
+ "the string '%s' instead of the correct(Win) string '%s' or the"
+ "correct(bsd) string '%s'.\n",
+ testCases[i].Value,
+ testCases[i].Digits,
+ result,
+ testCases[i].WinCorrectResult,
+ testCases[i].BsdCorrectResult);
+ }
+
+ memset(result, '\0', 128);
+ }
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_gcvt/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_gcvt/test2/testinfo.dat
new file mode 100644
index 0000000000..e9e192849a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_gcvt/test2/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _gcvt
+Name = Call _gcvt on normal values, negatives, exponents and hex digits.
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Call the _gcvt function on a number of cases. Check that it
+= handles negatives, exponents and hex digits properly. Also check that
+= the 'digit' specification works. (And that it doesn't truncate negative
+= signs or decimals)
diff --git a/src/pal/tests/palsuite/c_runtime/_getw/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_getw/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_getw/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_getw/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_getw/test1/CMakeLists.txt
new file mode 100644
index 0000000000..d44477b232
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_getw/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_getw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getw_test1 coreclrpal)
+
+target_link_libraries(paltest_getw_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_getw/test1/test.dat b/src/pal/tests/palsuite/c_runtime/_getw/test1/test.dat
new file mode 100644
index 0000000000..b20eae054c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_getw/test1/test.dat
Binary files differ
diff --git a/src/pal/tests/palsuite/c_runtime/_getw/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_getw/test1/test1.c
new file mode 100644
index 0000000000..34ce4ee7de
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_getw/test1/test1.c
@@ -0,0 +1,96 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Several integers are read from a previously written file
+** using _getw. The test passes if the values read match those known to
+** be in the file.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+/*Tests _getw using a previously written data file */
+int __cdecl main(int argc, char **argv)
+{
+ const int testValues[] =
+ {
+ 0,
+ 1,
+ -1,
+ 0x7FFFFFFF, /* largest positive integer on 32 bit systems */
+ 0x80000000, /* largest negative integer on 32 bit systems */
+ 0xFFFFFFFF,
+ 0xFFFFAAAA
+ };
+
+ int i = 0;
+ int input = 0;
+
+ const char filename[] = "test.dat";
+
+
+ FILE *fp = NULL;
+
+ /*
+ * Initialize the PAL and return FAIL if this fails
+ */
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* write the file that we will use to test */
+
+
+ /*
+ Don't uncomment this code, it was used to create the data file
+ initially on windows, but if it is run on all test platforms, the
+ tests will always pass.
+
+ fp = fopen(filename, "w");
+ if (fp == NULL)
+ {
+ Fail("Unable to open file for write.\n");
+ }
+ for (i = 0; i < sizeof(testValues) / sizeof(testValues[0]); i++)
+ {
+ _putw(testValues[i], fp);
+ }
+
+ if (fclose(fp) != 0)
+ {
+ Fail("Error closing file after writing to it with _putw.\n");
+ }
+ */
+
+
+ /*Now read values back from the file and see if they match.*/
+ fp = fopen(filename, "r");
+ if (fp == NULL)
+ {
+ Fail ("Unable to open file for read.\n");
+ }
+ for (i = 0; i < sizeof(testValues) / sizeof(testValues[0]); i++)
+ {
+ input = _getw(fp);
+ if (VAL32(input) != testValues[i])
+ {
+ Fail ("_getw did not get the expected values when reading "
+ "from a file.\n");
+ }
+ }
+
+ if (fclose(fp) != 0)
+ {
+ Fail ("Error closing file after reading from it with _getw\n");
+ }
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/_getw/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_getw/test1/testinfo.dat
new file mode 100644
index 0000000000..4044dadbcc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_getw/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _getw
+Name = Positive Test for _getw
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Several integers are read from a previously written file
+=using _getw. The test passes if the values read match those known to
+=be in the file.
+
diff --git a/src/pal/tests/palsuite/c_runtime/_isnan/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_isnan/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_isnan/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/_isnan/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_isnan/test1/CMakeLists.txt
new file mode 100644
index 0000000000..e14d0cc64b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_isnan/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_isnan_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_isnan_test1 coreclrpal)
+
+target_link_libraries(paltest_isnan_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_isnan/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_isnan/test1/test1.c
new file mode 100644
index 0000000000..d793c9b371
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_isnan/test1/test1.c
@@ -0,0 +1,115 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose:
+** Test _isnan with a number of trivial values, to ensure they indicated that
+** they are numbers. Then try with Positive/Negative Infinite, which should
+** also be numbers. Finally set the least and most significant bits of
+** the fraction to positive and negative, at which point it should return
+** the true value.
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+#define TO_DOUBLE(x) (*((double*)((void*)&x)))
+#define TO_I64(x) (*((INT64*)((void*)&x)))
+
+/*
+ * NaN: any double with maximum exponent (0x7ff) and non-zero fraction
+ */
+int __cdecl main(int argc, char *argv[])
+{
+ /*
+ * Initialize the PAL and return FAIL if this fails
+ */
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ /*
+ * Try some trivial values
+ */
+ if (_isnan(0.0))
+ {
+ Fail("_isnan() incorrectly identified %f as NaN!\n", 0.0);
+ }
+
+ if (_isnan(1.23456))
+ {
+ Fail("_isnan() incorrectly identified %f as NaN!\n", 1.234567);
+ }
+
+ if (_isnan(42.0))
+ {
+ Fail("_isnan() incorrectly identified %f as NaN!\n", 42.0);
+ }
+
+ UINT64 lneginf = UI64(0xfff0000000000000);
+ UINT64 lposinf = UI64(0x7ff0000000000000);
+
+ double neginf = TO_DOUBLE(lneginf);
+ double posinf = TO_DOUBLE(lposinf);
+
+ /*
+ * Try positive and negative infinity
+ */
+ if (_isnan(neginf))
+ {
+ Fail("_isnan() incorrectly identified negative infinity as NaN!\n");
+ }
+
+ if (_isnan(posinf))
+ {
+ Fail("_isnan() incorrectly identified infinity as NaN!\n");
+ }
+
+ /*
+ * Try setting the least significant bit of the fraction,
+ * positive and negative
+ */
+ UINT64 lsnan = UI64(0xfff0000000000001);
+ double snan = TO_DOUBLE(lsnan);
+
+ if (!_isnan(snan))
+ {
+ Fail("_isnan() failed to identify %I64x as NaN!\n", lsnan);
+ }
+
+ UINT64 lqnan = UI64(0x7ff0000000000001);
+ double qnan = TO_DOUBLE(lqnan);
+
+ if (!_isnan(qnan))
+ {
+ Fail("_isnan() failed to identify %I64x as NaN!\n", lqnan);
+ }
+
+ /*
+ * Try setting the most significant bit of the fraction,
+ * positive and negative
+ */
+ lsnan = UI64(0xfff8000000000000);
+ snan = TO_DOUBLE(lsnan);
+
+ if (!_isnan(snan))
+ {
+ Fail ("_isnan() failed to identify %I64x as NaN!\n", lsnan);
+ }
+
+ lqnan = UI64(0x7ff8000000000000);
+ qnan = TO_DOUBLE(lqnan);
+
+ if (!_isnan(qnan))
+ {
+ Fail ("_isnan() failed to identify %I64x as NaN!\n", lqnan);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_isnan/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_isnan/test1/testinfo.dat
new file mode 100644
index 0000000000..d5de17e219
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_isnan/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _isnan
+Name = Test #1 for _isnan
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Test _isnan with a number of trivial values, to ensure they indicated that
+= they are numbers. Then try with Positive/Negative Infinite, which should
+= also be numbers. Finally set the least and most significant bits of
+= the fraction to positive and negative, at which point it should return
+= the true value.
diff --git a/src/pal/tests/palsuite/c_runtime/_itow/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_itow/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_itow/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_itow/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_itow/test1/CMakeLists.txt
new file mode 100644
index 0000000000..bd37f31216
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_itow/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_itow_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_itow_test1 coreclrpal)
+
+target_link_libraries(paltest_itow_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_itow/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_itow/test1/test1.c
new file mode 100644
index 0000000000..745ce4acaa
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_itow/test1/test1.c
@@ -0,0 +1,102 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests the PAL implementation of the _itow function.
+** Test a number of ints with different radix on each,
+** to ensure that the string returned is correct.
+**
+**
+**===================================================================*/
+
+#define UNICODE
+
+#include <palsuite.h>
+
+struct testCase
+{
+ wchar_t *CorrectResult;
+ int value;
+ int radix;
+};
+
+int __cdecl main(int argc, char **argv)
+{
+
+ wchar_t result[20];
+ wchar_t *pResult = NULL;
+ char *PrintResult = NULL; /* Use with convertC so we can */
+ char *PrintCorrectResult = NULL; /* print out the results */
+ int i = 0;
+
+ WCHAR case1[] = {'5','0','\0'};
+ WCHAR case2[] = {'5','5','5','\0'};
+ WCHAR case3[] = {'1','0','1','0','\0'};
+ WCHAR case4[] = {'2','2','\0'};
+ WCHAR case5[] = {'a','\0'};
+ WCHAR case6[] = {'c','g','\0'};
+
+ /* Correct Result, Value to Convert, Radix to use */
+ struct testCase testCases[] =
+ {
+ {case1, 50, 10},
+ {case2,555,10},
+ {case3,10,2},
+ {case4,10,4},
+ {case5,10,16},
+ {case6,400,32}
+ };
+
+ /*
+ * Initialize the PAL and return FAIL if this fails
+ */
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Loop through each case. Convert the ints to strings. Check
+ to ensure they were converted properly.
+ */
+
+ for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++)
+ {
+ pResult = _itow(testCases[i].value,result,testCases[i].radix);
+
+ if(pResult != &result[0])
+ {
+ Fail("ERROR: _itow didn't return a correct pointer to the "
+ "newly formed string.\n");
+ }
+
+ if (0 != wcscmp(testCases[i].CorrectResult,pResult))
+ {
+ PrintResult = convertC(pResult);
+ PrintCorrectResult = convertC(testCases[i].CorrectResult);
+ Fail("ERROR: _itow was called on %i, returning the string %s "
+ "when it should have returned the string %s.\n"
+ , testCases[i].value, PrintResult, PrintCorrectResult);
+ }
+
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/_itow/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_itow/test1/testinfo.dat
new file mode 100644
index 0000000000..394c34dff3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_itow/test1/testinfo.dat
@@ -0,0 +1,18 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _itow
+Name = Positive Test for _itow
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests the PAL implementation of the _itow function.
+= Test a number of ints with different radix on each, to ensure that the
+= string returned is correct.
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/_makepath/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_makepath/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_makepath/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_makepath/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_makepath/test1/CMakeLists.txt
new file mode 100644
index 0000000000..9fd81cce1a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_makepath/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_makepath_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_makepath_test1 coreclrpal)
+
+target_link_libraries(paltest_makepath_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_makepath/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_makepath/test1/test1.c
new file mode 100644
index 0000000000..94b366a7bb
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_makepath/test1/test1.c
@@ -0,0 +1,65 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests the PAL implementation of the _makepath function.
+** Create a path, and ensure that it builds how it is
+** supposed to.
+**
+**
+**
+**===================================================================*/
+
+#if WIN32
+#define PATHNAME "C:\\test\\test.txt"
+#else
+#define PATHNAME "/test/test.txt"
+#endif
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ char FullPath[128];
+
+ /*
+ * Initialize the PAL and return FAIL if this fails
+ */
+ if (0 != (PAL_Initialize(argc,argv)))
+ {
+ return FAIL;
+ }
+
+#if WIN32
+ _makepath(FullPath,"C","\\test","test","txt");
+#else
+ _makepath(FullPath,NULL,"/test","test","txt");
+#endif
+
+ if(strcmp(FullPath,PATHNAME) != 0)
+ {
+ Fail("ERROR: The pathname which was created turned out to be %s "
+ "when it was supposed to be %s.\n",FullPath,PATHNAME);
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/_makepath/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_makepath/test1/testinfo.dat
new file mode 100644
index 0000000000..2aed8e549b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_makepath/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _makepath
+Name = Positive Test for _makepath
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Purpose: Tests the PAL implementation of the _makepath function.
+= Create a path, and ensure that it builds how it is supposed to.
+
diff --git a/src/pal/tests/palsuite/c_runtime/_mbsdec/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_mbsdec/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_mbsdec/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_mbsdec/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_mbsdec/test1/CMakeLists.txt
new file mode 100644
index 0000000000..064f241f24
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_mbsdec/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_mbsdec_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_mbsdec_test1 coreclrpal)
+
+target_link_libraries(paltest_mbsdec_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_mbsdec/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_mbsdec/test1/test1.c
new file mode 100644
index 0000000000..1cd7513293
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_mbsdec/test1/test1.c
@@ -0,0 +1,77 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose:
+** Ensure that this function moves the string pointer back one character.
+** First do a basic test to check that the pointer gets moved back the one
+** character, given str1 and str+1 as params. Then try with both
+** params being the same pointer, which should return NULL. Also test
+** when the first pointer is past the second pointer, which should
+** return null. Finally try this function on an array of single bytes,
+** which it assumes are characters and should work in the same fashion.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+/*
+ * Note: it seems like these functions would only be useful if they
+ * didn't assume a character was equivalent to a single byte. Be that
+ * as it may, I haven't seen a way to get it to behave otherwise.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ unsigned char *str1 = (unsigned char*) "foo";
+ unsigned char str2[] = {0xC0, 0x80, 0xC0, 0x80, 0};
+ unsigned char str3[] = {0};
+ unsigned char *ret = NULL;
+
+ /*
+ * Initialize the PAL and return FAIL if this fails
+ */
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ ret = _mbsdec(str1,str1+1);
+ if (ret != str1)
+ {
+ Fail ("ERROR: _mbsdec returned %p. Expected %p\n", ret, str1);
+ }
+
+ ret = _mbsdec(str1,str1);
+ if (ret != NULL)
+ {
+ Fail ("ERROR: _mbsdec returned %p. Expected %p\n", ret, NULL);
+ }
+
+ ret = _mbsdec(str1+100,str1);
+ if (ret != NULL)
+ {
+ Fail ("ERROR: _mbsdec returned %p. Expected %p\n", ret, NULL);
+ }
+
+ ret = _mbsdec(str2,str2+1);
+ if (ret != str2)
+ {
+ Fail ("ERROR: _mbsdec returned %p. Expected %p\n", ret, str2+1);
+ }
+
+ ret = _mbsdec(str3,str3+10);
+ if (ret != str3+9)
+ {
+ Fail ("ERROR: _mbsdec returned %p. Expected %p\n", ret, str3+9);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/_mbsdec/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_mbsdec/test1/testinfo.dat
new file mode 100644
index 0000000000..ce2aa29aa5
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_mbsdec/test1/testinfo.dat
@@ -0,0 +1,18 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _mbsdec
+Name = Positive Test for _mbsdec
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Ensure that this function moves the string pointer back one character.
+= First do a basic test to check that the pointer gets moved back the one
+= character, given str1 and str+1 as params. Then try with both
+= params being the same pointer, which should return NULL. Also test
+= when the first pointer is past the second pointer, which should
+= return null. Finally try this function on an array of single bytes,
+= which it assumes are characters and should work in the same fashion.
diff --git a/src/pal/tests/palsuite/c_runtime/_mbsinc/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_mbsinc/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_mbsinc/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_mbsinc/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_mbsinc/test1/CMakeLists.txt
new file mode 100644
index 0000000000..531ba8e793
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_mbsinc/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_mbsinc_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_mbsinc_test1 coreclrpal)
+
+target_link_libraries(paltest_mbsinc_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_mbsinc/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_mbsinc/test1/test1.c
new file mode 100644
index 0000000000..95a5041af2
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_mbsinc/test1/test1.c
@@ -0,0 +1,62 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose:
+** Ensure that this function moves the string pointer ahead one character.
+** First do a basic test to check that the pointer gets moved ahead the one
+** character. Then try with an array of bytes and a NULL array. Each of
+** these should still work by returning a pointer to thePointer+1.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+/*
+ * Note: it seems like these functions would only be useful if they
+ * didn't assume a character was equivalent to a single byte. Be that
+ * as it may, I haven't seen a way to get it to behave otherwise.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ unsigned char *str1 = (unsigned char*) "foo";
+ unsigned char str2[] = {0xC0, 0x80, 0xC0, 0x80, 0};
+ unsigned char str3[] = {0};
+ unsigned char *ret=NULL;
+
+ /*
+ * Initialize the PAL and return FAIL if this fails
+ */
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ ret = _mbsinc(str1);
+ if (ret != str1 + 1)
+ {
+ Fail ("ERROR: _mbsinc returned %p. Expected %p\n", ret, str1);
+ }
+
+ ret = _mbsinc(str2);
+ if (ret != str2 + 1)
+ {
+ Fail ("ERROR: _mbsinc returned %p. Expected %p\n", ret, str1);
+ }
+
+ ret = _mbsinc(str3);
+ if (ret != str3 + 1)
+ {
+ Fail ("ERROR: _mbsinc returned %p. Expected %p\n", ret, str1);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/_mbsinc/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_mbsinc/test1/testinfo.dat
new file mode 100644
index 0000000000..3f3883fa31
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_mbsinc/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _mbsinc
+Name = Positive Test for _mbsinc
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Ensure that this function moves the string pointer ahead one character.
+= First do a basic test to check that the pointer gets moved ahead the one
+= character. Then try with an array of bytes and a NULL array. Each of
+= these should still work by returning a pointer to thePointer+1.
diff --git a/src/pal/tests/palsuite/c_runtime/_mbslen/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_mbslen/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_mbslen/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_mbslen/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_mbslen/test1/CMakeLists.txt
new file mode 100644
index 0000000000..38aa6fb16e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_mbslen/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_mbslen_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_mbslen_test1 coreclrpal)
+
+target_link_libraries(paltest_mbslen_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_mbslen/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_mbslen/test1/test1.c
new file mode 100644
index 0000000000..fa24c77d8a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_mbslen/test1/test1.c
@@ -0,0 +1,66 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*========================================================================
+**
+** Source: test1.c
+**
+** Purpose:
+** Check the length of a number of arrays. The first is a normal string
+** which should return its length. The second has two bytes and a null
+** character, which only returns a size of 2, and the last is just a NULL
+** array which should return 0.
+**
+**
+**========================================================================*/
+
+#include <palsuite.h>
+
+/*
+ * Note: it seems like these functions would only be useful if they
+ * didn't assume a character was equivalent to a single byte. Be that
+ * as it may, I haven't seen a way to get it to behave otherwise
+ * (eg locale)
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ unsigned char *str1 = (unsigned char*) "foo";
+ unsigned char str2[] = {0xC0, 0x80, 0}; /* the char U+0080 */
+ unsigned char str3[] = {0};
+ int ret=0;
+
+ /*
+ * Initialize the PAL and return FAIL if this fails
+ */
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ ret = _mbslen(str1);
+ if (ret != 3)
+ {
+ Fail ("ERROR: _mbslen(\"%s\") returned %d. Expected %d\n",
+ str1, ret, 3);
+ }
+
+ ret = _mbslen(str2);
+ if (ret != 2)
+ {
+ Fail ("ERROR: _mbslen(\"%s\") returned %d. Expected %d\n",
+ str2, ret, 2);
+ }
+
+ ret = _mbslen(str3);
+ if (ret != 0)
+ {
+ Fail ("ERROR: _mbslen(\"%s\") returned %d. Expected %d\n",
+ str3, ret, 0);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/_mbslen/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_mbslen/test1/testinfo.dat
new file mode 100644
index 0000000000..cf830a7539
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_mbslen/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _mbsinc
+Name = Positive Test for _mbslen
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Check the length of a number of arrays. The first is a normal string
+= which should return its length. The second has two bytes and a null
+= character, which only returns a size of 2, and the last is just a NULL
+= array which should return 0.
diff --git a/src/pal/tests/palsuite/c_runtime/_mbsninc/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_mbsninc/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_mbsninc/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_mbsninc/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_mbsninc/test1/CMakeLists.txt
new file mode 100644
index 0000000000..7285ce229e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_mbsninc/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_mbsninc_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_mbsninc_test1 coreclrpal)
+
+target_link_libraries(paltest_mbsninc_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_mbsninc/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_mbsninc/test1/test1.c
new file mode 100644
index 0000000000..59ef50dcc3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_mbsninc/test1/test1.c
@@ -0,0 +1,65 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose:
+** Ensure that this functions increases a string pointer by n characters.
+** Use a for loop, and increase the pointer by a different number of characters
+** on each iteration, ensure that it is indeed pointing to the correct location
+** each time. The second test checks to see if you attempt to increase the
+** pointer past the end of the string, the pointer should just point at the
+** last character.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+/*
+ * Note: it seems like these functions would only be useful if they
+ * didn't assume a character was equivalent to a single byte. Be that
+ * as it may, I haven't seen a way to get it to behave otherwise.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ unsigned char str[] = {0xC0, 0x80, 0xC0, 0x80, 0};
+ int i=0;
+ unsigned char *ret=NULL;
+
+ /*
+ * Initialize the PAL and return FAIL if this fails
+ */
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ for (i=0; i<5; i++)
+ {
+ ret = _mbsninc(str, i);
+ if (ret != str + i)
+ {
+ Fail ("ERROR: _mbsninc returned %p. Expected %p\n", ret, str+i);
+ }
+ }
+
+ /*
+ * trying to advance past the end of the string should just
+ * return the end.
+ */
+ ret = _mbsninc(str, 5);
+ if (ret != str + 4)
+ {
+ Fail ("ERROR: _mbsninc returned %p. Expected %p\n", ret, str+4);
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/_mbsninc/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_mbsninc/test1/testinfo.dat
new file mode 100644
index 0000000000..b855222af9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_mbsninc/test1/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _mbsninc
+Name = Positive Test for _mbsninc
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Ensure that this functions increases a string pointer by n characters.
+= Use a for loop, and increase the pointer by a different number of characters
+= on each iteration, ensure that it is indeed pointing to the correct location
+= each time. The second test checks to see if you attempt to increase the
+= pointer past the end of the string, the pointer should just point at the
+= last character.
diff --git a/src/pal/tests/palsuite/c_runtime/_open_osfhandle/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_open_osfhandle/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_open_osfhandle/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_open_osfhandle/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_open_osfhandle/test1/CMakeLists.txt
new file mode 100644
index 0000000000..e9a3e29192
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_open_osfhandle/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_open_osfhandle_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_open_osfhandle_test1 coreclrpal)
+
+target_link_libraries(paltest_open_osfhandle_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_open_osfhandle/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_open_osfhandle/test1/test1.c
new file mode 100644
index 0000000000..ee2c8ea418
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_open_osfhandle/test1/test1.c
@@ -0,0 +1,132 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c (_open_osfhandle)
+**
+** Purpose: Tests the PAL implementation of the _open_osfhandle function.
+** This API accepts a OS Handle returned from CreatePipe() and
+** a flag of _O_RDONLY and returns a C Run-Time handle. The test
+** will write to the pipe and pass the C Run-Time handle to _fdopen
+** to open the Read Handle to compare what was written with what
+** was wrote. They should be the same.
+**
+** Depends: CreatePipe
+** WriteFile
+** _fdopen
+** fread
+** memcmp
+** fclose
+** strlen
+** CloseHandle
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+const char* cTestString = "one fish, two fish, red fish, blue fish.";
+
+int __cdecl main(int argc, char **argv)
+{
+ HANDLE hReadPipe = NULL;
+ HANDLE hWritePipe = NULL;
+ BOOL bRetVal = FALSE;
+ int iFiledes = 0;
+ DWORD dwBytesWritten;
+ char buffer[45];
+ FILE *fp;
+ size_t len;
+
+ SECURITY_ATTRIBUTES lpPipeAttributes;
+
+ /*Initialize the PAL*/
+ if ((PAL_Initialize(argc, argv)) != 0)
+ {
+ return (FAIL);
+ }
+
+ /*Setup SECURITY_ATTRIBUTES structure for CreatePipe*/
+ lpPipeAttributes.nLength = sizeof(lpPipeAttributes);
+ lpPipeAttributes.lpSecurityDescriptor = NULL;
+ lpPipeAttributes.bInheritHandle = TRUE;
+
+ /*Create a Pipe*/
+ bRetVal = CreatePipe(&hReadPipe, /* read handle*/
+ &hWritePipe, /* write handle */
+ &lpPipeAttributes, /* security attributes*/
+ 0); /* pipe size*/
+ if (bRetVal == FALSE)
+ {
+ Fail("ERROR: unable to create pipe");
+ }
+
+ /*Write to the write pipe handle*/
+ bRetVal = WriteFile(hWritePipe, /* handle to file*/
+ cTestString, /* data buffer*/
+ strlen(cTestString),/* number of bytes to write*/
+ &dwBytesWritten, /* number of bytes written*/
+ NULL); /* overlapped buffer*/
+ if (bRetVal == FALSE)
+ {
+ Fail("ERROR: unable to write to pipe write handle "
+ "hWritePipe=0x%lx", hWritePipe);
+ }
+
+ /*Test to see if the WriteFile wrote the correct amount*/
+ if(dwBytesWritten != strlen(cTestString))
+ {
+ Fail("Error: WriteFile wrote \"%d\", should have written \"%d\\n",
+ dwBytesWritten, strlen(cTestString));
+ }
+
+ /*Get a file descriptor for the read pipe handle.
+ *This is what we are testing.*/
+ iFiledes = _open_osfhandle((long)hReadPipe, _O_RDONLY);
+ if (iFiledes == -1)
+ {
+ Fail("ERROR: _open_osfhandle failed to open "
+ " hReadPipe=0x%lx", hReadPipe);
+ }
+
+ /*Open read pipe handle in read mode.
+ *Verify that we have returned a correct,
+ *C Run-time handle*/
+ fp = _fdopen(iFiledes, "r");
+ if (fp == NULL)
+ {
+ Fail("ERROR: unable to fdopen file descriptor"
+ " iFiledes=%d", iFiledes);
+ }
+
+ /*Read from the read pipe handle*/
+ len = fread(buffer, sizeof(char), strlen(cTestString), fp);
+ if((len == 0) || (len != strlen(cTestString)))
+ {
+ Fail("ERROR: Unable to read from file stream fp=0x%lx\n", fp);
+ }
+
+ /*Compare what was read with what was written.*/
+ if ((memcmp(cTestString, buffer, strlen(cTestString))) != 0)
+ {
+ Fail("ERROR: read \"%s\" expected \"%s\" \n", buffer, cTestString);
+ }
+
+ /*Close write pipe handle*/
+ if (CloseHandle(hWritePipe) == 0)
+ {
+ Fail("ERROR: Unable to close write pipe handle "
+ "hWritePipe=0x%lx", hWritePipe);
+ }
+
+ if ((fclose(fp)) != 0)
+ {
+ Fail("ERROR: Unable to close C-Runtime handle "
+ "iFilesdes=%d", iFiledes);
+ }
+
+ PAL_Terminate();
+ return (PASS);
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_open_osfhandle/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_open_osfhandle/test1/testinfo.dat
new file mode 100644
index 0000000000..16317bb188
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_open_osfhandle/test1/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _open_osfhandle
+Name = Test for _open_osfhandle
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests the PAL implementation of the _open_osfhandle function.
+= This API accepts a OS Handle returned from CreatePipe() and
+= a flag of _O_RDONLY and returns a C Run-Time handle. The test
+= will write to the pipe and pass the C Run-Time handle to _fdopen
+= to open the Read Handle to compare what was written with what
+= was wrote. They should be the same.
diff --git a/src/pal/tests/palsuite/c_runtime/_open_osfhandle/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_open_osfhandle/test2/CMakeLists.txt
new file mode 100644
index 0000000000..1031ec1df9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_open_osfhandle/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_open_osfhandle_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_open_osfhandle_test2 coreclrpal)
+
+target_link_libraries(paltest_open_osfhandle_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_open_osfhandle/test2/test2.c b/src/pal/tests/palsuite/c_runtime/_open_osfhandle/test2/test2.c
new file mode 100644
index 0000000000..6c756b177a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_open_osfhandle/test2/test2.c
@@ -0,0 +1,86 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test2.c (_open_osfhandle)
+**
+** Purpose: Tests the PAL implementation of the _open_osfhandle function.
+** This API accepts a OS Handle returned from CreatePipe() and
+** a flag of _O_RDONLY and returns a C Run-Time handle. The test
+** will pass a NULL handle, and unsupported flags. All cases
+** should fail.
+**
+** Depends: CreatePipe
+** CloseHandle
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ HANDLE hReadPipe = NULL;
+ HANDLE hWritePipe = NULL;
+ BOOL bRetVal = FALSE;
+ int iFiledes = 0;
+
+ SECURITY_ATTRIBUTES lpPipeAttributes;
+
+ /*Initialize the PAL*/
+ if ((PAL_Initialize(argc, argv)) != 0)
+ {
+ return (FAIL);
+ }
+
+ /*Setup SECURITY_ATTRIBUTES structure for CreatePipe*/
+ lpPipeAttributes.nLength = sizeof(lpPipeAttributes);
+ lpPipeAttributes.lpSecurityDescriptor = NULL;
+ lpPipeAttributes.bInheritHandle = TRUE;
+
+ /*Create a Pipe*/
+ bRetVal = CreatePipe(&hReadPipe, /* read handle*/
+ &hWritePipe, /* write handle */
+ &lpPipeAttributes, /* security attributes*/
+ 0); /* pipe size*/
+ if (bRetVal == FALSE)
+ {
+ Fail("ERROR: unable to create pipe");
+ }
+
+ /*Close write pipe handle*/
+ if (CloseHandle(hWritePipe) == 0)
+ {
+ Fail("ERROR: Unable to close write pipe handle "
+ "hWritePipe=0x%lx", hWritePipe);
+ }
+
+ /*Close read pipe handle*/
+ if (CloseHandle(hReadPipe) == 0)
+ {
+ Fail("ERROR: Unable to close read pipe handle "
+ "hReadPipe=0x%lx", hReadPipe);
+ }
+
+ /*Test with a Closed handle and supported flag _O_RDONLY*/
+ iFiledes = _open_osfhandle((long)hReadPipe, _O_RDONLY);
+ if (iFiledes != -1)
+ {
+ Fail("ERROR: _open_osfhandle successfullly opened "
+ " hReadPipe which was closed, with _O_RDONLY");
+ }
+
+ /*Test with a NULL handle and supported flag _O_RDONLY*/
+ hReadPipe = NULL;
+ iFiledes = _open_osfhandle((long)hReadPipe, _O_RDONLY);
+ if (iFiledes != -1)
+ {
+ Fail("ERROR: _open_osfhandle successfullly opened "
+ " hReadPipe=NULL with _O_RDONLY");
+ }
+
+ PAL_Terminate();
+ return (PASS);
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_open_osfhandle/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_open_osfhandle/test2/testinfo.dat
new file mode 100644
index 0000000000..822e23fedd
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_open_osfhandle/test2/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _open_osfhandle
+Name = Fail test for _open_osfhandle
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Tests the PAL implementation of the _open_osfhandle function.
+= This API accepts a OS Handle returned from CreatePipe() and
+= a flag of _O_RDONLY and returns a C Run-Time handle. The test
+= will pass a NULL handle, and unsupported flags. All cases
+= should fail.
diff --git a/src/pal/tests/palsuite/c_runtime/_putenv/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_putenv/CMakeLists.txt
new file mode 100644
index 0000000000..a3847f8ca9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_putenv/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_putenv/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_putenv/test1/CMakeLists.txt
new file mode 100644
index 0000000000..0a75b41113
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_putenv/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_putenv_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_putenv_test1 coreclrpal)
+
+target_link_libraries(paltest_putenv_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_putenv/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_putenv/test1/test1.c
new file mode 100644
index 0000000000..2d096adc78
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_putenv/test1/test1.c
@@ -0,0 +1,99 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Create an environment variable with _putenv and then use getenv
+** to check it. Check that we get the expected errors with invalid input.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+struct TestElement
+{
+ char _putenvString[1024]; /* argument string sent to putenv */
+ char varName[1024]; /* variable component of argument string */
+ char varValue[1024]; /* value component of argument string */
+ BOOL bValidString; /* valid argument string identifier */
+};
+
+struct TestElement TestCases[] =
+{
+ {"PalTestingEnvironmentVariable=A value", "PalTestingEnvironmentVariable",
+ "A value", TRUE},
+ {"AnotherVariable=", "AnotherVariable", "", TRUE},
+ {"YetAnotherVariable", "", "", FALSE},
+ {"=ADifferentVariable", "", "ADifferentVariable", FALSE},
+ {"", "", "", FALSE}
+
+};
+
+int __cdecl main(int argc, char **argv)
+{
+
+ int i;
+ char *variableValue;
+
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ for (i = 0; i < (sizeof(TestCases)/sizeof(struct TestElement)) ; i++)
+ {
+ if((_putenv(TestCases[i]._putenvString) == -1) &&
+ ( TestCases[i].bValidString == TRUE))
+ {
+ Fail("ERROR: _putenv failed to set an environment "
+ "variable with a valid format.\n Call was"
+ "_putenv(%s)\n", TestCases[i]._putenvString);
+ }
+ /*
+ * For valid _putenvString values, check to see the variable was set
+ */
+ if (TestCases[i].bValidString == TRUE)
+ {
+ variableValue = getenv(TestCases[i].varName);
+
+ if (variableValue == NULL)
+ {
+ if (*TestCases[i].varValue != '\0')
+ {
+ Fail("ERROR: getenv(%s) call returned NULL.\nThe call "
+ "should have returned \"%s\"\n", TestCases[i].varName
+ , TestCases[i].varValue);
+ }
+ }
+ else if ( strcmp(variableValue, TestCases[i].varValue) != 0)
+ {
+ Fail("ERROR: _putenv(%s)\nshould have set the variable "
+ "%s\n to \"%s\".\nA subsequent call to getenv(%s)\n"
+ "returned \"%s\" instead.\n", TestCases[i]._putenvString
+ , TestCases[i].varName, TestCases[i].varValue
+ , TestCases[i].varName, variableValue);
+ }
+ }
+ else
+ /*
+ * Check to see that putenv fails for malformed _putenvString values
+ */
+ {
+ variableValue = getenv(TestCases[i].varName);
+
+ if (variableValue != NULL)
+ {
+ Fail("ERROR: getenv(%s) call should have returned NULL.\n"
+ "Instead it returned \"%s\".\n", TestCases[i].varName
+ , TestCases[i].varValue);
+ }
+ }
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_putenv/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_putenv/test1/testinfo.dat
new file mode 100644
index 0000000000..d0978184fc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_putenv/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _putenv
+Name = Positive test for _putenv
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Create an environment variable with _putenv and then use getenv to
+= check it. Check that we get the expected errors with invalid input.
diff --git a/src/pal/tests/palsuite/c_runtime/_putenv/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_putenv/test2/CMakeLists.txt
new file mode 100644
index 0000000000..e0539681cd
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_putenv/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_putenv_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_putenv_test2 coreclrpal)
+
+target_link_libraries(paltest_putenv_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_putenv/test2/test2.c b/src/pal/tests/palsuite/c_runtime/_putenv/test2/test2.c
new file mode 100644
index 0000000000..39be4f68b4
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_putenv/test2/test2.c
@@ -0,0 +1,76 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test2.c
+**
+** Purpose: Create an environment variable with _putenv and then use getenv
+** to check it. This test resets an environment variable.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+const char *_putenvString0 = "AnUnusualVariable=AnUnusualValue";
+const char *_putenvString1 = "AnUnusualVariable=";
+const char *variable = "AnUnusualVariable";
+const char *value = "AnUnusualValue";
+
+int __cdecl main(int argc, char **argv)
+{
+
+ char *variableValue;
+
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ if(_putenv(_putenvString0) == -1)
+ {
+ Fail("ERROR: _putenv failed to set an environment "
+ "variable with a valid format.\n Call was"
+ "_putenv(%s)\n", _putenvString0);
+ }
+
+ variableValue = getenv(variable);
+
+ if (variableValue == NULL)
+ {
+ Fail("ERROR: getenv(%s) call returned NULL\nThe call "
+ "should have returned '%s'\n", variable, value);
+ }
+ else
+ {
+ if ( strcmp(variableValue, value) != 0 )
+ {
+ Fail("ERROR: _putenv(%s)\nshould have set the variable "
+ "'%s'\n to '%s'.\nA subsequent call to getenv(%s)\n"
+ "returned '%s' instead.\n", _putenvString0,
+ variable, value, variable, variableValue);
+ }
+ else
+ {
+ if(_putenv(_putenvString1) == -1)
+ {
+ Fail("ERROR: _putenv failed to set an environment "
+ "variable with a valid format.\n Call was"
+ "_putenv(%s)\n", _putenvString1);
+ }
+
+ variableValue = getenv(variable);
+
+ if (variableValue != NULL)
+ {
+ Fail("ERROR: getenv(%s) call did not return NULL.\nThe call "
+ "returned '%s'.\n", variable, value);
+ }
+ }
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_putenv/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_putenv/test2/testinfo.dat
new file mode 100644
index 0000000000..8d3a6ced1e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_putenv/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _putenv
+Name = Positive test for _putenv
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Create an environment variable with _putenv and then use getenv to
+= check it. This test resets an environment variable.
diff --git a/src/pal/tests/palsuite/c_runtime/_putenv/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_putenv/test3/CMakeLists.txt
new file mode 100644
index 0000000000..a67241022b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_putenv/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_putenv_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_putenv_test3 coreclrpal)
+
+target_link_libraries(paltest_putenv_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_putenv/test3/test3.c b/src/pal/tests/palsuite/c_runtime/_putenv/test3/test3.c
new file mode 100644
index 0000000000..8aa6777307
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_putenv/test3/test3.c
@@ -0,0 +1,102 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test3.c
+**
+** Purpose: Create environment variables that differ only in Case, and
+** verify that the BSD operating system treats the variables
+** differently.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+#if WIN32
+
+ return PASS;
+
+#else
+
+ const char* FirstVariable = "PalTestingEnvironmentVariable=The value";
+ const char* SecondVariable = "PALTESTINGEnvironmentVariable=Different value";
+ const char* FirstVarName = "PalTestingEnvironmentVariable";
+ const char* FirstVarValue = "The value";
+ char* result;
+
+
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Use _putenv to set an environment variable. This ensures that the
+ variable we're testing on is always present.
+ */
+
+ if(_putenv(FirstVariable) != 0)
+ {
+ Fail("ERROR: _putenv failed to set an environment variable that "
+ "getenv will be using for testing.\n");
+ }
+
+
+ /* Call getenv -- ensure it doesn't return NULL and the string it returns
+ is the value we set above. Also make sure that each environment variable,
+ differing only by case, returns it's own value.
+ */
+
+ result = getenv(FirstVarName);
+ if(result == NULL)
+ {
+ Fail("ERROR: The result of getenv on a valid Environment Variable "
+ "was NULL, which indicates the environment varaible was not "
+ "found.\n");
+ }
+
+ if(strcmp(result, FirstVarValue) != 0)
+ {
+ Fail("ERROR: The value obtained by getenv() was not equal to the "
+ "correct value of the environment variable. The correct "
+ "value is '%s' and the function returned '%s'.\n",
+ FirstVarValue,
+ result);
+ }
+
+ /* Set the second environment variable, which only differs in Case */
+ if(_putenv(SecondVariable) != 0)
+ {
+ Fail("ERROR: _putenv failed to set an environment variable that "
+ "getenv will be using for testing.\n");
+ }
+
+ /* Verify that the environment variables
+ */
+
+ result = getenv(FirstVarName);
+ if(result == NULL)
+ {
+ Fail("ERROR: The result of getenv on a valid Environment Variable "
+ "was NULL, which indicates the environment varaible was not "
+ "found.\n");
+ }
+
+ if(strcmp(result, FirstVarValue) != 0)
+ {
+ Fail("ERROR: The value obtained by getenv() was not equal to the "
+ "correct value of the environment variable. The correct "
+ "value is '%s' and the function returned '%s'.\n",
+ FirstVarValue,
+ result);
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+#endif
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_putenv/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_putenv/test3/testinfo.dat
new file mode 100644
index 0000000000..2c6af1b5cf
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_putenv/test3/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _putenv
+Name = Positive test for _putenv
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Create environment variables that only differ by case
+= and check that the BSD operating system treats them
+= as two separate variables.
diff --git a/src/pal/tests/palsuite/c_runtime/_putenv/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_putenv/test4/CMakeLists.txt
new file mode 100644
index 0000000000..518282ccc7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_putenv/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_putenv_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_putenv_test4 coreclrpal)
+
+target_link_libraries(paltest_putenv_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_putenv/test4/test4.c b/src/pal/tests/palsuite/c_runtime/_putenv/test4/test4.c
new file mode 100644
index 0000000000..48d7ba963c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_putenv/test4/test4.c
@@ -0,0 +1,75 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test4.c
+**
+** Purpose: Create an environment variable and try to retrieve
+** it using the same name but with different case. This
+** is to show that the Win32 representation of _putenv
+** is case insensitive.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+#if WIN32
+
+ const char* FirstVariable = "PalTestingEnvironmentVariable=The value";
+ const char* ModifiedName = "PALTESTINGEnvironmentVariable";
+ const char* FirstVarValue = "The value";
+ char* result;
+
+
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Use _putenv to set an environment variable. This ensures that the
+ variable we're testing on is always present.
+ */
+
+ if(_putenv(FirstVariable) != 0)
+ {
+ Fail("ERROR: _putenv failed to set an environment variable that "
+ "getenv will be using for testing.\n");
+ }
+
+
+ /* Call getenv -- ensure it doesn't return NULL and the string it returns
+ is the value we set above. Also make sure that each environment variable,
+ differing only by case, doesn't affect the return value.
+ */
+
+ result = getenv(ModifiedName);
+ if(result == NULL)
+ {
+ Fail("ERROR: The result of getenv on a valid Environment Variable "
+ "was NULL, which indicates the environment varaible was not "
+ "found.\n");
+ }
+
+ if(strcmp(result, FirstVarValue) != 0)
+ {
+ Fail("ERROR: The value obtained by getenv() was not equal to the "
+ "correct value of the environment variable. The correct "
+ "value is '%s' and the function returned '%s'.\n",
+ FirstVarValue,
+ result);
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+#else
+ return PASS;
+
+#endif
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_putenv/test4/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_putenv/test4/testinfo.dat
new file mode 100644
index 0000000000..af1a01c2fc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_putenv/test4/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _putenv
+Name = Positive test for _putenv
+TYPE = DEFAULT
+EXE1 = test4
+Description
+= Create an environment variable and check
+= that trying to retrieve it using a name with different
+= case, returns the correct value.
diff --git a/src/pal/tests/palsuite/c_runtime/_putw/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_putw/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_putw/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_putw/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_putw/test1/CMakeLists.txt
new file mode 100644
index 0000000000..c3018ad322
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_putw/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_putw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_putw_test1 coreclrpal)
+
+target_link_libraries(paltest_putw_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_putw/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_putw/test1/test1.c
new file mode 100644
index 0000000000..ecfc9046ac
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_putw/test1/test1.c
@@ -0,0 +1,112 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Writes a series of integers to a file, test.dat,
+** then verifies the results.
+**
+** Dependency: fopen(...)
+** fclose(...)
+** CloseHandle(...)
+** DeleteFileA(...)
+** _getw(...)
+**
+**
+**
+**==========================================================================*/
+
+
+#include <palsuite.h>
+
+const char testFileName[] = "test.dat";
+
+static void Cleanup(HANDLE hFile)
+{
+ if (fclose(hFile))
+ {
+ Trace("_putw: ERROR -> Unable to close file \"%s\".\n",
+ testFileName);
+ }
+ if (!DeleteFileA(testFileName))
+ {
+ Trace("_putw: ERROR -> Unable to delete file \"%s\". ",
+ "GetLastError returned %u.\n",
+ testFileName,
+ GetLastError());
+ }
+}
+
+
+int __cdecl main(int argc, char **argv)
+{
+
+ FILE * pfTest = NULL;
+ int testArray[] = {0,1,-1,0x7FFFFFFF,0x80000000,0xFFFFFFFF,0xFFFFAAAA};
+ int i = 0;
+ int retValue = 0;
+
+ /*
+ * Initialize the PAL and return FAIL if this fails
+ */
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /*write the file that we will use to test */
+ pfTest = fopen(testFileName, "w");
+ if (pfTest == NULL)
+ {
+ Fail ("Unable to write test file.\n");
+ }
+
+ for (i = 0; i < sizeof(testArray)/sizeof(int) ; i++)
+ {
+ _putw(testArray[i], pfTest);
+
+ if( ferror( pfTest ) )
+ {
+ Cleanup(pfTest);
+ Fail( "Error:in _putw -> error has occurred in the "
+ "stream while writing to the file: \"test.dat\"\n");
+ }
+
+ }
+
+ if (fclose(pfTest) != 0)
+ {
+ Cleanup(pfTest);
+ Fail ("Error closing file after writing with _putw(..).\n");
+ }
+
+ /*open the new test file and compare*/
+ pfTest = fopen(testFileName, "r");
+ if (pfTest == NULL)
+ {
+ Fail ("Error opening \"%s\", which is odd, since I just finished "
+ "creating that file.\n", testFileName);
+ }
+ retValue =_getw( pfTest );
+ i = 0;
+ while(retValue != EOF)
+ {
+ if(retValue != testArray[i])
+ {
+ Cleanup(pfTest);
+ Fail ("Integers written by _putw are not in the correct format\n",
+ testFileName);
+ }
+ retValue = _getw( pfTest );
+ i++ ;
+ }
+
+ Cleanup(pfTest);
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/_putw/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_putw/test1/testinfo.dat
new file mode 100644
index 0000000000..3007b82407
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_putw/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _putw
+Name = Positive test for _putw
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Several integers are written to a new file using _putw. This file is
+= closed, reopened and read from to verify the writes were successful.
diff --git a/src/pal/tests/palsuite/c_runtime/_rotl/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_rotl/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_rotl/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_rotl/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_rotl/test1/CMakeLists.txt
new file mode 100644
index 0000000000..bafaa23732
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_rotl/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.cpp
+)
+
+add_executable(paltest_rotl_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_rotl_test1 coreclrpal)
+
+target_link_libraries(paltest_rotl_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_rotl/test1/test1.cpp b/src/pal/tests/palsuite/c_runtime/_rotl/test1/test1.cpp
new file mode 100644
index 0000000000..3a31388893
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_rotl/test1/test1.cpp
@@ -0,0 +1,55 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c (_rotl)
+**
+** Purpose: Tests the PAL implementation of the _rotl function.
+** The _rotl function rotates the unsigned value. _rotl
+** rotates the value left and "wraps" bits rotated off
+** one end of value to the other end.
+** This test compares the result to a previously determined
+** value.
+**
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ unsigned results = 0;
+ int i,j;
+
+ unsigned hTestNums[5][8] = {
+ {0x00ff, 0x01fe, 0x03fc, 0x07f8, 0x0ff0, 0x1fe0, 0x3fc0, 0x7f80},
+ {0x0055, 0x00aa, 0x0154, 0x02a8, 0x0550, 0x0aa0, 0x1540, 0x2a80},
+ {0x0099, 0x0132, 0x0264, 0x04c8, 0x0990, 0x1320, 0x2640, 0x4c80},
+ {0x0036, 0x006c, 0x00d8, 0x01b0, 0x0360, 0x06c0, 0x0d80, 0x1b00},
+ {0x008f, 0x011e, 0x023c, 0x0478, 0x08f0, 0x11e0, 0x23c0, 0x4780}};
+
+ if ((PAL_Initialize(argc, argv)) != 0)
+ {
+ return (FAIL);
+ }
+
+ /*Loop through expected test results*/
+ for (j = 0; j <= 4; j++)
+ {
+ for(i = 1; i <= 7; i++)
+ {
+ results = _rotl(hTestNums[j][0], i);
+ if (results != hTestNums[j][i])
+ {
+ Fail("ERROR: \"0x%4.4x\" rotated bits to the left %d times"
+ " gave \"0x%4.4x\", expected \"0x%4.4x\"\n",
+ hTestNums[j][0], i, results, hTestNums[j][i]) ;
+ }
+ }
+ }
+
+ PAL_Terminate();
+ return (PASS);
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_rotl/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_rotl/test1/testinfo.dat
new file mode 100644
index 0000000000..9c87473f8e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_rotl/test1/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _rtol
+Name = Positive Test for _rotl
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests the PAL implementation of the _rotl function.
+= The _rotl function rotates the unsigned value. _rotl
+= rotates the value left and "wraps" bits rotated off
+= one end of value to the other end.
+= This test compares the result to a previously determined
+= value.
diff --git a/src/pal/tests/palsuite/c_runtime/_rotr/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_rotr/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_rotr/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_rotr/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_rotr/test1/CMakeLists.txt
new file mode 100644
index 0000000000..c0c76feb36
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_rotr/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.cpp
+)
+
+add_executable(paltest_rotr_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_rotr_test1 coreclrpal)
+
+target_link_libraries(paltest_rotr_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_rotr/test1/test1.cpp b/src/pal/tests/palsuite/c_runtime/_rotr/test1/test1.cpp
new file mode 100644
index 0000000000..cf461c0a6e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_rotr/test1/test1.cpp
@@ -0,0 +1,60 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c (_rotr)
+**
+** Purpose: Tests the PAL implementation of the _rotr function.
+** The _rotr function rotates the unsigned value. _rotr
+** rotates the value right and "wraps" bits rotated off
+** one end of value to the other end.
+** This test compares the result to a previously
+** determined value.
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ unsigned results = 0;
+ int i,j;
+
+ unsigned hTestNums[5][8] = {
+ {0x00ff, 0x8000007f, 0xc000003f, 0xe000001f,
+ 0xf000000f, 0xf8000007, 0xfc000003, 0xfe000001},
+ {0x0055, 0x8000002a, 0x40000015, 0xa000000a,
+ 0x50000005, 0xa8000002, 0x54000001, 0xaa000000},
+ {0x0099, 0x8000004c, 0x40000026, 0x20000013,
+ 0x90000009, 0xc8000004, 0x64000002, 0x32000001},
+ {0x0036, 0x001b, 0x8000000d, 0xc0000006,
+ 0x60000003, 0xb0000001, 0xd8000000, 0x6c000000},
+ {0x008f, 0x80000047, 0xc0000023, 0xe0000011,
+ 0xf0000008, 0x78000004, 0x3c000002 ,0x1e000001}};
+
+
+ if ((PAL_Initialize(argc, argv)) != 0)
+ {
+ return (FAIL);
+ }
+
+ /*Loop through expected test results*/
+ for (j = 0; j <= 4; j++)
+ {
+ for(i = 1; i <= 7; i++)
+ {
+ results = _rotr(hTestNums[j][0], i);
+ if (results != hTestNums[j][i])
+ {
+ Fail("ERROR: \"0x%4.4x\" rotated bits to the left %d times"
+ " gave \"0x%4.4x\", expected \"0x%4.4x\"\n",
+ hTestNums[j][0], i, results, hTestNums[j][i]) ;
+ }
+ }
+ }
+
+ PAL_Terminate();
+ return (PASS);
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_rotr/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_rotr/test1/testinfo.dat
new file mode 100644
index 0000000000..915f467662
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_rotr/test1/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _rtor
+Name = Positive Test for _rotr
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests the PAL implementation of the _rotr function.
+= The _rotr function rotates the unsigned value. _rotr
+= rotates the value right and "wraps" bits rotated off
+= one end of value to the other end.
+= This test compares the result to a previously determined
+= value.
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/CMakeLists.txt
new file mode 100644
index 0000000000..cafb9536b0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/CMakeLists.txt
@@ -0,0 +1,22 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test10)
+add_subdirectory(test11)
+add_subdirectory(test12)
+add_subdirectory(test13)
+add_subdirectory(test14)
+add_subdirectory(test15)
+add_subdirectory(test16)
+add_subdirectory(test17)
+add_subdirectory(test18)
+add_subdirectory(test19)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+add_subdirectory(test7)
+add_subdirectory(test8)
+add_subdirectory(test9)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/_snprintf.h b/src/pal/tests/palsuite/c_runtime/_snprintf/_snprintf.h
new file mode 100644
index 0000000000..84abf62f0b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/_snprintf.h
@@ -0,0 +1,194 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: _snprintf.h
+**
+** Purpose: Containts common testing functions for _snprintf
+**
+**
+**==========================================================================*/
+
+#ifndef __STRINGTEST_H__
+#define __STRINGTEST_H__
+
+void DoStrTest(char *formatstr, char* param, char *checkstr)
+{
+ char buf[256] = { 0 };
+
+ _snprintf(buf, 256, formatstr, param);
+ if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert string \"%s\" into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ param, formatstr, checkstr, buf);
+ }
+}
+
+void DoWStrTest(char *formatstr, WCHAR* param, char *checkstr)
+{
+ char buf[256] = { 0 };
+
+ _snprintf(buf, 256, formatstr, param);
+ if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert wide string \"%s\" into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ convertC(param), formatstr, checkstr, buf);
+ }
+}
+
+
+void DoPointerTest(char *formatstr, void* param, char* paramstr, char
+ *checkstr1)
+{
+ char buf[256] = { 0 };
+
+ _snprintf(buf, 256, formatstr, param);
+ if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %s into \"%s\"\n"
+ "Expected \"%s\", got \"%s\".\n",
+ paramstr, formatstr, checkstr1, buf);
+ }
+}
+
+void DoCountTest(char *formatstr, int param, char *checkstr)
+{
+ char buf[512] = { 0 };
+ int n = -1;
+
+ _snprintf(buf, 512, formatstr, &n);
+
+ if (n != param)
+ {
+ Fail("ERROR: Expected count parameter to resolve to %d, got %X\n",
+ param, n);
+ }
+ if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0)
+ {
+ Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf);
+ }
+}
+
+void DoShortCountTest(char *formatstr, int param, char *checkstr)
+{
+ char buf[256] = { 0 };
+ short int n = -1;
+
+ _snprintf(buf, 256, formatstr, &n);
+
+ if (n != param)
+ {
+ Fail("ERROR: Expected count parameter to resolve to %d, got %X\n",
+ param, n);
+ }
+ if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0)
+ {
+ Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf);
+ }
+}
+
+void DoCharTest(char *formatstr, char param, char *checkstr)
+{
+ char buf[256] = { 0 };
+
+ _snprintf(buf, 256, formatstr, param);
+ if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert char \'%c\' (%d) into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ param, param, formatstr, checkstr, buf);
+ }
+}
+
+void DoWCharTest(char *formatstr, WCHAR param, char *checkstr)
+{
+ char buf[256] = { 0 };
+
+ _snprintf(buf, 256, formatstr, param);
+ if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert wide char \'%c\' (%d) into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ (char)param, param, formatstr, checkstr, buf);
+ }
+}
+
+void DoNumTest(char *formatstr, int value, char *checkstr)
+{
+ char buf[256] = { 0 };
+
+ _snprintf(buf, 256, formatstr, value);
+ if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %#x into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ value, formatstr, checkstr, buf);
+ }
+}
+
+void DoI64Test(char *formatstr, INT64 value, char *valuestr, char *checkstr1)
+{
+ char buf[256] = { 0 };
+
+ _snprintf(buf, 256, formatstr, value);
+ if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %s into \"%s\"\n"
+ "Expected \"%s\", got \"%s\".\n",
+ valuestr, formatstr, checkstr1, buf);
+ }
+}
+
+void DoDoubleTest(char *formatstr, double value, char *checkstr1, char
+*checkstr2)
+{
+ char buf[256] = { 0 };
+
+ _snprintf(buf, 256, formatstr, value);
+ if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0
+ && memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %f into \"%s\"\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n",
+ value, formatstr, checkstr1, checkstr2, buf);
+ }
+}
+
+void DoArgumentPrecTest(char *formatstr, int precision, void *param, char
+*paramstr, char *checkstr1, char*checkstr2)
+{
+ char buf[256];
+
+ _snprintf(buf, 256, formatstr, precision, param);
+ if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 &&
+ memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n",
+ paramstr, formatstr, precision, checkstr1, checkstr2, buf);
+ }
+
+}
+
+void DoArgumentPrecDoubleTest(char *formatstr, int precision, double param,
+char *checkstr1, char *checkstr2)
+{
+ char buf[256];
+
+ _snprintf(buf, 256, formatstr, precision, param);
+ if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 &&
+ memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n",
+ param, formatstr, precision, checkstr1, checkstr2, buf);
+ }
+
+}
+
+#endif
+
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..ab126fc59d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_snprintf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snprintf_test1 coreclrpal)
+
+target_link_libraries(paltest_snprintf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test1/test1.c
new file mode 100644
index 0000000000..eef7406baa
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test1/test1.c
@@ -0,0 +1,58 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: General test to see if _snprintf works correctly
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ char checkstr[] = "hello world";
+ char buf[256] = { 0 };
+ int ret;
+
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ _snprintf(buf, 256, "hello world");
+ if (memcmp(checkstr, buf, strlen(checkstr)+1) != 0)
+ {
+ Fail("ERROR: expected \"%s\" (up to %d chars), got \"%s\"\n",
+ checkstr, 256, buf);
+ }
+
+ _snprintf(buf, 256, "xxxxxxxxxxxxxxxxx");
+ ret = _snprintf(buf, 8, "hello world");
+
+ if (ret >= 0)
+ {
+ Fail("ERROR: expected negative return value, got %d", ret);
+ }
+ if (memcmp(checkstr, buf, 8) != 0 || buf[8] != 'x')
+ {
+ Fail("ERROR: expected %s (up to %d chars), got %s\n",
+ checkstr, 8, buf);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test1/testinfo.dat
new file mode 100644
index 0000000000..c15ce1dcba
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snprintf
+Name = Positive Test for _snprintf
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= General test to see if _snprintf works correctly
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test10/CMakeLists.txt
new file mode 100644
index 0000000000..e8e9308849
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test10/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test10.c
+)
+
+add_executable(paltest_snprintf_test10
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snprintf_test10 coreclrpal)
+
+target_link_libraries(paltest_snprintf_test10
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test10/test10.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test10/test10.c
new file mode 100644
index 0000000000..9191ccef27
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test10/test10.c
@@ -0,0 +1,55 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test10.c
+**
+** Purpose: Tests _snprintf with octal numbers
+**
+**
+**==========================================================================*/
+
+
+
+
+#include <palsuite.h>
+#include "../_snprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest("foo %o", pos, "foo 52");
+ DoNumTest("foo %lo", 0xFFFF, "foo 177777");
+ DoNumTest("foo %ho", 0xFFFF, "foo 177777");
+ DoNumTest("foo %Lo", pos, "foo 52");
+ DoI64Test("foo %I64o", l, "42", "foo 52");
+ DoNumTest("foo %3o", pos, "foo 52");
+ DoNumTest("foo %-3o", pos, "foo 52 ");
+ DoNumTest("foo %.1o", pos, "foo 52");
+ DoNumTest("foo %.3o", pos, "foo 052");
+ DoNumTest("foo %03o", pos, "foo 052");
+ DoNumTest("foo %#o", pos, "foo 052");
+ DoNumTest("foo %+o", pos, "foo 52");
+ DoNumTest("foo % o", pos, "foo 52");
+ DoNumTest("foo %+o", neg, "foo 37777777726");
+ DoNumTest("foo % o", neg, "foo 37777777726");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test10/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test10/testinfo.dat
new file mode 100644
index 0000000000..44ff48e030
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test10/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snprintf
+Name = Positive Test for _snprintf
+TYPE = DEFAULT
+EXE1 = test10
+Description
+= Tests _snprintf with octal numbers
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test11/CMakeLists.txt
new file mode 100644
index 0000000000..ccf3dc2572
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test11/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test11.c
+)
+
+add_executable(paltest_snprintf_test11
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snprintf_test11 coreclrpal)
+
+target_link_libraries(paltest_snprintf_test11
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test11/test11.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test11/test11.c
new file mode 100644
index 0000000000..9d9302dee0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test11/test11.c
@@ -0,0 +1,54 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test11.c
+**
+** Purpose: Tests _snprintf with unsigned numbers
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest("foo %u", pos, "foo 42");
+ DoNumTest("foo %lu", 0xFFFF, "foo 65535");
+ DoNumTest("foo %hu", 0xFFFF, "foo 65535");
+ DoNumTest("foo %Lu", pos, "foo 42");
+ DoI64Test("foo %I64u", l, "42", "foo 42");
+ DoNumTest("foo %3u", pos, "foo 42");
+ DoNumTest("foo %-3u", pos, "foo 42 ");
+ DoNumTest("foo %.1u", pos, "foo 42");
+ DoNumTest("foo %.3u", pos, "foo 042");
+ DoNumTest("foo %03u", pos, "foo 042");
+ DoNumTest("foo %#u", pos, "foo 42");
+ DoNumTest("foo %+u", pos, "foo 42");
+ DoNumTest("foo % u", pos, "foo 42");
+ DoNumTest("foo %+u", neg, "foo 4294967254");
+ DoNumTest("foo % u", neg, "foo 4294967254");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test11/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test11/testinfo.dat
new file mode 100644
index 0000000000..1a77077950
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test11/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snprintf
+Name = Positive Test for _snprintf
+TYPE = DEFAULT
+EXE1 = test11
+Description
+= Tests _snprintf with unsigned numbers
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test12/CMakeLists.txt
new file mode 100644
index 0000000000..68b442f1d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test12/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test12.c
+)
+
+add_executable(paltest_snprintf_test12
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snprintf_test12 coreclrpal)
+
+target_link_libraries(paltest_snprintf_test12
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test12/test12.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test12/test12.c
new file mode 100644
index 0000000000..d782fce788
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test12/test12.c
@@ -0,0 +1,55 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test12.c
+**
+** Purpose: Tests _snprintf with hex numbers (lowercase)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 0x1234ab;
+ INT64 l = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest("foo %x", pos, "foo 1234ab");
+ DoNumTest("foo %lx", pos, "foo 1234ab");
+ DoNumTest("foo %hx", pos, "foo 34ab");
+ DoNumTest("foo %Lx", pos, "foo 1234ab");
+ DoI64Test("foo %I64x", l, "0x1234567887654321", "foo 1234567887654321");
+ DoNumTest("foo %7x", pos, "foo 1234ab");
+ DoNumTest("foo %-7x", pos, "foo 1234ab ");
+ DoNumTest("foo %.1x", pos, "foo 1234ab");
+ DoNumTest("foo %.7x", pos, "foo 01234ab");
+ DoNumTest("foo %07x", pos, "foo 01234ab");
+ DoNumTest("foo %#x", pos, "foo 0x1234ab");
+ DoNumTest("foo %+x", pos, "foo 1234ab");
+ DoNumTest("foo % x", pos, "foo 1234ab");
+ DoNumTest("foo %+x", neg, "foo ffffffd6");
+ DoNumTest("foo % x", neg, "foo ffffffd6");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test12/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test12/testinfo.dat
new file mode 100644
index 0000000000..6801c7417e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test12/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snprintf
+Name = Positive Test for _snprintf
+TYPE = DEFAULT
+EXE1 = test12
+Description
+= Tests _snprintf with hex numbers (lowercase)
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test13/CMakeLists.txt
new file mode 100644
index 0000000000..832b3fefbf
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test13/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test13.c
+)
+
+add_executable(paltest_snprintf_test13
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snprintf_test13 coreclrpal)
+
+target_link_libraries(paltest_snprintf_test13
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test13/test13.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test13/test13.c
new file mode 100644
index 0000000000..68ba554d93
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test13/test13.c
@@ -0,0 +1,55 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test13.c
+**
+** Purpose: Tests _snprintf with hex numbers (uppercase)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 0x1234AB;
+ INT64 l = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest("foo %X", pos, "foo 1234AB");
+ DoNumTest("foo %lX", pos, "foo 1234AB");
+ DoNumTest("foo %hX", pos, "foo 34AB");
+ DoNumTest("foo %LX", pos, "foo 1234AB");
+ DoI64Test("foo %I64X", l, "0x1234567887654321", "foo 1234567887654321");
+ DoNumTest("foo %7X", pos, "foo 1234AB");
+ DoNumTest("foo %-7X", pos, "foo 1234AB ");
+ DoNumTest("foo %.1X", pos, "foo 1234AB");
+ DoNumTest("foo %.7X", pos, "foo 01234AB");
+ DoNumTest("foo %07X", pos, "foo 01234AB");
+ DoNumTest("foo %#X", pos, "foo 0X1234AB");
+ DoNumTest("foo %+X", pos, "foo 1234AB");
+ DoNumTest("foo % X", pos, "foo 1234AB");
+ DoNumTest("foo %+X", neg, "foo FFFFFFD6");
+ DoNumTest("foo % X", neg, "foo FFFFFFD6");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test13/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test13/testinfo.dat
new file mode 100644
index 0000000000..6901589a1b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test13/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snprintf
+Name = Positive Test for _snprintf
+TYPE = DEFAULT
+EXE1 = test13
+Description
+= Tests _snprintf with hex numbers (uppercase)
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test14/CMakeLists.txt
new file mode 100644
index 0000000000..c2e3be148d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test14/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test14.c
+)
+
+add_executable(paltest_snprintf_test14
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snprintf_test14 coreclrpal)
+
+target_link_libraries(paltest_snprintf_test14
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test14/test14.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test14/test14.c
new file mode 100644
index 0000000000..d874690ba4
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test14/test14.c
@@ -0,0 +1,57 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test14.c
+**
+** Purpose: Tests _snprintf with exponential format doubles (lowercase)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 256.0;
+ double neg = -256.0;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest("foo %e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %le", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %he", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %Le", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %I64e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %14e", val, "foo 2.560000e+002",
+ "foo 2.560000e+02");
+ DoDoubleTest("foo %-14e", val, "foo 2.560000e+002 ",
+ "foo 2.560000e+02 ");
+ DoDoubleTest("foo %.1e", val, "foo 2.6e+002", "foo 2.6e+02");
+ DoDoubleTest("foo %.8e", val, "foo 2.56000000e+002",
+ "foo 2.56000000e+02");
+ DoDoubleTest("foo %014e", val, "foo 02.560000e+002",
+ "foo 002.560000e+02");
+ DoDoubleTest("foo %#e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %+e", val, "foo +2.560000e+002", "foo +2.560000e+02");
+ DoDoubleTest("foo % e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %+e", neg, "foo -2.560000e+002", "foo -2.560000e+02");
+ DoDoubleTest("foo % e", neg, "foo -2.560000e+002", "foo -2.560000e+02");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test14/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test14/testinfo.dat
new file mode 100644
index 0000000000..0f32b9b59a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test14/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snprintf
+Name = Positive Test for _snprintf
+TYPE = DEFAULT
+EXE1 = test14
+Description
+= Tests _snprintf with exponential format doubles (lowercase)
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test15/CMakeLists.txt
new file mode 100644
index 0000000000..1bd24d5ccd
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test15/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test15.c
+)
+
+add_executable(paltest_snprintf_test15
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snprintf_test15 coreclrpal)
+
+target_link_libraries(paltest_snprintf_test15
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test15/test15.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test15/test15.c
new file mode 100644
index 0000000000..a637a706f5
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test15/test15.c
@@ -0,0 +1,56 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test15.c
+**
+** Purpose: Tests _snprintf with exponential format doubles (uppercase)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 256.0;
+ double neg = -256.0;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest("foo %E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %lE", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %hE", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %LE", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %I64E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %14E", val, "foo 2.560000E+002",
+ "foo 2.560000E+02");
+ DoDoubleTest("foo %-14E", val, "foo 2.560000E+002 ",
+ "foo 2.560000E+02 ");
+ DoDoubleTest("foo %.1E", val, "foo 2.6E+002", "foo 2.6E+02");
+ DoDoubleTest("foo %.8E", val, "foo 2.56000000E+002",
+ "foo 2.56000000E+02");
+ DoDoubleTest("foo %014E", val, "foo 02.560000E+002",
+ "foo 002.560000E+02");
+ DoDoubleTest("foo %#E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %+E", val, "foo +2.560000E+002", "foo +2.560000E+02");
+ DoDoubleTest("foo % E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %+E", neg, "foo -2.560000E+002", "foo -2.560000E+02");
+ DoDoubleTest("foo % E", neg, "foo -2.560000E+002", "foo -2.560000E+02");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test15/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test15/testinfo.dat
new file mode 100644
index 0000000000..8008cff0b5
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test15/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snprintf
+Name = Positive Test for _snprintf
+TYPE = DEFAULT
+EXE1 = test15
+Description
+= Tests _snprintf with exponential format doubles (uppercase)
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test16/CMakeLists.txt
new file mode 100644
index 0000000000..952192e560
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test16/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test16.c
+)
+
+add_executable(paltest_snprintf_test16
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snprintf_test16 coreclrpal)
+
+target_link_libraries(paltest_snprintf_test16
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test16/test16.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test16/test16.c
new file mode 100644
index 0000000000..6793019383
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test16/test16.c
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test16.c
+**
+** Purpose: Test #15 for the _snprintf function
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest("foo %f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %lf", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %hf", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %Lf", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %I64f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %12f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %-12f", val, "foo 2560.001000 ", "foo 2560.001000 ");
+ DoDoubleTest("foo %.1f", val, "foo 2560.0", "foo 2560.0");
+ DoDoubleTest("foo %.8f", val, "foo 2560.00100000", "foo 2560.00100000");
+ DoDoubleTest("foo %012f", val, "foo 02560.001000", "foo 02560.001000");
+ DoDoubleTest("foo %#f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %+f", val, "foo +2560.001000", "foo +2560.001000");
+ DoDoubleTest("foo % f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %+f", neg, "foo -2560.001000", "foo -2560.001000");
+ DoDoubleTest("foo % f", neg, "foo -2560.001000", "foo -2560.001000");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test16/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test16/testinfo.dat
new file mode 100644
index 0000000000..e7a7df8f53
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test16/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snprintf
+Name = Positive Test for _snprintf
+TYPE = DEFAULT
+EXE1 = test16
+Description
+= Tests _snprintf with decimal point format doubles
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test17/CMakeLists.txt
new file mode 100644
index 0000000000..ce5cc1623e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test17/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test17.c
+)
+
+add_executable(paltest_snprintf_test17
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snprintf_test17 coreclrpal)
+
+target_link_libraries(paltest_snprintf_test17
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test17/test17.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test17/test17.c
new file mode 100644
index 0000000000..9981b44619
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test17/test17.c
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test17.c
+**
+** Purpose: Tests _snprintf with compact format doubles (lowercase)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest("foo %g", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %lg", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %hg", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %Lg", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %I64g", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %5g", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %-5g", val, "foo 2560 ", "foo 2560 ");
+ DoDoubleTest("foo %.1g", val, "foo 3e+003", "foo 3e+03");
+ DoDoubleTest("foo %.2g", val, "foo 2.6e+003", "foo 2.6e+03");
+ DoDoubleTest("foo %.12g", val, "foo 2560.001", "foo 2560.001");
+ DoDoubleTest("foo %06g", val, "foo 002560", "foo 002560");
+ DoDoubleTest("foo %#g", val, "foo 2560.00", "foo 2560.00");
+ DoDoubleTest("foo %+g", val, "foo +2560", "foo +2560");
+ DoDoubleTest("foo % g", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %+g", neg, "foo -2560", "foo -2560");
+ DoDoubleTest("foo % g", neg, "foo -2560", "foo -2560");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test17/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test17/testinfo.dat
new file mode 100644
index 0000000000..4756bd0d78
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test17/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snprintf
+Name = Positive Test for _snprintf
+TYPE = DEFAULT
+EXE1 = test17
+Description
+= Tests _snprintf with compact format doubles (lowercase)
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test18/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test18/CMakeLists.txt
new file mode 100644
index 0000000000..bb9c9c37cc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test18/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test18.c
+)
+
+add_executable(paltest_snprintf_test18
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snprintf_test18 coreclrpal)
+
+target_link_libraries(paltest_snprintf_test18
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test18/test18.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test18/test18.c
new file mode 100644
index 0000000000..d28aec57d0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test18/test18.c
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test18.c
+**
+** Purpose: Tests _snprintf with compact format doubles (uppercase)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest("foo %G", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %lG", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %hG", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %LG", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %I64G", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %5G", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %-5G", val, "foo 2560 ", "foo 2560 ");
+ DoDoubleTest("foo %.1G", val, "foo 3E+003", "foo 3E+03");
+ DoDoubleTest("foo %.2G", val, "foo 2.6E+003", "foo 2.6E+03");
+ DoDoubleTest("foo %.12G", val, "foo 2560.001", "foo 2560.001");
+ DoDoubleTest("foo %06G", val, "foo 002560", "foo 002560");
+ DoDoubleTest("foo %#G", val, "foo 2560.00", "foo 2560.00");
+ DoDoubleTest("foo %+G", val, "foo +2560", "foo +2560");
+ DoDoubleTest("foo % G", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %+G", neg, "foo -2560", "foo -2560");
+ DoDoubleTest("foo % G", neg, "foo -2560", "foo -2560");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test18/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test18/testinfo.dat
new file mode 100644
index 0000000000..819d28cec9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test18/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snprintf
+Name = Positive Test for _snprintf
+TYPE = DEFAULT
+EXE1 = test18
+Description
+= Tests _snprintf with compact format doubles (uppercase)
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test19/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test19/CMakeLists.txt
new file mode 100644
index 0000000000..f3fbb95013
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test19/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test19.c
+)
+
+add_executable(paltest_snprintf_test19
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snprintf_test19 coreclrpal)
+
+target_link_libraries(paltest_snprintf_test19
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test19/test19.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test19/test19.c
new file mode 100644
index 0000000000..26dffd9214
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test19/test19.c
@@ -0,0 +1,76 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test19.c
+**
+** Purpose:Tests _snprintf with argument specified precision
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int n = -1;
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ DoArgumentPrecTest("%.*s", 2, "bar", "bar", "ba", "ba");
+ DoArgumentPrecTest("%.*S", 2, convert("bar"), "bar", "ba", "ba");
+ DoArgumentPrecTest("%.*n", 3, &n, "pointer to int", "", "");
+ if (n != 0)
+ {
+ Fail("ERROR: Expected count parameter to resolve to %d, got %X\n",
+ 0, n);
+ }
+
+ DoArgumentPrecTest("%.*c", 0, (void*)'a', "a", "a", "a");
+ DoArgumentPrecTest("%.*c", 4, (void*)'a', "a", "a", "a");
+ DoArgumentPrecTest("%.*C", 0, (void*)'a', "a", "a", "a");
+ DoArgumentPrecTest("%.*C", 4, (void*)'a', "a", "a", "a");
+ DoArgumentPrecTest("%.*d", 1, (void*)42, "42", "42", "42");
+ DoArgumentPrecTest("%.*d", 3, (void*)42, "42", "042", "042");
+ DoArgumentPrecTest("%.*i", 1, (void*)42, "42", "42", "42");
+ DoArgumentPrecTest("%.*i", 3, (void*)42, "42", "042", "042");
+ DoArgumentPrecTest("%.*o", 1, (void*)42, "42", "52", "52");
+ DoArgumentPrecTest("%.*o", 3, (void*)42, "42", "052", "052");
+ DoArgumentPrecTest("%.*u", 1, (void*)42, "42", "42", "42");
+ DoArgumentPrecTest("%.*u", 3, (void*)42, "42", "042", "042");
+ DoArgumentPrecTest("%.*x", 1, (void*)0x42, "0x42", "42", "42");
+ DoArgumentPrecTest("%.*x", 3, (void*)0x42, "0x42", "042", "042");
+ DoArgumentPrecTest("%.*X", 1, (void*)0x42, "0x42", "42", "42") ;
+ DoArgumentPrecTest("%.*X", 3, (void*)0x42, "0x42", "042", "042");
+
+
+ DoArgumentPrecDoubleTest("%.*e", 1, 2.01, "2.0e+000", "2.0e+00");
+ DoArgumentPrecDoubleTest("%.*e", 3, 2.01, "2.010e+000", "2.010e+00");
+ DoArgumentPrecDoubleTest("%.*E", 1, 2.01, "2.0E+000", "2.0E+00");
+ DoArgumentPrecDoubleTest("%.*E", 3, 2.01, "2.010E+000", "2.010E+00");
+ DoArgumentPrecDoubleTest("%.*f", 1, 2.01, "2.0", "2.0");
+ DoArgumentPrecDoubleTest("%.*f", 3, 2.01, "2.010", "2.010");
+ DoArgumentPrecDoubleTest("%.*g", 1, 256.01, "3e+002", "3e+02");
+ DoArgumentPrecDoubleTest("%.*g", 3, 256.01, "256", "256");
+ DoArgumentPrecDoubleTest("%.*g", 4, 256.01, "256", "256");
+ DoArgumentPrecDoubleTest("%.*g", 6, 256.01, "256.01", "256.01");
+ DoArgumentPrecDoubleTest("%.*G", 1, 256.01, "3E+002", "3E+02");
+ DoArgumentPrecDoubleTest("%.*G", 3, 256.01, "256", "256");
+ DoArgumentPrecDoubleTest("%.*G", 4, 256.01, "256", "256");
+ DoArgumentPrecDoubleTest("%.*G", 6, 256.01, "256.01", "256.01");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test19/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test19/testinfo.dat
new file mode 100644
index 0000000000..875abf7071
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test19/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snprintf
+Name = Positive Test for _snprintf
+TYPE = DEFAULT
+EXE1 = test19
+Description
+= Tests _snprintf with argument specified precision
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test2/CMakeLists.txt
new file mode 100644
index 0000000000..8c617df108
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_snprintf_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snprintf_test2 coreclrpal)
+
+target_link_libraries(paltest_snprintf_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test2/test2.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test2/test2.c
new file mode 100644
index 0000000000..3ccb66c23e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test2/test2.c
@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test2.c
+**
+** Purpose:Tests _snprintf with strings
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snprintf.h"
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ DoStrTest("foo %s", "bar", "foo bar");
+ DoStrTest("foo %hs", "bar", "foo bar");
+ DoWStrTest("foo %ls", convert("bar"), "foo bar");
+ DoWStrTest("foo %ws", convert("bar"), "foo bar");
+ DoStrTest("foo %Ls", "bar", "foo bar");
+ DoStrTest("foo %I64s", "bar", "foo bar");
+ DoStrTest("foo %5s", "bar", "foo bar");
+ DoStrTest("foo %.2s", "bar", "foo ba");
+ DoStrTest("foo %5.2s", "bar", "foo ba");
+ DoStrTest("foo %-5s", "bar", "foo bar ");
+ DoStrTest("foo %05s", "bar", "foo 00bar");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test2/testinfo.dat
new file mode 100644
index 0000000000..40a1ede3d5
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test2/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snprintf
+Name = Positive Test for _snprintf
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Tests _snprintf with strings
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test3/CMakeLists.txt
new file mode 100644
index 0000000000..13330464a7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_snprintf_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snprintf_test3 coreclrpal)
+
+target_link_libraries(paltest_snprintf_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test3/test3.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test3/test3.c
new file mode 100644
index 0000000000..496159c51e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test3/test3.c
@@ -0,0 +1,45 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test3.c
+**
+** Purpose: Tests _snprintf with wide strings
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ DoWStrTest("foo %S", convert("bar"), "foo bar");
+ DoStrTest("foo %hS", "bar", "foo bar");
+ DoWStrTest("foo %lS", convert("bar"), "foo bar");
+ DoWStrTest("foo %wS", convert("bar"), "foo bar");
+ DoWStrTest("foo %LS", convert("bar"), "foo bar");
+ DoWStrTest("foo %I64S", convert("bar"), "foo bar");
+ DoWStrTest("foo %5S", convert("bar"), "foo bar");
+ DoWStrTest("foo %.2S", convert("bar"), "foo ba");
+ DoWStrTest("foo %5.2S", convert("bar"), "foo ba");
+ DoWStrTest("foo %-5S", convert("bar"), "foo bar ");
+ DoWStrTest("foo %05S", convert("bar"), "foo 00bar");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test3/testinfo.dat
new file mode 100644
index 0000000000..fa53224510
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test3/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snprintf
+Name = Positive Test for _snprintf
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Tests _snprintf with wide strings
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test4/CMakeLists.txt
new file mode 100644
index 0000000000..5132aa02de
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_snprintf_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snprintf_test4 coreclrpal)
+
+target_link_libraries(paltest_snprintf_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test4/test4.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test4/test4.c
new file mode 100644
index 0000000000..8c39f222cc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test4/test4.c
@@ -0,0 +1,69 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test4.c
+**
+** Purpose: Tests _snprintf with pointers
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ void *ptr = (void*) 0x123456;
+ INT64 lptr = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+ /*
+ ** Run only on 64 bit platforms
+ */
+ #if defined(BIT64) && defined(PLATFORM_UNIX)
+ Trace("Testing for 64 Bit Platforms \n");
+ DoPointerTest("%p", NULL, "NULL", "0000000000000000");
+ DoPointerTest("%p", ptr, "pointer to 0x123456", "0000000000123456");
+ DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456");
+ DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456");
+ DoPointerTest("%-17p", ptr, "pointer to 0x123456", "0000000000123456 ");
+ DoPointerTest("%+p", ptr, "pointer to 0x123456", "0000000000123456");
+ DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X0000000000123456");
+ DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456");
+ DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456");
+ DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456");
+ DoI64Test("%I64p", lptr, "pointer to 0x1234567887654321",
+ "1234567887654321");
+ #else
+ Trace("Testing for Non 64 Bit Platforms \n");
+ DoPointerTest("%p", NULL, "NULL", "00000000");
+ DoPointerTest("%p", ptr, "pointer to 0x123456", "00123456");
+ DoPointerTest("%9p", ptr, "pointer to 0x123456", " 00123456");
+ DoPointerTest("%09p", ptr, "pointer to 0x123456", " 00123456");
+ DoPointerTest("%-9p", ptr, "pointer to 0x123456", "00123456 ");
+ DoPointerTest("%+p", ptr, "pointer to 0x123456", "00123456");
+ DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X00123456");
+ DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456");
+ DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456");
+ DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456");
+ DoI64Test("%I64p", lptr, "pointer to 0x1234567887654321",
+ "1234567887654321");
+ #endif //defined(BIT64) && defined(PLATFORM_UNIX)
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test4/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test4/testinfo.dat
new file mode 100644
index 0000000000..5d822d160b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test4/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snprintf
+Name = Positive Test for _snprintf
+TYPE = DEFAULT
+EXE1 = test4
+Description
+= Tests _snprintf with pointers
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test5/CMakeLists.txt
new file mode 100644
index 0000000000..07e441cee0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test5.c
+)
+
+add_executable(paltest_snprintf_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snprintf_test5 coreclrpal)
+
+target_link_libraries(paltest_snprintf_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test5/test5.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test5/test5.c
new file mode 100644
index 0000000000..46ab1dd35e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test5/test5.c
@@ -0,0 +1,61 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test5.c
+**
+** Purpose: Tests _snprintf with the count specifier
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ char *longStr =
+ "really-long-string-that-just-keeps-going-on-and-on-and-on.."
+ "..................useless-filler.................................."
+ "..................useless-filler.................................."
+ "..................useless-filler.................................."
+ "%n bar";
+ char *longResult =
+ "really-long-string-that-just-keeps-going-on-and-on-and-on.."
+ "..................useless-filler.................................."
+ "..................useless-filler.................................."
+ "..................useless-filler.................................."
+ " bar";
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ DoCountTest("foo %n bar", 4, "foo bar");
+ DoCountTest(longStr, 257, longResult);
+ DoCountTest("fo%n bar", 2, "fo bar");
+ DoCountTest("%n", 0, "");
+ DoCountTest("foo %#n bar", 4, "foo bar");
+ DoCountTest("foo % n bar", 4, "foo bar");
+ DoCountTest("foo %+n bar", 4, "foo bar");
+ DoCountTest("foo %-n bar", 4, "foo bar");
+ DoCountTest("foo %0n bar", 4, "foo bar");
+ DoShortCountTest("foo %hn bar", 4, "foo bar");
+ DoCountTest("foo %ln bar", 4, "foo bar");
+ DoCountTest("foo %Ln bar", 4, "foo bar");
+ DoCountTest("foo %I64n bar", 4, "foo bar");
+ DoCountTest("foo %20.3n bar", 4, "foo bar");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test5/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test5/testinfo.dat
new file mode 100644
index 0000000000..33056defd8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test5/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snprintf
+Name = Positive Test for _snprintf
+TYPE = DEFAULT
+EXE1 = test5
+Description
+= Tests _snprintf with the count specifier
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test6/CMakeLists.txt
new file mode 100644
index 0000000000..9ee5d90544
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test6.c
+)
+
+add_executable(paltest_snprintf_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snprintf_test6 coreclrpal)
+
+target_link_libraries(paltest_snprintf_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test6/test6.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test6/test6.c
new file mode 100644
index 0000000000..32001c2d20
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test6/test6.c
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test6.c
+**
+** Purpose: Tests _snprintf with characters
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR wc = (WCHAR) 'c';
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoCharTest("foo %c", 'b', "foo b");
+ DoCharTest("foo %hc", 'b', "foo b");
+ DoWCharTest("foo %lc", wc, "foo c");
+ DoCharTest("foo %Lc", 'b', "foo b");
+ DoCharTest("foo %I64c", 'b', "foo b");
+ DoCharTest("foo %5c", 'b', "foo b");
+ DoCharTest("foo %.0c", 'b', "foo b");
+ DoCharTest("foo %-5c", 'b', "foo b ");
+ DoCharTest("foo %05c", 'b', "foo 0000b");
+ DoCharTest("foo % c", 'b', "foo b");
+ DoCharTest("foo %#c", 'b', "foo b");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test6/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test6/testinfo.dat
new file mode 100644
index 0000000000..ba2ff818aa
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test6/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snprintf
+Name =Positive Test for _snprintf
+TYPE = DEFAULT
+EXE1 = test6
+Description
+= Tests _snprintf with characters
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test7/CMakeLists.txt
new file mode 100644
index 0000000000..f7651218e0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test7/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test7.c
+)
+
+add_executable(paltest_snprintf_test7
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snprintf_test7 coreclrpal)
+
+target_link_libraries(paltest_snprintf_test7
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test7/test7.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test7/test7.c
new file mode 100644
index 0000000000..bfd5c3f4f1
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test7/test7.c
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test7.c
+**
+** Purpose: Tests _snprintf with wide characters
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snprintf.h"
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR wb = (WCHAR) 'b';
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoWCharTest("foo %C", wb, "foo b");
+ DoWCharTest("foo %hC", wb, "foo b");
+ DoCharTest("foo %lC", 'c', "foo c");
+ DoWCharTest("foo %LC", wb, "foo b");
+ DoWCharTest("foo %I64C", wb, "foo b");
+ DoWCharTest("foo %5C", wb, "foo b");
+ DoWCharTest("foo %.0C", wb, "foo b");
+ DoWCharTest("foo %-5C", wb, "foo b ");
+ DoWCharTest("foo %05C", wb, "foo 0000b");
+ DoWCharTest("foo % C", wb, "foo b");
+ DoWCharTest("foo %#C", wb, "foo b");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test7/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test7/testinfo.dat
new file mode 100644
index 0000000000..5c2406c7b2
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test7/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snprintf
+Name = Positive Test for _snprintf
+TYPE = DEFAULT
+EXE1 = test7
+Description
+= Tests _snprintf with wide characters
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test8/CMakeLists.txt
new file mode 100644
index 0000000000..26af119852
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test8/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test8.c
+)
+
+add_executable(paltest_snprintf_test8
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snprintf_test8 coreclrpal)
+
+target_link_libraries(paltest_snprintf_test8
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test8/test8.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test8/test8.c
new file mode 100644
index 0000000000..60ff1b05b8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test8/test8.c
@@ -0,0 +1,56 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test8.c
+**
+** Purpose: Tests _snprintf with decimal numbers
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest("foo %d", pos, "foo 42");
+ DoNumTest("foo %ld", 0xFFFF, "foo 65535");
+ DoNumTest("foo %hd", 0xFFFF, "foo -1");
+ DoNumTest("foo %Ld", pos, "foo 42");
+ DoI64Test("foo %I64d", l, "42", "foo 42");
+ DoNumTest("foo %3d", pos, "foo 42");
+ DoNumTest("foo %-3d", pos, "foo 42 ");
+ DoNumTest("foo %.1d", pos, "foo 42");
+ DoNumTest("foo %.3d", pos, "foo 042");
+ DoNumTest("foo %03d", pos, "foo 042");
+ DoNumTest("foo %#d", pos, "foo 42");
+ DoNumTest("foo %+d", pos, "foo +42");
+ DoNumTest("foo % d", pos, "foo 42");
+ DoNumTest("foo %+d", neg, "foo -42");
+ DoNumTest("foo % d", neg, "foo -42");
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test8/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test8/testinfo.dat
new file mode 100644
index 0000000000..f6520d8dde
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test8/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snprintf
+Name = Positive Test for _snprintf
+TYPE = DEFAULT
+EXE1 = test8
+Description
+= Tests _snprintf with decimal numbers
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test9/CMakeLists.txt
new file mode 100644
index 0000000000..484075919e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test9/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test9.c
+)
+
+add_executable(paltest_snprintf_test9
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snprintf_test9 coreclrpal)
+
+target_link_libraries(paltest_snprintf_test9
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test9/test9.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test9/test9.c
new file mode 100644
index 0000000000..e836bcaee3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test9/test9.c
@@ -0,0 +1,55 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test9.c
+**
+** Purpose: Tests _snprintf with integer numbers
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest("foo %i", pos, "foo 42");
+ DoNumTest("foo %li", 0xFFFF, "foo 65535");
+ DoNumTest("foo %hi", 0xFFFF, "foo -1");
+ DoNumTest("foo %Li", pos, "foo 42");
+ DoI64Test("foo %I64i", l, "42", "foo 42");
+ DoNumTest("foo %3i", pos, "foo 42");
+ DoNumTest("foo %-3i", pos, "foo 42 ");
+ DoNumTest("foo %.1i", pos, "foo 42");
+ DoNumTest("foo %.3i", pos, "foo 042");
+ DoNumTest("foo %03i", pos, "foo 042");
+ DoNumTest("foo %#i", pos, "foo 42");
+ DoNumTest("foo %+i", pos, "foo +42");
+ DoNumTest("foo % i", pos, "foo 42");
+ DoNumTest("foo %+i", neg, "foo -42");
+ DoNumTest("foo % i", neg, "foo -42");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test9/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test9/testinfo.dat
new file mode 100644
index 0000000000..2a64b26030
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snprintf/test9/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snprintf
+Name = Positive Test for _snprintf
+TYPE = DEFAULT
+EXE1 = test9
+Description
+= Tests _snprintf with integer numbers
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/CMakeLists.txt
new file mode 100644
index 0000000000..cafb9536b0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/CMakeLists.txt
@@ -0,0 +1,22 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test10)
+add_subdirectory(test11)
+add_subdirectory(test12)
+add_subdirectory(test13)
+add_subdirectory(test14)
+add_subdirectory(test15)
+add_subdirectory(test16)
+add_subdirectory(test17)
+add_subdirectory(test18)
+add_subdirectory(test19)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+add_subdirectory(test7)
+add_subdirectory(test8)
+add_subdirectory(test9)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/_snwprintf.h b/src/pal/tests/palsuite/c_runtime/_snwprintf/_snwprintf.h
new file mode 100644
index 0000000000..73bf4d6c12
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/_snwprintf.h
@@ -0,0 +1,199 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: _snwprintf.h
+**
+** Purpose: Containts common testing functions for _snwprintf
+**
+**
+**==========================================================================*/
+
+#ifndef ___SNWPRINTF_H__
+#define ___SNWPRINTF_H__
+
+void DoWStrTest(WCHAR *formatstr, WCHAR *param, WCHAR *checkstr)
+{
+ WCHAR buf[256] = { 0 };
+
+ _snwprintf(buf, 256, formatstr, param);
+
+ if (memcmp(buf, checkstr, wcslen(checkstr) * 2 + 2) != 0)
+ {
+ Fail("ERROR: failed to insert wide string \"%s\" into \"%s\".\n"
+ "Expected \"%s\", got \"%s\".\n", convertC(param),
+ convertC(formatstr), convertC(checkstr), convertC(buf));
+ }
+}
+
+void DoStrTest(WCHAR *formatstr, char *param, WCHAR *checkstr)
+{
+ WCHAR buf[256] = { 0 };
+
+ _snwprintf(buf, 256, formatstr, param);
+
+ if (memcmp(buf, checkstr, wcslen(checkstr) * 2 + 2) != 0)
+ {
+ Fail("ERROR: failed to insert wide string \"%s\" into \"%s\".\n"
+ "Expected \"%s\", got \"%s\".\n",
+ param, convertC(formatstr), convertC(checkstr), convertC(buf));
+ }
+}
+
+void DoPointerTest(WCHAR *formatstr, void* param, WCHAR *checkstr1)
+{
+ WCHAR buf[256] = { 0 };
+
+ _snwprintf(buf, 256, formatstr, param);
+ if (memcmp(buf, checkstr1, wcslen(checkstr1)*2 + 2) != 0)
+ {
+ Fail("ERROR: failed to insert pointer to %#p into \"%s\"\n"
+ "Expected \"%s\", got \"%s\".\n", param, convertC(formatstr),
+ convertC(checkstr1), convertC(buf));
+ }
+}
+
+void DoCountTest(WCHAR *formatstr, int param, WCHAR *checkstr)
+{
+ WCHAR buf[512] = { 0 };
+ int n = -1;
+
+ _snwprintf(buf, 512, formatstr, &n);
+
+ if (n != param)
+ {
+ Fail("ERROR: Expected count parameter to resolve to %d, got %d\n",
+ param, n);
+ }
+
+ if (memcmp(buf, checkstr, wcslen(checkstr)*2 + 2) != 0)
+ {
+ Fail("ERROR: Expected \"%s\" got \"%s\".\n",
+ convertC(checkstr), convertC(buf));
+ }
+}
+
+void DoShortCountTest(WCHAR *formatstr, int param, WCHAR *checkstr)
+{
+ WCHAR buf[256] = { 0 };
+ short int n = -1;
+
+ _snwprintf(buf, 256, formatstr, &n);
+
+ if (n != param)
+ {
+ Fail("ERROR: Expected count parameter to resolve to %d, got %d\n",
+ param, n);
+ }
+
+ if (memcmp(buf, checkstr, wcslen(checkstr)*2 + 2) != 0)
+ {
+ Fail("ERROR: Expected \"%s\" got \"%s\".\n",
+ convertC(checkstr), convertC(buf));
+ }
+}
+
+void DoCharTest(WCHAR *formatstr, char param, WCHAR *checkstr)
+{
+ WCHAR buf[256] = { 0 };
+
+ _snwprintf(buf, 256, formatstr, param);
+ if (memcmp(buf, checkstr, wcslen(checkstr)*2 + 2) != 0)
+ {
+ Fail("ERROR: failed to insert char \'%c\' (%d) into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n", param, param,
+ convertC(formatstr), convertC(checkstr), convertC(buf));
+ }
+}
+
+void DoWCharTest(WCHAR *formatstr, WCHAR param, WCHAR *checkstr)
+{
+ WCHAR buf[256] = { 0 };
+
+ _snwprintf(buf, 256, formatstr, param);
+ if (memcmp(buf, checkstr, wcslen(checkstr)*2 + 2) != 0)
+ {
+ Fail("ERROR: failed to insert wide char \'%c\' (%d) into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n", (char) param, param,
+ convertC(formatstr), convertC(checkstr), convertC(buf));
+ }
+}
+
+void DoNumTest(WCHAR *formatstr, int value, WCHAR*checkstr)
+{
+ WCHAR buf[256] = { 0 };
+
+ _snwprintf(buf, 256, formatstr, value);
+ if (memcmp(buf, checkstr, wcslen(checkstr)* 2 + 2) != 0)
+ {
+ Fail("ERROR: failed to insert %#x into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n", value, convertC(formatstr),
+ convertC(checkstr), convertC(buf));
+ }
+}
+
+
+void DoI64Test(WCHAR *formatstr, INT64 param, char *paramdesc,
+ WCHAR *checkstr1)
+{
+ WCHAR buf[256] = { 0 };
+
+ _snwprintf(buf, 256, formatstr, param);
+ if (memcmp(buf, checkstr1, wcslen(checkstr1)*2 + 2) != 0)
+ {
+ Fail("ERROR: failed to insert %s into \"%s\"\n"
+ "Expected \"%s\", got \"%s\".\n", paramdesc,
+ convertC(formatstr), convertC(checkstr1), convertC(buf));
+ }
+}
+
+void DoDoubleTest(WCHAR *formatstr, double value, WCHAR *checkstr1,
+ WCHAR *checkstr2)
+{
+ WCHAR buf[256] = { 0 };
+
+ _snwprintf(buf, 256, formatstr, value);
+ if (memcmp(buf, checkstr1, wcslen(checkstr1)*2 + 2) != 0 &&
+ memcmp(buf, checkstr2, wcslen(checkstr2)*2 + 2) != 0)
+ {
+ Fail("ERROR: failed to insert %f into \"%s\"\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n",
+ value, convertC(formatstr), convertC(checkstr1),
+ convertC(checkstr2), convertC(buf));
+ }
+}
+
+void DoArgumentPrecTest(WCHAR *formatstr, int precision, void *param,
+ char *paramstr, WCHAR *checkstr1, WCHAR *checkstr2)
+{
+ WCHAR buf[256];
+
+ _snwprintf(buf, 256, formatstr, precision, param);
+ if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0 &&
+ memcmp(buf, checkstr2, wcslen(checkstr2) + 2) != 0)
+ {
+ Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n",
+ paramstr, convertC(formatstr), precision,
+ convertC(checkstr1), convertC(checkstr2) ,convertC(buf));
+ }
+}
+
+void DoArgumentPrecDoubleTest(WCHAR *formatstr, int precision, double param,
+ WCHAR *checkstr)
+{
+ WCHAR buf[256];
+
+ _snwprintf(buf, 256, formatstr, precision, param);
+ if (memcmp(buf, checkstr, wcslen(checkstr) + 2) != 0)
+ {
+ Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n"
+ "Expected \"%s\", got \"%s\".\n", param, convertC(formatstr),
+ precision, convertC(checkstr), convertC(buf));
+ }
+}
+
+#endif
+
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..b4ab6d5161
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_snwprintf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snwprintf_test1 coreclrpal)
+
+target_link_libraries(paltest_snwprintf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test1/test1.c
new file mode 100644
index 0000000000..5d13aaf05d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test1/test1.c
@@ -0,0 +1,62 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: General test to see if _snwprintf works correctly
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR *checkstr;
+ WCHAR buf[256] = { 0 };
+ int ret;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ checkstr = convert("hello world");
+ _snwprintf(buf, 256, checkstr);
+ if (memcmp(checkstr, buf, wcslen(checkstr)*2+2) != 0)
+ {
+ Fail("ERROR: Expected \"%s\", got \"%s\"\n",
+ convertC(checkstr), convertC(buf));
+ }
+
+ _snwprintf(buf, 256, convert("xxxxxxxxxxxxxxxxx"));
+ ret = _snwprintf(buf, 8, checkstr);
+ if (memcmp(checkstr, buf, 16) != 0)
+ {
+ Fail("ERROR: Expected \"%8s\", got \"%8s\"\n",
+ convertC(checkstr), convertC(buf));
+ }
+ if (ret >= 0)
+ {
+ Fail("ERROR: Expected negative return value, got %d.\n", ret);
+ }
+ if (buf[8] != (WCHAR) 'x')
+ {
+ Fail("ERROR: buffer overflow using \"%s\" with length 8.\n",
+ convertC(checkstr));
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test1/testinfo.dat
new file mode 100644
index 0000000000..079a3b3989
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snwprintf
+Name = Positive Test for _snwprintf
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= General test to see if _snwprintf works correctly
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test10/CMakeLists.txt
new file mode 100644
index 0000000000..27aaca3bb9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test10/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test10.c
+)
+
+add_executable(paltest_snwprintf_test10
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snwprintf_test10 coreclrpal)
+
+target_link_libraries(paltest_snwprintf_test10
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test10/test10.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test10/test10.c
new file mode 100644
index 0000000000..e8a6d93ea3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test10/test10.c
@@ -0,0 +1,54 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test10.c
+**
+** Purpose: Tests _snwprintf with octal numbers
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest(convert("foo %o"), pos, convert("foo 52"));
+ DoNumTest(convert("foo %lo"), 0xFFFF, convert("foo 177777"));
+ DoNumTest(convert("foo %ho"), 0xFFFF, convert("foo 177777"));
+ DoNumTest(convert("foo %Lo"), pos, convert("foo 52"));
+ DoI64Test(convert("foo %I64o"), l, "42", convert("foo 52"));
+ DoNumTest(convert("foo %3o"), pos, convert("foo 52"));
+ DoNumTest(convert("foo %-3o"), pos, convert("foo 52 "));
+ DoNumTest(convert("foo %.1o"), pos, convert("foo 52"));
+ DoNumTest(convert("foo %.3o"), pos, convert("foo 052"));
+ DoNumTest(convert("foo %03o"), pos, convert("foo 052"));
+ DoNumTest(convert("foo %#o"), pos, convert("foo 052"));
+ DoNumTest(convert("foo %+o"), pos, convert("foo 52"));
+ DoNumTest(convert("foo % o"), pos, convert("foo 52"));
+ DoNumTest(convert("foo %+o"), neg, convert("foo 37777777726"));
+ DoNumTest(convert("foo % o"), neg, convert("foo 37777777726"));
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test10/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test10/testinfo.dat
new file mode 100644
index 0000000000..2c07cc6e45
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test10/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snwprintf
+Name = Positive Test for _snwprintf
+TYPE = DEFAULT
+EXE1 = test10
+Description
+= Tests _snwprintf with octal numbers
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test11/CMakeLists.txt
new file mode 100644
index 0000000000..e18ad4a31b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test11/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test11.c
+)
+
+add_executable(paltest_snwprintf_test11
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snwprintf_test11 coreclrpal)
+
+target_link_libraries(paltest_snwprintf_test11
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test11/test11.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test11/test11.c
new file mode 100644
index 0000000000..95f7f53210
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test11/test11.c
@@ -0,0 +1,54 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test11.c
+**
+** Purpose: Tests _snwprintf with unsigned numbers
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest(convert("foo %u"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %lu"), 0xFFFF, convert("foo 65535"));
+ DoNumTest(convert("foo %hu"), 0xFFFF, convert("foo 65535"));
+ DoNumTest(convert("foo %Lu"), pos, convert("foo 42"));
+ DoI64Test(convert("foo %I64u"), l, "42", convert("foo 42"));
+ DoNumTest(convert("foo %3u"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %-3u"), pos, convert("foo 42 "));
+ DoNumTest(convert("foo %.1u"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %.3u"), pos, convert("foo 042"));
+ DoNumTest(convert("foo %03u"), pos, convert("foo 042"));
+ DoNumTest(convert("foo %#u"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %+u"), pos, convert("foo 42"));
+ DoNumTest(convert("foo % u"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %+u"), neg, convert("foo 4294967254"));
+ DoNumTest(convert("foo % u"), neg, convert("foo 4294967254"));
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test11/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test11/testinfo.dat
new file mode 100644
index 0000000000..f81a7861bf
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test11/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snwprintf
+Name = Positive Test for _snwprintf
+TYPE = DEFAULT
+EXE1 = test11
+Description
+= Tests _snwprintf with unsigned numbers
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test12/CMakeLists.txt
new file mode 100644
index 0000000000..f2ae07c1b0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test12/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test12.c
+)
+
+add_executable(paltest_snwprintf_test12
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snwprintf_test12 coreclrpal)
+
+target_link_libraries(paltest_snwprintf_test12
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test12/test12.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test12/test12.c
new file mode 100644
index 0000000000..ab58fa345f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test12/test12.c
@@ -0,0 +1,54 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test12.c
+**
+** Purpose: Tests _snwprintf with hex numbers (lowercase)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 0x1234ab;
+ INT64 l = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest(convert("foo %x"), pos, convert("foo 1234ab"));
+ DoNumTest(convert("foo %lx"), pos, convert("foo 1234ab"));
+ DoNumTest(convert("foo %hx"), pos, convert("foo 34ab"));
+ DoNumTest(convert("foo %Lx"), pos, convert("foo 1234ab"));
+ DoI64Test(convert("foo %I64x"), l, "0x1234567887654321",
+ convert("foo 1234567887654321"));
+ DoNumTest(convert("foo %7x"), pos, convert("foo 1234ab"));
+ DoNumTest(convert("foo %-7x"), pos, convert("foo 1234ab "));
+ DoNumTest(convert("foo %.1x"), pos, convert("foo 1234ab"));
+ DoNumTest(convert("foo %.7x"), pos, convert("foo 01234ab"));
+ DoNumTest(convert("foo %07x"), pos, convert("foo 01234ab"));
+ DoNumTest(convert("foo %#x"), pos, convert("foo 0x1234ab"));
+ DoNumTest(convert("foo %+x"), pos, convert("foo 1234ab"));
+ DoNumTest(convert("foo % x"), pos, convert("foo 1234ab"));
+ DoNumTest(convert("foo %+x"), neg, convert("foo ffffffd6"));
+ DoNumTest(convert("foo % x"), neg, convert("foo ffffffd6"));
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test12/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test12/testinfo.dat
new file mode 100644
index 0000000000..653babae84
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test12/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snwprintf
+Name = Positive Test for _snwprintf
+TYPE = DEFAULT
+EXE1 = test12
+Description
+= Tests _snwprintf with hex numbers (lowercase)
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test13/CMakeLists.txt
new file mode 100644
index 0000000000..42847b6bcd
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test13/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test13.c
+)
+
+add_executable(paltest_snwprintf_test13
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snwprintf_test13 coreclrpal)
+
+target_link_libraries(paltest_snwprintf_test13
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test13/test13.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test13/test13.c
new file mode 100644
index 0000000000..5a3e22802d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test13/test13.c
@@ -0,0 +1,54 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test13.c
+**
+** Purpose: Tests _snwprintf with hex numbers (uppercase)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 0x1234ab;
+ INT64 l = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest(convert("foo %X"), pos, convert("foo 1234AB"));
+ DoNumTest(convert("foo %lX"), pos, convert("foo 1234AB"));
+ DoNumTest(convert("foo %hX"), pos, convert("foo 34AB"));
+ DoNumTest(convert("foo %LX"), pos, convert("foo 1234AB"));
+ DoI64Test(convert("foo %I64X"), l, "0x1234567887654321",
+ convert("foo 1234567887654321"));
+ DoNumTest(convert("foo %7X"), pos, convert("foo 1234AB"));
+ DoNumTest(convert("foo %-7X"), pos, convert("foo 1234AB "));
+ DoNumTest(convert("foo %.1X"), pos, convert("foo 1234AB"));
+ DoNumTest(convert("foo %.7X"), pos, convert("foo 01234AB"));
+ DoNumTest(convert("foo %07X"), pos, convert("foo 01234AB"));
+ DoNumTest(convert("foo %#X"), pos, convert("foo 0X1234AB"));
+ DoNumTest(convert("foo %+X"), pos, convert("foo 1234AB"));
+ DoNumTest(convert("foo % X"), pos, convert("foo 1234AB"));
+ DoNumTest(convert("foo %+X"), neg, convert("foo FFFFFFD6"));
+ DoNumTest(convert("foo % X"), neg, convert("foo FFFFFFD6"));
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test13/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test13/testinfo.dat
new file mode 100644
index 0000000000..cdeced6654
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test13/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snwprintf
+Name = Positive Test for _snwprintf
+TYPE = DEFAULT
+EXE1 = test13
+Description
+= Tests _snwprintf with hex numbers (uppercase)
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test14/CMakeLists.txt
new file mode 100644
index 0000000000..e5cdbfad87
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test14/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test14.c
+)
+
+add_executable(paltest_snwprintf_test14
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snwprintf_test14 coreclrpal)
+
+target_link_libraries(paltest_snwprintf_test14
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test14/test14.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test14/test14.c
new file mode 100644
index 0000000000..c34875246d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test14/test14.c
@@ -0,0 +1,66 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test14.c
+**
+** Purpose: Tests _snwprintf with exponential format doubles (lowercase)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 256.0;
+ double neg = -256.0;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest(convert("foo %e"), val, convert("foo 2.560000e+002"),
+ convert("foo 2.560000e+02"));
+ DoDoubleTest(convert("foo %le"), val, convert("foo 2.560000e+002"),
+ convert("foo 2.560000e+02"));
+ DoDoubleTest(convert("foo %he"), val, convert("foo 2.560000e+002"),
+ convert("foo 2.560000e+02"));
+ DoDoubleTest(convert("foo %Le"), val, convert("foo 2.560000e+002"),
+ convert("foo 2.560000e+02"));
+ DoDoubleTest(convert("foo %I64e"), val, convert("foo 2.560000e+002"),
+ convert("foo 2.560000e+02"));
+ DoDoubleTest(convert("foo %14e"), val, convert("foo 2.560000e+002"),
+ convert("foo 2.560000e+02"));
+ DoDoubleTest(convert("foo %-14e"), val, convert("foo 2.560000e+002 "),
+ convert("foo 2.560000e+02 "));
+ DoDoubleTest(convert("foo %.1e"), val, convert("foo 2.6e+002"),
+ convert("foo 2.6e+02"));
+ DoDoubleTest(convert("foo %.8e"), val, convert("foo 2.56000000e+002"),
+ convert("foo 2.56000000e+02"));
+ DoDoubleTest(convert("foo %014e"), val, convert("foo 02.560000e+002"),
+ convert("foo 002.560000e+02"));
+ DoDoubleTest(convert("foo %#e"), val, convert("foo 2.560000e+002"),
+ convert("foo 2.560000e+02"));
+ DoDoubleTest(convert("foo %+e"), val, convert("foo +2.560000e+002"),
+ convert("foo +2.560000e+02"));
+ DoDoubleTest(convert("foo % e"), val, convert("foo 2.560000e+002"),
+ convert("foo 2.560000e+02"));
+ DoDoubleTest(convert("foo %+e"), neg, convert("foo -2.560000e+002"),
+ convert("foo -2.560000e+02"));
+ DoDoubleTest(convert("foo % e"), neg, convert("foo -2.560000e+002"),
+ convert("foo -2.560000e+02"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test14/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test14/testinfo.dat
new file mode 100644
index 0000000000..b47611aa44
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test14/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snwprintf
+Name = Positive Test for _snwprintf
+TYPE = DEFAULT
+EXE1 = test14
+Description
+= Tests _snwprintf with exponential format doubles (lowercase)
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test15/CMakeLists.txt
new file mode 100644
index 0000000000..dc7b4d66e9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test15/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test15.c
+)
+
+add_executable(paltest_snwprintf_test15
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snwprintf_test15 coreclrpal)
+
+target_link_libraries(paltest_snwprintf_test15
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test15/test15.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test15/test15.c
new file mode 100644
index 0000000000..f45005b758
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test15/test15.c
@@ -0,0 +1,67 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test15.c
+**
+** Purpose: Tests _snwprintf with exponential format doubles (uppercase)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 256.0;
+ double neg = -256.0;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest(convert("foo %E"), val, convert("foo 2.560000E+002"),
+ convert("foo 2.560000E+02"));
+ DoDoubleTest(convert("foo %lE"), val, convert("foo 2.560000E+002"),
+ convert("foo 2.560000E+02"));
+ DoDoubleTest(convert("foo %hE"), val, convert("foo 2.560000E+002"),
+ convert("foo 2.560000E+02"));
+ DoDoubleTest(convert("foo %LE"), val, convert("foo 2.560000E+002"),
+ convert("foo 2.560000E+02"));
+ DoDoubleTest(convert("foo %I64E"), val, convert("foo 2.560000E+002"),
+ convert("foo 2.560000E+02"));
+ DoDoubleTest(convert("foo %14E"), val, convert("foo 2.560000E+002"),
+ convert("foo 2.560000E+02"));
+ DoDoubleTest(convert("foo %-14E"), val, convert("foo 2.560000E+002 "),
+ convert("foo 2.560000E+02 "));
+ DoDoubleTest(convert("foo %.1E"), val, convert("foo 2.6E+002"),
+ convert("foo 2.6E+02"));
+ DoDoubleTest(convert("foo %.8E"), val, convert("foo 2.56000000E+002"),
+ convert("foo 2.56000000E+02"));
+ DoDoubleTest(convert("foo %014E"), val, convert("foo 02.560000E+002"),
+ convert("foo 002.560000E+02"));
+ DoDoubleTest(convert("foo %#E"), val, convert("foo 2.560000E+002"),
+ convert("foo 2.560000E+02"));
+ DoDoubleTest(convert("foo %+E"), val, convert("foo +2.560000E+002"),
+ convert("foo +2.560000E+02"));
+ DoDoubleTest(convert("foo % E"), val, convert("foo 2.560000E+002"),
+ convert("foo 2.560000E+02"));
+ DoDoubleTest(convert("foo %+E"), neg, convert("foo -2.560000E+002"),
+ convert("foo -2.560000E+02"));
+ DoDoubleTest(convert("foo % E"), neg, convert("foo -2.560000E+002"),
+ convert("foo -2.560000E+02"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test15/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test15/testinfo.dat
new file mode 100644
index 0000000000..2c81391689
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test15/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snwprintf
+Name = Positive Test for _snwprintf
+TYPE = DEFAULT
+EXE1 = test15
+Description
+= Tests _snwprintf with exponential format doubles (uppercase)
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test16/CMakeLists.txt
new file mode 100644
index 0000000000..f147ad7e67
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test16/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test16.c
+)
+
+add_executable(paltest_snwprintf_test16
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snwprintf_test16 coreclrpal)
+
+target_link_libraries(paltest_snwprintf_test16
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test16/test16.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test16/test16.c
new file mode 100644
index 0000000000..88f55bdc10
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test16/test16.c
@@ -0,0 +1,65 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test16.c
+**
+** Purpose: Tests _snwprintf with decimal point format doubles
+**
+**
+**==========================================================================*/
+
+
+#include <palsuite.h>
+#include "../_snwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest(convert("foo %f"), val, convert("foo 2560.001000"),
+ convert("foo 2560.001000"));
+ DoDoubleTest(convert("foo %lf"), val, convert("foo 2560.001000"),
+ convert("foo 2560.001000"));
+ DoDoubleTest(convert("foo %hf"), val, convert("foo 2560.001000"),
+ convert("foo 2560.001000"));
+ DoDoubleTest(convert("foo %Lf"), val, convert("foo 2560.001000"),
+ convert("foo 2560.001000"));
+ DoDoubleTest(convert("foo %I64f"), val, convert("foo 2560.001000"),
+ convert("foo 2560.001000"));
+ DoDoubleTest(convert("foo %12f"), val, convert("foo 2560.001000"),
+ convert("foo 2560.001000"));
+ DoDoubleTest(convert("foo %-12f"), val, convert("foo 2560.001000 "),
+ convert("foo 2560.001000 "));
+ DoDoubleTest(convert("foo %.1f"), val, convert("foo 2560.0"),
+ convert("foo 2560.0"));
+ DoDoubleTest(convert("foo %.8f"), val, convert("foo 2560.00100000"),
+ convert("foo 2560.00100000"));
+ DoDoubleTest(convert("foo %012f"), val, convert("foo 02560.001000"),
+ convert("foo 02560.001000"));
+ DoDoubleTest(convert("foo %#f"), val, convert("foo 2560.001000"),
+ convert("foo 2560.001000"));
+ DoDoubleTest(convert("foo %+f"), val, convert("foo +2560.001000"),
+ convert("foo +2560.001000"));
+ DoDoubleTest(convert("foo % f"), val, convert("foo 2560.001000"),
+ convert("foo 2560.001000"));
+ DoDoubleTest(convert("foo %+f"), neg, convert("foo -2560.001000"),
+ convert("foo -2560.001000"));
+ DoDoubleTest(convert("foo % f"), neg, convert("foo -2560.001000"),
+ convert("foo -2560.001000"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test16/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test16/testinfo.dat
new file mode 100644
index 0000000000..8d844e0b18
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test16/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snwprintf
+Name = Positive Test for _snwprintf
+TYPE = DEFAULT
+EXE1 = test16
+Description
+= Tests _snwprintf with decimal point format doubles
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test17/CMakeLists.txt
new file mode 100644
index 0000000000..e40d3f4106
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test17/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test17.c
+)
+
+add_executable(paltest_snwprintf_test17
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snwprintf_test17 coreclrpal)
+
+target_link_libraries(paltest_snwprintf_test17
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test17/test17.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test17/test17.c
new file mode 100644
index 0000000000..82f2330b48
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test17/test17.c
@@ -0,0 +1,68 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test17.c
+**
+** Purpose: Tests _snwprintf with compact format doubles (lowercase)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest(convert("foo %g"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %lg"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %hg"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %Lg"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %I64g"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %5g"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %-5g"), val, convert("foo 2560 "),
+ convert("foo 2560 "));
+ DoDoubleTest(convert("foo %.1g"), val, convert("foo 3e+003"),
+ convert("foo 3e+03"));
+ DoDoubleTest(convert("foo %.2g"), val, convert("foo 2.6e+003"),
+ convert("foo 2.6e+03"));
+ DoDoubleTest(convert("foo %.12g"), val, convert("foo 2560.001"),
+ convert("foo 2560.001"));
+ DoDoubleTest(convert("foo %06g"), val, convert("foo 002560"),
+ convert("foo 002560"));
+ DoDoubleTest(convert("foo %#g"), val, convert("foo 2560.00"),
+ convert("foo 2560.00"));
+ DoDoubleTest(convert("foo %+g"), val, convert("foo +2560"),
+ convert("foo +2560"));
+ DoDoubleTest(convert("foo % g"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %+g"), neg, convert("foo -2560"),
+ convert("foo -2560"));
+ DoDoubleTest(convert("foo % g"), neg, convert("foo -2560"),
+ convert("foo -2560"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test17/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test17/testinfo.dat
new file mode 100644
index 0000000000..6b01fb3d7d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test17/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snwprintf
+Name = Positive Test for _snwprintf
+TYPE = DEFAULT
+EXE1 = test17
+Description
+= Tests _snwprintf with compact format doubles (lowercase)
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test18/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test18/CMakeLists.txt
new file mode 100644
index 0000000000..68a014cb66
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test18/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test18.c
+)
+
+add_executable(paltest_snwprintf_test18
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snwprintf_test18 coreclrpal)
+
+target_link_libraries(paltest_snwprintf_test18
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test18/test18.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test18/test18.c
new file mode 100644
index 0000000000..dbb6233061
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test18/test18.c
@@ -0,0 +1,69 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test18.c
+**
+** Purpose: Tests _snwprintf with compact format doubles (uppercase)
+**
+**
+**==========================================================================*/
+
+
+
+
+#include <palsuite.h>
+#include "../_snwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest(convert("foo %G"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %lG"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %hG"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %LG"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %I64G"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %5G"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %-5G"), val, convert("foo 2560 "),
+ convert("foo 2560 "));
+ DoDoubleTest(convert("foo %.1G"), val, convert("foo 3E+003"),
+ convert("foo 3E+03"));
+ DoDoubleTest(convert("foo %.2G"), val, convert("foo 2.6E+003"),
+ convert("foo 2.6E+03"));
+ DoDoubleTest(convert("foo %.12G"), val, convert("foo 2560.001"),
+ convert("foo 2560.001"));
+ DoDoubleTest(convert("foo %06G"), val, convert("foo 002560"),
+ convert("foo 002560"));
+ DoDoubleTest(convert("foo %#G"), val, convert("foo 2560.00"),
+ convert("foo 2560.00"));
+ DoDoubleTest(convert("foo %+G"), val, convert("foo +2560"),
+ convert("foo +2560"));
+ DoDoubleTest(convert("foo % G"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %+G"), neg, convert("foo -2560"),
+ convert("foo -2560"));
+ DoDoubleTest(convert("foo % G"), neg, convert("foo -2560"),
+ convert("foo -2560"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test18/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test18/testinfo.dat
new file mode 100644
index 0000000000..480087f560
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test18/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snwprintf
+Name = Positive Test for _snwprintf
+TYPE = DEFAULT
+EXE1 = test18
+Description
+= Tests _snwprintf with compact format doubles (uppercase)
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test19/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test19/CMakeLists.txt
new file mode 100644
index 0000000000..6dc30b4d33
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test19/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test19.c
+)
+
+add_executable(paltest_snwprintf_test19
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snwprintf_test19 coreclrpal)
+
+target_link_libraries(paltest_snwprintf_test19
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test19/test19.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test19/test19.c
new file mode 100644
index 0000000000..efb222c6ba
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test19/test19.c
@@ -0,0 +1,90 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test19.c
+**
+** Purpose: Tests _snwprintf with argument specified precision
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snwprintf.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+ int n = -1;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ DoArgumentPrecTest(convert("%.*s"), 2, convert("bar"), "bar",
+ convert("ba"), convert("ba"));
+ DoArgumentPrecTest(convert("%.*S"), 2, "bar", "bar",
+ convert("ba"), convert("ba"));
+ DoArgumentPrecTest(convert("%.*n"), 3, &n, "pointer to int",
+ convert(""), convert(""));
+ if (n != 0)
+ {
+ Fail("ERROR: Expected count parameter to resolve to %d, got %X\n",
+ 0, n);
+ }
+
+ DoArgumentPrecTest(convert("%.*c"), 0, (void*)'a', "a",
+ convert("a"), convert("a"));
+ DoArgumentPrecTest(convert("%.*c"), 4, (void*)'a', "a",
+ convert("a"), convert("a"));
+ DoArgumentPrecTest(convert("%.*C"), 0, (void*)'a', "a",
+ convert("a"), convert("a"));
+ DoArgumentPrecTest(convert("%.*C"), 4, (void*)'a', "a",
+ convert("a"), convert("a"));
+ DoArgumentPrecTest(convert("%.*d"), 1, (void*)42, "42",
+ convert("42"), convert("42"));
+ DoArgumentPrecTest(convert("%.*d"), 3, (void*)42, "42",
+ convert("042"), convert("042"));
+ DoArgumentPrecTest(convert("%.*i"), 1, (void*)42, "42",
+ convert("42"), convert("42"));
+ DoArgumentPrecTest(convert("%.*i"), 3, (void*)42, "42",
+ convert("042"), convert("042"));
+ DoArgumentPrecTest(convert("%.*o"), 1, (void*)42, "42",
+ convert("52"), convert("52"));
+ DoArgumentPrecTest(convert("%.*o"), 3, (void*)42, "42",
+ convert("052"), convert("052"));
+ DoArgumentPrecTest(convert("%.*u"), 1, (void*)42, "42",
+ convert("42"), convert("42"));
+ DoArgumentPrecTest(convert("%.*u"), 3, (void*)42, "42",
+ convert("042"), convert("042"));
+ DoArgumentPrecTest(convert("%.*x"), 1, (void*)0x42, "0x42",
+ convert("42"), convert("42"));
+ DoArgumentPrecTest(convert("%.*x"), 3, (void*)0x42, "0x42",
+ convert("042"), convert("042"));
+ DoArgumentPrecTest(convert("%.*X"), 1, (void*)0x42, "0x42",
+ convert("42"), convert("42"));
+ DoArgumentPrecTest(convert("%.*X"), 3, (void*)0x42, "0x42",
+ convert("042"), convert("042"));
+ DoArgumentPrecDoubleTest(convert("%.*e"), 1, 2.01, convert("2.0e+000"));
+ DoArgumentPrecDoubleTest(convert("%.*e"), 3, 2.01, convert("2.010e+000"));
+ DoArgumentPrecDoubleTest(convert("%.*E"), 1, 2.01, convert("2.0E+000"));
+ DoArgumentPrecDoubleTest(convert("%.*E"), 3, 2.01, convert("2.010E+000"));
+ DoArgumentPrecDoubleTest(convert("%.*f"), 1, 2.01, convert("2.0"));
+ DoArgumentPrecDoubleTest(convert("%.*f"), 3, 2.01, convert("2.010"));
+ DoArgumentPrecDoubleTest(convert("%.*g"), 1, 256.01, convert("3e+002"));
+ DoArgumentPrecDoubleTest(convert("%.*g"), 3, 256.01, convert("256"));
+ DoArgumentPrecDoubleTest(convert("%.*g"), 4, 256.01, convert("256"));
+ DoArgumentPrecDoubleTest(convert("%.*g"), 6, 256.01, convert("256.01"));
+ DoArgumentPrecDoubleTest(convert("%.*G"), 1, 256.01, convert("3E+002"));
+ DoArgumentPrecDoubleTest(convert("%.*G"), 3, 256.01, convert("256"));
+ DoArgumentPrecDoubleTest(convert("%.*G"), 4, 256.01, convert("256"));
+ DoArgumentPrecDoubleTest(convert("%.*G"), 6, 256.01, convert("256.01"));
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test19/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test19/testinfo.dat
new file mode 100644
index 0000000000..376cbc84d1
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test19/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snwprintf
+Name = Positive Test for _snwprintf
+TYPE = DEFAULT
+EXE1 = test19
+Description
+= Tests _snwprintf with argument specified precision
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test2/CMakeLists.txt
new file mode 100644
index 0000000000..9e0d950885
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_snwprintf_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snwprintf_test2 coreclrpal)
+
+target_link_libraries(paltest_snwprintf_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test2/test2.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test2/test2.c
new file mode 100644
index 0000000000..974b7967f2
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test2/test2.c
@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test2.c
+**
+** Purpose:Tests _snwprintf with strings
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ DoWStrTest(convert("foo %s"), convert("bar"), convert("foo bar"));
+ DoStrTest(convert("foo %hs"), "bar", convert("foo bar"));
+ DoWStrTest(convert("foo %ls"), convert("bar"), convert("foo bar"));
+ DoWStrTest(convert("foo %ws"), convert("bar"), convert("foo bar"));
+ DoWStrTest(convert("foo %Ls"), convert("bar"), convert("foo bar"));
+ DoWStrTest(convert("foo %I64s"), convert("bar"), convert("foo bar"));
+ DoWStrTest(convert("foo %5s"), convert("bar"), convert("foo bar"));
+ DoWStrTest(convert("foo %.2s"), convert("bar"), convert("foo ba"));
+ DoWStrTest(convert("foo %5.2s"), convert("bar"), convert("foo ba"));
+ DoWStrTest(convert("foo %-5s"), convert("bar"), convert("foo bar "));
+ DoWStrTest(convert("foo %05s"), convert("bar"), convert("foo 00bar"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test2/testinfo.dat
new file mode 100644
index 0000000000..9c65c93e5a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test2/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snwprintf
+Name = Positive Test for _snwprintf
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Tests _snwprintf with strings
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test3/CMakeLists.txt
new file mode 100644
index 0000000000..4d5a28b0fe
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_snwprintf_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snwprintf_test3 coreclrpal)
+
+target_link_libraries(paltest_snwprintf_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test3/test3.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test3/test3.c
new file mode 100644
index 0000000000..bfb75ce323
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test3/test3.c
@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test3.c
+**
+** Purpose: Tests _snwprintf with wide strings
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ DoStrTest(convert("foo %S"), "bar", convert("foo bar"));
+ DoStrTest(convert("foo %hS"), "bar", convert("foo bar"));
+ DoWStrTest(convert("foo %lS"), convert("bar"), convert("foo bar"));
+ DoWStrTest(convert("foo %wS"), convert("bar"), convert("foo bar"));
+ DoStrTest(convert("foo %LS"), "bar", convert("foo bar"));
+ DoStrTest(convert("foo %I64S"), "bar", convert("foo bar"));
+ DoStrTest(convert("foo %5S"), "bar", convert("foo bar"));
+ DoStrTest(convert("foo %.2S"), "bar", convert("foo ba"));
+ DoStrTest(convert("foo %5.2S"), "bar", convert("foo ba"));
+ DoStrTest(convert("foo %-5S"), "bar", convert("foo bar "));
+ DoStrTest(convert("foo %05S"), "bar", convert("foo 00bar"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test3/testinfo.dat
new file mode 100644
index 0000000000..b39f4f56b7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test3/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snwprintf
+Name = Positive Test for _snwprintf
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Tests _snwprintf with wide strings
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test4/CMakeLists.txt
new file mode 100644
index 0000000000..0102b0acea
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_snwprintf_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snwprintf_test4 coreclrpal)
+
+target_link_libraries(paltest_snwprintf_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test4/test4.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test4/test4.c
new file mode 100644
index 0000000000..28f7998591
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test4/test4.c
@@ -0,0 +1,71 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test4.c
+**
+** Purpose: Tests _snwprintf with pointers
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ void *ptr = (void*) 0x123456;
+ INT64 lptr = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+/*
+** Run only on 64 bit platforms
+*/
+#if defined(BIT64) && defined(PLATFORM_UNIX)
+ Trace("Testing for 64 Bit Platforms \n");
+ DoPointerTest(convert("%p"), NULL, convert("0000000000000000"));
+ DoPointerTest(convert("%p"), ptr, convert("0000000000123456"));
+ DoPointerTest(convert("%17p"), ptr, convert(" 0000000000123456"));
+ DoPointerTest(convert("%17p"), ptr, convert(" 0000000000123456"));
+ DoPointerTest(convert("%-17p"), ptr, convert("0000000000123456 "));
+ DoPointerTest(convert("%+p"), ptr, convert("0000000000123456"));
+ DoPointerTest(convert("% p"), ptr, convert("0000000000123456"));
+ DoPointerTest(convert("%#p"), ptr, convert("0X0000000000123456"));
+ DoPointerTest(convert("%lp"), ptr, convert("00123456"));
+ DoPointerTest(convert("%hp"), ptr, convert("00003456"));
+ DoPointerTest(convert("%Lp"), ptr, convert("00123456"));
+ DoI64Test(convert("%I64p"), lptr, "1234567887654321",
+ convert("1234567887654321"));
+#else
+ Trace("Testing for Non 64 Bit Platforms \n");
+ DoPointerTest(convert("%p"), NULL, convert("00000000"));
+ DoPointerTest(convert("%p"), ptr, convert("00123456"));
+ DoPointerTest(convert("%9p"), ptr, convert(" 00123456"));
+ DoPointerTest(convert("%09p"), ptr, convert(" 00123456"));
+ DoPointerTest(convert("%-9p"), ptr, convert("00123456 "));
+ DoPointerTest(convert("%+p"), ptr, convert("00123456"));
+ DoPointerTest(convert("% p"), ptr, convert("00123456"));
+ DoPointerTest(convert("%#p"), ptr, convert("0X00123456"));
+ DoPointerTest(convert("%lp"), ptr, convert("00123456"));
+ DoPointerTest(convert("%hp"), ptr, convert("00003456"));
+ DoPointerTest(convert("%Lp"), ptr, convert("00123456"));
+ DoI64Test(convert("%I64p"), lptr, "1234567887654321",
+ convert("1234567887654321"));
+#endif
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test4/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test4/testinfo.dat
new file mode 100644
index 0000000000..3f3600160f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test4/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snwprintf
+Name = Positive Test for _snwprintf
+TYPE = DEFAULT
+EXE1 = test4
+Description
+= Tests _snwprintf with pointers
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test5/CMakeLists.txt
new file mode 100644
index 0000000000..c835c94845
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test5.c
+)
+
+add_executable(paltest_snwprintf_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snwprintf_test5 coreclrpal)
+
+target_link_libraries(paltest_snwprintf_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test5/test5.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test5/test5.c
new file mode 100644
index 0000000000..bbe459751b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test5/test5.c
@@ -0,0 +1,63 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test5.c
+**
+** Purpose: Tests _snwprintf with the count specifier
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR *longStr;
+ WCHAR *longResult;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ longStr = convert("really-long-string-that-just-keeps-going-on-and-on-and-on.."
+ "..................useless-filler.................................."
+ "..................useless-filler.................................."
+ "..................useless-filler.................................."
+ "%n bar");
+ longResult = convert("really-long-string-that-just-keeps-going-on-and-on-and-on.."
+ "..................useless-filler.................................."
+ "..................useless-filler.................................."
+ "..................useless-filler.................................."
+ " bar");
+ DoCountTest(convert("foo %n bar"), 4, convert("foo bar"));
+ DoCountTest(longStr, 257, longResult);
+ DoCountTest(convert("fo%n bar"), 2, convert("fo bar"));
+ DoCountTest(convert("%n"), 0, convert(""));
+ DoCountTest(convert("foo %#n bar"), 4, convert("foo bar"));
+ DoCountTest(convert("foo % n bar"), 4, convert("foo bar"));
+ DoCountTest(convert("foo %+n bar"), 4, convert("foo bar"));
+ DoCountTest(convert("foo %-n bar"), 4, convert("foo bar"));
+ DoCountTest(convert("foo %0n bar"), 4, convert("foo bar"));
+ DoShortCountTest(convert("foo %hn bar"), 4, convert("foo bar"));
+ DoCountTest(convert("foo %ln bar"), 4, convert("foo bar"));
+ DoCountTest(convert("foo %Ln bar"), 4, convert("foo bar"));
+ DoCountTest(convert("foo %I64n bar"), 4, convert("foo bar"));
+ DoCountTest(convert("foo %20.3n bar"), 4, convert("foo bar"));
+
+ free(longStr);
+ free(longResult);
+
+ PAL_Terminate();
+
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test5/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test5/testinfo.dat
new file mode 100644
index 0000000000..2180b81cf5
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test5/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snwprintf
+Name = Positive Test for _snwprintf
+TYPE = DEFAULT
+EXE1 = test5
+Description
+= Tests _snwprintf with the count specifier
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test6/CMakeLists.txt
new file mode 100644
index 0000000000..37a415ed86
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test6.c
+)
+
+add_executable(paltest_snwprintf_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snwprintf_test6 coreclrpal)
+
+target_link_libraries(paltest_snwprintf_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test6/test6.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test6/test6.c
new file mode 100644
index 0000000000..3d4ed3f882
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test6/test6.c
@@ -0,0 +1,46 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test6.c
+**
+** Purpose: Tests _snwprintf with characters
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR wc = (WCHAR) 'c';
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoWCharTest(convert("foo %c"), wc, convert("foo c"));
+ DoCharTest(convert("foo %hc"), 'b', convert("foo b"));
+ DoWCharTest(convert("foo %lc"), wc, convert("foo c"));
+ DoWCharTest(convert("foo %Lc"), wc, convert("foo c"));
+ DoWCharTest(convert("foo %I64c"), wc, convert("foo c"));
+ DoWCharTest(convert("foo %5c"), wc, convert("foo c"));
+ DoWCharTest(convert("foo %.0c"), wc, convert("foo c"));
+ DoWCharTest(convert("foo %-5c"), wc, convert("foo c "));
+ DoWCharTest(convert("foo %05c"), wc, convert("foo 0000c"));
+ DoWCharTest(convert("foo % c"), wc, convert("foo c"));
+ DoWCharTest(convert("foo %#c"), wc, convert("foo c"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test6/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test6/testinfo.dat
new file mode 100644
index 0000000000..6a170cd549
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test6/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snwprintf
+Name = Positive Test for _snwprintf
+TYPE = DEFAULT
+EXE1 = test6
+Description
+= Tests _snwprintf with characters
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test7/CMakeLists.txt
new file mode 100644
index 0000000000..b1a07eeaa4
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test7/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test7.c
+)
+
+add_executable(paltest_snwprintf_test7
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snwprintf_test7 coreclrpal)
+
+target_link_libraries(paltest_snwprintf_test7
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test7/test7.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test7/test7.c
new file mode 100644
index 0000000000..7954ff71ca
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test7/test7.c
@@ -0,0 +1,46 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test7.c
+**
+** Purpose: Tests _snwprintf with wide characters
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR wc = (WCHAR) 'c';
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoCharTest(convert("foo %C"), 'b', convert("foo b"));
+ DoWCharTest(convert("foo %hC"), wc, convert("foo c"));
+ DoCharTest(convert("foo %lC"), 'b', convert("foo b"));
+ DoCharTest(convert("foo %LC"), 'b', convert("foo b"));
+ DoCharTest(convert("foo %I64C"), 'b', convert("foo b"));
+ DoCharTest(convert("foo %5C"), 'b', convert("foo b"));
+ DoCharTest(convert("foo %.0C"), 'b', convert("foo b"));
+ DoCharTest(convert("foo %-5C"), 'b', convert("foo b "));
+ DoCharTest(convert("foo %05C"), 'b', convert("foo 0000b"));
+ DoCharTest(convert("foo % C"), 'b', convert("foo b"));
+ DoCharTest(convert("foo %#C"), 'b', convert("foo b"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test7/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test7/testinfo.dat
new file mode 100644
index 0000000000..5749539e3f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test7/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snwprintf
+Name = Positive Test for _snwprintf
+TYPE = DEFAULT
+EXE1 = test7
+Description
+= Tests _snwprintf with wide characters
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test8/CMakeLists.txt
new file mode 100644
index 0000000000..063ee2b9b6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test8/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test8.c
+)
+
+add_executable(paltest_snwprintf_test8
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snwprintf_test8 coreclrpal)
+
+target_link_libraries(paltest_snwprintf_test8
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test8/test8.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test8/test8.c
new file mode 100644
index 0000000000..91c2820076
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test8/test8.c
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test8.c
+**
+** Purpose: Tests _snwprintf with decimal numbers
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest(convert("foo %d"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %ld"), 0xFFFF, convert("foo 65535"));
+ DoNumTest(convert("foo %hd"), 0xFFFF, convert("foo -1"));
+ DoNumTest(convert("foo %Ld"), pos, convert("foo 42"));
+ DoI64Test(convert("foo %I64d"), l, "42", convert("foo 42"));
+ DoNumTest(convert("foo %3d"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %-3d"), pos, convert("foo 42 "));
+ DoNumTest(convert("foo %.1d"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %.3d"), pos, convert("foo 042"));
+ DoNumTest(convert("foo %03d"), pos, convert("foo 042"));
+ DoNumTest(convert("foo %#d"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %+d"), pos, convert("foo +42"));
+ DoNumTest(convert("foo % d"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %+d"), neg, convert("foo -42"));
+ DoNumTest(convert("foo % d"), neg, convert("foo -42"));
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test8/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test8/testinfo.dat
new file mode 100644
index 0000000000..6398f60183
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test8/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snwprintf
+Name = Positive Test for _snwprintf
+TYPE = DEFAULT
+EXE1 = test8
+Description
+= Tests _snwprintf with decimal numbers
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test9/CMakeLists.txt
new file mode 100644
index 0000000000..8d5e41131d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test9/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test9.c
+)
+
+add_executable(paltest_snwprintf_test9
+ ${SOURCES}
+)
+
+add_dependencies(paltest_snwprintf_test9 coreclrpal)
+
+target_link_libraries(paltest_snwprintf_test9
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test9/test9.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test9/test9.c
new file mode 100644
index 0000000000..f8f994fdcc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test9/test9.c
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test9.c
+**
+** Purpose: Tests _snwprintf with integer numbers
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../_snwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest(convert("foo %i"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %li"), 0xFFFF, convert("foo 65535"));
+ DoNumTest(convert("foo %hi"), 0xFFFF, convert("foo -1"));
+ DoNumTest(convert("foo %Li"), pos, convert("foo 42"));
+ DoI64Test(convert("foo %I64i"), l, "42", convert("foo 42"));
+ DoNumTest(convert("foo %3i"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %-3i"), pos, convert("foo 42 "));
+ DoNumTest(convert("foo %.1i"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %.3i"), pos, convert("foo 042"));
+ DoNumTest(convert("foo %03i"), pos, convert("foo 042"));
+ DoNumTest(convert("foo %#i"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %+i"), pos, convert("foo +42"));
+ DoNumTest(convert("foo % i"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %+i"), neg, convert("foo -42"));
+ DoNumTest(convert("foo % i"), neg, convert("foo -42"));
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test9/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test9/testinfo.dat
new file mode 100644
index 0000000000..287de4a9e9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_snwprintf/test9/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _snwprintf
+Name = Positive Test for _snwprintf
+TYPE = DEFAULT
+EXE1 = test9
+Description
+= Tests _snwprintf with integer numbers
diff --git a/src/pal/tests/palsuite/c_runtime/_splitpath/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_splitpath/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_splitpath/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_splitpath/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_splitpath/test1/CMakeLists.txt
new file mode 100644
index 0000000000..361b9084d7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_splitpath/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_splitpath_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_splitpath_test1 coreclrpal)
+
+target_link_libraries(paltest_splitpath_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_splitpath/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_splitpath/test1/test1.c
new file mode 100644
index 0000000000..e98354c2ee
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_splitpath/test1/test1.c
@@ -0,0 +1,108 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Passes _splitpath() a series of sample paths and checks that it
+** parses them as expected.
+**
+**
+**==========================================================================*/
+
+
+#include <palsuite.h>
+
+struct testCase
+{
+ const char path[_MAX_PATH]; /* The path to parse. */
+ const char drive[_MAX_DRIVE]; /* The expected values... */
+ const char dir[_MAX_DIR];
+ const char fname[_MAX_FNAME];
+ const char ext[_MAX_EXT];
+};
+
+
+int __cdecl main(int argc, char **argv)
+{
+ struct testCase testCases[] =
+ {
+#if WIN32
+ {"c:\\foo\\bar\\foo.bar", "c:", "\\foo\\bar\\", "foo", ".bar"},
+ {"c:/foo/bar/foo.bar", "c:", "/foo/bar/", "foo", ".bar"},
+ {"c:/foo/bar/foo", "c:", "/foo/bar/", "foo", ""},
+ {"c:/foo/bar/.bar", "c:", "/foo/bar/", "", ".bar"},
+ {"c:/foo/bar/", "c:", "/foo/bar/", "", ""},
+ {"/foo/bar/foo.bar", "", "/foo/bar/", "foo", ".bar"},
+ {"c:foo.bar", "c:", "", "foo", ".bar"}
+#else
+ {"c:\\foo\\bar\\foo.bar", "","c:/foo/bar/", "foo", ".bar"},
+ {"c:/foo/bar/foo.bar", "", "c:/foo/bar/", "foo", ".bar"},
+ {"c:/foo/bar/foo", "", "c:/foo/bar/", "foo", ""},
+ {"c:/foo/bar/.bar", "", "c:/foo/bar/", ".bar", ""},
+ {"c:/foo/bar/", "", "c:/foo/bar/", "", ""},
+ {"/foo/bar/foo.bar", "", "/foo/bar/", "foo", ".bar"},
+ {"c:foo.bar", "", "", "c:foo", ".bar"}
+#endif
+ };
+ char drive[_MAX_DRIVE];
+ char dir[_MAX_DIR];
+ char fname[_MAX_FNAME];
+ char ext[_MAX_EXT];
+
+ int i=0;
+
+ /*
+ * Initialize the PAL and return FAIL if this fails
+ */
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ for (i = 0; i < sizeof(testCases)/sizeof(struct testCase); i++)
+ {
+ _splitpath(testCases[i].path, drive, dir, fname, ext);
+
+
+ /*on platforms that don't support drive letters, the drive
+ returned should always be "" */
+ if (strcmp(drive, testCases[i].drive) != 0)
+ {
+ Fail("_splitpath read the path \"%s\" and thought the drive was "
+ "\"%s\" instead of \"%s\"\n"
+ , testCases[i].path, drive, testCases[i].drive);
+ }
+
+ if (strcmp(dir, testCases[i].dir) != 0)
+ {
+ Fail("_splitpath read the path \"%s\" and thought the directory "
+ "was \"%s\" instead of \"%s\"\n"
+ , testCases[i].path, dir, testCases[i].dir);
+ }
+
+ if (strcmp(fname, testCases[i].fname) != 0)
+ {
+ Fail("_splitpath read the path \"%s\" and thought the filename "
+ "was \"%s\" instead of \"%s\"\n"
+ , testCases[i].path, fname, testCases[i].fname);
+ }
+
+ if (strcmp(ext, testCases[i].ext) != 0)
+ {
+ Fail("_splitpath read the path \"%s\" and thought the file "
+ "extension was \"%s\" instead of \"%s\"\n"
+ , testCases[i].path, ext, testCases[i].ext);
+ }
+ }
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/_splitpath/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_splitpath/test1/testinfo.dat
new file mode 100644
index 0000000000..0a93e27456
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_splitpath/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _splitpath
+Name = Positive Test for _splitpath
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes _splitpath() a series of sample paths and checks that it
+= parses them as expected.
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/_stricmp/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_stricmp/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_stricmp/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_stricmp/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_stricmp/test1/CMakeLists.txt
new file mode 100644
index 0000000000..766660ccfc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_stricmp/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_stricmp_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_stricmp_test1 coreclrpal)
+
+target_link_libraries(paltest_stricmp_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_stricmp/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_stricmp/test1/test1.c
new file mode 100644
index 0000000000..60e2f9eb8b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_stricmp/test1/test1.c
@@ -0,0 +1,70 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Do a lower case compare. Check two strings, only different
+** because they have different capitalization, and they should return 0. Try
+** two strings which will return less than 0 (one is smaller than the other).
+** Also try the opposite, to get a return value greater than 0.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+/*
+ * Note: The _stricmp is dependent on the LC_CTYPE category of the locale,
+ * and this is ignored by these tests.
+ */
+int __cdecl main(int argc, char *argv[])
+{
+ char *str1 = "foo";
+ char *str2 = "fOo";
+ char *str3 = "foo_bar";
+ char *str4 = "foobar";
+
+ /*
+ * Initialize the PAL and return FAIL if this fails
+ */
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ if (_stricmp(str1, str2) != 0)
+ {
+ Fail ("ERROR: _stricmp returning incorrect value:\n"
+ "_stricmp(\"%s\", \"%s\") != 0\n", str1, str2);
+ }
+
+ if (_stricmp(str2, str3) >= 0)
+ {
+ Fail ("ERROR: _stricmp returning incorrect value:\n"
+ "_stricmp(\"%s\", \"%s\") >= 0\n", str2, str3);
+ }
+
+ if (_stricmp(str3, str4) >= 0)
+ {
+ Fail ("ERROR: _stricmp returning incorrect value:\n"
+ "_stricmp(\"%s\", \"%s\") >= 0\n", str3, str4);
+ }
+
+ if (_stricmp(str4, str1) <= 0)
+ {
+ Fail ("ERROR: _stricmp returning incorrect value:\n"
+ "_stricmp(\"%s\", \"%s\") <= 0\n", str4, str1);
+ }
+
+ if (_stricmp(str3, str2) <= 0)
+ {
+ Fail ("ERROR: _stricmp returning incorrect value:\n"
+ "_stricmp(\"%s\", \"%s\") <= 0\n", str2, str3);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_stricmp/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_stricmp/test1/testinfo.dat
new file mode 100644
index 0000000000..89d4e0f57b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_stricmp/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _stricmp
+Name = Positive Test for _stricmp
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Do a lower case compare. Check two strings, only different because they
+= have different capitalization, and they should return 0. Try two strings
+= which will return less than 0 (one is smaller than the other). Also try
+= the opposite, to get a return value greater than 0.
diff --git a/src/pal/tests/palsuite/c_runtime/_strlwr/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_strlwr/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_strlwr/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_strlwr/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_strlwr/test1/CMakeLists.txt
new file mode 100644
index 0000000000..3a9394ca60
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_strlwr/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_strlwr_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_strlwr_test1 coreclrpal)
+
+target_link_libraries(paltest_strlwr_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_strlwr/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_strlwr/test1/test1.c
new file mode 100644
index 0000000000..1c4015e3e2
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_strlwr/test1/test1.c
@@ -0,0 +1,42 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose:
+** Using memcmp, check to see that after changing a string into all lowercase
+** that it is the lowercase string that was expected.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ char string[] = "aASdff";
+ char checkstr[] = "aasdff";
+ char *ret=NULL;
+
+ /*
+ * Initialize the PAL and return FAIL if this fails
+ */
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ ret = _strlwr(string);
+
+ if (memcmp(ret, checkstr, sizeof(checkstr)) != 0)
+ {
+ Fail ("ERROR: _strlwr returning incorrect value\n"
+ "Expected %s, got %s\n", checkstr, ret);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_strlwr/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_strlwr/test1/testinfo.dat
new file mode 100644
index 0000000000..4c2a1ad558
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_strlwr/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _strlwr
+Name = Positive Test for _strlwr
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Using memcmp, check to see that after changing a string into all lowercase
+= that it is the lowercase string that was expected.
diff --git a/src/pal/tests/palsuite/c_runtime/_strnicmp/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_strnicmp/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_strnicmp/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_strnicmp/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_strnicmp/test1/CMakeLists.txt
new file mode 100644
index 0000000000..6a38747592
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_strnicmp/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_strnicmp_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_strnicmp_test1 coreclrpal)
+
+target_link_libraries(paltest_strnicmp_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_strnicmp/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_strnicmp/test1/test1.c
new file mode 100644
index 0000000000..3c915dc621
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_strnicmp/test1/test1.c
@@ -0,0 +1,85 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test #1 for the _strnicmp function
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ char str1[] = "foo";
+ char str2[] = "foox";
+ char str3[] = "fOo";
+ char str4[] = "ABCDE";
+ char str5[] = "ABCD[";
+ char str6[] = "abcde";
+ char str7[] = "abcd^";
+
+ /*
+ * Initialize the PAL and return FAIL if this fails
+ */
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ if (_strnicmp(str1, str2, strlen(str2)) >= 0)
+ {
+ Fail ("ERROR: _strnicmp(\"%s\", \"%s\", %d) returned >= 0\n",
+ str1, str2, strlen(str2));
+ }
+
+ if (_strnicmp(str2, str1, strlen(str2)) <= 0)
+ {
+ Fail ("ERROR: _strnicmp(\"%s\", \"%s\", %d) returned <= 0\n",
+ str2, str1, strlen(str2));
+ }
+
+ if (_strnicmp(str1, str2, strlen(str1)) != 0)
+ {
+ Fail ("ERROR: _strnicmp(\"%s\", \"%s\", %d) returned != 0\n",
+ str1, str2, strlen(str1));
+ }
+
+ if (_strnicmp(str1, str3, strlen(str1)) != 0)
+ {
+ Fail ("ERROR: _strnicmp(\"%s\", \"%s\", %d) returned != 0\n",
+ str1, str3, strlen(str3));
+ }
+
+ if (_strnicmp(str3, str1, strlen(str1)) != 0)
+ {
+ Fail ("ERROR: _strnicmp(\"%s\", \"%s\", %d) returned != 0\n",
+ str3, str1, strlen(str1));
+ }
+
+ /* new testing */
+
+ /* str4 should be greater than str5 */
+ if (_strnicmp(str4, str5, strlen(str4)) <= 0)
+ {
+ Fail ("ERROR: _strnicmp(\"%s\", \"%s\", %d) returned >= 0\n",
+ str4, str5, strlen(str4));
+ }
+
+ /* str6 should be greater than str7 */
+ if (_strnicmp(str6, str7, strlen(str6)) <= 0)
+ {
+ Fail ("ERROR: _strnicmp(\"%s\", \"%s\", %d) returned <= 0\n",
+ str6, str7, strlen(str6));
+ }
+
+
+ PAL_Terminate();
+
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_strnicmp/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_strnicmp/test1/testinfo.dat
new file mode 100644
index 0000000000..86744c04df
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_strnicmp/test1/testinfo.dat
@@ -0,0 +1,18 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _strnicmp
+Name = Test #1 for _strnicmp
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Take two strings and compare them, giving different lengths.
+= Comparing str1 and str2 with str2 length, should return <0
+= Comparing str2 and str1 with str2 length, should return >0
+= Comparing str1 and str2 with str1 lenght, should return 0
+= Bring in str3, which has a capital, but this function is doing a lower
+= case compare. Just ensure that two strings which differ only by capitals
+= return 0.
diff --git a/src/pal/tests/palsuite/c_runtime/_swab/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_swab/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_swab/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_swab/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_swab/test1/CMakeLists.txt
new file mode 100644
index 0000000000..fc7fbef8b4
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_swab/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_swab_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swab_test1 coreclrpal)
+
+target_link_libraries(paltest_swab_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_swab/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_swab/test1/test1.c
new file mode 100644
index 0000000000..203e3b3a06
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_swab/test1/test1.c
@@ -0,0 +1,45 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Calls _swab on a buffer, and checks that it has correctly
+** swapped adjacent bytes
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ char before[] = "abcdefghijklmn";
+ char after[] = "--------------";
+ const char check[] = "badcfehgjilknm";
+
+ /*
+ * Initialize the PAL and return FAIL if this fails
+ */
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ _swab(before, after, sizeof(before));
+ if (memcmp(after, check, sizeof(after)) != 0)
+ {
+ Fail ("_swab did not correctly swap adjacent bytes in a buffer.\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/_swab/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_swab/test1/testinfo.dat
new file mode 100644
index 0000000000..c59b017762
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_swab/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _swab
+Name = Positive Test for _swab
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Calls _swab on a buffer, and checks that it has correctly swapped
+= adjacent bytes
+
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/CMakeLists.txt
new file mode 100644
index 0000000000..cafb9536b0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/CMakeLists.txt
@@ -0,0 +1,22 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test10)
+add_subdirectory(test11)
+add_subdirectory(test12)
+add_subdirectory(test13)
+add_subdirectory(test14)
+add_subdirectory(test15)
+add_subdirectory(test16)
+add_subdirectory(test17)
+add_subdirectory(test18)
+add_subdirectory(test19)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+add_subdirectory(test7)
+add_subdirectory(test8)
+add_subdirectory(test9)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/_vsnprintf.h b/src/pal/tests/palsuite/c_runtime/_vsnprintf/_vsnprintf.h
new file mode 100644
index 0000000000..240a72f017
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/_vsnprintf.h
@@ -0,0 +1,124 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: _vsnprintf.h
+**
+** Purpose: Contains common testing functions for _vsnprintf
+**
+**
+**==========================================================================*/
+
+#ifndef __STRINGTEST_H__
+#define __STRINGTEST_H__
+
+/* These functions leaks memory like crazy. C'est la vie. */
+int Testvsnprintf(char* buf, size_t count, const char* format, ...)
+{
+ int retVal;
+ va_list arglist;
+
+ va_start(arglist, format);
+ retVal = _vsnprintf(buf, count, format, arglist);
+ va_end(arglist);
+
+ return (retVal);
+}
+
+
+void DoStrTest(char *formatstr, char* param, char *checkstr)
+{
+ char buf[256] = { 0 };
+
+ Testvsnprintf(buf, 256, formatstr, param);
+ if (memcmp(buf, checkstr, strlen(buf) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert string \"%s\" into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ param, formatstr, checkstr, buf);
+ }
+}
+
+void DoWStrTest(char *formatstr, WCHAR* param, char *checkstr)
+{
+ char buf[256] = { 0 };
+
+ Testvsnprintf(buf, 256, formatstr, param);
+ if (memcmp(buf, checkstr, strlen(buf) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert wide string \"%s\" into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ convertC(param), formatstr, checkstr, buf);
+ }
+}
+
+
+void DoCharTest(char *formatstr, char param, char *checkstr)
+{
+ char buf[256] = { 0 };
+
+ Testvsnprintf(buf, 256, formatstr, param);
+ if (memcmp(buf, checkstr, strlen(buf) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert char \'%c\' (%d) into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ param, param, formatstr, checkstr, buf);
+ }
+}
+
+void DoWCharTest(char *formatstr, WCHAR param, char *checkstr)
+{
+ char buf[256] = { 0 };
+
+ Testvsnprintf(buf, 256, formatstr, param);
+ if (memcmp(buf, checkstr, strlen(buf) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert wide char \'%c\' (%d) into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ (char)param, param, formatstr, checkstr, buf);
+ }
+}
+
+void DoNumTest(char *formatstr, int value, char *checkstr)
+{
+ char buf[256] = { 0 };
+
+ Testvsnprintf(buf, 256, formatstr, value);
+ if (memcmp(buf, checkstr, strlen(buf) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %#x into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ value, formatstr, checkstr, buf);
+ }
+}
+
+void DoI64Test(char *formatstr, INT64 value, char *valuestr, char *checkstr)
+{
+ char buf[256] = { 0 };
+
+ Testvsnprintf(buf, 256, formatstr, value);
+ if (memcmp(buf, checkstr, strlen(buf) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %s into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ valuestr, formatstr, checkstr, buf);
+ }
+}
+void DoDoubleTest(char *formatstr, double value, char *checkstr1, char
+ *checkstr2)
+{
+ char buf[256] = { 0 };
+
+ Testvsnprintf(buf,256, formatstr, value);
+ if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 &&
+ memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %f into \"%s\"\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n",
+ value, formatstr, checkstr1, checkstr2, buf);
+ }
+}
+
+#endif
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..7c346a4638
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_vsnprintf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnprintf_test1 coreclrpal)
+
+target_link_libraries(paltest_vsnprintf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test1/test1.c
new file mode 100644
index 0000000000..88aeec27a5
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test1/test1.c
@@ -0,0 +1,55 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test #1 for the _vsnprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ char checkstr[] = "hello world";
+ char buf[256] = { 0 };
+ int ret;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ Testvsnprintf(buf, 256, "hello world");
+
+ if (memcmp(checkstr, buf, strlen(checkstr)+1) != 0)
+ {
+ Fail("ERROR: expected \"%s\" (up to %d chars), got \"%s\"\n",
+ checkstr, 256, buf);
+ }
+
+ Testvsnprintf(buf, 256, "xxxxxxxxxxxxxxxxx");
+
+ ret = Testvsnprintf(buf, 8, "hello world");
+
+ if (ret >= 0)
+ {
+ Fail("ERROR: expected negative return value, got %d", ret);
+ }
+ if (memcmp(checkstr, buf, 8) != 0 || buf[8] != 'x')
+ {
+ Fail("ERROR: expected %s (up to %d chars), got %s\n", checkstr, 8, buf);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test1/testinfo.dat
new file mode 100644
index 0000000000..0e97856927
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnprintf
+Name = Positive Test for _vsnprintf
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests the PAL implementation of the _vsnprintf function.
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test10/CMakeLists.txt
new file mode 100644
index 0000000000..00dccc260d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test10/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test10.c
+)
+
+add_executable(paltest_vsnprintf_test10
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnprintf_test10 coreclrpal)
+
+target_link_libraries(paltest_vsnprintf_test10
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test10/test10.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test10/test10.c
new file mode 100644
index 0000000000..3099957ab7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test10/test10.c
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test10.c
+**
+** Purpose: Test #10 for the _vsnprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoNumTest("foo %o", pos, "foo 52");
+ DoNumTest("foo %lo", 0xFFFF, "foo 177777");
+ DoNumTest("foo %ho", 0xFFFF, "foo 177777");
+ DoNumTest("foo %Lo", pos, "foo 52");
+ DoI64Test("foo %I64o", l, "42", "foo 52");
+ DoNumTest("foo %3o", pos, "foo 52");
+ DoNumTest("foo %-3o", pos, "foo 52 ");
+ DoNumTest("foo %.1o", pos, "foo 52");
+ DoNumTest("foo %.3o", pos, "foo 052");
+ DoNumTest("foo %03o", pos, "foo 052");
+ DoNumTest("foo %#o", pos, "foo 052");
+ DoNumTest("foo %+o", pos, "foo 52");
+ DoNumTest("foo % o", pos, "foo 52");
+ DoNumTest("foo %+o", neg, "foo 37777777726");
+ DoNumTest("foo % o", neg, "foo 37777777726");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test10/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test10/testinfo.dat
new file mode 100644
index 0000000000..1399afae05
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test10/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnprintf
+Name = Positive Test for _vsnprintf
+TYPE = DEFAULT
+EXE1 = test10
+Description
+= Tests the PAL implementation of the _vsnprintf function.
+= Tests _vsnprintf with octal numbers.
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test11/CMakeLists.txt
new file mode 100644
index 0000000000..fd709f2a31
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test11/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test11.c
+)
+
+add_executable(paltest_vsnprintf_test11
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnprintf_test11 coreclrpal)
+
+target_link_libraries(paltest_vsnprintf_test11
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test11/test11.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test11/test11.c
new file mode 100644
index 0000000000..74b0435c6d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test11/test11.c
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test11.c
+**
+** Purpose: Test #11 for the _vsnprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoNumTest("foo %u", pos, "foo 42");
+ DoNumTest("foo %lu", 0xFFFF, "foo 65535");
+ DoNumTest("foo %hu", 0xFFFF, "foo 65535");
+ DoNumTest("foo %Lu", pos, "foo 42");
+ DoI64Test("foo %I64u", l, "42", "foo 42");
+ DoNumTest("foo %3u", pos, "foo 42");
+ DoNumTest("foo %-3u", pos, "foo 42 ");
+ DoNumTest("foo %.1u", pos, "foo 42");
+ DoNumTest("foo %.3u", pos, "foo 042");
+ DoNumTest("foo %03u", pos, "foo 042");
+ DoNumTest("foo %#u", pos, "foo 42");
+ DoNumTest("foo %+u", pos, "foo 42");
+ DoNumTest("foo % u", pos, "foo 42");
+ DoNumTest("foo %+u", neg, "foo 4294967254");
+ DoNumTest("foo % u", neg, "foo 4294967254");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test11/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test11/testinfo.dat
new file mode 100644
index 0000000000..faa7428eff
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test11/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnprintf
+Name = Positive Test for _vsnprintf
+TYPE = DEFAULT
+EXE1 = test11
+Description
+= Tests the PAL implementation of the _vsnprintf function.
+= Tests _vsnprintf with unsigned numbers.
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test12/CMakeLists.txt
new file mode 100644
index 0000000000..02dac0cb91
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test12/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test12.c
+)
+
+add_executable(paltest_vsnprintf_test12
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnprintf_test12 coreclrpal)
+
+target_link_libraries(paltest_vsnprintf_test12
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test12/test12.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test12/test12.c
new file mode 100644
index 0000000000..3718620971
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test12/test12.c
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test12.c
+**
+** Purpose: Test #12 for the _vsnprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 0x1234ab;
+ INT64 l = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return (FAIL);
+ }
+
+ DoNumTest("foo %x", pos, "foo 1234ab");
+ DoNumTest("foo %lx", pos, "foo 1234ab");
+ DoNumTest("foo %hx", pos, "foo 34ab");
+ DoNumTest("foo %Lx", pos, "foo 1234ab");
+ DoI64Test("foo %I64x", l, "0x1234567887654321",
+ "foo 1234567887654321");
+ DoNumTest("foo %7x", pos, "foo 1234ab");
+ DoNumTest("foo %-7x", pos, "foo 1234ab ");
+ DoNumTest("foo %.1x", pos, "foo 1234ab");
+ DoNumTest("foo %.7x", pos, "foo 01234ab");
+ DoNumTest("foo %07x", pos, "foo 01234ab");
+ DoNumTest("foo %#x", pos, "foo 0x1234ab");
+ DoNumTest("foo %+x", pos, "foo 1234ab");
+ DoNumTest("foo % x", pos, "foo 1234ab");
+ DoNumTest("foo %+x", neg, "foo ffffffd6");
+ DoNumTest("foo % x", neg, "foo ffffffd6");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test12/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test12/testinfo.dat
new file mode 100644
index 0000000000..d48a5cc60d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test12/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnprintf
+Name = Positive Test for _vsnprintf
+TYPE = DEFAULT
+EXE1 = test12
+Description
+= Tests the PAL implementation of the _vsnprintf function.
+= Tests _vsnprintf with hex numbers (lowercase).
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test13/CMakeLists.txt
new file mode 100644
index 0000000000..52562c99f8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test13/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test13.c
+)
+
+add_executable(paltest_vsnprintf_test13
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnprintf_test13 coreclrpal)
+
+target_link_libraries(paltest_vsnprintf_test13
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test13/test13.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test13/test13.c
new file mode 100644
index 0000000000..1abada4033
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test13/test13.c
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test13.c
+**
+** Purpose: Test #13 for the _vsnprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 0x1234AB;
+ INT64 l = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoNumTest("foo %X", pos, "foo 1234AB");
+ DoNumTest("foo %lX", pos, "foo 1234AB");
+ DoNumTest("foo %hX", pos, "foo 34AB");
+ DoNumTest("foo %LX", pos, "foo 1234AB");
+ DoI64Test("foo %I64X", l, "0x1234567887654321",
+ "foo 1234567887654321");
+ DoNumTest("foo %7X", pos, "foo 1234AB");
+ DoNumTest("foo %-7X", pos, "foo 1234AB ");
+ DoNumTest("foo %.1X", pos, "foo 1234AB");
+ DoNumTest("foo %.7X", pos, "foo 01234AB");
+ DoNumTest("foo %07X", pos, "foo 01234AB");
+ DoNumTest("foo %#X", pos, "foo 0X1234AB");
+ DoNumTest("foo %+X", pos, "foo 1234AB");
+ DoNumTest("foo % X", pos, "foo 1234AB");
+ DoNumTest("foo %+X", neg, "foo FFFFFFD6");
+ DoNumTest("foo % X", neg, "foo FFFFFFD6");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test13/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test13/testinfo.dat
new file mode 100644
index 0000000000..a3f14c21dc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test13/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnprintf
+Name = Positive Test for _vsnprintf
+TYPE = DEFAULT
+EXE1 = test13
+Description
+= Tests the PAL implementation of the _vsnprintf function.
+= Tests _vsnprintf with hex numbers (uppercase).
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test14/CMakeLists.txt
new file mode 100644
index 0000000000..3fc8c814a6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test14/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test14.c
+)
+
+add_executable(paltest_vsnprintf_test14
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnprintf_test14 coreclrpal)
+
+target_link_libraries(paltest_vsnprintf_test14
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test14/test14.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test14/test14.c
new file mode 100644
index 0000000000..2e98f6ad4e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test14/test14.c
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test14.c
+**
+** Purpose: Test #14 for the _vsnprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 256.0;
+ double neg = -256.0;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoDoubleTest("foo %e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %le", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %he", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %Le", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %I64e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %14e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %-14e", val, "foo 2.560000e+002 ", "foo 2.560000e+02 ");
+ DoDoubleTest("foo %.1e", val, "foo 2.6e+002", "foo 2.6e+02");
+ DoDoubleTest("foo %.8e", val, "foo 2.56000000e+002", "foo 2.56000000e+02");
+ DoDoubleTest("foo %014e", val, "foo 02.560000e+002", "foo 002.560000e+02");
+ DoDoubleTest("foo %#e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %+e", val, "foo +2.560000e+002", "foo +2.560000e+02");
+ DoDoubleTest("foo % e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %+e", neg, "foo -2.560000e+002", "foo -2.560000e+02");
+ DoDoubleTest("foo % e", neg, "foo -2.560000e+002", "foo -2.560000e+02");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test14/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test14/testinfo.dat
new file mode 100644
index 0000000000..f4d921c139
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test14/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnprintf
+Name = Positive Test for _vsnprintf
+TYPE = DEFAULT
+EXE1 = test14
+Description
+= Tests the PAL implementation of the _vsnprintf function.
+= Tests _vsnprintf with exponential format doubles (lowercase).
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test15/CMakeLists.txt
new file mode 100644
index 0000000000..f6bdc83779
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test15/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test15.c
+)
+
+add_executable(paltest_vsnprintf_test15
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnprintf_test15 coreclrpal)
+
+target_link_libraries(paltest_vsnprintf_test15
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test15/test15.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test15/test15.c
new file mode 100644
index 0000000000..4d32e9c638
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test15/test15.c
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test15.c
+**
+** Purpose: Test #15 for the _vsnprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 256.0;
+ double neg = -256.0;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoDoubleTest("foo %E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %lE", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %hE", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %LE", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %I64E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %14E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %-14E", val, "foo 2.560000E+002 ", "foo 2.560000E+02 ");
+ DoDoubleTest("foo %.1E", val, "foo 2.6E+002", "foo 2.6E+02");
+ DoDoubleTest("foo %.8E", val, "foo 2.56000000E+002", "foo 2.56000000E+02");
+ DoDoubleTest("foo %014E", val, "foo 02.560000E+002", "foo 002.560000E+02");
+ DoDoubleTest("foo %#E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %+E", val, "foo +2.560000E+002", "foo +2.560000E+02");
+ DoDoubleTest("foo % E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %+E", neg, "foo -2.560000E+002", "foo -2.560000E+02");
+ DoDoubleTest("foo % E", neg, "foo -2.560000E+002", "foo -2.560000E+02");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test15/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test15/testinfo.dat
new file mode 100644
index 0000000000..3a6620ba46
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test15/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnprintf
+Name = Positive Test for _vsnprintf
+TYPE = DEFAULT
+EXE1 = test15
+Description
+= Tests the PAL implementation of the _vsnprintf function.
+= Tests _vsnprintf with exponential format doubles (uppercase).
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test16/CMakeLists.txt
new file mode 100644
index 0000000000..b7b06d19bb
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test16/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test16.c
+)
+
+add_executable(paltest_vsnprintf_test16
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnprintf_test16 coreclrpal)
+
+target_link_libraries(paltest_vsnprintf_test16
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test16/test16.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test16/test16.c
new file mode 100644
index 0000000000..118ba1453c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test16/test16.c
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test16.c
+**
+** Purpose: Test #16 for the _vsnprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoDoubleTest("foo %f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %lf", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %hf", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %Lf", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %I64f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %12f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %-12f", val, "foo 2560.001000 ", "foo 2560.001000 ");
+ DoDoubleTest("foo %.1f", val, "foo 2560.0", "foo 2560.0");
+ DoDoubleTest("foo %.8f", val, "foo 2560.00100000", "foo 2560.00100000");
+ DoDoubleTest("foo %012f", val, "foo 02560.001000", "foo 02560.001000");
+ DoDoubleTest("foo %#f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %+f", val, "foo +2560.001000", "foo +2560.001000");
+ DoDoubleTest("foo % f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %+f", neg, "foo -2560.001000", "foo -2560.001000");
+ DoDoubleTest("foo % f", neg, "foo -2560.001000", "foo -2560.001000");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test16/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test16/testinfo.dat
new file mode 100644
index 0000000000..6363f294af
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test16/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnprintf
+Name = Positive Test for _vsnprintf
+TYPE = DEFAULT
+EXE1 = test16
+Description
+= Tests the PAL implementation of the _vsnprintf function.
+= Tests _vsnprintf with decimal point format doubles.
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test17/CMakeLists.txt
new file mode 100644
index 0000000000..2c91cccd4a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test17/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test17.c
+)
+
+add_executable(paltest_vsnprintf_test17
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnprintf_test17 coreclrpal)
+
+target_link_libraries(paltest_vsnprintf_test17
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test17/test17.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test17/test17.c
new file mode 100644
index 0000000000..9b5063ddf0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test17/test17.c
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test17.c
+**
+** Purpose: Test #17 for the _vsnprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoDoubleTest("foo %g", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %lg", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %hg", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %Lg", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %I64g", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %5g", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %-5g", val, "foo 2560 ", "foo 2560 ");
+ DoDoubleTest("foo %.1g", val, "foo 3e+003", "foo 3e+03");
+ DoDoubleTest("foo %.2g", val, "foo 2.6e+003", "foo 2.6e+03");
+ DoDoubleTest("foo %.12g", val, "foo 2560.001", "foo 2560.001");
+ DoDoubleTest("foo %06g", val, "foo 002560", "foo 002560");
+ DoDoubleTest("foo %#g", val, "foo 2560.00", "foo 2560.00");
+ DoDoubleTest("foo %+g", val, "foo +2560", "foo +2560");
+ DoDoubleTest("foo % g", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %+g", neg, "foo -2560", "foo -2560");
+ DoDoubleTest("foo % g", neg, "foo -2560", "foo -2560");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test17/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test17/testinfo.dat
new file mode 100644
index 0000000000..ecec515de3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test17/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnprintf
+Name = Positive Test for _vsnprintf
+TYPE = DEFAULT
+EXE1 = test17
+Description
+= Tests the PAL implementation of the _vsnprintf function.
+= Tests _vsnprintf with compact format doubles (lowercase).
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test18/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test18/CMakeLists.txt
new file mode 100644
index 0000000000..1a06ce01ee
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test18/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test18.c
+)
+
+add_executable(paltest_vsnprintf_test18
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnprintf_test18 coreclrpal)
+
+target_link_libraries(paltest_vsnprintf_test18
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test18/test18.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test18/test18.c
new file mode 100644
index 0000000000..5232befc7f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test18/test18.c
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test18.c
+**
+** Purpose: Test #18 for the _vsnprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoDoubleTest("foo %G", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %lG", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %hG", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %LG", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %I64G", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %5G", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %-5G", val, "foo 2560 ", "foo 2560 ");
+ DoDoubleTest("foo %.1G", val, "foo 3E+003", "foo 3E+03");
+ DoDoubleTest("foo %.2G", val, "foo 2.6E+003", "foo 2.6E+03");
+ DoDoubleTest("foo %.12G", val, "foo 2560.001", "foo 2560.001");
+ DoDoubleTest("foo %06G", val, "foo 002560", "foo 002560");
+ DoDoubleTest("foo %#G", val, "foo 2560.00", "foo 2560.00");
+ DoDoubleTest("foo %+G", val, "foo +2560", "foo +2560");
+ DoDoubleTest("foo % G", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %+G", neg, "foo -2560", "foo -2560");
+ DoDoubleTest("foo % G", neg, "foo -2560", "foo -2560");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test18/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test18/testinfo.dat
new file mode 100644
index 0000000000..34fd7ae2ff
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test18/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnprintf
+Name = Positive Test for _vsnprintf
+TYPE = DEFAULT
+EXE1 = test18
+Description
+= Tests the PAL implementation of the _vsnprintf function.
+= Tests _vsnprintf with compact format doubles (uppercase).
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test19/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test19/CMakeLists.txt
new file mode 100644
index 0000000000..6f2e42cc6b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test19/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test19.c
+)
+
+add_executable(paltest_vsnprintf_test19
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnprintf_test19 coreclrpal)
+
+target_link_libraries(paltest_vsnprintf_test19
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test19/test19.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test19/test19.c
new file mode 100644
index 0000000000..075a528aba
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test19/test19.c
@@ -0,0 +1,103 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test19.c
+**
+** Purpose: Test #19 for the _vsnprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+#define DOTEST(a,b,c,d,e) DoTest(a,b,(void*)c,d,e)
+
+void DoArgumentPrecTest(char *formatstr, int precision, void *param,
+ char *paramstr, char *checkstr1, char *checkstr2)
+{
+ char buf[256];
+
+ Testvsnprintf(buf,256,formatstr, precision, param);
+ if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 &&
+ memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n",
+ paramstr, formatstr, precision, checkstr1, checkstr2, buf);
+ }
+
+}
+
+void DoArgumentPrecDoubleTest(char *formatstr, int precision, double param,
+ char *checkstr1, char *checkstr2)
+{
+ char buf[256];
+
+ Testvsnprintf(buf,256,formatstr, precision, param);
+ if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 &&
+ memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n",
+ param, formatstr, precision, checkstr1, checkstr2, buf);
+ }
+
+}
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+
+ DoArgumentPrecTest("%.*s", 2, "bar", "bar", "ba", "ba");
+ DoArgumentPrecTest("%.*S", 2, convert("bar"), "bar", "ba", "ba");
+ DoArgumentPrecTest("%.*c", 0, (void*)'a', "a", "a", "a");
+ DoArgumentPrecTest("%.*c", 4, (void*)'a', "a", "a", "a");
+ DoArgumentPrecTest("%.*C", 0, (void*)'a', "a", "a", "a");
+ DoArgumentPrecTest("%.*C", 4, (void*)'a', "a", "a", "a");
+ DoArgumentPrecTest("%.*d", 1, (void*)42, "42", "42", "42");
+ DoArgumentPrecTest("%.*d", 3, (void*)42, "42", "042", "042");
+ DoArgumentPrecTest("%.*i", 1, (void*)42, "42", "42", "42");
+ DoArgumentPrecTest("%.*i", 3, (void*)42, "42", "042", "042");
+ DoArgumentPrecTest("%.*o", 1, (void*)42, "42", "52", "52");
+ DoArgumentPrecTest("%.*o", 3, (void*)42, "42", "052", "052");
+ DoArgumentPrecTest("%.*u", 1, (void*)42, "42", "42", "42");
+ DoArgumentPrecTest("%.*u", 3, (void*)42, "42", "042", "042");
+ DoArgumentPrecTest("%.*x", 1, (void*)0x42, "0x42", "42", "42");
+ DoArgumentPrecTest("%.*x", 3, (void*)0x42, "0x42", "042", "042");
+ DoArgumentPrecTest("%.*X", 1, (void*)0x42, "0x42", "42", "42");
+ DoArgumentPrecTest("%.*X", 3, (void*)0x42, "0x42", "042", "042");
+
+
+ DoArgumentPrecDoubleTest("%.*e", 1, 2.01, "2.0e+000", "2.0e+00");
+ DoArgumentPrecDoubleTest("%.*e", 3, 2.01, "2.010e+000", "2.010e+00");
+ DoArgumentPrecDoubleTest("%.*E", 1, 2.01, "2.0E+000", "2.0E+00");
+ DoArgumentPrecDoubleTest("%.*E", 3, 2.01, "2.010E+000", "2.010E+00");
+ DoArgumentPrecDoubleTest("%.*f", 1, 2.01, "2.0", "2.0");
+ DoArgumentPrecDoubleTest("%.*f", 3, 2.01, "2.010", "2.010");
+ DoArgumentPrecDoubleTest("%.*g", 1, 256.01, "3e+002", "3e+02");
+ DoArgumentPrecDoubleTest("%.*g", 3, 256.01, "256", "256");
+ DoArgumentPrecDoubleTest("%.*g", 4, 256.01, "256", "256");
+ DoArgumentPrecDoubleTest("%.*g", 6, 256.01, "256.01", "256.01");
+ DoArgumentPrecDoubleTest("%.*G", 1, 256.01, "3E+002", "3E+02");
+ DoArgumentPrecDoubleTest("%.*G", 3, 256.01, "256", "256");
+ DoArgumentPrecDoubleTest("%.*G", 4, 256.01, "256", "256");
+ DoArgumentPrecDoubleTest("%.*G", 6, 256.01, "256.01", "256.01");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test19/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test19/testinfo.dat
new file mode 100644
index 0000000000..05f4b5bd87
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test19/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnprintf
+Name = Positive Test for _vsnprintf
+TYPE = DEFAULT
+EXE1 = test19
+Description
+= Tests the PAL implementation of the _vsnprintf function.
+= Tests _vsnprintf with argument specified precision.
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test2/CMakeLists.txt
new file mode 100644
index 0000000000..a3871d64cf
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_vsnprintf_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnprintf_test2 coreclrpal)
+
+target_link_libraries(paltest_vsnprintf_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test2/test2.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test2/test2.c
new file mode 100644
index 0000000000..4bac4d2c83
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test2/test2.c
@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test2.c
+**
+** Purpose: Test #2 for the _vsnprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnprintf.h"
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR szwStr[] = {'b','a','r','\0'};
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoStrTest("foo %s", "bar", "foo bar");
+ DoStrTest("foo %hs", "bar", "foo bar");
+ DoWStrTest("foo %ls", szwStr, "foo bar");
+ DoWStrTest("foo %ws", szwStr, "foo bar");
+ DoStrTest("foo %Ls", "bar", "foo bar");
+ DoStrTest("foo %I64s", "bar", "foo bar");
+ DoStrTest("foo %5s", "bar", "foo bar");
+ DoStrTest("foo %.2s", "bar", "foo ba");
+ DoStrTest("foo %5.2s", "bar", "foo ba");
+ DoStrTest("foo %-5s", "bar", "foo bar ");
+ DoStrTest("foo %05s", "bar", "foo 00bar");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test2/testinfo.dat
new file mode 100644
index 0000000000..5ee925e3f6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test2/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnprintf
+Name = Positive Test for _vsnprintf
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Tests the PAL implementation of the _vsnprintf function.
+= Tests _vsnprintf with strings.
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test3/CMakeLists.txt
new file mode 100644
index 0000000000..1beae06277
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_vsnprintf_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnprintf_test3 coreclrpal)
+
+target_link_libraries(paltest_vsnprintf_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test3/test3.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test3/test3.c
new file mode 100644
index 0000000000..2b30c9ad99
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test3/test3.c
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test3.c
+**
+** Purpose: Test #3 for the _vsnprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoWStrTest("foo %S", convert("bar"), "foo bar");
+ DoStrTest("foo %hS", "bar", "foo bar");
+ DoWStrTest("foo %lS", convert("bar"), "foo bar");
+ DoWStrTest("foo %wS", convert("bar"), "foo bar");
+ DoWStrTest("foo %LS", convert("bar"), "foo bar");
+ DoWStrTest("foo %I64S", convert("bar"), "foo bar");
+ DoWStrTest("foo %5S", convert("bar"), "foo bar");
+ DoWStrTest("foo %.2S", convert("bar"), "foo ba");
+ DoWStrTest("foo %5.2S", convert("bar"), "foo ba");
+ DoWStrTest("foo %-5S", convert("bar"), "foo bar ");
+ DoWStrTest("foo %05S", convert("bar"), "foo 00bar");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test3/testinfo.dat
new file mode 100644
index 0000000000..626949c7c8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test3/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnprintf
+Name = Positive Test for _vsnprintf
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Tests the PAL implementation of the _vsnprintf function.
+= Tests _vsnprintf with wide strings.
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test4/CMakeLists.txt
new file mode 100644
index 0000000000..daf7757ddb
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_vsnprintf_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnprintf_test4 coreclrpal)
+
+target_link_libraries(paltest_vsnprintf_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test4/test4.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test4/test4.c
new file mode 100644
index 0000000000..33fc49deba
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test4/test4.c
@@ -0,0 +1,98 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test4.c
+**
+** Purpose: Test #4 for the _vsnprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+static void DoPointerTest(char *formatstr, void* param, char* paramstr,
+ char *checkstr1)
+{
+ char buf[256] = { 0 };
+
+ Testvsnprintf(buf,256, formatstr, param);
+ if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %s into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ paramstr, formatstr, checkstr1, buf);
+ }
+}
+
+static void DoI64DoubleTest(char *formatstr, INT64 value, char *valuestr, char
+*checkstr1)
+{
+ char buf[256] = { 0 };
+
+ Testvsnprintf(buf,256,formatstr, value);
+ if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %s into \"%s\"\n"
+ "Expected \"%s\", got \"%s\".\n",
+ valuestr, formatstr, checkstr1, buf);
+ }
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ void *ptr = (void*) 0x123456;
+ INT64 lptr = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+
+ /*
+** Run only on 64 bit platforms
+*/
+#if defined(BIT64) && defined(PLATFORM_UNIX)
+ Trace("Testing for 64 Bit Platforms \n");
+ DoPointerTest("%p", NULL, "NULL", "0000000000000000");
+ DoPointerTest("%p", ptr, "pointer to 0x123456", "0000000000123456");
+ DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456");
+ DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456");
+ DoPointerTest("%-17p", ptr, "pointer to 0x123456", "0000000000123456 ");
+ DoPointerTest("%+p", ptr, "pointer to 0x123456", "0000000000123456");
+ DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X0000000000123456");
+ DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456");
+ DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456");
+ DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456");
+ DoI64DoubleTest("%I64p", lptr, "pointer to 0x1234567887654321",
+ "1234567887654321");
+
+#else
+ Trace("Testing for Non 64 Bit Platforms \n");
+ DoPointerTest("%p", NULL, "NULL", "00000000");
+ DoPointerTest("%p", ptr, "pointer to 0x123456", "00123456");
+ DoPointerTest("%9p", ptr, "pointer to 0x123456", " 00123456");
+ DoPointerTest("%09p", ptr, "pointer to 0x123456", " 00123456");
+ DoPointerTest("%-9p", ptr, "pointer to 0x123456", "00123456 ");
+ DoPointerTest("%+p", ptr, "pointer to 0x123456", "00123456");
+ DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X00123456");
+ DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456");
+ DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456");
+ DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456");
+ DoI64DoubleTest("%I64p", lptr, "pointer to 0x1234567887654321",
+ "1234567887654321");
+#endif
+
+
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test4/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test4/testinfo.dat
new file mode 100644
index 0000000000..bdfdef85ae
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test4/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnprintf
+Name = Positive Test for _vsnprintf
+TYPE = DEFAULT
+EXE1 = test4
+Description
+= Tests the PAL implementation of the _vsnprintf function.
+= Tests _vsnprintf with pointers.
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test5/CMakeLists.txt
new file mode 100644
index 0000000000..c255b07b42
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test5.c
+)
+
+add_executable(paltest_vsnprintf_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnprintf_test5 coreclrpal)
+
+target_link_libraries(paltest_vsnprintf_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test5/test5.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test5/test5.c
new file mode 100644
index 0000000000..534e42e293
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test5/test5.c
@@ -0,0 +1,78 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test5.c
+**
+** Purpose: Test #5 for the _vsnprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+static void DoTest(char *formatstr, int param, char *checkstr)
+{
+ char buf[256] = { 0 };
+ int n = -1;
+
+ Testvsnprintf(buf, 256, formatstr, &n);
+
+ if (n != param)
+ {
+ Fail("ERROR: Expected count parameter to resolve to %d, got %X\n",
+ param, n);
+ }
+ if (memcmp(buf, checkstr, strlen(buf) + 1) != 0)
+ {
+ Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf);
+ }
+}
+
+static void DoShortTest(char *formatstr, int param, char *checkstr)
+{
+ char buf[256] = { 0 };
+ short int n = -1;
+
+ Testvsnprintf(buf, 256, formatstr, &n);
+
+ if (n != param)
+ {
+ Fail("ERROR: Expected count parameter to resolve to %d, got %X\n",
+ param, n);
+ }
+ if (memcmp(buf, checkstr, strlen(buf) + 1) != 0)
+ {
+ Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf);
+ }
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoTest("foo %n bar", 4, "foo bar");
+ DoTest("foo %#n bar", 4, "foo bar");
+ DoTest("foo % n bar", 4, "foo bar");
+ DoTest("foo %+n bar", 4, "foo bar");
+ DoTest("foo %-n bar", 4, "foo bar");
+ DoTest("foo %0n bar", 4, "foo bar");
+ DoShortTest("foo %hn bar", 4, "foo bar");
+ DoTest("foo %ln bar", 4, "foo bar");
+ DoTest("foo %Ln bar", 4, "foo bar");
+ DoTest("foo %I64n bar", 4, "foo bar");
+ DoTest("foo %20.3n bar", 4, "foo bar");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test5/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test5/testinfo.dat
new file mode 100644
index 0000000000..3cd3f7ee86
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test5/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnprintf
+Name = Positive Test for _vsnprintf
+TYPE = DEFAULT
+EXE1 = test5
+Description
+= Tests the PAL implementation of the _vsnprintf function.
+= Tests _vsnprintf with the count specifier.
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test6/CMakeLists.txt
new file mode 100644
index 0000000000..8e041f4af8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test6.c
+)
+
+add_executable(paltest_vsnprintf_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnprintf_test6 coreclrpal)
+
+target_link_libraries(paltest_vsnprintf_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test6/test6.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test6/test6.c
new file mode 100644
index 0000000000..103d1181c2
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test6/test6.c
@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test6.c
+**
+** Purpose: Test #6 for the _vsnprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR wc = (WCHAR) 'c';
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoCharTest("foo %c", 'b', "foo b");
+ DoCharTest("foo %hc", 'b', "foo b");
+ DoWCharTest("foo %lc", wc, "foo c");
+ DoCharTest("foo %Lc", 'b', "foo b");
+ DoCharTest("foo %I64c", 'b', "foo b");
+ DoCharTest("foo %5c", 'b', "foo b");
+ DoCharTest("foo %.0c", 'b', "foo b");
+ DoCharTest("foo %-5c", 'b', "foo b ");
+ DoCharTest("foo %05c", 'b', "foo 0000b");
+ DoCharTest("foo % c", 'b', "foo b");
+ DoCharTest("foo %#c", 'b', "foo b");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test6/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test6/testinfo.dat
new file mode 100644
index 0000000000..e379e0b3b8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test6/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnprintf
+Name = Positive Test for _vsnprintf
+TYPE = DEFAULT
+EXE1 = test6
+Description
+= Tests the PAL implementation of the _vsnprintf function.
+= Tests _vsnprintf with characters.
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test7/CMakeLists.txt
new file mode 100644
index 0000000000..01f9620184
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test7/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test7.c
+)
+
+add_executable(paltest_vsnprintf_test7
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnprintf_test7 coreclrpal)
+
+target_link_libraries(paltest_vsnprintf_test7
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test7/test7.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test7/test7.c
new file mode 100644
index 0000000000..c7e45d67fa
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test7/test7.c
@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test7.c
+**
+** Purpose: Test #7 for the _vsnprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnprintf.h"
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR wb = (WCHAR) 'b';
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoWCharTest("foo %c", wb, "foo b");
+ DoWCharTest("foo %hc", wb, "foo b");
+ DoCharTest("foo %lc", 'c', "foo c");
+ DoWCharTest("foo %Lc", wb, "foo b");
+ DoWCharTest("foo %I64c", wb, "foo b");
+ DoWCharTest("foo %5c", wb, "foo b");
+ DoWCharTest("foo %.0c", wb, "foo b");
+ DoWCharTest("foo %-5c", wb, "foo b ");
+ DoWCharTest("foo %05c", wb, "foo 0000b");
+ DoWCharTest("foo % c", wb, "foo b");
+ DoWCharTest("foo %#c", wb, "foo b");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test7/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test7/testinfo.dat
new file mode 100644
index 0000000000..90749400a5
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test7/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnprintf
+Name = Positive Test for _vsnprintf
+TYPE = DEFAULT
+EXE1 = test7
+Description
+= Tests the PAL implementation of the _vsnprintf function.
+= Tests _vsnprintf with wide characters.
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test8/CMakeLists.txt
new file mode 100644
index 0000000000..9c525de15a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test8/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test8.c
+)
+
+add_executable(paltest_vsnprintf_test8
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnprintf_test8 coreclrpal)
+
+target_link_libraries(paltest_vsnprintf_test8
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test8/test8.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test8/test8.c
new file mode 100644
index 0000000000..2cefbeac25
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test8/test8.c
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test8.c
+**
+** Purpose: Test #8 for the _vsnprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoNumTest("foo %d", pos, "foo 42");
+ DoNumTest("foo %ld", 0xFFFF, "foo 65535");
+ DoNumTest("foo %hd", 0xFFFF, "foo -1");
+ DoNumTest("foo %Ld", pos, "foo 42");
+ DoI64Test("foo %I64d", l, "42", "foo 42");
+ DoNumTest("foo %3d", pos, "foo 42");
+ DoNumTest("foo %-3d", pos, "foo 42 ");
+ DoNumTest("foo %.1d", pos, "foo 42");
+ DoNumTest("foo %.3d", pos, "foo 042");
+ DoNumTest("foo %03d", pos, "foo 042");
+ DoNumTest("foo %#d", pos, "foo 42");
+ DoNumTest("foo %+d", pos, "foo +42");
+ DoNumTest("foo % d", pos, "foo 42");
+ DoNumTest("foo %+d", neg, "foo -42");
+ DoNumTest("foo % d", neg, "foo -42");
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test8/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test8/testinfo.dat
new file mode 100644
index 0000000000..0afc334a67
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test8/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnprintf
+Name = Positive Test for _vsnprintf
+TYPE = DEFAULT
+EXE1 = test8
+Description
+= Tests the PAL implementation of the _vsnprintf function.
+= Tests _vsnprintf with decimal numbers.
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test9/CMakeLists.txt
new file mode 100644
index 0000000000..bfe2572a6d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test9/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test9.c
+)
+
+add_executable(paltest_vsnprintf_test9
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnprintf_test9 coreclrpal)
+
+target_link_libraries(paltest_vsnprintf_test9
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test9/test9.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test9/test9.c
new file mode 100644
index 0000000000..d2cd8165c0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test9/test9.c
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test9.c
+**
+** Purpose: Test #9 for the _vsnprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoNumTest("foo %i", pos, "foo 42");
+ DoNumTest("foo %li", 0xFFFF, "foo 65535");
+ DoNumTest("foo %hi", 0xFFFF, "foo -1");
+ DoNumTest("foo %Li", pos, "foo 42");
+ DoI64Test("foo %I64i", l, "42", "foo 42");
+ DoNumTest("foo %3i", pos, "foo 42");
+ DoNumTest("foo %-3i", pos, "foo 42 ");
+ DoNumTest("foo %.1i", pos, "foo 42");
+ DoNumTest("foo %.3i", pos, "foo 042");
+ DoNumTest("foo %03i", pos, "foo 042");
+ DoNumTest("foo %#i", pos, "foo 42");
+ DoNumTest("foo %+i", pos, "foo +42");
+ DoNumTest("foo % i", pos, "foo 42");
+ DoNumTest("foo %+i", neg, "foo -42");
+ DoNumTest("foo % i", neg, "foo -42");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test9/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test9/testinfo.dat
new file mode 100644
index 0000000000..125724a36b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test9/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnprintf
+Name = Positive Test for _vsnprintf
+TYPE = DEFAULT
+EXE1 = test9
+Description
+= Tests the PAL implementation of the _vsnprintf function.
+= Tests _vsnprintf with integer numbers.
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/CMakeLists.txt
new file mode 100644
index 0000000000..cafb9536b0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/CMakeLists.txt
@@ -0,0 +1,22 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test10)
+add_subdirectory(test11)
+add_subdirectory(test12)
+add_subdirectory(test13)
+add_subdirectory(test14)
+add_subdirectory(test15)
+add_subdirectory(test16)
+add_subdirectory(test17)
+add_subdirectory(test18)
+add_subdirectory(test19)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+add_subdirectory(test7)
+add_subdirectory(test8)
+add_subdirectory(test9)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/_vsnwprintf.h b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/_vsnwprintf.h
new file mode 100644
index 0000000000..a3a932f822
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/_vsnwprintf.h
@@ -0,0 +1,133 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: _vsnwprintf.h
+**
+** Purpose: Containts common testing functions for _vsnwprintf
+**
+**
+**==========================================================================*/
+
+#ifndef ___VSNWPRINTF_H__
+#define ___VSNWPRINTF_H__
+
+/* These functions leaks memory like crazy. C'est la vie. */
+int TestVsnwprintf(wchar_t* buf, size_t count, const wchar_t* format, ...)
+{
+ int retVal = 0;
+ va_list arglist;
+
+ va_start(arglist, format);
+ retVal = _vsnwprintf(buf, count, format, arglist);
+ va_end(arglist);
+
+ return( retVal);
+}
+
+
+void DoWStrTest(WCHAR *formatstr, WCHAR *param, WCHAR *checkstr)
+{
+ WCHAR buf[256] = { 0 };
+
+ TestVsnwprintf(buf, 256, formatstr, param);
+
+ if (memcmp(buf, checkstr, wcslen(buf) * 2 + 2) != 0)
+ {
+ Fail("ERROR: failed to insert wide string \"%s\" into \"%s\".\n"
+ "Expected \"%s\", got \"%s\".\n",
+ convertC(param), convertC(formatstr),
+ convertC(checkstr), convertC(buf));
+ }
+}
+
+void DoStrTest(WCHAR *formatstr, char *param, WCHAR *checkstr)
+{
+ WCHAR buf[256] = { 0 };
+
+ TestVsnwprintf(buf, 256, formatstr, param);
+
+ if (memcmp(buf, checkstr, wcslen(buf) * 2 + 2) != 0)
+ {
+ Fail("ERROR: failed to insert wide string \"%s\" into \"%s\".\n"
+ "Expected \"%s\", got \"%s\".\n",
+ param, convertC(formatstr), convertC(checkstr),
+ convertC(buf));
+ }
+}
+
+void DoCharTest(WCHAR *formatstr, char param, WCHAR *checkstr)
+{
+ WCHAR buf[256] = { 0 };
+
+ TestVsnwprintf(buf, 256, formatstr, param);
+ if (memcmp(buf, checkstr, wcslen(buf)*2 + 2) != 0)
+ {
+ Fail("ERROR: failed to insert char \'%c\' (%d) into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ param, param, convertC(formatstr), convertC(checkstr),
+ convertC(buf));
+ }
+}
+
+void DoWCharTest(WCHAR *formatstr, WCHAR param, WCHAR *checkstr)
+{
+ WCHAR buf[256] = { 0 };
+
+ TestVsnwprintf(buf, 256, formatstr, param);
+ if (memcmp(buf, checkstr, wcslen(buf)*2 + 2) != 0)
+ {
+ Fail("ERROR: failed to insert wide char \'%c\' (%d) into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ (char) param, param, convertC(formatstr),
+ convertC(checkstr), convertC(buf));
+ }
+}
+
+void DoNumTest(WCHAR *formatstr, int value, WCHAR*checkstr)
+{
+ WCHAR buf[256] = { 0 };
+
+ TestVsnwprintf(buf, 256, formatstr, value);
+ if (memcmp(buf, checkstr, wcslen(buf)* 2 + 2) != 0)
+ {
+ Fail("ERROR: failed to insert %#x into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n", value, convertC(formatstr),
+ convertC(checkstr), convertC(buf));
+ }
+}
+
+void DoI64NumTest(WCHAR *formatstr, INT64 value, char *valuestr, WCHAR*checkstr)
+{
+ WCHAR buf[256] = { 0 };
+
+ TestVsnwprintf(buf, 256, formatstr, value);
+ if (memcmp(buf, checkstr, wcslen(buf)* 2 + 2) != 0)
+ {
+ Fail("ERROR: failed to insert %s into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n", valuestr, convertC(formatstr),
+ convertC(checkstr), convertC(buf));
+ }
+}
+void DoDoubleTest(WCHAR *formatstr, double value,
+ WCHAR *checkstr1, WCHAR *checkstr2)
+{
+ WCHAR buf[256] = { 0 };
+
+ TestVsnwprintf(buf, 256, formatstr, value);
+ if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0 &&
+ memcmp(buf, checkstr2, wcslen(checkstr2) + 2) != 0)
+ {
+ Fail("ERROR: failed to insert %f into \"%s\"\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n",
+ value,
+ convertC(formatstr),
+ convertC(checkstr1),
+ convertC(checkstr2),
+ convertC(buf));
+ }
+}
+
+#endif
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..52c442d572
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_vsnwprintf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnwprintf_test1 coreclrpal)
+
+target_link_libraries(paltest_vsnwprintf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test1/test1.c
new file mode 100644
index 0000000000..0238e42611
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test1/test1.c
@@ -0,0 +1,60 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test #1 for the _vsnwprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR *checkstr;
+ WCHAR buf[256] = { 0 };
+ int ret;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ checkstr = convert("hello world");
+ TestVsnwprintf(buf, 256, checkstr);
+ if (memcmp(checkstr, buf, wcslen(checkstr)*2+2) != 0)
+ {
+ Fail("ERROR: Expected \"%s\", got \"%s\"\n",
+ convertC(checkstr), convertC(buf));
+ }
+
+ TestVsnwprintf(buf, 256, convert("xxxxxxxxxxxxxxxxx"));
+ ret = TestVsnwprintf(buf, 8, checkstr);
+ if (memcmp(checkstr, buf, 16) != 0)
+ {
+ Fail("ERROR: Expected \"%8s\", got \"%8s\"\n",
+ convertC(checkstr), convertC(buf));
+ }
+ if (ret >= 0)
+ {
+ Fail("ERROR: Expected negative return value, got %d.\n", ret);
+ }
+ if (buf[8] != (WCHAR) 'x')
+ {
+ Fail("ERROR: buffer overflow using \"%s\" with length 8.\n",
+ convertC(checkstr));
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test1/testinfo.dat
new file mode 100644
index 0000000000..d806fb8ed8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnwprintf
+Name = Positive Test for _vsnwprintf
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests the PAL implementation of the _vsnwprintf function.
+= General test to see if _vsnwprintf works correctly.
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test10/CMakeLists.txt
new file mode 100644
index 0000000000..86ea1a3160
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test10/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test10.c
+)
+
+add_executable(paltest_vsnwprintf_test10
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnwprintf_test10 coreclrpal)
+
+target_link_libraries(paltest_vsnwprintf_test10
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test10/test10.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test10/test10.c
new file mode 100644
index 0000000000..6e188e56ff
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test10/test10.c
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test10.c
+**
+** Purpose: Test #10 for the _vsnwprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoNumTest(convert("foo %o"), pos, convert("foo 52"));
+ DoNumTest(convert("foo %lo"), 0xFFFF, convert("foo 177777"));
+ DoNumTest(convert("foo %ho"), 0xFFFF, convert("foo 177777"));
+ DoNumTest(convert("foo %Lo"), pos, convert("foo 52"));
+ DoI64NumTest(convert("foo %I64o"), l, "42", convert("foo 52"));
+ DoNumTest(convert("foo %3o"), pos, convert("foo 52"));
+ DoNumTest(convert("foo %-3o"), pos, convert("foo 52 "));
+ DoNumTest(convert("foo %.1o"), pos, convert("foo 52"));
+ DoNumTest(convert("foo %.3o"), pos, convert("foo 052"));
+ DoNumTest(convert("foo %03o"), pos, convert("foo 052"));
+ DoNumTest(convert("foo %#o"), pos, convert("foo 052"));
+ DoNumTest(convert("foo %+o"), pos, convert("foo 52"));
+ DoNumTest(convert("foo % o"), pos, convert("foo 52"));
+ DoNumTest(convert("foo %+o"), neg, convert("foo 37777777726"));
+ DoNumTest(convert("foo % o"), neg, convert("foo 37777777726"));
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test10/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test10/testinfo.dat
new file mode 100644
index 0000000000..beb5b41be9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test10/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnwprintf
+Name = Positive Test for _vsnwprintf
+TYPE = DEFAULT
+EXE1 = test10
+Description
+= Tests the PAL implementation of the _vsnwprintf function.
+= Tests _vsnwprintf with octal numbers.
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test11/CMakeLists.txt
new file mode 100644
index 0000000000..c6011dc1de
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test11/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test11.c
+)
+
+add_executable(paltest_vsnwprintf_test11
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnwprintf_test11 coreclrpal)
+
+target_link_libraries(paltest_vsnwprintf_test11
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test11/test11.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test11/test11.c
new file mode 100644
index 0000000000..af54985bdc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test11/test11.c
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test11.c
+**
+** Purpose: Test #11 for the _vsnwprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoNumTest(convert("foo %u"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %lu"), 0xFFFF, convert("foo 65535"));
+ DoNumTest(convert("foo %hu"), 0xFFFF, convert("foo 65535"));
+ DoNumTest(convert("foo %Lu"), pos, convert("foo 42"));
+ DoI64NumTest(convert("foo %I64u"), l, "42", convert("foo 42"));
+ DoNumTest(convert("foo %3u"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %-3u"), pos, convert("foo 42 "));
+ DoNumTest(convert("foo %.1u"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %.3u"), pos, convert("foo 042"));
+ DoNumTest(convert("foo %03u"), pos, convert("foo 042"));
+ DoNumTest(convert("foo %#u"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %+u"), pos, convert("foo 42"));
+ DoNumTest(convert("foo % u"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %+u"), neg, convert("foo 4294967254"));
+ DoNumTest(convert("foo % u"), neg, convert("foo 4294967254"));
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test11/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test11/testinfo.dat
new file mode 100644
index 0000000000..083b0fa5af
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test11/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnwprintf
+Name = Positive Test for _vsnwprintf
+TYPE = DEFAULT
+EXE1 = test11
+Description
+= Tests the PAL implementation of the _vsnwprintf function.
+= Tests _vsnwprintf with unsigned numbers.
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test12/CMakeLists.txt
new file mode 100644
index 0000000000..bd9652c2fb
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test12/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test12.c
+)
+
+add_executable(paltest_vsnwprintf_test12
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnwprintf_test12 coreclrpal)
+
+target_link_libraries(paltest_vsnwprintf_test12
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test12/test12.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test12/test12.c
new file mode 100644
index 0000000000..b593a82b4b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test12/test12.c
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test12.c
+**
+** Purpose: Test #12 for the _vsnwprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 0x1234ab;
+ INT64 l = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoNumTest(convert("foo %x"), pos, convert("foo 1234ab"));
+ DoNumTest(convert("foo %lx"), pos, convert("foo 1234ab"));
+ DoNumTest(convert("foo %hx"), pos, convert("foo 34ab"));
+ DoNumTest(convert("foo %Lx"), pos, convert("foo 1234ab"));
+ DoI64NumTest(convert("foo %I64x"), l, "0x1234567887654321",
+ convert("foo 1234567887654321"));
+ DoNumTest(convert("foo %7x"), pos, convert("foo 1234ab"));
+ DoNumTest(convert("foo %-7x"), pos, convert("foo 1234ab "));
+ DoNumTest(convert("foo %.1x"), pos, convert("foo 1234ab"));
+ DoNumTest(convert("foo %.7x"), pos, convert("foo 01234ab"));
+ DoNumTest(convert("foo %07x"), pos, convert("foo 01234ab"));
+ DoNumTest(convert("foo %#x"), pos, convert("foo 0x1234ab"));
+ DoNumTest(convert("foo %+x"), pos, convert("foo 1234ab"));
+ DoNumTest(convert("foo % x"), pos, convert("foo 1234ab"));
+ DoNumTest(convert("foo %+x"), neg, convert("foo ffffffd6"));
+ DoNumTest(convert("foo % x"), neg, convert("foo ffffffd6"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test12/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test12/testinfo.dat
new file mode 100644
index 0000000000..a4450ed8d0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test12/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnwprintf
+Name = Positive Test for _vsnwprintf
+TYPE = DEFAULT
+EXE1 = test12
+Description
+= Tests the PAL implementation of the _vsnwprintf function.
+= Tests _vsnwprintf with hex numbers (lowercase).
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test13/CMakeLists.txt
new file mode 100644
index 0000000000..c608ab84e3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test13/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test13.c
+)
+
+add_executable(paltest_vsnwprintf_test13
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnwprintf_test13 coreclrpal)
+
+target_link_libraries(paltest_vsnwprintf_test13
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test13/test13.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test13/test13.c
new file mode 100644
index 0000000000..59a9dc496f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test13/test13.c
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test13.c
+**
+** Purpose: Test #13 for the _vsnwprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 0x1234ab;
+ INT64 l = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoNumTest(convert("foo %X"), pos, convert("foo 1234AB"));
+ DoNumTest(convert("foo %lX"), pos, convert("foo 1234AB"));
+ DoNumTest(convert("foo %hX"), pos, convert("foo 34AB"));
+ DoNumTest(convert("foo %LX"), pos, convert("foo 1234AB"));
+ DoI64NumTest(convert("foo %I64X"), l, "0x1234567887654321",
+ convert("foo 1234567887654321"));
+ DoNumTest(convert("foo %7X"), pos, convert("foo 1234AB"));
+ DoNumTest(convert("foo %-7X"), pos, convert("foo 1234AB "));
+ DoNumTest(convert("foo %.1X"), pos, convert("foo 1234AB"));
+ DoNumTest(convert("foo %.7X"), pos, convert("foo 01234AB"));
+ DoNumTest(convert("foo %07X"), pos, convert("foo 01234AB"));
+ DoNumTest(convert("foo %#X"), pos, convert("foo 0X1234AB"));
+ DoNumTest(convert("foo %+X"), pos, convert("foo 1234AB"));
+ DoNumTest(convert("foo % X"), pos, convert("foo 1234AB"));
+ DoNumTest(convert("foo %+X"), neg, convert("foo FFFFFFD6"));
+ DoNumTest(convert("foo % X"), neg, convert("foo FFFFFFD6"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test13/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test13/testinfo.dat
new file mode 100644
index 0000000000..fa54ae8a62
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test13/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnwprintf
+Name = Positive Test for _vsnwprintf
+TYPE = DEFAULT
+EXE1 = test13
+Description
+= Tests the PAL implementation of the _vsnwprintf function.
+= Tests _vsnwprintf with hex numbers (uppercase).
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test14/CMakeLists.txt
new file mode 100644
index 0000000000..3bf157a2b3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test14/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test14.c
+)
+
+add_executable(paltest_vsnwprintf_test14
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnwprintf_test14 coreclrpal)
+
+target_link_libraries(paltest_vsnwprintf_test14
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test14/test14.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test14/test14.c
new file mode 100644
index 0000000000..633f9d68ae
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test14/test14.c
@@ -0,0 +1,63 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test14.c
+**
+** Purpose: Test #14 for the _vsnwprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 256.0;
+ double neg = -256.0;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoDoubleTest(convert("foo %e"), val, convert("foo 2.560000e+002"),
+ convert("foo 2.560000e+02"));
+ DoDoubleTest(convert("foo %le"), val, convert("foo 2.560000e+002"),
+ convert("foo 2.560000e+02"));
+ DoDoubleTest(convert("foo %he"), val, convert("foo 2.560000e+002"),
+ convert("foo 2.560000e+02"));
+ DoDoubleTest(convert("foo %Le"), val, convert("foo 2.560000e+002"),
+ convert("foo 2.560000e+02"));
+ DoDoubleTest(convert("foo %I64e"), val, convert("foo 2.560000e+002"),
+ convert("foo 2.560000e+02"));
+ DoDoubleTest(convert("foo %14e"), val, convert("foo 2.560000e+002"),
+ convert("foo 2.560000e+02"));
+ DoDoubleTest(convert("foo %-14e"), val, convert("foo 2.560000e+002 "),
+ convert("foo 2.560000e+02 "));
+ DoDoubleTest(convert("foo %.1e"), val, convert("foo 2.6e+002"),
+ convert("foo 2.6e+02"));
+ DoDoubleTest(convert("foo %.8e"), val, convert("foo 2.56000000e+002"),
+ convert("foo 2.56000000e+02"));
+ DoDoubleTest(convert("foo %014e"), val, convert("foo 02.560000e+002"),
+ convert("foo 002.560000e+02"));
+ DoDoubleTest(convert("foo %#e"), val, convert("foo 2.560000e+002"),
+ convert("foo 2.560000e+02"));
+ DoDoubleTest(convert("foo %+e"), val, convert("foo +2.560000e+002"),
+ convert("foo +2.560000e+02"));
+ DoDoubleTest(convert("foo % e"), val, convert("foo 2.560000e+002"),
+ convert("foo 2.560000e+02"));
+ DoDoubleTest(convert("foo %+e"), neg, convert("foo -2.560000e+002"),
+ convert("foo -2.560000e+02"));
+ DoDoubleTest(convert("foo % e"), neg, convert("foo -2.560000e+002"),
+ convert("foo -2.560000e+02"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test14/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test14/testinfo.dat
new file mode 100644
index 0000000000..0796f5e81c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test14/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnwprintf
+Name = Positive Test for _vsnwprintf
+TYPE = DEFAULT
+EXE1 = test14
+Description
+= Tests the PAL implementation of the _vsnwprintf function.
+= Tests _vsnwprintf with exponential format doubles (lowercase).
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test15/CMakeLists.txt
new file mode 100644
index 0000000000..eedc7bb9db
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test15/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test15.c
+)
+
+add_executable(paltest_vsnwprintf_test15
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnwprintf_test15 coreclrpal)
+
+target_link_libraries(paltest_vsnwprintf_test15
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test15/test15.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test15/test15.c
new file mode 100644
index 0000000000..0af41fe1dc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test15/test15.c
@@ -0,0 +1,64 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test15.c
+**
+** Purpose: Test #15 for the _vsnwprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 256.0;
+ double neg = -256.0;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoDoubleTest(convert("foo %E"), val, convert("foo 2.560000E+002"),
+ convert("foo 2.560000E+02"));
+ DoDoubleTest(convert("foo %lE"), val, convert("foo 2.560000E+002"),
+ convert("foo 2.560000E+02"));
+ DoDoubleTest(convert("foo %hE"), val, convert("foo 2.560000E+002"),
+ convert("foo 2.560000E+02"));
+ DoDoubleTest(convert("foo %LE"), val, convert("foo 2.560000E+002"),
+ convert("foo 2.560000E+02"));
+ DoDoubleTest(convert("foo %I64E"), val, convert("foo 2.560000E+002"),
+ convert("foo 2.560000E+02"));
+ DoDoubleTest(convert("foo %14E"), val, convert("foo 2.560000E+002"),
+ convert("foo 2.560000E+02"));
+ DoDoubleTest(convert("foo %-14E"), val, convert("foo 2.560000E+002 "),
+ convert("foo 2.560000E+02 "));
+ DoDoubleTest(convert("foo %.1E"), val, convert("foo 2.6E+002"),
+ convert("foo 2.6E+02"));
+ DoDoubleTest(convert("foo %.8E"), val, convert("foo 2.56000000E+002"),
+ convert("foo 2.56000000E+02"));
+ DoDoubleTest(convert("foo %014E"), val, convert("foo 02.560000E+002"),
+ convert("foo 002.560000E+02"));
+ DoDoubleTest(convert("foo %#E"), val, convert("foo 2.560000E+002"),
+ convert("foo 2.560000E+02"));
+ DoDoubleTest(convert("foo %+E"), val, convert("foo +2.560000E+002"),
+ convert("foo +2.560000E+02"));
+ DoDoubleTest(convert("foo % E"), val, convert("foo 2.560000E+002"),
+ convert("foo 2.560000E+02"));
+ DoDoubleTest(convert("foo %+E"), neg, convert("foo -2.560000E+002"),
+ convert("foo -2.560000E+02"));
+ DoDoubleTest(convert("foo % E"), neg, convert("foo -2.560000E+002"),
+ convert("foo -2.560000E+002"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test15/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test15/testinfo.dat
new file mode 100644
index 0000000000..9de3c83b8a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test15/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnwprintf
+Name = Positive Test for _vsnwprintf
+TYPE = DEFAULT
+EXE1 = test15
+Description
+= Tests the PAL implementation of the _vsnwprintf function.
+= Tests _vsnwprintf with exponential format doubles (uppercase).
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test16/CMakeLists.txt
new file mode 100644
index 0000000000..a469c497e9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test16/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test16.c
+)
+
+add_executable(paltest_vsnwprintf_test16
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnwprintf_test16 coreclrpal)
+
+target_link_libraries(paltest_vsnwprintf_test16
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test16/test16.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test16/test16.c
new file mode 100644
index 0000000000..77571b01b3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test16/test16.c
@@ -0,0 +1,63 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test16.c
+**
+** Purpose: Test #16 for the _vsnwprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoDoubleTest(convert("foo %f"), val, convert("foo 2560.001000"),
+ convert("foo 2560.001000"));
+ DoDoubleTest(convert("foo %lf"), val, convert("foo 2560.001000"),
+ convert("foo 2560.001000"));
+ DoDoubleTest(convert("foo %hf"), val, convert("foo 2560.001000"),
+ convert("foo 2560.001000"));
+ DoDoubleTest(convert("foo %Lf"), val, convert("foo 2560.001000"),
+ convert("foo 2560.001000"));
+ DoDoubleTest(convert("foo %I64f"), val, convert("foo 2560.001000"),
+ convert("foo 2560.001000"));
+ DoDoubleTest(convert("foo %12f"), val, convert("foo 2560.001000"),
+ convert("foo 2560.001000"));
+ DoDoubleTest(convert("foo %-12f"), val, convert("foo 2560.001000 "),
+ convert("foo 2560.001000 "));
+ DoDoubleTest(convert("foo %.1f"), val, convert("foo 2560.0"),
+ convert("foo 2560.0"));
+ DoDoubleTest(convert("foo %.8f"), val, convert("foo 2560.00100000"),
+ convert("foo 2560.00100000"));
+ DoDoubleTest(convert("foo %012f"), val, convert("foo 02560.001000"),
+ convert("foo 02560.001000"));
+ DoDoubleTest(convert("foo %#f"), val, convert("foo 2560.001000"),
+ convert("foo 2560.001000"));
+ DoDoubleTest(convert("foo %+f"), val, convert("foo +2560.001000"),
+ convert("foo +2560.001000"));
+ DoDoubleTest(convert("foo % f"), val, convert("foo 2560.001000"),
+ convert("foo 2560.001000"));
+ DoDoubleTest(convert("foo %+f"), neg, convert("foo -2560.001000"),
+ convert("foo -2560.001000"));
+ DoDoubleTest(convert("foo % f"), neg, convert("foo -2560.001000"),
+ convert("foo -2560.001000"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test16/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test16/testinfo.dat
new file mode 100644
index 0000000000..b7134c785b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test16/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnwprintf
+Name = Positive Test for _vsnwprintf
+TYPE = DEFAULT
+EXE1 = test16
+Description
+= Tests the PAL implementation of the _vsnwprintf function.
+= Tests _vsnwprintf with decimal point format doubles.
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test17/CMakeLists.txt
new file mode 100644
index 0000000000..f429e94417
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test17/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test17.c
+)
+
+add_executable(paltest_vsnwprintf_test17
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnwprintf_test17 coreclrpal)
+
+target_link_libraries(paltest_vsnwprintf_test17
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test17/test17.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test17/test17.c
new file mode 100644
index 0000000000..3a9d70ad03
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test17/test17.c
@@ -0,0 +1,65 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test17.c
+**
+** Purpose: Test #17 for the _vsnwprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoDoubleTest(convert("foo %g"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %lg"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %hg"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %Lg"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %I64g"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %5g"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %-5g"), val, convert("foo 2560 "),
+ convert("foo 2560 "));
+ DoDoubleTest(convert("foo %.1g"), val, convert("foo 3e+003"),
+ convert("foo 3e+03"));
+ DoDoubleTest(convert("foo %.2g"), val, convert("foo 2.6e+003"),
+ convert("foo 2.6e+03"));
+ DoDoubleTest(convert("foo %.12g"), val, convert("foo 2560.001"),
+ convert("foo 2560.001"));
+ DoDoubleTest(convert("foo %06g"), val, convert("foo 002560"),
+ convert("foo 002560"));
+ DoDoubleTest(convert("foo %#g"), val, convert("foo 2560.00"),
+ convert("foo 2560.00"));
+ DoDoubleTest(convert("foo %+g"), val, convert("foo +2560"),
+ convert("foo +2560"));
+ DoDoubleTest(convert("foo % g"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %+g"), neg, convert("foo -2560"),
+ convert("foo -2560"));
+ DoDoubleTest(convert("foo % g"), neg, convert("foo -2560"),
+ convert("foo -2560"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test17/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test17/testinfo.dat
new file mode 100644
index 0000000000..5d5553151e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test17/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnwprintf
+Name = Positive Test for _vsnwprintf
+TYPE = DEFAULT
+EXE1 = test17
+Description
+= Tests the PAL implementation of the _vsnwprintf function.
+= Tests _vsnwprintf with compact format doubles (lowercase).
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test18/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test18/CMakeLists.txt
new file mode 100644
index 0000000000..25dd6a2c5b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test18/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test18.c
+)
+
+add_executable(paltest_vsnwprintf_test18
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnwprintf_test18 coreclrpal)
+
+target_link_libraries(paltest_vsnwprintf_test18
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test18/test18.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test18/test18.c
new file mode 100644
index 0000000000..03f9870113
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test18/test18.c
@@ -0,0 +1,65 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test18.c
+**
+** Purpose: Test #18 for the _vsnwprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoDoubleTest(convert("foo %G"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %lG"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %hG"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %LG"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %I64G"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %5G"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %-5G"), val, convert("foo 2560 "),
+ convert("foo 2560 "));
+ DoDoubleTest(convert("foo %.1G"), val, convert("foo 3E+003"),
+ convert("foo 3E+03"));
+ DoDoubleTest(convert("foo %.2G"), val, convert("foo 2.6E+003"),
+ convert("foo 2.6E+03"));
+ DoDoubleTest(convert("foo %.12G"), val, convert("foo 2560.001"),
+ convert("foo 2560.001"));
+ DoDoubleTest(convert("foo %06G"), val, convert("foo 002560"),
+ convert("foo 002560"));
+ DoDoubleTest(convert("foo %#G"), val, convert("foo 2560.00"),
+ convert("foo 2560.00"));
+ DoDoubleTest(convert("foo %+G"), val, convert("foo +2560"),
+ convert("foo +2560"));
+ DoDoubleTest(convert("foo % G"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %+G"), neg, convert("foo -2560"),
+ convert("foo -2560"));
+ DoDoubleTest(convert("foo % G"), neg, convert("foo -2560"),
+ convert("foo -2560"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test18/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test18/testinfo.dat
new file mode 100644
index 0000000000..f56c80980d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test18/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnwprintf
+Name = Positive Test for _vsnwprintf
+TYPE = DEFAULT
+EXE1 = test18
+Description
+= Tests the PAL implementation of the _vsnwprintf function.
+= Tests _vsnwprintf with compact format doubles (uppercase).
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test19/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test19/CMakeLists.txt
new file mode 100644
index 0000000000..9c636b8b0a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test19/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test19.c
+)
+
+add_executable(paltest_vsnwprintf_test19
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnwprintf_test19 coreclrpal)
+
+target_link_libraries(paltest_vsnwprintf_test19
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test19/test19.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test19/test19.c
new file mode 100644
index 0000000000..fea275a242
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test19/test19.c
@@ -0,0 +1,139 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test18.c
+**
+** Purpose: Test #18 for the _vsnwprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+#define DOTEST(a,b,c,d,e) DoTest(a,b,(void*)c,d,e)
+
+void DoArgumentPrecTest(WCHAR *formatstr, int precision, void *param,
+ WCHAR *paramstr, WCHAR *checkstr1, WCHAR *checkstr2)
+{
+ WCHAR buf[256];
+
+ TestVsnwprintf(buf, 256, formatstr, precision, param);
+ if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0 &&
+ memcmp(buf, checkstr2, wcslen(checkstr2) + 2) != 0)
+ {
+ Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n",
+ paramstr,
+ convertC(formatstr),
+ precision,
+ convertC(checkstr1),
+ convertC(checkstr2),
+ convertC(buf));
+ }
+}
+void DoArgumentPrecDoubleTest(WCHAR *formatstr, int precision, double param,
+ WCHAR *checkstr1, WCHAR *checkstr2)
+{
+ WCHAR buf[256];
+
+ TestVsnwprintf(buf, 256, formatstr, precision, param);
+ if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0 &&
+ memcmp(buf, checkstr2, wcslen(checkstr2) + 2) != 0)
+ {
+ Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n",
+ param, convertC(formatstr),
+ precision,
+ convertC(checkstr1),
+ convertC(checkstr2),
+ convertC(buf));
+ }
+}
+
+/*
+ * Uses memcmp & wcslen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoArgumentPrecTest(convert("%.*s"), 2, convert("bar"), convert("bar"),
+ convert("ba"), convert("ba"));
+ DoArgumentPrecTest(convert("%.*c"), 0, (void*)'a', convert("a"),
+ convert("a"), convert("a"));
+ DoArgumentPrecTest(convert("%.*c"), 4, (void*)'a', convert("a"),
+ convert("a"), convert("a"));
+ DoArgumentPrecTest(convert("%.*C"), 0, (void*)'a', convert("a"),
+ convert("a"), convert("a"));
+ DoArgumentPrecTest(convert("%.*C"), 4, (void*)'a', convert("a"),
+ convert("a"), convert("a"));
+ DoArgumentPrecTest(convert("%.*d"), 1, (void*)42, convert("42"),
+ convert("42"), convert("42"));
+ DoArgumentPrecTest(convert("%.*d"), 3, (void*)42, convert("42"),
+ convert("042"), convert("042"));
+ DoArgumentPrecTest(convert("%.*i"), 1, (void*)42, convert("42"),
+ convert("42"), convert("42"));
+ DoArgumentPrecTest(convert("%.*i"), 3, (void*)42, convert("42"),
+ convert("042"), convert("042"));
+ DoArgumentPrecTest(convert("%.*o"), 1, (void*)42, convert("42"),
+ convert("52"), convert("52"));
+ DoArgumentPrecTest(convert("%.*o"), 3, (void*)42, convert("42"),
+ convert("052"), convert("052"));
+ DoArgumentPrecTest(convert("%.*u"), 1, (void*)42, convert("42"),
+ convert("42"), convert("42"));
+ DoArgumentPrecTest(convert("%.*u"), 3, (void*)42, convert("42"),
+ convert("042"), convert("042"));
+ DoArgumentPrecTest(convert("%.*x"), 1, (void*)0x42, convert("0x42"),
+ convert("42"), convert("42"));
+ DoArgumentPrecTest(convert("%.*x"), 3, (void*)0x42, convert("0x42"),
+ convert("042"), convert("042"));
+ DoArgumentPrecTest(convert("%.*X"), 1, (void*)0x42, convert("0x42"),
+ convert("42"), convert("42"));
+ DoArgumentPrecTest(convert("%.*X"), 3, (void*)0x42, convert("0x42"),
+ convert("042"), convert("042"));
+
+
+ DoArgumentPrecDoubleTest(convert("%.*e"), 1, 2.01, convert("2.0e+000"),
+ convert("2.0e+00"));
+ DoArgumentPrecDoubleTest(convert("%.*e"), 3, 2.01, convert("2.010e+000"),
+ convert("2.010e+00"));
+ DoArgumentPrecDoubleTest(convert("%.*E"), 1, 2.01, convert("2.0E+000"),
+ convert("2.0E+00"));
+ DoArgumentPrecDoubleTest(convert("%.*E"), 3, 2.01, convert("2.010E+000"),
+ convert("2.010E+00"));
+ DoArgumentPrecDoubleTest(convert("%.*f"), 1, 2.01, convert("2.0"),
+ convert("2.0"));
+ DoArgumentPrecDoubleTest(convert("%.*f"), 3, 2.01, convert("2.010"),
+ convert("2.010"));
+ DoArgumentPrecDoubleTest(convert("%.*g"), 1, 256.01, convert("3e+002"),
+ convert("3e+02"));
+ DoArgumentPrecDoubleTest(convert("%.*g"), 3, 256.01, convert("256"),
+ convert("256"));
+ DoArgumentPrecDoubleTest(convert("%.*g"), 4, 256.01, convert("256"),
+ convert("256"));
+ DoArgumentPrecDoubleTest(convert("%.*g"), 6, 256.01, convert("256.01"),
+ convert("256.01"));
+ DoArgumentPrecDoubleTest(convert("%.*G"), 1, 256.01, convert("3E+002"),
+ convert("3E+02"));
+ DoArgumentPrecDoubleTest(convert("%.*G"), 3, 256.01, convert("256"),
+ convert("256"));
+ DoArgumentPrecDoubleTest(convert("%.*G"), 4, 256.01, convert("256"),
+ convert("256"));
+ DoArgumentPrecDoubleTest(convert("%.*G"), 6, 256.01, convert("256.01"),
+ convert("256.01"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test19/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test19/testinfo.dat
new file mode 100644
index 0000000000..77178f1471
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test19/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnwprintf
+Name = Positive Test for _vsnwprintf
+TYPE = DEFAULT
+EXE1 = test19
+Description
+= Tests the PAL implementation of the _vsnwprintf function.
+= Tests _vsnwprintf with argument specified precision.
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test2/CMakeLists.txt
new file mode 100644
index 0000000000..817657ea61
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_vsnwprintf_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnwprintf_test2 coreclrpal)
+
+target_link_libraries(paltest_vsnwprintf_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test2/test2.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test2/test2.c
new file mode 100644
index 0000000000..20499954db
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test2/test2.c
@@ -0,0 +1,40 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test2.c
+**
+** Purpose: Test #2 for the _vsnwprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoWStrTest(convert("foo %s"), convert("bar"), convert("foo bar"));
+ DoStrTest(convert("foo %hs"), "bar", convert("foo bar"));
+ DoWStrTest(convert("foo %ls"), convert("bar"), convert("foo bar"));
+ DoWStrTest(convert("foo %ws"), convert("bar"), convert("foo bar"));
+ DoWStrTest(convert("foo %Ls"), convert("bar"), convert("foo bar"));
+ DoWStrTest(convert("foo %I64s"), convert("bar"), convert("foo bar"));
+ DoWStrTest(convert("foo %5s"), convert("bar"), convert("foo bar"));
+ DoWStrTest(convert("foo %.2s"), convert("bar"), convert("foo ba"));
+ DoWStrTest(convert("foo %5.2s"), convert("bar"), convert("foo ba"));
+ DoWStrTest(convert("foo %-5s"), convert("bar"), convert("foo bar "));
+ DoWStrTest(convert("foo %05s"), convert("bar"), convert("foo 00bar"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test2/testinfo.dat
new file mode 100644
index 0000000000..429911bd83
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test2/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnwprintf
+Name = Positive Test for _vsnwprintf
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Tests the PAL implementation of the _vsnwprintf function.
+= Tests _vsnwprintf with strings.
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test3/CMakeLists.txt
new file mode 100644
index 0000000000..4af3e36f3b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_vsnwprintf_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnwprintf_test3 coreclrpal)
+
+target_link_libraries(paltest_vsnwprintf_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test3/test3.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test3/test3.c
new file mode 100644
index 0000000000..9a37d3fc4b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test3/test3.c
@@ -0,0 +1,40 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test3.c
+**
+** Purpose: Test #3 for the _vsnwprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoStrTest(convert("foo %S"), "bar", convert("foo bar"));
+ DoStrTest(convert("foo %hS"), "bar", convert("foo bar"));
+ DoWStrTest(convert("foo %lS"), convert("bar"), convert("foo bar"));
+ DoWStrTest(convert("foo %wS"), convert("bar"), convert("foo bar"));
+ DoStrTest(convert("foo %LS"), "bar", convert("foo bar"));
+ DoStrTest(convert("foo %I64S"), "bar", convert("foo bar"));
+ DoStrTest(convert("foo %5S"), "bar", convert("foo bar"));
+ DoStrTest(convert("foo %.2S"), "bar", convert("foo ba"));
+ DoStrTest(convert("foo %5.2S"), "bar", convert("foo ba"));
+ DoStrTest(convert("foo %-5S"), "bar", convert("foo bar "));
+ DoStrTest(convert("foo %05S"), "bar", convert("foo 00bar"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test3/testinfo.dat
new file mode 100644
index 0000000000..d4e2686763
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test3/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnwprintf
+Name = Positive Test for _vsnwprintf
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Tests the PAL implementation of the _vsnwprintf function.
+= Tests _vsnwprintf with wide strings.
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test4/CMakeLists.txt
new file mode 100644
index 0000000000..b7ff9e7bb3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_vsnwprintf_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnwprintf_test4 coreclrpal)
+
+target_link_libraries(paltest_vsnwprintf_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test4/test4.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test4/test4.c
new file mode 100644
index 0000000000..6f39be2a80
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test4/test4.c
@@ -0,0 +1,121 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test4.c
+**
+** Purpose: Test #4 for the _vsnwprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+static void DoPointerTest(WCHAR *formatstr, void* param, WCHAR* paramstr,
+ WCHAR *checkstr1)
+{
+ WCHAR buf[256] = { 0 };
+
+ TestVsnwprintf(buf, 256, formatstr, param);
+ if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0)
+
+ {
+ Fail("ERROR: failed to insert pointer to %#p into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ paramstr,
+ convertC(formatstr),
+ convertC(checkstr1),
+ convertC(buf));
+ }
+}
+
+static void DoI64DoubleTest(WCHAR *formatstr, INT64 value, WCHAR *valuestr,
+ WCHAR *checkstr1)
+{
+ WCHAR buf[256] = { 0 };
+
+ TestVsnwprintf(buf, 256, formatstr, value);
+ if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0)
+ {
+ Fail("ERROR: failed to insert %s into \"%s\"\n"
+ "Expected \"%s\", got \"%s\".\n",
+ value,
+ convertC(formatstr),
+ convertC(checkstr1),
+ convertC(buf));
+ }
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ void *ptr = (void*) 0x123456;
+ INT64 lptr = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+/*
+** Run only on 64 bit platforms
+*/
+#if defined(BIT64) && defined(PLATFORM_UNIX)
+ Trace("Testing for 64 Bit Platforms \n");
+ DoPointerTest(convert("%p"), NULL, convert("NULL"), convert("00000000"));
+ DoPointerTest(convert("%p"), ptr, convert("pointer to 0x123456"),
+ convert("0000000000123456"));
+ DoPointerTest(convert("%17p"), ptr, convert("pointer to 0x123456"),
+ convert(" 0000000000123456"));
+ DoPointerTest(convert("%17p"), ptr, convert("pointer to 0x123456"),
+ convert(" 0000000000123456"));
+ DoPointerTest(convert("%-17p"), ptr, convert("pointer to 0x123456"),
+ convert("0000000000123456 "));
+ DoPointerTest(convert("%+p"), ptr, convert("pointer to 0x123456"),
+ convert("0000000000123456"));
+ DoPointerTest(convert("%#p"), ptr, convert("pointer to 0x123456"),
+ convert("0X0000000000123456"));
+ DoPointerTest(convert("%lp"), ptr, convert("pointer to 0x123456"),
+ convert("00123456"));
+ DoPointerTest(convert("%hp"), ptr, convert("pointer to 0x123456"),
+ convert("00003456"));
+ DoPointerTest(convert("%Lp"), ptr, convert("pointer to 0x123456"),
+ convert("00123456"));
+ DoI64DoubleTest(convert("%I64p"), lptr,
+ convert("pointer to 0x1234567887654321"),
+ convert("1234567887654321"));
+
+#else
+ Trace("Testing for Non 64 Bit Platforms \n");
+ DoPointerTest(convert("%p"), NULL, convert("NULL"), convert("00000000"));
+ DoPointerTest(convert("%p"), ptr, convert("pointer to 0x123456"),
+ convert("00123456"));
+ DoPointerTest(convert("%9p"), ptr, convert("pointer to 0x123456"),
+ convert(" 00123456"));
+ DoPointerTest(convert("%09p"), ptr, convert("pointer to 0x123456"),
+ convert(" 00123456"));
+ DoPointerTest(convert("%-9p"), ptr, convert("pointer to 0x123456"),
+ convert("00123456 "));
+ DoPointerTest(convert("%+p"), ptr, convert("pointer to 0x123456"),
+ convert("00123456"));
+ DoPointerTest(convert("%#p"), ptr, convert("pointer to 0x123456"),
+ convert("0X00123456"));
+ DoPointerTest(convert("%lp"), ptr, convert("pointer to 0x123456"),
+ convert("00123456"));
+ DoPointerTest(convert("%hp"), ptr, convert("pointer to 0x123456"),
+ convert("00003456"));
+ DoPointerTest(convert("%Lp"), ptr, convert("pointer to 0x123456"),
+ convert("00123456"));
+ DoI64DoubleTest(convert("%I64p"), lptr,
+ convert("pointer to 0x1234567887654321"),
+ convert("1234567887654321"));
+#endif
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test4/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test4/testinfo.dat
new file mode 100644
index 0000000000..56f488a66a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test4/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnwprintf
+Name = Positive Test for _vsnwprintf
+TYPE = DEFAULT
+EXE1 = test4
+Description
+= Tests the PAL implementation of the _vsnwprintf function.
+= Tests _vsnwprintf with pointers.
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test5/CMakeLists.txt
new file mode 100644
index 0000000000..9b316b9f90
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test5.c
+)
+
+add_executable(paltest_vsnwprintf_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnwprintf_test5 coreclrpal)
+
+target_link_libraries(paltest_vsnwprintf_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test5/test5.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test5/test5.c
new file mode 100644
index 0000000000..224db766ff
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test5/test5.c
@@ -0,0 +1,81 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test5.c
+**
+** Purpose: Test #5 for the _vsnwprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+static void DoTest(WCHAR *formatstr, int param, WCHAR *checkstr)
+{
+ WCHAR buf[256] = { 0 };
+ int n = -1;
+
+ TestVsnwprintf(buf, 256, formatstr, &n);
+
+ if (n != param)
+ {
+ Fail("ERROR: Expected count parameter to resolve to %d, got %d\n",
+ param, n);
+ }
+
+ if (memcmp(buf, checkstr, wcslen(buf)*2 + 2) != 0)
+ {
+ Fail("ERROR: Expected \"%s\" got \"%s\".\n",
+ convertC(checkstr), convertC(buf));
+ }
+}
+
+static void DoShortTest(WCHAR *formatstr, int param, WCHAR *checkstr)
+{
+ WCHAR buf[256] = { 0 };
+ short int n = -1;
+
+ TestVsnwprintf(buf, 256, formatstr, &n);
+
+ if (n != param)
+ {
+ Fail("ERROR: Expected count parameter to resolve to %d, got %d\n",
+ param, n);
+ }
+
+ if (memcmp(buf, checkstr, wcslen(buf)*2 + 2) != 0)
+ {
+ Fail("ERROR: Expected \"%s\" got \"%s\".\n",
+ convertC(checkstr), convertC(buf));
+ }
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoTest(convert("foo %n bar"), 4, convert("foo bar"));
+ DoTest(convert("foo %#n bar"), 4, convert("foo bar"));
+ DoTest(convert("foo % n bar"), 4, convert("foo bar"));
+ DoTest(convert("foo %+n bar"), 4, convert("foo bar"));
+ DoTest(convert("foo %-n bar"), 4, convert("foo bar"));
+ DoTest(convert("foo %0n bar"), 4, convert("foo bar"));
+ DoShortTest(convert("foo %hn bar"), 4, convert("foo bar"));
+ DoTest(convert("foo %ln bar"), 4, convert("foo bar"));
+ DoTest(convert("foo %Ln bar"), 4, convert("foo bar"));
+ DoTest(convert("foo %I64n bar"), 4, convert("foo bar"));
+ DoTest(convert("foo %20.3n bar"), 4, convert("foo bar"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test5/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test5/testinfo.dat
new file mode 100644
index 0000000000..35d3816a76
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test5/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnwprintf
+Name = Positive Test for _vsnwprintf
+TYPE = DEFAULT
+EXE1 = test5
+Description
+= Tests the PAL implementation of the _vsnwprintf function.
+= Tests _vsnwprintf with the count specifier.
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test6/CMakeLists.txt
new file mode 100644
index 0000000000..d3fad03597
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test6.c
+)
+
+add_executable(paltest_vsnwprintf_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnwprintf_test6 coreclrpal)
+
+target_link_libraries(paltest_vsnwprintf_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test6/test6.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test6/test6.c
new file mode 100644
index 0000000000..1bd83ea85c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test6/test6.c
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test6.c
+**
+** Purpose: Test #6 for the _vsnwprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR wc = (WCHAR) 'c';
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoWCharTest(convert("foo %c"), wc, convert("foo c"));
+ DoCharTest(convert("foo %hc"), 'b', convert("foo b"));
+ DoWCharTest(convert("foo %lc"), wc, convert("foo c"));
+ DoWCharTest(convert("foo %Lc"), wc, convert("foo c"));
+ DoWCharTest(convert("foo %I64c"), wc, convert("foo c"));
+ DoWCharTest(convert("foo %5c"), wc, convert("foo c"));
+ DoWCharTest(convert("foo %.0c"), wc, convert("foo c"));
+ DoWCharTest(convert("foo %-5c"), wc, convert("foo c "));
+ DoWCharTest(convert("foo %05c"), wc, convert("foo 0000c"));
+ DoWCharTest(convert("foo % c"), wc, convert("foo c"));
+ DoWCharTest(convert("foo %#c"), wc, convert("foo c"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test6/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test6/testinfo.dat
new file mode 100644
index 0000000000..6afe96d1cd
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test6/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnwprintf
+Name = Positive Test for _vsnwprintf
+TYPE = DEFAULT
+EXE1 = test6
+Description
+= Tests the PAL implementation of the _vsnwprintf function.
+= Tests _vsnwprintf with characters.
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test7/CMakeLists.txt
new file mode 100644
index 0000000000..cede861358
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test7/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test7.c
+)
+
+add_executable(paltest_vsnwprintf_test7
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnwprintf_test7 coreclrpal)
+
+target_link_libraries(paltest_vsnwprintf_test7
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test7/test7.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test7/test7.c
new file mode 100644
index 0000000000..e13798b784
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test7/test7.c
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test7.c
+**
+** Purpose: Test #7 for the _vsnwprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR wc = (WCHAR) 'c';
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoCharTest(convert("foo %C"), 'b', convert("foo b"));
+ DoWCharTest(convert("foo %hC"), wc, convert("foo c"));
+ DoCharTest(convert("foo %lC"), 'b', convert("foo b"));
+ DoCharTest(convert("foo %LC"), 'b', convert("foo b"));
+ DoCharTest(convert("foo %I64C"), 'b', convert("foo b"));
+ DoCharTest(convert("foo %5C"), 'b', convert("foo b"));
+ DoCharTest(convert("foo %.0C"), 'b', convert("foo b"));
+ DoCharTest(convert("foo %-5C"), 'b', convert("foo b "));
+ DoCharTest(convert("foo %05C"), 'b', convert("foo 0000b"));
+ DoCharTest(convert("foo % C"), 'b', convert("foo b"));
+ DoCharTest(convert("foo %#C"), 'b', convert("foo b"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test7/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test7/testinfo.dat
new file mode 100644
index 0000000000..ece40aa195
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test7/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnwprintf
+Name = Positive Test for _vsnwprintf
+TYPE = DEFAULT
+EXE1 = test7
+Description
+= Tests the PAL implementation of the _vsnwprintf function.
+= Tests _vsnwprintf with wide characters.
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test8/CMakeLists.txt
new file mode 100644
index 0000000000..846e7b9219
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test8/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test8.c
+)
+
+add_executable(paltest_vsnwprintf_test8
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnwprintf_test8 coreclrpal)
+
+target_link_libraries(paltest_vsnwprintf_test8
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test8/test8.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test8/test8.c
new file mode 100644
index 0000000000..8f02412eb0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test8/test8.c
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test8.c
+**
+** Purpose: Test #8 for the _vsnwprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoNumTest(convert("foo %d"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %ld"), 0xFFFF, convert("foo 65535"));
+ DoNumTest(convert("foo %hd"), 0xFFFF, convert("foo -1"));
+ DoNumTest(convert("foo %Ld"), pos, convert("foo 42"));
+ DoI64NumTest(convert("foo %I64d"), l, "42", convert("foo 42"));
+ DoNumTest(convert("foo %3d"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %-3d"), pos, convert("foo 42 "));
+ DoNumTest(convert("foo %.1d"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %.3d"), pos, convert("foo 042"));
+ DoNumTest(convert("foo %03d"), pos, convert("foo 042"));
+ DoNumTest(convert("foo %#d"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %+d"), pos, convert("foo +42"));
+ DoNumTest(convert("foo % d"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %+d"), neg, convert("foo -42"));
+ DoNumTest(convert("foo % d"), neg, convert("foo -42"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test8/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test8/testinfo.dat
new file mode 100644
index 0000000000..d7a567a6d6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test8/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnwprintf
+Name = Positive Test for _vsnwprintf
+TYPE = DEFAULT
+EXE1 = test8
+Description
+= Tests the PAL implementation of the _vsnwprintf function.
+= Tests _vsnwprintf with decimal numbers.
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test9/CMakeLists.txt
new file mode 100644
index 0000000000..e25eded172
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test9/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test9.c
+)
+
+add_executable(paltest_vsnwprintf_test9
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsnwprintf_test9 coreclrpal)
+
+target_link_libraries(paltest_vsnwprintf_test9
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test9/test9.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test9/test9.c
new file mode 100644
index 0000000000..7b5b6cd8a6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test9/test9.c
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test9.c
+**
+** Purpose: Test #9 for the _vsnwprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../_vsnwprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoNumTest(convert("foo %i"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %li"), 0xFFFF, convert("foo 65535"));
+ DoNumTest(convert("foo %hi"), 0xFFFF, convert("foo -1"));
+ DoNumTest(convert("foo %Li"), pos, convert("foo 42"));
+ DoI64NumTest(convert("foo %I64i"), l, "42", convert("foo 42"));
+ DoNumTest(convert("foo %3i"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %-3i"), pos, convert("foo 42 "));
+ DoNumTest(convert("foo %.1i"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %.3i"), pos, convert("foo 042"));
+ DoNumTest(convert("foo %03i"), pos, convert("foo 042"));
+ DoNumTest(convert("foo %#i"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %+i"), pos, convert("foo +42"));
+ DoNumTest(convert("foo % i"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %+i"), neg, convert("foo -42"));
+ DoNumTest(convert("foo % i"), neg, convert("foo -42"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test9/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test9/testinfo.dat
new file mode 100644
index 0000000000..726b060240
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test9/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _vsnwprintf
+Name = Positive Test for _vsnwprintf
+TYPE = DEFAULT
+EXE1 = test9
+Description
+= Tests the PAL implementation of the _vsnwprintf function.
+= Tests _vsnwprintf with integer numbers
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/_wcsicmp/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wcsicmp/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wcsicmp/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/CMakeLists.txt
new file mode 100644
index 0000000000..5f085cc723
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_wcsicmp_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wcsicmp_test1 coreclrpal)
+
+target_link_libraries(paltest_wcsicmp_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/test1.c
new file mode 100644
index 0000000000..dd4bb54680
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/test1.c
@@ -0,0 +1,68 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests that _wcsicmp correctly compares two strings with
+** case insensitivity.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+/*
+ * Note: The _wcsicmp is dependent on the LC_CTYPE category of the locale,
+ * and this is ignored by these tests.
+ */
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR str1[] = {'f','o','o',0};
+ WCHAR str2[] = {'f','O','o',0};
+ WCHAR str3[] = {'f','o','o','_','b','a','r',0};
+ WCHAR str4[] = {'f','o','o','b','a','r',0};
+
+ /*
+ * Initialize the PAL and return FAIL if this fails
+ */
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ if (_wcsicmp(str1, str2) != 0)
+ {
+ Fail ("ERROR: _wcsicmp returning incorrect value:\n"
+ "_wcsicmp(\"%S\", \"%S\") != 0\n", str1, str2);
+ }
+
+ if (_wcsicmp(str2, str3) >= 0)
+ {
+ Fail ("ERROR: _wcsicmp returning incorrect value:\n"
+ "_wcsicmp(\"%S\", \"%S\") >= 0\n", str2, str3);
+ }
+
+ if (_wcsicmp(str3, str4) >= 0)
+ {
+ Fail ("ERROR: _wcsicmp returning incorrect value:\n"
+ "_wcsicmp(\"%S\", \"%S\") >= 0\n", str3, str4);
+ }
+
+ if (_wcsicmp(str4, str1) <= 0)
+ {
+ Fail ("ERROR: _wcsicmp returning incorrect value:\n"
+ "_wcsicmp(\"%S\", \"%S\") <= 0\n", str4, str1);
+ }
+
+ if (_wcsicmp(str3, str2) <= 0)
+ {
+ Fail ("ERROR: _wcsicmp returning incorrect value:\n"
+ "_wcsicmp(\"%S\", \"%S\") <= 0\n", str2, str3);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/testinfo.dat
new file mode 100644
index 0000000000..9351a156e0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _wcsicmp
+Name = Test #1 for _wcsicmp
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests that _wcsicmp correctly compares two strings with case insensitivity.
diff --git a/src/pal/tests/palsuite/c_runtime/_wcslwr/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wcslwr/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wcslwr/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_wcslwr/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wcslwr/test1/CMakeLists.txt
new file mode 100644
index 0000000000..a78098f86a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wcslwr/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_wcslwr_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wcslwr_test1 coreclrpal)
+
+target_link_libraries(paltest_wcslwr_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_wcslwr/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_wcslwr/test1/test1.c
new file mode 100644
index 0000000000..3a758de39b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wcslwr/test1/test1.c
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Using memcmp to check the result, convert a wide character string
+** with capitals, to all lowercase using this function. Test #1 for the
+** wcslwr function
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+/* uses memcmp,wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR *test_str = NULL;
+ WCHAR *expect_str = NULL;
+ WCHAR *result_str = NULL;
+
+ /*
+ * Initialize the PAL and return FAIL if this fails
+ */
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ test_str = convert("aSdF 1#");
+ expect_str = convert("asdf 1#");
+
+ result_str = _wcslwr(test_str);
+ if (memcmp(result_str, expect_str, wcslen(expect_str)*2 + 2) != 0)
+ {
+ Fail ("ERROR: Expected to get \"%s\", got \"%s\".\n",
+ convertC(expect_str), convertC(result_str));
+ }
+
+ free(result_str);
+ free(expect_str);
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/_wcslwr/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_wcslwr/test1/testinfo.dat
new file mode 100644
index 0000000000..5d691d84d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wcslwr/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _wcslwr
+Name = Positive Test for _wcslwr
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Using memcmp to check the result, convert a wide character string
+= with capitals, to all lowercase using this function.
+
diff --git a/src/pal/tests/palsuite/c_runtime/_wcsnicmp/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wcsnicmp/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wcsnicmp/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/CMakeLists.txt
new file mode 100644
index 0000000000..afd3560b10
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_wcsnicmp_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wcsnicmp_test1 coreclrpal)
+
+target_link_libraries(paltest_wcsnicmp_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/test1.c
new file mode 100644
index 0000000000..0271bcc60d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/test1.c
@@ -0,0 +1,95 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Take two wide strings and compare them, giving different lengths.
+** Comparing str1 and str2 with str2 length, should return <0
+** Comparing str2 and str1 with str2 length, should return >0
+** Comparing str1 and str2 with str1 lenght, should return 0
+** Bring in str3, which has a capital, but this function is doing a lower
+** case compare. Just ensure that two strings which differ only by capitals
+** return 0.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+/*
+ * Notes: uses wcslen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR str1[] = {'f','o','o',0};
+ WCHAR str2[] = {'f','o','o','x',0};
+ WCHAR str3[] = {'f','O','o',0};
+ WCHAR str4[] = {'A','B','C','D','E',0};
+ WCHAR str5[] = {'A','B','C','D',']',0};
+ WCHAR str6[] = {'a','b','c','d','e',0};
+ WCHAR str7[] = {'a','b','c','d',']',0};
+ char cstr1[] = "foo";
+ char cstr2[] = "foox";
+ char cstr3[] = "fOo";
+ char cstr4[] = "ABCDE";
+ char cstr5[] = "ABCD]";
+ char cstr6[] = "abcde";
+ char cstr7[] = "abcd]";
+
+
+ /*
+ * Initialize the PAL and return FAIL if this fails
+ */
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ if (_wcsnicmp(str1, str2, wcslen(str2)) >= 0)
+ {
+ Fail ("ERROR: wcsnicmp(\"%s\", \"%s\", %d) returned >= 0\n", cstr1,
+ cstr2, wcslen(str2));
+ }
+
+ if (_wcsnicmp(str2, str1, wcslen(str2)) <= 0)
+ {
+ Fail ("ERROR: wcsnicmp(\"%s\", \"%s\", %d) returned <= 0\n", cstr2,
+ cstr1, wcslen(str2));
+ }
+
+ if (_wcsnicmp(str1, str2, wcslen(str1)) != 0)
+ {
+ Fail ("ERROR: wcsnicmp(\"%s\", \"%s\", %d) returned != 0\n", cstr1,
+ cstr2, wcslen(str1));
+ }
+
+ if (_wcsnicmp(str1, str3, wcslen(str1)) != 0)
+ {
+ Fail ("ERROR: wcsnicmp(\"%s\", \"%s\", %d) returned != 0\n", cstr1,
+ cstr3, wcslen(str1));
+ }
+
+ /* new testing */
+
+ /* str4 should be greater than str5 */
+ if (_wcsnicmp(str4, str5, wcslen(str4)) <= 0)
+ {
+ Fail ("ERROR: _wcsnicmp(\"%s\", \"%s\", %d) returned >= 0\n",
+ cstr4, cstr5, wcslen(str4));
+ }
+
+ /* str6 should be greater than str7 */
+ if (_wcsnicmp(str6, str7, wcslen(str6)) <= 0)
+ {
+ Fail ("ERROR: _wcsnicmp(\"%s\", \"%s\", %d) returned <= 0\n",
+ cstr6, cstr7, wcslen(str6));
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/testinfo.dat
new file mode 100644
index 0000000000..df49cc1a9a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/testinfo.dat
@@ -0,0 +1,18 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _wcsnicmp
+Name = Positive Test for _wcsnicmp
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Take two wide strings and compare them, giving different lengths.
+= Comparing str1 and str2 with str2 length, should return <0
+= Comparing str2 and str1 with str2 length, should return >0
+= Comparing str1 and str2 with str1 lenght, should return 0
+= Bring in str3, which has a capital, but this function is doing a lower
+= case compare. Just ensure that two strings which differ only by capitals
+= return 0.
diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wfopen/CMakeLists.txt
new file mode 100644
index 0000000000..19ee487a6a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wfopen/CMakeLists.txt
@@ -0,0 +1,10 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+add_subdirectory(test7)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wfopen/test1/CMakeLists.txt
new file mode 100644
index 0000000000..96df58ee54
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wfopen/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_wfopen_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wfopen_test1 coreclrpal)
+
+target_link_libraries(paltest_wfopen_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_wfopen/test1/test1.c
new file mode 100644
index 0000000000..81d2502cd5
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wfopen/test1/test1.c
@@ -0,0 +1,79 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests the PAL implementation of the _wfopen function.
+** This test simply attempts to open a number of files with
+** different modes. It checks to ensure a valid file
+** pointer is returned. It doesn't do any checking to
+** ensure the mode is really what it claims.
+**
+
+**
+**===================================================================*/
+
+
+#define UNICODE
+#include <palsuite.h>
+
+struct testCase
+{
+ int CorrectResult;
+ WCHAR mode[20];
+};
+
+int __cdecl main(int argc, char **argv)
+{
+
+ FILE *fp;
+ WCHAR name[128];
+ WCHAR base[] = {'t','e','s','t','f','i','l','e','s','\0'};
+ char * PrintResult;
+ int i;
+
+ struct testCase testCases[] =
+ {
+ {0, {'r','\0' }}, {1, {'w','\0'}}, {1, {'a','\0'}},
+ {0, {'r','+','\0'}}, {1, {'w','+','\0'}}, {1, {'a','+','\0'}},
+ {1, {'w','t','\0'}}, {1, {'w','b','\0'}}, {1, {'w','S','\0'}},
+ {1, {'w','c','\0'}}, {1, {'w','n','\0'}}, {1, {'w', 'R','\0'}},
+ {1, {'w','T','\0'}}, {0, {'t','w','\0'}}, {0, {'.','\0'}}
+ };
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+
+ for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++)
+ {
+ wcscpy(name,base);
+ wcscat(name,testCases[i].mode);
+
+ fp = _wfopen(name,testCases[i].mode);
+
+ if ((fp == 0 && testCases[i].CorrectResult != 0) ||
+ (testCases[i].CorrectResult == 0 && fp != 0) )
+ {
+ PrintResult = convertC(testCases[i].mode);
+ Fail("ERROR: fopen returned incorrectly "
+ "opening a file in %s mode. Perhaps it opened a "
+ "read only file which didn't exist and returned a correct "
+ "pointer?",PrintResult);
+ free(PrintResult);
+ }
+
+ memset(name, '\0', 128);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_wfopen/test1/testinfo.dat
new file mode 100644
index 0000000000..6514137c2f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wfopen/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _wfopen
+Name = Positive Test for _wfopen
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= This test simply attempts to open a number of files with different
+= modes. It checks to ensure a valid file pointer is returned. It
+= doesn't do any checking to ensure the mode is really what it claims.
+
diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wfopen/test2/CMakeLists.txt
new file mode 100644
index 0000000000..47203d86d5
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wfopen/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_wfopen_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wfopen_test2 coreclrpal)
+
+target_link_libraries(paltest_wfopen_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test2/test2.c b/src/pal/tests/palsuite/c_runtime/_wfopen/test2/test2.c
new file mode 100644
index 0000000000..921ffef19d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wfopen/test2/test2.c
@@ -0,0 +1,68 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test2.c
+**
+** Purpose: Tests the PAL implementation of the _wfopen function.
+** Test to ensure that you can write to a 'w' mode file.
+** And that you can't read from a 'w' mode file.
+**
+** Depends:
+** fprintf
+** fseek
+** fgets
+**
+
+**
+**===================================================================*/
+
+#define UNICODE
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+
+ FILE *fp;
+ char buffer[128];
+ WCHAR filename[] = {'t','e','s','t','f','i','l','e','\0'};
+ WCHAR write[] = {'w','\0'};
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ if( (fp = _wfopen( filename, write )) == NULL )
+ {
+ Fail( "ERROR: The file failed to open with 'w' mode.\n" );
+ }
+
+ /* Test that you can write */
+ if(fprintf(fp,"%s","some text") <= 0)
+ {
+ Fail("ERROR: Attempted to WRITE to a file opened with 'w' mode "
+ "but fprintf failed. Either fopen or fprintf have problems.");
+ }
+
+ if(fseek(fp, 0, SEEK_SET))
+ {
+ Fail("ERROR: fseek failed, and this test depends on it.");
+ }
+
+ /* Test that you can't read */
+ if(fgets(buffer,10,fp) != NULL)
+ {
+ Fail("ERROR: Tried to READ from a file with only 'w' mode set. "
+ "This should fail, but fgets didn't return NULL. "
+ "Either fgets or fopen is broken.");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_wfopen/test2/testinfo.dat
new file mode 100644
index 0000000000..3ed2e3bbed
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wfopen/test2/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _wfopen
+Name = Positive Test for _wfopen
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Test to ensure that you can write to a 'w' mode file. And that you can't
+= read from a 'w' mode file.
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wfopen/test3/CMakeLists.txt
new file mode 100644
index 0000000000..deec8bbfe6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wfopen/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_wfopen_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wfopen_test3 coreclrpal)
+
+target_link_libraries(paltest_wfopen_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test3/test3.c b/src/pal/tests/palsuite/c_runtime/_wfopen/test3/test3.c
new file mode 100644
index 0000000000..3b67818bc5
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wfopen/test3/test3.c
@@ -0,0 +1,70 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test3.c
+**
+** Purpose: Tests the PAL implementation of the _wfopen function.
+** Test to ensure that you can write to a 'w+' mode file.
+** And that you can read from a 'w+' mode file.
+**
+** Depends:
+** fprintf
+** fseek
+** fgets
+**
+
+**
+**===================================================================*/
+
+#define UNICODE
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+
+ FILE *fp;
+ char buffer[128];
+ WCHAR filename[] = {'t','e','s','t','f','i','l','e','\0'};
+ WCHAR writeplus[] = {'w','+','\0'};
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /* Open a file with 'w+' mode */
+ if( (fp = _wfopen( filename, writeplus )) == NULL )
+ {
+ Fail( "ERROR: The file failed to open with 'w+' mode.\n" );
+ }
+
+ /* Write some text to the file */
+ if(fprintf(fp,"%s","some text") <= 0)
+ {
+ Fail("ERROR: Attempted to WRITE to a file opened with 'w+' mode "
+ "but fprintf failed. Either fopen or fprintf have problems.");
+ }
+
+ if(fseek(fp, 0, SEEK_SET))
+ {
+ Fail("ERROR: fseek failed, and this test depends on it.");
+ }
+
+ /* Attempt to read from the 'w+' only file, should pass */
+ if(fgets(buffer,10,fp) == NULL)
+ {
+ Fail("ERROR: Tried to READ from a file with 'w+' mode set. "
+ "This should succeed, but fgets returned NULL. Either fgets "
+ "or fopen is broken.");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_wfopen/test3/testinfo.dat
new file mode 100644
index 0000000000..3dd23e7946
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wfopen/test3/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _wfopen
+Name = Positive Test for _wfopen
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Test to ensure that you can write to a 'w+' mode file. And that you can
+= read from a 'w+' mode file.
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wfopen/test4/CMakeLists.txt
new file mode 100644
index 0000000000..e93cdd58de
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wfopen/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_wfopen_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wfopen_test4 coreclrpal)
+
+target_link_libraries(paltest_wfopen_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test4/test4.c b/src/pal/tests/palsuite/c_runtime/_wfopen/test4/test4.c
new file mode 100644
index 0000000000..0948fa11cc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wfopen/test4/test4.c
@@ -0,0 +1,87 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test4.c
+**
+** Purpose: Tests the PAL implementation of the _wfopen function.
+** Test to ensure that you can't write to a 'r' mode file.
+** And that you can read from a 'r' mode file.
+**
+** Depends:
+** fprintf
+** fclose
+** fgets
+**
+
+**
+**===================================================================*/
+
+#define UNICODE
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+
+ FILE *fp;
+ char buffer[128];
+ WCHAR filename[] = {'t','e','s','t','f','i','l','e','\0'};
+ WCHAR write[] = {'w','\0'};
+ WCHAR read[] = {'r','\0'};
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /* Open a file with 'w' mode */
+ if( (fp = _wfopen( filename, write )) == NULL )
+ {
+ Fail( "ERROR: The file failed to open with 'w' mode.\n" );
+ }
+
+ /* Write some text to the file */
+ if(fprintf(fp,"%s","some text") <= 0)
+ {
+ Fail("ERROR: Attempted to WRITE to a file opened with 'w' mode "
+ "but fprintf failed. Either fopen or fprintf have problems.");
+ }
+
+ if(fclose(fp))
+ {
+ Fail("ERROR: Attempted to close a file, but fclose failed. "
+ "This test depends upon it.");
+ }
+
+ /* Open a file with 'r' mode */
+ if( (fp = _wfopen( filename, read )) == NULL )
+ {
+ Fail( "ERROR: The file failed to open with 'r' mode.\n" );
+ }
+
+ /* Attempt to read from the 'r' only file, should pass */
+ if(fgets(buffer,10,fp) == NULL)
+ {
+ Fail("ERROR: Tried to READ from a file with 'r' mode set. "
+ "This should succeed, but fgets returned NULL. Either fgets "
+ "or fopen is broken.");
+ }
+
+ /* Write some text to the file */
+ if(fprintf(fp,"%s","some text") > 0)
+ {
+ Fail("ERROR: Attempted to WRITE to a file opened with 'r' mode "
+ "but fprintf succeeded It should have failed. "
+ "Either fopen or fprintf have problems.");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test4/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_wfopen/test4/testinfo.dat
new file mode 100644
index 0000000000..de41d77317
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wfopen/test4/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _wfopen
+Name = Positive Test for _wfopen
+TYPE = DEFAULT
+EXE1 = test4
+Description
+= Test to ensure that you can't write to a 'r' mode file. And that you can
+= read from a 'r' mode file.
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wfopen/test5/CMakeLists.txt
new file mode 100644
index 0000000000..1530416795
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wfopen/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test5.c
+)
+
+add_executable(paltest_wfopen_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wfopen_test5 coreclrpal)
+
+target_link_libraries(paltest_wfopen_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test5/test5.c b/src/pal/tests/palsuite/c_runtime/_wfopen/test5/test5.c
new file mode 100644
index 0000000000..21e5ec84ed
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wfopen/test5/test5.c
@@ -0,0 +1,82 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test5.c
+**
+** Purpose: Tests the PAL implementation of the _wfopen function.
+** Test to ensure that you can write to a 'r+' mode file.
+** And that you can read from a 'r+' mode file.
+**
+** Depends:
+** fprintf
+** fclose
+** fgets
+** fseek
+**
+
+**
+**===================================================================*/
+#define UNICODE
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+
+ FILE *fp;
+ char buffer[128];
+ WCHAR filename[] = {'t','e','s','t','f','i','l','e','\0'};
+ WCHAR write[] = {'w','\0'};
+ WCHAR readplus[] = {'r','+','\0'};
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /* Open a file with 'w' mode */
+ if( (fp = _wfopen( filename,write )) == NULL )
+ {
+ Fail( "ERROR: The file failed to open with 'w' mode.\n" );
+ }
+
+ if(fclose(fp))
+ {
+ Fail("ERROR: Attempted to close a file, but fclose failed. "
+ "This test depends upon it.");
+ }
+
+ if( (fp = _wfopen( filename, readplus )) == NULL )
+ {
+ Fail( "ERROR: The file failed to open with 'r+' mode.\n" );
+ }
+
+ /* Write some text to the file */
+ if(fprintf(fp,"%s","some text") <= 0)
+ {
+ Fail("ERROR: Attempted to WRITE to a file opened with 'r+' mode "
+ "but fprintf failed. Either fopen or fprintf have problems.");
+ }
+
+ if(fseek(fp, 0, SEEK_SET))
+ {
+ Fail("ERROR: fseek failed, and this test depends on it.");
+ }
+
+ /* Attempt to read from the 'r+' only file, should pass */
+ if(fgets(buffer,10,fp) == NULL)
+ {
+ Fail("ERROR: Tried to READ from a file with 'r+' mode set. "
+ "This should succeed, but fgets returned NULL. Either fgets "
+ "or fopen is broken.");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test5/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_wfopen/test5/testinfo.dat
new file mode 100644
index 0000000000..6be33cb2be
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wfopen/test5/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _wfopen
+Name = Positive Test for _wfopen
+TYPE = DEFAULT
+EXE1 = test5
+Description
+= Test to ensure that you can write to a 'r+' mode file. And that you can
+= read from a 'r+' mode file.
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wfopen/test6/CMakeLists.txt
new file mode 100644
index 0000000000..c401c6f40f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wfopen/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test6.c
+)
+
+add_executable(paltest_wfopen_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wfopen_test6 coreclrpal)
+
+target_link_libraries(paltest_wfopen_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test6/test6.c b/src/pal/tests/palsuite/c_runtime/_wfopen/test6/test6.c
new file mode 100644
index 0000000000..17d36a0c50
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wfopen/test6/test6.c
@@ -0,0 +1,152 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test6.c
+**
+** Purpose: Tests the PAL implementation of the _wfopen function.
+** Test to ensure that you can write to an 'a' mode file.
+** And that you can't read from a 'a' mode file.
+**
+** Depends:
+** fprintf
+** fgets
+** fseek
+**
+
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ FILE *fp;
+ char buffer[128];
+ WCHAR filename[] = {'t','e','s','t','f','i','l','e','\0'};
+ WCHAR filename2[] = {'t','e','s','t','f','i','l','e','2','\0'};
+ WCHAR append[] = {'a','\0'};
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Open a file with 'a' mode */
+ if( (fp = _wfopen( filename, append )) == NULL )
+ {
+ Fail( "ERROR: file failed to open with 'a' mode.\n" );
+ }
+
+ /* Write some text to the file */
+ if(fprintf(fp,"%s","some text") <= 0)
+ {
+ Fail("ERROR: Attempted to WRITE to a file opened with 'a' mode "
+ "but fprintf failed. Either fopen or fprintf have problems.");
+ }
+
+ if(fseek(fp, 0, SEEK_SET))
+ {
+ Fail("ERROR: fseek failed, and this test depends on it.");
+ }
+
+ /* Attempt to read from the 'a' only file, should fail */
+ if(fgets(buffer,10,fp) != NULL)
+ {
+ Fail("ERROR: Tried to READ from a file with 'a' mode set. "
+ "This should fail, but fgets returned success. Either fgets "
+ "or fopen is broken.");
+ }
+
+ // Delete the file now that we're done with it.
+ if (fclose(fp) != 0)
+ {
+ Fail("ERROR: fclose failed to close \"testfile\".\n");
+ }
+
+ if (!DeleteFileA("testfile"))
+ {
+ Fail("ERROR: Failed to delete \"testfile\".\n"
+ " Error is %d\n",
+ GetLastError());
+ }
+
+ /* Attempt to write to a file after using 'a' and fseek */
+ fp = _wfopen(filename2, append);
+ if(fp == NULL)
+ {
+ Fail("ERROR: _wfopen failed to be created with 'a' mode.\n");
+ }
+
+ /* write text to the file initially */
+ if(fprintf(fp,"%s","abcd") <= 0)
+ {
+ Fail("ERROR: Attempted to WRITE to a file opened with 'a' mode "
+ "but fprintf failed. Either fopen or fprintf have problems.\n");
+ }
+
+ /* set the pointer to the front of the file */
+ if(fseek(fp, 0, SEEK_SET))
+ {
+ Fail("ERROR: fseek failed, and this test depends on it.\n");
+ }
+
+ /* using 'a' should still write to the end of the file, not the front */
+ if(fputs("efgh", fp) < 0)
+ {
+ Fail("ERROR: Attempt to WRITE with fputs to the beginning of a file "
+ "opened with 'a' mode succeeded.\n");
+ }
+
+ /* set the pointer to the front of the file */
+ if(fseek(fp, 0, SEEK_SET))
+ {
+ Fail("ERROR: fseek failed, and this test depends on it.\n");
+ }
+
+ /* a file with 'a' mode can only write, so close the file before reading */
+ if(fclose(fp))
+ {
+ Fail("ERROR: fclose failed when it should have succeeded.\n");
+ }
+
+ /* open the file again to read */
+ fp = fopen("testfile2","r");
+ if(fp == NULL)
+ {
+ Fail("ERROR: fopen failed to open the file using 'r' mode");
+ }
+
+ /* Attempt to read from the 'a' only file, should succeed */
+ if(fgets(buffer,10,fp) == NULL)
+ {
+ Fail("ERROR: Tried to READ from a file with 'a' mode set. "
+ "This should pass, but fgets returned failure. Either fgets "
+ "or fopen is broken.\n");
+ }
+
+ /* Compare what was read and what should have been in the file */
+ if(memcmp(buffer,"abcdefgh",8))
+ {
+ Fail("ERROR: The string read should have equaled 'abcdefgh' "
+ "but instead it is %s\n", buffer);
+ }
+
+ // Delete the file now that we're done with it.
+ if (fclose(fp) != 0)
+ {
+ Fail("ERROR: fclose failed to close \"testfile\".\n");
+ }
+
+ if (!DeleteFileA("testfile2"))
+ {
+ Fail("ERROR: Failed to delete \"testfile2\".\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test6/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_wfopen/test6/testinfo.dat
new file mode 100644
index 0000000000..832f102416
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wfopen/test6/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _wfopen
+Name = Positive Test for _wfopen
+TYPE = DEFAULT
+EXE1 = test6
+Description
+= Test to ensure that you can write to a 'a' mode file. And that you can't
+= read from a 'a' mode file.
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wfopen/test7/CMakeLists.txt
new file mode 100644
index 0000000000..47f4804b43
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wfopen/test7/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test7.c
+)
+
+add_executable(paltest_wfopen_test7
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wfopen_test7 coreclrpal)
+
+target_link_libraries(paltest_wfopen_test7
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test7/test7.c b/src/pal/tests/palsuite/c_runtime/_wfopen/test7/test7.c
new file mode 100644
index 0000000000..0a889adc8a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wfopen/test7/test7.c
@@ -0,0 +1,119 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test7.c
+**
+** Purpose: Tests the PAL implementation of the _wfopen function.
+** Test to ensure that you can write to an 'a+' mode file.
+** And that you can read from a 'a+' mode file.
+**
+** Depends:
+** fprintf
+** fgets
+** fseek
+**
+
+**
+**===================================================================*/
+#define UNICODE
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+
+ FILE *fp;
+ char buffer[128];
+ WCHAR filename[] = {'t','e','s','t','f','i','l','e','\0'};
+ WCHAR filename2[] = {'t','e','s','t','f','i','l','e','2','\0'};
+ WCHAR appendplus[] = {'a','+','\0'};
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /* Open a file with 'a+' mode */
+ if( (fp = _wfopen( filename, appendplus )) == NULL )
+ {
+ Fail( "ERROR: The file failed to open with 'a+' mode.\n" );
+ }
+
+ /* Write some text to the file */
+ if(fprintf(fp,"%s","some text") <= 0)
+ {
+ Fail("ERROR: Attempted to WRITE to a file opened with 'a+' mode "
+ "but fprintf failed. Either fopen or fprintf have problems.");
+ }
+
+ if(fseek(fp, 0, SEEK_SET))
+ {
+ Fail("ERROR: fseek failed, and this test depends on it.");
+ }
+
+ /* Attempt to read from the 'a+' only file, should succeed */
+ if(fgets(buffer,10,fp) == NULL)
+ {
+ Fail("ERROR: Tried to READ from a file with 'a+' mode set. "
+ "This should pass, but fgets returned failure. Either fgets "
+ "or fopen is broken.");
+ }
+
+
+ /* Attempt to write to a file after using 'a+' and fseek */
+ fp = _wfopen(filename2, appendplus);
+ if(fp == NULL)
+ {
+ Fail("ERROR: _wfopen failed to be created with 'a+' mode.\n");
+ }
+
+ /* write text to the file initially */
+ if(fprintf(fp,"%s","abcd") <= 0)
+ {
+ Fail("ERROR: Attempted to WRITE to a file opened with 'a+' mode "
+ "but fprintf failed. Either fopen or fprintf have problems.\n");
+ }
+
+ /* set the pointer to the front of the file */
+ if(fseek(fp, 0, SEEK_SET))
+ {
+ Fail("ERROR: fseek failed, and this test depends on it.\n");
+ }
+
+ /* using 'a+' should still write to the end of the file, not the front */
+ if(fputs("efgh",fp) < 0)
+ {
+ Fail("ERROR: Attempted to WRITE to a file opened with 'a+' mode "
+ "but fputs failed.\n");
+ }
+
+ /* set the pointer to the front of the file */
+ if(fseek(fp, 0, SEEK_SET))
+ {
+ Fail("ERROR: fseek failed, and this test depends on it.\n");
+ }
+
+ /* Attempt to read from the 'a+' only file, should succeed */
+ if(fgets(buffer,10,fp) == NULL)
+ {
+ Fail("ERROR: Tried to READ from a file with 'a+' mode set. "
+ "This should pass, but fgets returned failure. Either fgets "
+ "or fopen is broken.\n");
+ }
+
+ /* Compare what was read and what should have been in the file */
+ if(memcmp(buffer,"abcdefgh",8))
+ {
+ Fail("ERROR: The string read should have equaled 'abcdefgh' "
+ "but instead it is %s\n", buffer);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test7/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_wfopen/test7/testinfo.dat
new file mode 100644
index 0000000000..0c50efb759
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wfopen/test7/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _wfopen
+Name = Positive Test for _wfopen
+TYPE = DEFAULT
+EXE1 = test7
+Description
+= Test to ensure that you can write to a 'a+' mode file. And that you can
+= read from a 'a+' mode file.
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/_wmakepath/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wmakepath/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wmakepath/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_wmakepath/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wmakepath/test1/CMakeLists.txt
new file mode 100644
index 0000000000..343cb41f51
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wmakepath/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_wmakepath_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wmakepath_test1 coreclrpal)
+
+target_link_libraries(paltest_wmakepath_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_wmakepath/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_wmakepath/test1/test1.c
new file mode 100644
index 0000000000..eb79dc6286
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wmakepath/test1/test1.c
@@ -0,0 +1,76 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests the PAL implementation of the _wmakepath function.
+** Create a path, and ensure that it builds how it is
+** supposed to.
+**
+**
+**===================================================================*/
+
+#define UNICODE
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ WCHAR FullPath[128];
+ WCHAR File[] = {'t','e','s','t','\0'};
+ WCHAR Ext[] = {'t','x','t','\0'};
+ char * PrintResult=NULL; /* Used for printing out errors */
+ char * PrintCorrect=NULL;
+
+#if WIN32
+ WCHAR Drive[] = {'C','\0'};
+ WCHAR Dir[] = {'\\','t','e','s','t','\0'};
+ WCHAR PathName[] =
+ {'C',':','\\','t','e','s','t','\\','t','e',
+ 's','t','.','t','x','t','\0'};
+#else
+ WCHAR *Drive = NULL;
+ WCHAR Dir[] = {'/','t','e','s','t','\0'};
+ WCHAR PathName[] =
+ {'/','t','e','s','t','/','t','e','s','t','.','t','x','t','\0'};
+#endif
+
+ /*
+ * Initialize the PAL and return FAIL if this fails
+ */
+ if (0 != (PAL_Initialize(argc,argv)))
+ {
+ return FAIL;
+ }
+
+ _wmakepath(FullPath, Drive, Dir, File, Ext);
+
+ if(wcscmp(FullPath,PathName) != 0)
+ {
+ PrintResult = convertC(FullPath);
+ PrintCorrect = convertC(PathName);
+
+ Fail("ERROR: The pathname which was created turned out to be %s "
+ "when it was supposed to be %s.\n",PrintResult,PrintCorrect);
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/_wmakepath/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_wmakepath/test1/testinfo.dat
new file mode 100644
index 0000000000..6720d342ce
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wmakepath/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _wmakepath
+Name = Positive Test for _wmakepath
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Purpose: Tests the PAL implementation of the _wmakepath function.
+= Create a path, and ensure that it builds how it is supposed to.
diff --git a/src/pal/tests/palsuite/c_runtime/_wsplitpath/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wsplitpath/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wsplitpath/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_wsplitpath/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wsplitpath/test1/CMakeLists.txt
new file mode 100644
index 0000000000..ee9a7a8e96
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wsplitpath/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_wsplitpath_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wsplitpath_test1 coreclrpal)
+
+target_link_libraries(paltest_wsplitpath_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_wsplitpath/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_wsplitpath/test1/test1.c
new file mode 100644
index 0000000000..305768e53a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wsplitpath/test1/test1.c
@@ -0,0 +1,151 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Passes _wsplitpath() a series of sample paths and checks
+** that it parses them as expected.
+**
+**
+**==========================================================================*/
+
+
+#include <palsuite.h>
+
+struct testCase
+{
+ char path[_MAX_PATH]; /* The path to parse. */
+ char drive[_MAX_DRIVE]; /* The expected values... */
+ char dir[_MAX_DIR];
+ char fname[_MAX_FNAME];
+ char ext[_MAX_EXT];
+};
+
+struct wTestCase
+{
+ WCHAR *path; /* The path to parse. */
+ WCHAR *drive; /* The expected values... */
+ WCHAR *dir;
+ WCHAR *fname;
+ WCHAR *ext;
+};
+
+
+
+int __cdecl main(int argc, char **argv)
+{
+ struct testCase testCases[] =
+ {
+#if WIN32
+ {"c:\\foo\\bar\\foo.bar", "c:", "\\foo\\bar\\", "foo", ".bar"},
+ {"c:/foo/bar/foo.bar", "c:", "/foo/bar/", "foo", ".bar"},
+ {"c:/foo/bar/foo", "c:", "/foo/bar/", "foo", ""},
+ {"c:/foo/bar/.bar", "c:", "/foo/bar/", "", ".bar"},
+ {"c:/foo/bar/", "c:", "/foo/bar/", "", ""},
+ {"/foo/bar/foo.bar", "", "/foo/bar/", "foo", ".bar"},
+ {"c:foo.bar", "c:", "", "foo", ".bar"}
+#else
+ {"c:\\foo\\bar\\foo.bar", "","c:/foo/bar/", "foo", ".bar"},
+ {"c:/foo/bar/foo.bar", "", "c:/foo/bar/", "foo", ".bar"},
+ {"c:/foo/bar/foo", "", "c:/foo/bar/", "foo", ""},
+ {"c:/foo/bar/.bar", "", "c:/foo/bar/", ".bar", ""},
+ {"c:/foo/bar/", "", "c:/foo/bar/", "", ""},
+ {"/foo/bar/foo.bar", "", "/foo/bar/", "foo", ".bar"},
+ {"c:foo.bar", "", "", "c:foo", ".bar"}
+#endif
+ };
+
+ struct wTestCase wTestCases[sizeof(testCases)/sizeof(struct testCase)];
+
+ wchar_t wDrive[_MAX_DRIVE];
+ wchar_t wDir[_MAX_DIR];
+ wchar_t wFname[_MAX_FNAME];
+ wchar_t wExt[_MAX_EXT];
+
+ char *drive;
+ char *dir;
+ char *fname;
+ char *ext;
+
+ int i;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /*create wide character versions of the test cases*/
+ for(i = 0; i < sizeof(testCases)/sizeof(struct testCase); i ++)
+ {
+ wTestCases[i].path = convert(testCases[i].path);
+ wTestCases[i].drive = convert(testCases[i].drive);
+ wTestCases[i].dir = convert(testCases[i].dir);
+ wTestCases[i].fname = convert(testCases[i].fname);
+ wTestCases[i].ext = convert(testCases[i].ext);
+ }
+
+
+ for (i = 0; i < sizeof(wTestCases)/sizeof(struct wTestCase); i++)
+ {
+ _wsplitpath(wTestCases[i].path, wDrive, wDir, wFname, wExt);
+
+ /*Convert the results to regular ANSI strings.*/
+ drive = convertC(wDrive);
+ dir = convertC(wDir);
+ fname = convertC(wFname);
+ ext = convertC(wExt);
+
+
+ /*on platforms that don't support drive letters, the drive
+ returned should always be "" */
+ if (wcscmp(wDrive, wTestCases[i].drive) != 0)
+ {
+ Fail("_wsplitpath read the path \"%s\" and thought the drive was "
+ "\"%s\" instead of \"%s\""
+ , testCases[i].path, drive, testCases[i].drive);
+ }
+
+ if (wcscmp(wDir, wTestCases[i].dir) != 0)
+ {
+ Fail("_wsplitpath read the path \"%s\" and thought the directory "
+ "was \"%s\" instead of \"%s\""
+ , testCases[i].path, dir, testCases[i].dir);
+ }
+
+ if (wcscmp(wFname, wTestCases[i].fname) != 0)
+ {
+ Fail("_wsplitpath read the path \"%s\" and thought the filename "
+ "was \"%s\" instead of \"%s\""
+ , testCases[i].path, fname, testCases[i].fname);
+ }
+
+ if (wcscmp(wExt, wTestCases[i].ext) != 0)
+ {
+ Fail("_wsplitpath read the path \"%s\" and thought the file "
+ "extension was \"%s\" instead of \"%s\""
+ , testCases[i].path, ext, testCases[i].ext);
+ }
+
+ free(drive);
+ free(dir);
+ free(fname);
+ free(ext);
+ }
+
+ for(i = 0; i < sizeof(testCases)/sizeof(struct testCase); i++)
+ {
+ free(wTestCases[i].path);
+ free(wTestCases[i].drive);
+ free(wTestCases[i].dir);
+ free(wTestCases[i].fname);
+ free(wTestCases[i].ext);
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_wsplitpath/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_wsplitpath/test1/testinfo.dat
new file mode 100644
index 0000000000..30be680bb4
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wsplitpath/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _wsplitpath
+Name = Positive Test for _wsplitpath
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes _wsplitpath() a series of sample paths and checks that it
+= parses them as expected.
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/_wtoi/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wtoi/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wtoi/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/_wtoi/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wtoi/test1/CMakeLists.txt
new file mode 100644
index 0000000000..9e6610fc0f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wtoi/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_wtoi_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wtoi_test1 coreclrpal)
+
+target_link_libraries(paltest_wtoi_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/_wtoi/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_wtoi/test1/test1.c
new file mode 100644
index 0000000000..0b14dedd60
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wtoi/test1/test1.c
@@ -0,0 +1,79 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests the PAL implementation of the _wtoi function.
+** Check to ensure that the different ints are handled properly.
+** Exponents and decimals should be treated as invalid characters,
+** causing the conversion to quit. Whitespace before the int is valid.
+** Check would-be octal/hex digits to ensure they're treated no
+** differently than other strings.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+struct testCase
+{
+ int IntValue;
+ char avalue[20];
+};
+
+int __cdecl main(int argc, char **argv)
+{
+
+ int result=0;
+ int i=0;
+ WCHAR* temp;
+
+ struct testCase testCases[] =
+ {
+ {1234, "1234"},
+ {-1234, "-1234"},
+ {1234, "+1234"},
+ {1234, "1234.44"},
+ {1234, "1234e-5"},
+ {1234, "1234e+5"},
+ {1234, "1234E5"},
+ {1234, "\t1234"},
+ {0, "0x21"},
+ {17, "017"},
+ {1234, "1234.657e-8"},
+ {1234567, " 1234567e-8 foo"},
+ {0, "foo 32 bar"}
+ };
+
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Loop through each case. Convert the wide string to an int
+ and then compare to ensure that it is the correct value.
+ */
+
+ for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++)
+ {
+ /* Convert to a wide string, then call _wtoi to convert to an int */
+ temp = convert(testCases[i].avalue);
+ result = _wtoi(temp);
+ free(temp);
+ if (testCases[i].IntValue != result)
+ {
+ Fail("ERROR: _wtoi misinterpreted \"%s\" as %i instead of %i.\n",
+ testCases[i].avalue,
+ result,
+ testCases[i].IntValue);
+ }
+
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/_wtoi/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_wtoi/test1/testinfo.dat
new file mode 100644
index 0000000000..4a1f21d4b9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/_wtoi/test1/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = _wtoi
+Name = Test _wtoi on valid and invalid ints in a variety of formats
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests the PAL implementation of the _wtoi function.
+= Check to ensure that the different ints are handled properly.
+= Exponents and decimals should be treated as invalid characters,
+= causing the conversion to quit. Whitespace before the int is valid.
+= Check would-be octal/hex digits to ensure they're treated no
+= differently than other strings.
diff --git a/src/pal/tests/palsuite/c_runtime/abs/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/abs/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/abs/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/abs/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/abs/test1/CMakeLists.txt
new file mode 100644
index 0000000000..c8a8595d01
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/abs/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ abs.c
+)
+
+add_executable(paltest_abs_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_abs_test1 coreclrpal)
+
+target_link_libraries(paltest_abs_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/abs/test1/abs.c b/src/pal/tests/palsuite/c_runtime/abs/test1/abs.c
new file mode 100644
index 0000000000..233a5dcb30
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/abs/test1/abs.c
@@ -0,0 +1,54 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: abs.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the abs function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+struct TESTS
+{
+ int nTest;
+ int nResult;
+};
+
+int __cdecl main(int argc, char *argv[])
+{
+ int i = 0;
+ int nRc = 0;
+ struct TESTS testCase[] =
+ {
+ {0, 0},
+ {1, 1},
+ {-1, 1}
+ };
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ for (i = 0; i < (sizeof(testCase)/sizeof(struct TESTS)); i++)
+ {
+ nRc = abs(testCase[i].nTest);
+ if (nRc != testCase[i].nResult)
+ {
+ Fail("abs: ERROR -> abs(%d) returned %d "
+ "when it was expected to return %d \n",
+ testCase[i].nTest,
+ nRc,
+ testCase[i].nResult);
+ }
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/abs/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/abs/test1/testinfo.dat
new file mode 100644
index 0000000000..98e2af21d4
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/abs/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C runtime
+Function = abs
+Name = test for abs (test 1)
+Type = DEFAULT
+EXE1 = abs
+Description
+= Test abs by passing a list of values and ensuring the
+= proper absolute value is returned.
diff --git a/src/pal/tests/palsuite/c_runtime/acos/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/acos/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/acos/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/acos/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/acos/test1/CMakeLists.txt
new file mode 100644
index 0000000000..978ab427e8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/acos/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_acos_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_acos_test1 coreclrpal)
+
+target_link_libraries(paltest_acos_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/acos/test1/test1.c b/src/pal/tests/palsuite/c_runtime/acos/test1/test1.c
new file mode 100644
index 0000000000..c6ed0692c7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/acos/test1/test1.c
@@ -0,0 +1,130 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test to ensure that acos return the correct values
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** fabs
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (15-17 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use
+// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx
+// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will
+// use PAL_EPSILON * 10.
+#define PAL_EPSILON 8.8817841970012523e-16
+
+#define PAL_NAN sqrt(-1.0)
+#define PAL_POSINF -log(0.0)
+#define PAL_NEGINF log(0.0)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ double value; /* value to test the function with */
+ double expected; /* expected result */
+ double variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(double value, double expected, double variance)
+{
+ double result = acos(value);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ double delta = fabs(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("acos(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(double value)
+{
+ double result = acos(value);
+
+ if (!_isnan(result))
+ {
+ Fail("acos(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char **argv)
+{
+ struct test tests[] =
+ {
+ /* value expected variance */
+ { -1, 3.1415926535897932, PAL_EPSILON * 10 }, // expected: pi
+ { -0.91173391478696510, 2.7182818284590452, PAL_EPSILON * 10 }, // expected: e
+ { -0.66820151019031295, 2.3025850929940457, PAL_EPSILON * 10 }, // expected: ln(10)
+ { 0, 1.5707963267948966, PAL_EPSILON * 10 }, // expected: pi / 2
+ { 0.12775121753523991, 1.4426950408889634, PAL_EPSILON * 10 }, // expected: log2(e)
+ { 0.15594369476537447, 1.4142135623730950, PAL_EPSILON * 10 }, // expected: sqrt(2)
+ { 0.42812514788535792, 1.1283791670955126, PAL_EPSILON * 10 }, // expected: 2 / sqrt(pi)
+ { 0.54030230586813972, 1, PAL_EPSILON * 10 },
+ { 0.70710678118654752, 0.78539816339744831, PAL_EPSILON }, // expected: pi / 4, value: 1 / sqrt(2)
+ { 0.76024459707563015, 0.70710678118654752, PAL_EPSILON }, // expected: 1 / sqrt(2)
+ { 0.76923890136397213, 0.69314718055994531, PAL_EPSILON }, // expected: ln(2)
+ { 0.80410982822879171, 0.63661977236758134, PAL_EPSILON }, // expected: 2 / pi
+ { 0.90716712923909839, 0.43429448190325183, PAL_EPSILON }, // expected: log10(e)
+ { 0.94976571538163866, 0.31830988618379067, PAL_EPSILON }, // expected: 1 / pi
+ { 1, 0, PAL_EPSILON },
+ };
+
+ /* PAL initialization */
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate(tests[i].value, tests[i].expected, tests[i].variance);
+ }
+
+ validate_isnan(PAL_NEGINF);
+ validate_isnan(PAL_NAN);
+ validate_isnan(PAL_POSINF);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/acos/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/acos/test1/testinfo.dat
new file mode 100644
index 0000000000..4b43982fca
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/acos/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = acos
+Name = Positive Test for acos
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes a series of values to the acos() function,
+= checking each for the expected result. Also checks
+= for proper handling of out-of-range values.
diff --git a/src/pal/tests/palsuite/c_runtime/asin/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/asin/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/asin/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/asin/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/asin/test1/CMakeLists.txt
new file mode 100644
index 0000000000..a3aec3f60f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/asin/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_asin_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_asin_test1 coreclrpal)
+
+target_link_libraries(paltest_asin_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/asin/test1/test1.c b/src/pal/tests/palsuite/c_runtime/asin/test1/test1.c
new file mode 100644
index 0000000000..0a63356ed0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/asin/test1/test1.c
@@ -0,0 +1,146 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test to ensure that asin return the correct values
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** fabs
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (15-17 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use
+// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx
+// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will
+// use PAL_EPSILON * 10.
+#define PAL_EPSILON 8.8817841970012523e-16
+
+#define PAL_NAN sqrt(-1.0)
+#define PAL_POSINF -log(0.0)
+#define PAL_NEGINF log(0.0)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ double value; /* value to test the function with */
+ double expected; /* expected result */
+ double variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(double value, double expected, double variance)
+{
+ double result = asin(value);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ double delta = fabs(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("asin(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(double value)
+{
+ double result = asin(value);
+
+ if (!_isnan(result))
+ {
+ Fail("asin(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, PAL_NAN);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning +INF
+ */
+void __cdecl validate_isinf_positive(double value)
+{
+ double result = asin(value);
+
+ if (result != PAL_POSINF)
+ {
+ Fail("asin(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, PAL_POSINF);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char **argv)
+{
+ struct test tests[] =
+ {
+ /* value expected variance */
+ { 0, 0, PAL_EPSILON },
+ { 0.31296179620778659, 0.31830988618379067, PAL_EPSILON }, // expected: 1 / pi
+ { 0.41078129050290870, 0.42331082513074800, PAL_EPSILON }, // expected: pi - e
+ { 0.42077048331375735, 0.43429448190325183, PAL_EPSILON }, // expected: log10(e)
+ { 0.59448076852482208, 0.63661977236758134, PAL_EPSILON }, // expected: 2 / pi
+ { 0.63896127631363480, 0.69314718055994531, PAL_EPSILON }, // expected: ln(2)
+ { 0.64963693908006244, 0.70710678118654752, PAL_EPSILON }, // expected: 1 / sqrt(2)
+ { 0.70710678118654752, 0.78539816339744831, PAL_EPSILON }, // expected: pi / 4, value: 1 / sqrt(2)
+ { 0.74398033695749319, 0.83900756059574755, PAL_EPSILON }, // expected: pi - ln(10)
+ { 0.84147098480789651, 1, PAL_EPSILON * 10 },
+ { 0.90371945743584630, 1.1283791670955126, PAL_EPSILON * 10 }, // expected: 2 / sqrt(pi)
+ { 0.98776594599273553, 1.4142135623730950, PAL_EPSILON * 10 }, // expected: sqrt(2)
+ { 0.99180624439366372, 1.4426950408889634, PAL_EPSILON * 10 }, // expected: log2(e)
+ { 1, 1.5707963267948966, PAL_EPSILON * 10 }, // expected: pi / 2
+ };
+
+ /* PAL initialization */
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate( tests[i].value, tests[i].expected, tests[i].variance);
+ validate(-tests[i].value, -tests[i].expected, tests[i].variance);
+ }
+
+ validate_isnan(PAL_NEGINF);
+ validate_isnan(PAL_NAN);
+ validate_isnan(PAL_POSINF);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/asin/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/asin/test1/testinfo.dat
new file mode 100644
index 0000000000..fba9f95a21
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/asin/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = asin
+Name = Positive Test for asin
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes a series of values to the asin() function,
+= checking each for the expected result. Also checks
+= for proper handling of out-of-range values.
diff --git a/src/pal/tests/palsuite/c_runtime/atan/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/atan/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/atan/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/atan/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/atan/test1/CMakeLists.txt
new file mode 100644
index 0000000000..b0b84e7c07
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/atan/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_atan_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_atan_test1 coreclrpal)
+
+target_link_libraries(paltest_atan_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/atan/test1/test1.c b/src/pal/tests/palsuite/c_runtime/atan/test1/test1.c
new file mode 100644
index 0000000000..6840d46172
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/atan/test1/test1.c
@@ -0,0 +1,128 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test to ensure that atan return the correct values
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** fabs
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (15-17 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use
+// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx
+// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will
+// use PAL_EPSILON * 10.
+#define PAL_EPSILON 8.8817841970012523e-16
+
+#define PAL_NAN sqrt(-1.0)
+#define PAL_POSINF -log(0.0)
+#define PAL_NEGINF log(0.0)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ double value; /* value to test the function with */
+ double expected; /* expected result */
+ double variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(double value, double expected, double variance)
+{
+ double result = atan(value);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ double delta = fabs(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("atan(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(double value)
+{
+ double result = atan(value);
+
+ if (!_isnan(result))
+ {
+ Fail("atan(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char **argv)
+{
+ struct test tests[] =
+ {
+ /* value expected variance */
+ { 0, 0, PAL_EPSILON },
+ { 0.32951473309607836, 0.31830988618379067, PAL_EPSILON }, // expected: 1 / pi
+ { 0.45054953406980750, 0.42331082513074800, PAL_EPSILON }, // expected: pi - e
+ { 0.46382906716062964, 0.43429448190325183, PAL_EPSILON }, // expected: log10(e)
+ { 0.73930295048660405, 0.63661977236758134, PAL_EPSILON }, // expected: 2 / pi
+ { 0.83064087786078395, 0.69314718055994531, PAL_EPSILON }, // expected: ln(2)
+ { 0.85451043200960189, 0.70710678118654752, PAL_EPSILON }, // expected: 1 / sqrt(2)
+ { 1, 0.78539816339744831, PAL_EPSILON }, // expected: pi / 4
+ { 1.1134071468135374, 0.83900756059574755, PAL_EPSILON }, // expected: pi - ln(10)
+ { 1.5574077246549022, 1, PAL_EPSILON * 10 },
+ { 2.1108768356626451, 1.1283791670955126, PAL_EPSILON * 10 }, // expected: 2 / sqrt(pi)
+ { 6.3341191670421916, 1.4142135623730950, PAL_EPSILON * 10 }, // expected: sqrt(2)
+ { 7.7635756709721848, 1.4426950408889634, PAL_EPSILON * 10 }, // expected: log2(e)
+ { PAL_POSINF, 1.5707963267948966, PAL_EPSILON * 10 }, // expected: pi / 2
+ };
+
+ /* PAL initialization */
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate( tests[i].value, tests[i].expected, tests[i].variance);
+ validate(-tests[i].value, -tests[i].expected, tests[i].variance);
+ }
+
+ validate_isnan(PAL_NAN);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/atan/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/atan/test1/testinfo.dat
new file mode 100644
index 0000000000..8a181b8a94
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/atan/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = atan
+Name = Positive Test for atan
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes a series of values to the atan() function,
+= checking each for the expected result.
diff --git a/src/pal/tests/palsuite/c_runtime/atan2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/atan2/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/atan2/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/atan2/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/atan2/test1/CMakeLists.txt
new file mode 100644
index 0000000000..8bd69da2fa
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/atan2/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_atan2_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_atan2_test1 coreclrpal)
+
+target_link_libraries(paltest_atan2_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/atan2/test1/test1.c b/src/pal/tests/palsuite/c_runtime/atan2/test1/test1.c
new file mode 100644
index 0000000000..15aa8f53b9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/atan2/test1/test1.c
@@ -0,0 +1,148 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests that atan2 returns correct values for a subset of values.
+** Tests with positive and negative values of x and y to ensure
+** atan2 is returning results from the correct quadrant.
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (15-17 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use
+// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx
+// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will
+// use PAL_EPSILON * 10.
+#define PAL_EPSILON 8.8817841970012523e-16
+
+#define PAL_NAN sqrt(-1.0)
+#define PAL_POSINF -log(0.0)
+#define PAL_NEGINF log(0.0)
+
+struct test
+{
+ double y; /* second component of the value to test the function with */
+ double x; /* first component of the value to test the function with */
+ double expected; /* expected result */
+ double variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(double y, double x, double expected, double variance)
+{
+ double result = atan2(y, x);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ double delta = fabs(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("atan2(%g, %g) returned %20.17g when it should have returned %20.17g",
+ y, x, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(double y, double x)
+{
+ double result = atan2(y, x);
+
+ if (!_isnan(result))
+ {
+ Fail("atan2(%g, %g) returned %20.17g when it should have returned %20.17g",
+ y, x, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char **argv)
+{
+ struct test tests[] =
+ {
+ /* y x expected variance */
+ { 0, PAL_POSINF, 0, PAL_EPSILON },
+ { 0, 0, 0, PAL_EPSILON },
+ { 0.31296179620778659, 0.94976571538163866, 0.31830988618379067, PAL_EPSILON }, // expected: 1 / pi
+ { 0.42077048331375735, 0.90716712923909839, 0.43429448190325183, PAL_EPSILON }, // expected: log10(e)
+ { 0.59448076852482208, 0.80410982822879171, 0.63661977236758134, PAL_EPSILON }, // expected: 2 / pi
+ { 0.63896127631363480, 0.76923890136397213, 0.69314718055994531, PAL_EPSILON }, // expected: ln(2)
+ { 0.64963693908006244, 0.76024459707563015, 0.70710678118654752, PAL_EPSILON }, // expected: 1 / sqrt(2)
+ { 0.70710678118654752, 0.70710678118654752, 0.78539816339744831, PAL_EPSILON }, // expected: pi / 4, value: 1 / sqrt(2)
+ { 1, 1, 0.78539816339744831, PAL_EPSILON }, // expected: pi / 4
+ { PAL_POSINF, PAL_POSINF, 0.78539816339744831, PAL_EPSILON }, // expected: pi / 4
+ { 0.84147098480789651, 0.54030230586813972, 1, PAL_EPSILON * 10 },
+ { 0.90371945743584630, 0.42812514788535792, 1.1283791670955126, PAL_EPSILON * 10 }, // expected: 2 / sqrt(pi)
+ { 0.98776594599273553, 0.15594369476537447, 1.4142135623730950, PAL_EPSILON * 10 }, // expected: sqrt(2)
+ { 0.99180624439366372, 0.12775121753523991, 1.4426950408889634, PAL_EPSILON * 10 }, // expected: log2(e)
+ { 1, 0, 1.5707963267948966, PAL_EPSILON * 10 }, // expected: pi / 2
+ { PAL_POSINF, 0, 1.5707963267948966, PAL_EPSILON * 10 }, // expected: pi / 2
+ { PAL_POSINF, 1, 1.5707963267948966, PAL_EPSILON * 10 }, // expected: pi / 2
+ { 0.74398033695749319, -0.66820151019031295, 2.3025850929940457, PAL_EPSILON * 10 }, // expected: ln(10)
+ { 0.41078129050290870, -0.91173391478696510, 2.7182818284590452, PAL_EPSILON * 10 }, // expected: e
+ { 0, -1, 3.1415926535897932, PAL_EPSILON * 10 }, // expected: pi
+ { 1, PAL_POSINF, 0, PAL_EPSILON },
+ };
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ const double pi = 3.1415926535897932;
+
+ validate( tests[i].y, tests[i].x, tests[i].expected, tests[i].variance);
+ validate(-tests[i].y, tests[i].x, -tests[i].expected, tests[i].variance);
+ validate( tests[i].y, -tests[i].x, pi - tests[i].expected, tests[i].variance);
+ validate(-tests[i].y, -tests[i].x, tests[i].expected - pi, tests[i].variance);
+ }
+
+ validate_isnan(PAL_NEGINF, PAL_NAN);
+ validate_isnan(PAL_NAN, PAL_NEGINF);
+ validate_isnan(PAL_NAN, PAL_POSINF);
+ validate_isnan(PAL_POSINF, PAL_NAN);
+
+ validate_isnan(PAL_NAN, -1);
+ validate_isnan(PAL_NAN, -0.0);
+ validate_isnan(PAL_NAN, 0);
+ validate_isnan(PAL_NAN, 1);
+
+ validate_isnan(-1, PAL_NAN);
+ validate_isnan(-0.0, PAL_NAN);
+ validate_isnan( 0, PAL_NAN);
+ validate_isnan( 1, PAL_NAN);
+
+ validate_isnan(PAL_NAN, PAL_NAN);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/atan2/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/atan2/test1/testinfo.dat
new file mode 100644
index 0000000000..78fb09118e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/atan2/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = atan2
+Name = Test #1 for atan2
+Type = DEFAULT
+EXE1 = test1
+Description
+=Tests that atan2 returns correct values for a subset of values.
+=Tests with positive and negative values of x and y to ensure
+=atan2 is returning results from the correct quadrant.
diff --git a/src/pal/tests/palsuite/c_runtime/atof/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/atof/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/atof/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/atof/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/atof/test1/CMakeLists.txt
new file mode 100644
index 0000000000..1f34b7ebf5
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/atof/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_atof_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_atof_test1 coreclrpal)
+
+target_link_libraries(paltest_atof_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/atof/test1/test1.c b/src/pal/tests/palsuite/c_runtime/atof/test1/test1.c
new file mode 100644
index 0000000000..a973133f9e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/atof/test1/test1.c
@@ -0,0 +1,75 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Passes to atof() a series of strings containing floats,
+** checking that each one is correctly extracted.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include <float.h>
+
+struct testCase
+{
+ float fvalue;
+ char avalue[20];
+};
+
+int __cdecl main(int argc, char **argv)
+{
+ int i = 0;
+ double f = 0;
+ struct testCase testCases[] =
+ {
+ {1234, "1234"},
+ {-1234, "-1234"},
+ {1234e-5, "1234e-5"},
+ {1234e+5, "1234e+5"},
+ {1234e5, "1234E5"},
+ {1234.567e-8, "1234.567e-8"},
+ {1234.567e-8, " 1234.567e-8 foo"},
+ {0,"a12"}
+ };
+
+ /*
+ * Initialize the PAL and return FAIL if this fails
+ */
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++)
+ {
+ /*Convert the string to a float.*/
+ f = atof(testCases[i].avalue);
+ double result = f - testCases[i].fvalue;
+
+ if (fabs(result) > FLT_EPSILON)
+ {
+ Fail ("atof misinterpreted \"%s\" as %g instead of %g. result %g fabs %g\n",
+ testCases[i].avalue, f, testCases[i].fvalue, result, fabs(result));
+ }
+ }
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/atof/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/atof/test1/testinfo.dat
new file mode 100644
index 0000000000..7f37affb9c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/atof/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = atof
+Name = Positive Test for atof
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes to atof() a series of strings containing floats, checking that
+= each one is correctly extracted.
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/atoi/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/atoi/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/atoi/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/atoi/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/atoi/test1/CMakeLists.txt
new file mode 100644
index 0000000000..3549aca737
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/atoi/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_atoi_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_atoi_test1 coreclrpal)
+
+target_link_libraries(paltest_atoi_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/atoi/test1/test1.c b/src/pal/tests/palsuite/c_runtime/atoi/test1/test1.c
new file mode 100644
index 0000000000..2554d4c353
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/atoi/test1/test1.c
@@ -0,0 +1,86 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests the PAL implementation of the atoi function.
+** Check to ensure that the different ints (normal,
+** negative, decimal,exponent), all work as expected with
+** this function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+struct testCase
+{
+ int IntValue;
+ char avalue[20];
+};
+
+int __cdecl main(int argc, char **argv)
+{
+
+ int result=0;
+ int i=0;
+
+ struct testCase testCases[] =
+ {
+ {1234, "1234"},
+ {-1234, "-1234"},
+ {1234, "1234.44"},
+ {1234, "1234e-5"},
+ {1234, "1234e+5"},
+ {1234, "1234E5"},
+ {1234, "1234.657e-8"},
+ {1234567, " 1234567e-8 foo"},
+ {0, "aaa 32 test"}
+ };
+
+ /*
+ * Initialize the PAL and return FAIL if this fails
+ */
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Loop through each case. Convert the string to an int
+ and then compare to ensure that it is the correct value.
+ */
+
+ for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++)
+ {
+ /*Convert the string to an int.*/
+ result = atoi(testCases[i].avalue);
+
+ if (testCases[i].IntValue != result)
+ {
+ Fail("ERROR: atoi misinterpreted \"%s\" as %i instead of %i.\n"
+ , testCases[i].avalue, result, testCases[i].IntValue);
+ }
+
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/atoi/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/atoi/test1/testinfo.dat
new file mode 100644
index 0000000000..36a1a4499f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/atoi/test1/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = atoi
+Name = Positive Test for atoi
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests the PAL implementation of the atoi function.
+= Check to ensure that the different ints (normal, negative, decimal,
+= exponent), all work as expected with this function.
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/atol/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/atol/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/atol/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/atol/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/atol/test1/CMakeLists.txt
new file mode 100644
index 0000000000..4fea187ad8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/atol/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_atol_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_atol_test1 coreclrpal)
+
+target_link_libraries(paltest_atol_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/atol/test1/test1.c b/src/pal/tests/palsuite/c_runtime/atol/test1/test1.c
new file mode 100644
index 0000000000..5ad85d873f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/atol/test1/test1.c
@@ -0,0 +1,88 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests the PAL implementation of the atol function.
+** Check to ensure that the different ints (normal,
+** negative, decimal,exponent), all work as expected with
+** this function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+struct testCase
+{
+ LONG LongValue;
+ char avalue[20];
+};
+
+int __cdecl main(int argc, char **argv)
+{
+
+ LONG result=0;
+ int i=0;
+
+ struct testCase testCases[] =
+ {
+ {1234, "1234"},
+ {-1234, "-1234"},
+ {1234, "1234.44"},
+ {1234, "1234e-5"},
+ {1234, "1234e+5"},
+ {1234, "1234E5"},
+ {1234, "1234.657e-8"},
+ {1234, "1234d-5"},
+ {1234, "1234d+5"},
+ {1234, "1234D5"},
+ {1234567, " 1234567e-8 foo"},
+ {0, "aaa 32 test"}
+ };
+
+ /*
+ * Initialize the PAL and return FAIL if this fails
+ */
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Loop through each case. Convert the string to a LONG
+ and then compare to ensure that it is the correct value.
+ */
+
+ for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++)
+ {
+ /*Convert the string to a LONG.*/
+ result = atol(testCases[i].avalue);
+
+ if (testCases[i].LongValue != result)
+ {
+ Fail("ERROR: atol misinterpreted \"%s\" as %d instead of %d.\n"
+ , testCases[i].avalue, result, testCases[i].LongValue);
+ }
+
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/atol/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/atol/test1/testinfo.dat
new file mode 100644
index 0000000000..962a1676a1
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/atol/test1/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = atol
+Name = Positive Test for atol
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests the PAL implementation of the atol function.
+= Check to ensure that the different ints (normal, negative, decimal,
+= exponent), all work as expected with this function.
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/bsearch/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/bsearch/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/bsearch/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/c_runtime/bsearch/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/bsearch/test1/CMakeLists.txt
new file mode 100644
index 0000000000..d2018f3325
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/bsearch/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_bsearch_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_bsearch_test1 coreclrpal)
+
+target_link_libraries(paltest_bsearch_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/bsearch/test1/test1.c b/src/pal/tests/palsuite/c_runtime/bsearch/test1/test1.c
new file mode 100644
index 0000000000..c4b91738eb
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/bsearch/test1/test1.c
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Calls bsearch to find a character in a sorted buffer, and
+** verifies that the correct position is returned.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl charcmp(const void *pa, const void *pb)
+{
+ return memcmp(pa, pb, 1);
+}
+
+int __cdecl main(int argc, char **argv)
+{
+
+ const char array[] = "abcdefghij";
+ char * found=NULL;
+
+ /*
+ * Initialize the PAL and return FAIL if this fails
+ */
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ found = (char *)bsearch(&"d", array, sizeof(array) - 1, (sizeof(char))
+ , charcmp);
+ if (found != array + 3)
+ {
+ Fail ("bsearch was unable to find a specified character in a "
+ "sorted list.\n");
+ }
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/bsearch/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/bsearch/test1/testinfo.dat
new file mode 100644
index 0000000000..3eb7369ac2
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/bsearch/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = bsearch
+Name = Positive Test for bsearch
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Calls bsearch to find a character in a sorted buffer, and
+= verifies that the correct position is returned.
+
diff --git a/src/pal/tests/palsuite/c_runtime/bsearch/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/bsearch/test2/CMakeLists.txt
new file mode 100644
index 0000000000..dc65560196
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/bsearch/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_bsearch_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_bsearch_test2 coreclrpal)
+
+target_link_libraries(paltest_bsearch_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/bsearch/test2/test2.c b/src/pal/tests/palsuite/c_runtime/bsearch/test2/test2.c
new file mode 100644
index 0000000000..6de1b3fada
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/bsearch/test2/test2.c
@@ -0,0 +1,57 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Calls bsearch to find a character in a sorted buffer,
+** that does not exist.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl charcmp(const void *pa, const void *pb)
+{
+ return *(const char *)pa - *(const char *)pb;
+}
+
+int __cdecl main(int argc, char **argv)
+{
+
+ const char array[] = "abcefghij";
+ const char missing[] = "0dz";
+ char * found=NULL;
+ const char * candidate = missing;
+
+ /*
+ * Initialize the PAL and return FAIL if this fails
+ */
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ while (*candidate) {
+ found = (char *)bsearch(candidate, array, sizeof(array) - 1,
+ (sizeof(char)), charcmp);
+ if (found != NULL)
+ {
+ Fail ("ERROR: bsearch was able to find a specified character '%c' "
+ "in a sorted list '%s' as '%c' "
+ "even though the character is not in the list.\n",
+ *candidate, array, *found);
+ }
+
+ candidate++;
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/bsearch/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/bsearch/test2/testinfo.dat
new file mode 100644
index 0000000000..faa9dc1be6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/bsearch/test2/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = bsearch
+Name = Negative Test for bsearch
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Calls bsearch to find a character in a sorted buffer,
+= that does not exist.
+
diff --git a/src/pal/tests/palsuite/c_runtime/ceil/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/ceil/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ceil/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/ceil/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/ceil/test1/CMakeLists.txt
new file mode 100644
index 0000000000..c73ad1dbbe
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ceil/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_ceil_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_ceil_test1 coreclrpal)
+
+target_link_libraries(paltest_ceil_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/ceil/test1/test1.c b/src/pal/tests/palsuite/c_runtime/ceil/test1/test1.c
new file mode 100644
index 0000000000..e6e36e6e33
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ceil/test1/test1.c
@@ -0,0 +1,132 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests ceil with simple positive and negative values. Also tests
+** extreme cases like extremely small values and positive and
+** negative infinity. Makes sure that calling ceil on NaN returns
+** NaN
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (15-17 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use
+// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx
+// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will
+// use PAL_EPSILON * 10.
+#define PAL_EPSILON 8.8817841970012523e-16
+
+#define PAL_NAN sqrt(-1.0)
+#define PAL_POSINF -log(0.0)
+#define PAL_NEGINF log(0.0)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ double value; /* value to test the function with */
+ double expected; /* expected result */
+ double variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(double value, double expected, double variance)
+{
+ double result = ceil(value);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ double delta = fabs(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("ceil(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(double value)
+{
+ double result = ceil(value);
+
+ if (!_isnan(result))
+ {
+ Fail("ceil(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char *argv[])
+{
+ struct test tests[] =
+ {
+ /* value expected variance */
+ { 0.31830988618379067, 1, PAL_EPSILON * 10 }, // value: 1 / pi
+ { 0.43429448190325183, 1, PAL_EPSILON * 10 }, // value: log10(e)
+ { 0.63661977236758134, 1, PAL_EPSILON * 10 }, // value: 2 / pi
+ { 0.69314718055994531, 1, PAL_EPSILON * 10 }, // value: ln(2)
+ { 0.70710678118654752, 1, PAL_EPSILON * 10 }, // value: 1 / sqrt(2)
+ { 0.78539816339744831, 1, PAL_EPSILON * 10 }, // value: pi / 4
+ { 1.1283791670955126, 2, PAL_EPSILON * 10 }, // value: 2 / sqrt(pi)
+ { 1.4142135623730950, 2, PAL_EPSILON * 10 }, // value: sqrt(2)
+ { 1.4426950408889634, 2, PAL_EPSILON * 10 }, // value: log2(e)
+ { 1.5707963267948966, 2, PAL_EPSILON * 10 }, // value: pi / 2
+ { 2.3025850929940457, 3, PAL_EPSILON * 10 }, // value: ln(10)
+ { 2.7182818284590452, 3, PAL_EPSILON * 10 }, // value: e
+ { 3.1415926535897932, 4, PAL_EPSILON * 10 }, // value: pi
+ { PAL_POSINF, PAL_POSINF, 0 }
+ };
+
+ /* PAL initialization */
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ validate( 0, 0, PAL_EPSILON);
+ validate(-0.0, 0, PAL_EPSILON);
+
+ validate( 1, 1, PAL_EPSILON * 10);
+ validate(-1.0, -1, PAL_EPSILON * 10);
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate( tests[i].value, tests[i].expected, tests[i].variance);
+ validate(-tests[i].value, 1 - tests[i].expected, tests[i].variance);
+ }
+
+ validate_isnan(PAL_NAN);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/ceil/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/ceil/test1/testinfo.dat
new file mode 100644
index 0000000000..84e80a9cb7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ceil/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = ceil
+Name = Test #1 for ceil
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Tests ceil with simple positive and negative values. Also tests
+=extreme cases like extremely small values and positive and negative
+=infinity. Makes sure that calling ceil on NaN returns NaN
diff --git a/src/pal/tests/palsuite/c_runtime/cos/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/cos/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/cos/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/cos/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/cos/test1/CMakeLists.txt
new file mode 100644
index 0000000000..1dda9a2563
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/cos/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_cos_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_cos_test1 coreclrpal)
+
+target_link_libraries(paltest_cos_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/cos/test1/test1.c b/src/pal/tests/palsuite/c_runtime/cos/test1/test1.c
new file mode 100644
index 0000000000..8c1c7300e6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/cos/test1/test1.c
@@ -0,0 +1,131 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test to ensure that cos return the correct values
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** fabs
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (15-17 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use
+// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx
+// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will
+// use PAL_EPSILON * 10.
+#define PAL_EPSILON 8.8817841970012523e-16
+
+#define PAL_NAN sqrt(-1.0)
+#define PAL_POSINF -log(0.0)
+#define PAL_NEGINF log(0.0)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ double value; /* value to test the function with */
+ double expected; /* expected result */
+ double variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(double value, double expected, double variance)
+{
+ double result = cos(value);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ double delta = fabs(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("cos(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(double value)
+{
+ double result = cos(value);
+
+ if (!_isnan(result))
+ {
+ Fail("cos(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char **argv)
+{
+ struct test tests[] =
+ {
+ /* value expected variance */
+ { 0, 1, PAL_EPSILON * 10 },
+ { 0.31830988618379067, 0.94976571538163866, PAL_EPSILON }, // value: 1 / pi
+ { 0.43429448190325183, 0.90716712923909839, PAL_EPSILON }, // value: log10(e)
+ { 0.63661977236758134, 0.80410982822879171, PAL_EPSILON }, // value: 2 / pi
+ { 0.69314718055994531, 0.76923890136397213, PAL_EPSILON }, // value: ln(2)
+ { 0.70710678118654752, 0.76024459707563015, PAL_EPSILON }, // value: 1 / sqrt(2)
+ { 0.78539816339744831, 0.70710678118654752, PAL_EPSILON }, // value: pi / 4, expected: 1 / sqrt(2)
+ { 1, 0.54030230586813972, PAL_EPSILON },
+ { 1.1283791670955126, 0.42812514788535792, PAL_EPSILON }, // value: 2 / sqrt(pi)
+ { 1.4142135623730950, 0.15594369476537447, PAL_EPSILON }, // value: sqrt(2)
+ { 1.4426950408889634, 0.12775121753523991, PAL_EPSILON }, // value: log2(e)
+ { 1.5707963267948966, 0, PAL_EPSILON }, // value: pi / 2
+ { 2.3025850929940457, -0.66820151019031295, PAL_EPSILON }, // value: ln(10)
+ { 2.7182818284590452, -0.91173391478696510, PAL_EPSILON }, // value: e
+ { 3.1415926535897932, -1, PAL_EPSILON * 10 }, // value: pi
+ };
+
+ /* PAL initialization */
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate( tests[i].value, tests[i].expected, tests[i].variance);
+ validate(-tests[i].value, tests[i].expected, tests[i].variance);
+ }
+
+ validate_isnan(PAL_NEGINF);
+ validate_isnan(PAL_NAN);
+ validate_isnan(PAL_POSINF);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/cos/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/cos/test1/testinfo.dat
new file mode 100644
index 0000000000..9e57b7f8ab
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/cos/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = cos
+Name = Positive Test for cos
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes to cos() a series of angle value, checking that
+= each one return the correct value.
diff --git a/src/pal/tests/palsuite/c_runtime/cosh/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/cosh/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/cosh/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/cosh/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/cosh/test1/CMakeLists.txt
new file mode 100644
index 0000000000..bea7b7a3b7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/cosh/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_cosh_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_cosh_test1 coreclrpal)
+
+target_link_libraries(paltest_cosh_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/cosh/test1/test1.c b/src/pal/tests/palsuite/c_runtime/cosh/test1/test1.c
new file mode 100644
index 0000000000..40c2fca85d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/cosh/test1/test1.c
@@ -0,0 +1,130 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test to ensure that cosh return the correct values
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** fabs
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (15-17 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use
+// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx
+// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will
+// use PAL_EPSILON * 10.
+#define PAL_EPSILON 8.8817841970012523e-16
+
+#define PAL_NAN sqrt(-1.0)
+#define PAL_POSINF -log(0.0)
+#define PAL_NEGINF log(0.0)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ double value; /* value to test the function with */
+ double expected; /* expected result */
+ double variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(double value, double expected, double variance)
+{
+ double result = cosh(value);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ double delta = fabs(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("cosh(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning PAL_NAN
+ */
+void __cdecl validate_isnan(double value)
+{
+ double result = cosh(value);
+
+ if (!_isnan(result))
+ {
+ Fail("cosh(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char **argv)
+{
+ struct test tests[] =
+ {
+ /* value expected variance */
+ { 0, 1, PAL_EPSILON * 10 },
+ { 0.31830988618379067, 1.0510897883672876, PAL_EPSILON * 10 }, // value: 1 / pi
+ { 0.43429448190325183, 1.0957974645564909, PAL_EPSILON * 10 }, // value: log10(e)
+ { 0.63661977236758134, 1.2095794864199787, PAL_EPSILON * 10 }, // value: 2 / pi
+ { 0.69314718055994531, 1.25, PAL_EPSILON * 10 }, // value: ln(2)
+ { 0.70710678118654752, 1.2605918365213561, PAL_EPSILON * 10 }, // value: 1 / sqrt(2)
+ { 0.78539816339744831, 1.3246090892520058, PAL_EPSILON * 10 }, // value: pi / 4
+ { 1, 1.5430806348152438, PAL_EPSILON * 10 },
+ { 1.1283791670955126, 1.7071001431069344, PAL_EPSILON * 10 }, // value: 2 / sqrt(pi)
+ { 1.4142135623730950, 2.1781835566085709, PAL_EPSILON * 10 }, // value: sqrt(2)
+ { 1.4426950408889634, 2.2341880974508023, PAL_EPSILON * 10 }, // value: log2(e)
+ { 1.5707963267948966, 2.5091784786580568, PAL_EPSILON * 10 }, // value: pi / 2
+ { 2.3025850929940457, 5.05, PAL_EPSILON * 10 }, // value: ln(10)
+ { 2.7182818284590452, 7.6101251386622884, PAL_EPSILON * 10 }, // value: e
+ { 3.1415926535897932, 11.591953275521521, PAL_EPSILON * 100 }, // value: pi
+ { PAL_POSINF, PAL_POSINF, 0 },
+ };
+
+ /* PAL initialization */
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate( tests[i].value, tests[i].expected, tests[i].variance);
+ validate(-tests[i].value, tests[i].expected, tests[i].variance);
+ }
+
+ validate_isnan(PAL_NAN);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/cosh/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/cosh/test1/testinfo.dat
new file mode 100644
index 0000000000..131512289f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/cosh/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = cosh
+Name = Positive Test for cosh
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes to cosh() a series of angle value, checking that
+= each one return to correct value.
diff --git a/src/pal/tests/palsuite/c_runtime/ctime/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/ctime/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ctime/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/ctime/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/ctime/test1/CMakeLists.txt
new file mode 100644
index 0000000000..aa64a71d1e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ctime/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_ctime_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_ctime_test1 coreclrpal)
+
+target_link_libraries(paltest_ctime_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/ctime/test1/test1.c b/src/pal/tests/palsuite/c_runtime/ctime/test1/test1.c
new file mode 100644
index 0000000000..5d5e22ce89
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ctime/test1/test1.c
@@ -0,0 +1,154 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test to ensure that ctime return a valid
+** string when it received a valid number of second.
+** Test to ensure that ctime return null when it
+** receives a invalid number of second.
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** IsBadReadPtr
+** strcmp
+**
+
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+/*
+ * Date strings generated under win2000/WinXP, times & Strings are GMT
+ */
+const time_t VAL_SUN_JAN_17_2038 = 2147383647;
+const char *STR_SUN_JAN_17_2038 = "Sun Jan 17 23:27:27 2038\n";
+
+/* Note, there are two acceptable strings for this date. */
+/* The day can have a leading 0 under Windows. */
+const time_t VAL_FRI_JAN_02_1970 = 100000;
+const char *STR_FRI_JAN_02_1970 = "Fri Jan 02 03:46:40 1970\n";
+const char *STR_FRI_JAN__2_1970 = "Fri Jan 2 03:46:40 1970\n";
+
+const int STR_TIME_SIZE = 26; /* returned date size in byte*/
+
+
+
+int __cdecl main(int argc, char **argv)
+{
+ time_t LTime;
+ char *DateResult;
+ TIME_ZONE_INFORMATION tzInformation;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ // Get the current timezone information
+ GetTimeZoneInformation(&tzInformation);
+
+ /*
+ * Test #1
+ */
+
+ /* set the valid date in time_t format, adjusted for current time zone*/
+ LTime = VAL_SUN_JAN_17_2038 + (tzInformation.Bias * 60);
+
+ /* convert it to string using ctime*/
+ DateResult = ctime( &LTime );
+
+ /* if it's null, ctime failed*/
+ if (DateResult == NULL)
+ {
+ Fail ("ERROR: (Test #1) ctime returned NULL. Expected string\n");
+ }
+
+ /* test if the entire string can ba access normaly */
+ if(IsBadReadPtr(DateResult, STR_TIME_SIZE)==0)
+ {
+ /* compare result with win2000 result */
+ if(strcmp( DateResult, STR_SUN_JAN_17_2038)!=0)
+ {
+ Fail("ERROR: (Test #1) ctime returned an unexpected string "
+ "%s, expexted string is %s\n"
+ ,DateResult, STR_SUN_JAN_17_2038);
+ }
+ }
+ else
+ {
+ Fail ("ERROR: (Test #1) ctime returned a bad pointer.\n");
+ }
+
+
+ /*
+ * Test #2
+ */
+
+ /* Set the valid date in time_t format, adjusted for current time zone */
+ LTime = VAL_FRI_JAN_02_1970 + (tzInformation.Bias * 60);
+
+ /* convert it to string using ctime */
+ DateResult = ctime( &LTime );
+
+ /* if it's null, ctime failed*/
+ if (DateResult == NULL)
+ {
+ Fail ("ERROR: (Test #2) ctime returned NULL. Expected string\n");
+ }
+
+ /* test if the entire string can ba access normaly */
+ if(IsBadReadPtr(DateResult, STR_TIME_SIZE)==0)
+ {
+ /* compare result with win2000 result */
+ if (strcmp(DateResult, STR_FRI_JAN_02_1970) != 0
+ && strcmp(DateResult, STR_FRI_JAN__2_1970) != 0)
+ {
+ Fail("ERROR: (Test #2) ctime returned an unexpected string "
+ "%s, expected string is %s\n"
+ ,DateResult, STR_FRI_JAN_02_1970);
+ }
+ }
+ else
+ {
+ Fail ("ERROR: (Test #2) ctime returned a bad pointer.\n");
+ }
+
+
+
+ /*
+ * Test #3
+ */
+
+ /* specify an invalid time */
+ LTime = -1;
+
+ /* try to convert it */
+ DateResult = ctime( &LTime );
+
+ /* Check the result for errors, should fail in this case */
+ if (DateResult != NULL)
+ {
+ Fail ("ERROR: (Test #3) ctime returned something different from NULL.:"
+ "Expected NULL\n");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/ctime/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/ctime/test1/testinfo.dat
new file mode 100644
index 0000000000..c5aa3df65e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ctime/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = ctime
+Name = Positive Test for ctime
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Call ctime with a valid number of second in it's t_time parameter
+= and expect a non-null char* as a return value.
+= Call ctime with a invalid number of second (-1) and expect
+= a null char* as a return value.
diff --git a/src/pal/tests/palsuite/c_runtime/errno/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/errno/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/errno/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/c_runtime/errno/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/errno/test1/CMakeLists.txt
new file mode 100644
index 0000000000..89b25a4fac
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/errno/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_errno_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_errno_test1 coreclrpal)
+
+target_link_libraries(paltest_errno_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/errno/test1/test1.c b/src/pal/tests/palsuite/c_runtime/errno/test1/test1.c
new file mode 100644
index 0000000000..3ae25fb02a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/errno/test1/test1.c
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test that errno begins as 0, and sets to ERANGE when that
+** error is forced with wcstoul.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR overstr[] = {'4','2','9','4','9','6','7','2','9','6',0};
+ WCHAR *end;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /*
+ From rotor.doc: The only value that must be supported is
+ ERANGE, in the event that wcstoul() fails due to overflow.
+ */
+
+ wcstoul(overstr, &end, 10);
+
+ if (errno != ERANGE)
+ {
+ Fail("ERROR: wcstoul did not set errno to ERANGE. Instead "
+ "the value of errno is %d\n", errno);
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/errno/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/errno/test1/testinfo.dat
new file mode 100644
index 0000000000..3291dbc60a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/errno/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = errno
+Name = Positive Test for errno
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Test that errno begins as 0, and sets to ERANGE when that
+= error is forced with wcstoul.
diff --git a/src/pal/tests/palsuite/c_runtime/errno/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/errno/test2/CMakeLists.txt
new file mode 100644
index 0000000000..edd4cf7975
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/errno/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_errno_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_errno_test2 coreclrpal)
+
+target_link_libraries(paltest_errno_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/errno/test2/test2.c b/src/pal/tests/palsuite/c_runtime/errno/test2/test2.c
new file mode 100644
index 0000000000..f418d2f199
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/errno/test2/test2.c
@@ -0,0 +1,76 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test2.c
+**
+** Purpose: Test that errno is 'per-thread' as noted in the documentation.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+/*
+ This thread function just checks that errno is initially 0 and then sets
+ it to a new value before returning.
+*/
+DWORD PALAPI ThreadFunc( LPVOID lpParam )
+{
+
+ if(errno != 0)
+ {
+ *((DWORD*)lpParam) = 1;
+ }
+
+ errno = 20;
+
+ return 0;
+}
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ DWORD dwThreadId, dwThrdParam = 0;
+ HANDLE hThread;
+
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Set errno to a value within this thread */
+
+ errno = 50;
+
+ hThread = CreateThread(NULL, 0, ThreadFunc, &dwThrdParam, 0, &dwThreadId);
+
+ if (hThread == NULL)
+ {
+ Fail("ERROR: CreateThread failed to create a thread. "
+ "GetLastError() returned %d.\n",GetLastError());
+ }
+
+ WaitForSingleObject(hThread, INFINITE);
+
+ /* This checks the result of calling the thread */
+ if(dwThrdParam)
+ {
+ Fail("ERROR: errno was not set to 0 in the new thread. Each "
+ "thread should have its own value for errno.\n");
+ }
+
+ /* Check to make sure errno is still set to 50 */
+ if(errno != 50)
+ {
+ Fail("ERROR: errno should be 50 in the main thread, even though "
+ "it was set to 20 in another thread. Currently it is %d.\n",
+ errno);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/errno/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/errno/test2/testinfo.dat
new file mode 100644
index 0000000000..90c232866f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/errno/test2/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = errno
+Name = Positive Test for errno
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Test that errno is 'per-thread' as noted in the documentation.
diff --git a/src/pal/tests/palsuite/c_runtime/exit/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/exit/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/exit/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/c_runtime/exit/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/exit/test1/CMakeLists.txt
new file mode 100644
index 0000000000..eb9ca4e780
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/exit/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_exit_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_exit_test1 coreclrpal)
+
+target_link_libraries(paltest_exit_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/exit/test1/test1.c b/src/pal/tests/palsuite/c_runtime/exit/test1/test1.c
new file mode 100644
index 0000000000..87c9d22b8a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/exit/test1/test1.c
@@ -0,0 +1,37 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Calls exit, and verifies that it actually stops program execution.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ /*
+ * Initialize the PAL and return FAIL if this fails
+ */
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /*should return 0*/
+ exit(0);
+
+ Fail ("Exit didn't actually stop execution.\n");
+
+ return FAIL;
+}
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/exit/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/exit/test1/testinfo.dat
new file mode 100644
index 0000000000..3d9583bf96
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/exit/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = exit
+Name = Positive Test for exit
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Calls exit, and verifies that it actually stops program execution.
diff --git a/src/pal/tests/palsuite/c_runtime/exit/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/exit/test2/CMakeLists.txt
new file mode 100644
index 0000000000..47d3a44c85
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/exit/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_exit_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_exit_test2 coreclrpal)
+
+target_link_libraries(paltest_exit_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/exit/test2/test2.c b/src/pal/tests/palsuite/c_runtime/exit/test2/test2.c
new file mode 100644
index 0000000000..16fbdfed2f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/exit/test2/test2.c
@@ -0,0 +1,38 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test2.c
+**
+** Purpose: Calls exit on fail, and verifies that it actually
+** stops program execution and return 1.
+
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ /*
+ * Initialize the PAL and return FAIL if this fails
+ */
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /*should return 1*/
+ exit(1);
+
+}
+
+
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/exit/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/exit/test2/testinfo.dat
new file mode 100644
index 0000000000..6887f27c36
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/exit/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = exit
+Name = Positive Test for exit
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Calls exit on fail, and verifies that it actually stops program execution,
+= and return 1.
diff --git a/src/pal/tests/palsuite/c_runtime/exp/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/exp/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/exp/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/exp/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/exp/test1/CMakeLists.txt
new file mode 100644
index 0000000000..9cdd4ec5ed
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/exp/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_exp_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_exp_test1 coreclrpal)
+
+target_link_libraries(paltest_exp_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/exp/test1/test1.c b/src/pal/tests/palsuite/c_runtime/exp/test1/test1.c
new file mode 100644
index 0000000000..20e071aa68
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/exp/test1/test1.c
@@ -0,0 +1,138 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests exp with a normal set of values.
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (15-17 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use
+// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx
+// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will
+// use PAL_EPSILON * 10.
+#define PAL_EPSILON 8.8817841970012523e-16
+
+#define PAL_NAN sqrt(-1.0)
+#define PAL_POSINF -log(0.0)
+#define PAL_NEGINF log(0.0)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ double value; /* value to test the function with */
+ double expected; /* expected result */
+ double variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(double value, double expected, double variance)
+{
+ double result = exp(value);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ double delta = fabs(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("exp(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(double value)
+{
+ double result = exp(value);
+
+ if (!_isnan(result))
+ {
+ Fail("exp(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char **argv)
+{
+ struct test tests[] =
+ {
+ /* value expected variance */
+ { PAL_NEGINF, 0, PAL_EPSILON },
+ { -3.1415926535897932, 0.043213918263772250, PAL_EPSILON / 10 }, // value: -(pi)
+ { -2.7182818284590452, 0.065988035845312537, PAL_EPSILON / 10 }, // value: -(e)
+ { -2.3025850929940457, 0.1, PAL_EPSILON }, // value: -(ln(10))
+ { -1.5707963267948966, 0.20787957635076191, PAL_EPSILON }, // value: -(pi / 2)
+ { -1.4426950408889634, 0.23629008834452270, PAL_EPSILON }, // value: -(log2(e))
+ { -1.4142135623730950, 0.24311673443421421, PAL_EPSILON }, // value: -(sqrt(2))
+ { -1.1283791670955126, 0.32355726390307110, PAL_EPSILON }, // value: -(2 / sqrt(pi))
+ { -1, 0.36787944117144232, PAL_EPSILON }, // value: -(1)
+ { -0.78539816339744831, 0.45593812776599624, PAL_EPSILON }, // value: -(pi / 4)
+ { -0.70710678118654752, 0.49306869139523979, PAL_EPSILON }, // value: -(1 / sqrt(2))
+ { -0.69314718055994531, 0.5, PAL_EPSILON }, // value: -(ln(2))
+ { -0.63661977236758134, 0.52907780826773535, PAL_EPSILON }, // value: -(2 / pi)
+ { -0.43429448190325183, 0.64772148514180065, PAL_EPSILON }, // value: -(log10(e))
+ { -0.31830988618379067, 0.72737734929521647, PAL_EPSILON }, // value: -(1 / pi)
+ { 0, 1, PAL_EPSILON * 10 },
+ { 0.31830988618379067, 1.3748022274393586, PAL_EPSILON * 10 }, // value: 1 / pi
+ { 0.43429448190325183, 1.5438734439711811, PAL_EPSILON * 10 }, // value: log10(e)
+ { 0.63661977236758134, 1.8900811645722220, PAL_EPSILON * 10 }, // value: 2 / pi
+ { 0.69314718055994531, 2, PAL_EPSILON * 10 }, // value: ln(2)
+ { 0.70710678118654752, 2.0281149816474725, PAL_EPSILON * 10 }, // value: 1 / sqrt(2)
+ { 0.78539816339744831, 2.1932800507380155, PAL_EPSILON * 10 }, // value: pi / 4
+ { 1, 2.7182818284590452, PAL_EPSILON * 10 }, // expected: e
+ { 1.1283791670955126, 3.0906430223107976, PAL_EPSILON * 10 }, // value: 2 / sqrt(pi)
+ { 1.4142135623730950, 4.1132503787829275, PAL_EPSILON * 10 }, // value: sqrt(2)
+ { 1.4426950408889634, 4.2320861065570819, PAL_EPSILON * 10 }, // value: log2(e)
+ { 1.5707963267948966, 4.8104773809653517, PAL_EPSILON * 10 }, // value: pi / 2
+ { 2.3025850929940457, 10, PAL_EPSILON * 100 }, // value: ln(10)
+ { 2.7182818284590452, 15.154262241479264, PAL_EPSILON * 100 }, // value: e
+ { 3.1415926535897932, 23.140692632779269, PAL_EPSILON * 100 }, // value: pi
+ { PAL_POSINF, PAL_POSINF, 0 },
+ };
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate(tests[i].value, tests[i].expected, tests[i].variance);
+ }
+
+ validate_isnan(PAL_NAN);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/exp/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/exp/test1/testinfo.dat
new file mode 100644
index 0000000000..65fc192cd9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/exp/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = exp
+Name = Test #1 for exp
+Type = DEFAULT
+EXE1 = test1
+Description
+=Tests exp with a normal set of values.
diff --git a/src/pal/tests/palsuite/c_runtime/fabs/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fabs/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fabs/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/fabs/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fabs/test1/CMakeLists.txt
new file mode 100644
index 0000000000..ab27230ac2
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fabs/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_fabs_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fabs_test1 coreclrpal)
+
+target_link_libraries(paltest_fabs_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fabs/test1/test1.c b/src/pal/tests/palsuite/c_runtime/fabs/test1/test1.c
new file mode 100644
index 0000000000..0a74d5c1c5
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fabs/test1/test1.c
@@ -0,0 +1,130 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test to ensure that fabs return the correct values
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (15-17 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use
+// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx
+// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will
+// use PAL_EPSILON * 10.
+#define PAL_EPSILON 8.8817841970012523e-16
+
+#define PAL_NAN sqrt(-1.0)
+#define PAL_POSINF -log(0.0)
+#define PAL_NEGINF log(0.0)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ double value; /* value to test the function with */
+ double expected; /* expected result */
+ double variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(double value, double expected, double variance)
+{
+ double result = fabs(value);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ double delta = fabs(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("fabs(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(double value)
+{
+ double result = fabs(value);
+
+ if (!_isnan(result))
+ {
+ Fail("fabs(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+INT __cdecl main(INT argc, CHAR **argv)
+{
+ struct test tests[] =
+ {
+ /* value expected variance */
+ { PAL_NEGINF, PAL_POSINF, 0 },
+ { -3.1415926535897932, 3.1415926535897932, PAL_EPSILON * 10 }, // value: -(pi) expected: pi
+ { -2.7182818284590452, 2.7182818284590452, PAL_EPSILON * 10 }, // value: -(e) expected: e
+ { -2.3025850929940457, 2.3025850929940457, PAL_EPSILON * 10 }, // value: -(ln(10)) expected: ln(10)
+ { -1.5707963267948966, 1.5707963267948966, PAL_EPSILON * 10 }, // value: -(pi / 2) expected: pi / 2
+ { -1.4426950408889634, 1.4426950408889634, PAL_EPSILON * 10 }, // value: -(log2(e)) expected: log2(e)
+ { -1.4142135623730950, 1.4142135623730950, PAL_EPSILON * 10 }, // value: -(sqrt(2)) expected: sqrt(2)
+ { -1.1283791670955126, 1.1283791670955126, PAL_EPSILON * 10 }, // value: -(2 / sqrt(pi)) expected: 2 / sqrt(pi)
+ { -1, 1, PAL_EPSILON * 10 },
+ { -0.78539816339744831, 0.78539816339744831, PAL_EPSILON }, // value: -(pi / 4) expected: pi / 4
+ { -0.70710678118654752, 0.70710678118654752, PAL_EPSILON }, // value: -(1 / sqrt(2)) expected: 1 / sqrt(2)
+ { -0.69314718055994531, 0.69314718055994531, PAL_EPSILON }, // value: -(ln(2)) expected: ln(2)
+ { -0.63661977236758134, 0.63661977236758134, PAL_EPSILON }, // value: -(2 / pi) expected: 2 / pi
+ { -0.43429448190325183, 0.43429448190325183, PAL_EPSILON }, // value: -(log10(e)) expected: log10(e)
+ { -0.31830988618379067, 0.31830988618379067, PAL_EPSILON }, // value: -(1 / pi) expected: 1 / pi
+ { -0.0, 0, PAL_EPSILON },
+ };
+
+
+ // PAL initialization
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate( tests[i].value, tests[i].expected, tests[i].variance);
+ validate(-tests[i].value, tests[i].expected, tests[i].variance);
+ }
+
+ validate_isnan(PAL_NAN);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fabs/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fabs/test1/testinfo.dat
new file mode 100644
index 0000000000..d5b2321edd
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fabs/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fabs
+Name = Positive Test for fabs
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes to fabs() a series of values, checking that
+= each one return to correct value.
diff --git a/src/pal/tests/palsuite/c_runtime/fabsf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fabsf/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fabsf/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/fabsf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fabsf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..06512ebd7c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fabsf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_fabsf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fabsf_test1 coreclrpal)
+
+target_link_libraries(paltest_fabsf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fabsf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/fabsf/test1/test1.c
new file mode 100644
index 0000000000..0b020729b8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fabsf/test1/test1.c
@@ -0,0 +1,130 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test to ensure that fabsf return the correct values
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (6-9 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON
+// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use
+// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10.
+#define PAL_EPSILON 4.76837158e-07
+
+
+#define PAL_NAN sqrt(-1.0)
+#define PAL_POSINF -log(0.0)
+#define PAL_NEGINF log(0.0)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ float value; /* value to test the function with */
+ float expected; /* expected result */
+ float variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(float value, float expected, float variance)
+{
+ float result = fabsf(value);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ float delta = fabsf(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("fabsf(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(float value)
+{
+ float result = fabsf(value);
+
+ if (!_isnan(result))
+ {
+ Fail("fabsf(%g) returned %10.9g when it should have returned %10.9g",
+ value, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+INT __cdecl main(INT argc, CHAR **argv)
+{
+ struct test tests[] =
+ {
+ /* value expected variance */
+ { PAL_NEGINF, PAL_POSINF, 0 },
+ { -3.14159265f, 3.14159265f, PAL_EPSILON * 10 }, // value: -(pi) expected: pi
+ { -2.71828183f, 2.71828183f, PAL_EPSILON * 10 }, // value: -(e) expected: e
+ { -2.30258509f, 2.30258509f, PAL_EPSILON * 10 }, // value: -(ln(10)) expected: ln(10)
+ { -1.57079633f, 1.57079633f, PAL_EPSILON * 10 }, // value: -(pi / 2) expected: pi / 2
+ { -1.44269504f, 1.44269504f, PAL_EPSILON * 10 }, // value: -(log2(e)) expected: log2(e)
+ { -1.41421356f, 1.41421356f, PAL_EPSILON * 10 }, // value: -(sqrt(2)) expected: sqrt(2)
+ { -1.12837917f, 1.12837917f, PAL_EPSILON * 10 }, // value: -(2 / sqrt(pi)) expected: 2 / sqrt(pi)
+ { -1, 1, PAL_EPSILON * 10 },
+ { -0.785398163f, 0.785398163f, PAL_EPSILON }, // value: -(pi / 4) expected: pi / 4
+ { -0.707106781f, 0.707106781f, PAL_EPSILON }, // value: -(1 / sqrt(2)) expected: 1 / sqrt(2)
+ { -0.693147181f, 0.693147181f, PAL_EPSILON }, // value: -(ln(2)) expected: ln(2)
+ { -0.636619772f, 0.636619772f, PAL_EPSILON }, // value: -(2 / pi) expected: 2 / pi
+ { -0.434294482f, 0.434294482f, PAL_EPSILON }, // value: -(log10(e)) expected: log10(e)
+ { -0.318309886f, 0.318309886f, PAL_EPSILON }, // value: -(1 / pi) expected: 1 / pi
+ { -0.0f, 0, PAL_EPSILON },
+ };
+
+
+ // PAL initialization
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate( tests[i].value, tests[i].expected, tests[i].variance);
+ validate(-tests[i].value, tests[i].expected, tests[i].variance);
+ }
+
+ validate_isnan(PAL_NAN);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fabsf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fabsf/test1/testinfo.dat
new file mode 100644
index 0000000000..a927f1e3df
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fabsf/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fabsf
+Name = Positive Test for fabsf
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes to fabsf() a series of values, checking that
+= each one return to correct value.
diff --git a/src/pal/tests/palsuite/c_runtime/fclose/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fclose/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fclose/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/c_runtime/fclose/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fclose/test1/CMakeLists.txt
new file mode 100644
index 0000000000..55ed7c674e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fclose/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_fclose_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fclose_test1 coreclrpal)
+
+target_link_libraries(paltest_fclose_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fclose/test1/test1.c b/src/pal/tests/palsuite/c_runtime/fclose/test1/test1.c
new file mode 100644
index 0000000000..0a8463823d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fclose/test1/test1.c
@@ -0,0 +1,79 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c (fclose)
+**
+** Purpose: Tests the PAL implementation of the fclose function.
+** This test will use fdopen to create a file stream,
+** that will be used to test fclose. fclose will also
+** be passed a closed file handle to make sure it handle
+** it accordingly.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ HANDLE hReadPipe = NULL;
+ HANDLE hWritePipe = NULL;
+ BOOL bRetVal = FALSE;
+ int iFiledes = 0;
+ FILE *fp;
+
+ SECURITY_ATTRIBUTES lpPipeAttributes;
+
+ /*Initialize the PAL*/
+ if ((PAL_Initialize(argc, argv)) != 0)
+ {
+ return (FAIL);
+ }
+
+ /*Setup SECURITY_ATTRIBUTES structure for CreatePipe*/
+ lpPipeAttributes.nLength = sizeof(lpPipeAttributes);
+ lpPipeAttributes.lpSecurityDescriptor = NULL;
+ lpPipeAttributes.bInheritHandle = TRUE;
+
+ /*Create a Pipe*/
+ bRetVal = CreatePipe(&hReadPipe, // read handle
+ &hWritePipe, // write handle
+ &lpPipeAttributes,// security attributes
+ 0); // pipe size
+
+ if (bRetVal == FALSE)
+ {
+ Fail("ERROR: Unable to create pipe; returned error code %ld"
+ , GetLastError());
+ }
+
+ /*Get a file descriptor for the read pipe handle*/
+ iFiledes = _open_osfhandle((long)hReadPipe,_O_RDONLY);
+
+ if (iFiledes == -1)
+ {
+ Fail("ERROR: _open_osfhandle failed to open "
+ " hReadPipe=0x%lx", hReadPipe);
+ }
+
+ /*Open read pipe handle in read mode*/
+ fp = _fdopen(iFiledes, "r");
+
+ if (fp == NULL)
+ {
+ Fail("ERROR: unable to fdopen file descriptor"
+ " iFiledes=%d", iFiledes);
+ }
+
+ /*Attempt to close the file stream*/
+ if (fclose(fp) != 0)
+ {
+ Fail("ERROR: Unable to fclose file stream fp=0x%lx\n",fp);
+ }
+
+ PAL_Terminate();
+ return (PASS);
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fclose/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fclose/test1/testinfo.dat
new file mode 100644
index 0000000000..0904c4fa9d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fclose/test1/testinfo.dat
@@ -0,0 +1,18 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fclose
+Name = Test for fclose
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests the PAL implementation of the fclose function.
+= This test will use fdopen to create a file stream,
+= that will be used to test fclose. fclose will also
+= be passed a closed file handle to make sure it handle
+= it accordingly.
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/fclose/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fclose/test2/CMakeLists.txt
new file mode 100644
index 0000000000..178dc7d19a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fclose/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_fclose_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fclose_test2 coreclrpal)
+
+target_link_libraries(paltest_fclose_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fclose/test2/test2.c b/src/pal/tests/palsuite/c_runtime/fclose/test2/test2.c
new file mode 100644
index 0000000000..f4da535535
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fclose/test2/test2.c
@@ -0,0 +1,77 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test2.c (fclose)
+**
+** Purpose: Tests the PAL implementation of the fclose function.
+** fclose will be passed a closed file handle to make
+** sure it handles it accordingly.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ HANDLE hReadPipe = NULL;
+ HANDLE hWritePipe = NULL;
+ BOOL bRetVal = FALSE;
+ int iFiledes = 0;
+ FILE *fp;
+
+ SECURITY_ATTRIBUTES lpPipeAttributes;
+
+ /*Initialize the PAL*/
+ if ((PAL_Initialize(argc, argv)) != 0)
+ {
+ return (FAIL);
+ }
+
+ /*Setup SECURITY_ATTRIBUTES structure for CreatePipe*/
+ lpPipeAttributes.nLength = sizeof(lpPipeAttributes);
+ lpPipeAttributes.lpSecurityDescriptor = NULL;
+ lpPipeAttributes.bInheritHandle = TRUE;
+
+ /*Create a Pipe*/
+ bRetVal = CreatePipe(&hReadPipe, /* read handle */
+ &hWritePipe, /* write handle */
+ &lpPipeAttributes,/* security attributes */
+ 0); /* pipe size */
+
+ if (bRetVal == FALSE)
+ {
+ Fail("ERROR: Unable to create pipe; returned error code %ld"
+ , GetLastError());
+ }
+
+ /*Get a file descriptor for the read pipe handle*/
+ iFiledes = _open_osfhandle((long)hReadPipe,_O_RDONLY);
+
+ if (iFiledes == -1)
+ {
+ Fail("ERROR: _open_osfhandle failed to open "
+ " hReadPipe=0x%lx", hReadPipe);
+ }
+
+ /*Open read pipe handle in read mode*/
+ fp = _fdopen(iFiledes, "r");
+
+ if (fp == NULL)
+ {
+ Fail("ERROR: unable to fdopen file descriptor"
+ " iFiledes=%d", iFiledes);
+ }
+
+ /*Attempt to close the file stream*/
+ if (fclose(fp) != 0)
+ {
+ Fail("ERROR: Unable to fclose file stream fp=0x%lx\n", fp);
+ }
+
+ PAL_Terminate();
+ return (PASS);
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fclose/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fclose/test2/testinfo.dat
new file mode 100644
index 0000000000..192b8d2f6b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fclose/test2/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fclose
+Name = Test for fclose
+TYPE = DEFAULT
+EXE1 = test2
+LANG = cpp
+Description
+= Tests the PAL implementation of the fclose function.
+= fclose will be passed a closed file handle to
+= make sure it handles it accordingly.
diff --git a/src/pal/tests/palsuite/c_runtime/feof/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/feof/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/feof/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/feof/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/feof/test1/CMakeLists.txt
new file mode 100644
index 0000000000..ee1389deb0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/feof/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_feof_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_feof_test1 coreclrpal)
+
+target_link_libraries(paltest_feof_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/feof/test1/test1.c b/src/pal/tests/palsuite/c_runtime/feof/test1/test1.c
new file mode 100644
index 0000000000..ba018aa91d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/feof/test1/test1.c
@@ -0,0 +1,88 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests the PAL implementation of the feof function.
+** Open a file, and read some characters. Check that
+** feof states that it hasn't gone by the EOF. Then
+** read enough characters to go beyond the EOF, and check
+** that feof states this is so.
+**
+** Depends:
+** fopen
+** fread
+**
+**
+**
+**===================================================================*/
+
+/* The file 'testfile' should exist with 15 characters in it. If not,
+ something has been lost ...
+*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ const char filename[] = "testfile";
+ char buffer[128];
+ FILE * fp = NULL;
+ int result;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /* Open a file in READ mode */
+
+ if((fp = fopen(filename, "r")) == NULL)
+ {
+ Fail("Unable to open a file for reading. Is the file "
+ "in the directory? It should be.");
+ }
+
+ /* Read 10 characters from the file. The file has 15
+ characters in it.
+ */
+
+ if((result = fread(buffer,1,10,fp)) == 0)
+ {
+ Fail("ERROR: Zero characters read from the file. It should have "
+ "read 10 character in it.");
+ }
+
+ if(feof(fp))
+ {
+ Fail("ERROR: feof returned a value greater than 0. No read "
+ "operation has gone beyond the EOF yet, and feof should "
+ "return 0 still.");
+ }
+
+ /* Read 10 characters from the file. The file has 15
+ characters in it. The file pointer should have no passed
+ the end of file.
+ */
+
+ if((result = fread(buffer,1,10,fp)) == 0)
+ {
+ Fail("ERROR: Zero characters read from the file. It should have "
+ "read 5 character in it.");
+ }
+
+ if(feof(fp) == 0)
+ {
+ Fail("ERROR: feof returned 0. The file pointer has gone beyond "
+ "the EOF and this function should return positive now.");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/feof/test1/testfile b/src/pal/tests/palsuite/c_runtime/feof/test1/testfile
new file mode 100644
index 0000000000..273c1a9ffd
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/feof/test1/testfile
@@ -0,0 +1 @@
+This is a test. \ No newline at end of file
diff --git a/src/pal/tests/palsuite/c_runtime/feof/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/feof/test1/testinfo.dat
new file mode 100644
index 0000000000..e14044ee17
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/feof/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = feof
+Name = Positive Test for feof
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests the PAL implementation of the feof function.
+= Open a file, and read some characters. Check that feof states that
+= it hasn't gone by the EOF. Then read enough characters to go beyond
+= the EOF, and check that feof states this is so.
+
diff --git a/src/pal/tests/palsuite/c_runtime/ferror/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/ferror/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ferror/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/c_runtime/ferror/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/ferror/test1/CMakeLists.txt
new file mode 100644
index 0000000000..2ab12b5db3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ferror/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_ferror_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_ferror_test1 coreclrpal)
+
+target_link_libraries(paltest_ferror_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/ferror/test1/test1.c b/src/pal/tests/palsuite/c_runtime/ferror/test1/test1.c
new file mode 100644
index 0000000000..516f2531ed
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ferror/test1/test1.c
@@ -0,0 +1,74 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests the PAL implementation of the ferror function.
+**
+** Depends:
+** fopen
+** fread
+** fclose
+**
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ const char filename[] = "testfile";
+ char buffer[128];
+ FILE * fp = NULL;
+ int result;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /* Open a file in READ mode */
+
+ if((fp = fopen(filename, "r")) == NULL)
+ {
+ Fail("Unable to open a file for reading. Is the file "
+ "in the directory? It should be.");
+ }
+
+ /* Read 10 characters from the file. The file has 15
+ characters in it.
+ */
+
+ if((result = fread(buffer,1,10,fp)) == 0)
+ {
+ Fail("ERROR: Zero characters read from the file. It should have "
+ "read 10 character in from a 15 character file.");
+ }
+
+ if(ferror(fp) != 0)
+ {
+ Fail("ERROR: ferror returned a value not equal to 0. The read "
+ "operation shouldn't have caused an error, and ferror should "
+ "return 0 still.");
+ }
+
+ /*
+ Close the open file and end the test.
+ */
+
+ if(fclose(fp) != 0)
+ {
+ Fail("ERROR: fclose failed when trying to close a file pointer. "
+ "This test depends on fclose working properly.");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/ferror/test1/testfile b/src/pal/tests/palsuite/c_runtime/ferror/test1/testfile
new file mode 100644
index 0000000000..273c1a9ffd
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ferror/test1/testfile
@@ -0,0 +1 @@
+This is a test. \ No newline at end of file
diff --git a/src/pal/tests/palsuite/c_runtime/ferror/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/ferror/test1/testinfo.dat
new file mode 100644
index 0000000000..32e55a3b0d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ferror/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = ferror
+Name = Positive Test for ferror
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests the PAL implementation of the ferror function.
+= Open a file, and read some characters. Check that ferror states that
+= no error has occurred. Then close the file pointer. Attempt to read
+= some more. Check ferror now, and it should indicate that an error has
+= occurred.
diff --git a/src/pal/tests/palsuite/c_runtime/ferror/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/ferror/test2/CMakeLists.txt
new file mode 100644
index 0000000000..077dde0bc6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ferror/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_ferror_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_ferror_test2 coreclrpal)
+
+target_link_libraries(paltest_ferror_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/ferror/test2/test2.c b/src/pal/tests/palsuite/c_runtime/ferror/test2/test2.c
new file mode 100644
index 0000000000..fdf9e032c8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ferror/test2/test2.c
@@ -0,0 +1,69 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test2.c
+**
+** Purpose: Open a read-only file and attempt to write some data to it.
+** Check to ensure that an ferror occurs.
+**
+** Depends:
+** fopen
+** fwrite
+** fclose
+**
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ const char filename[] = "testfile";
+ FILE * fp = NULL;
+ int result;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Open a file in READONLY mode */
+
+ if((fp = fopen(filename, "r")) == NULL)
+ {
+ Fail("Unable to open a file for reading.");
+ }
+
+ /* Attempt to write 14 characters to the file. */
+
+ if((result = fwrite("This is a test",1,14,fp)) != 0)
+ {
+ Fail("ERROR: %d characters written. 0 characters should "
+ "have been written, since this file is read-only.", result);
+ }
+
+ if(ferror(fp) == 0)
+ {
+ Fail("ERROR: ferror should have generated an error when "
+ "write was called on a read-only file. But, it "
+ "retured 0, indicating no error.\n");
+ }
+
+ /* Close the file. */
+
+ if(fclose(fp) != 0)
+ {
+ Fail("ERROR: fclose failed when trying to close a file pointer. "
+ "This test depends on fclose working properly.");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/ferror/test2/testfile b/src/pal/tests/palsuite/c_runtime/ferror/test2/testfile
new file mode 100644
index 0000000000..0135842a03
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ferror/test2/testfile
@@ -0,0 +1 @@
+This is a test file. This needs to be kept in CVS. \ No newline at end of file
diff --git a/src/pal/tests/palsuite/c_runtime/ferror/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/ferror/test2/testinfo.dat
new file mode 100644
index 0000000000..d724a4c4e7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ferror/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = ferror
+Name = Positive Test for ferror, call write on a readonly file.
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Open a read-only file and attempt to write some data to it.
+= Check to ensure that an ferror occurs.
diff --git a/src/pal/tests/palsuite/c_runtime/fflush/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fflush/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fflush/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/fflush/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fflush/test1/CMakeLists.txt
new file mode 100644
index 0000000000..743f1d2111
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fflush/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_fflush_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fflush_test1 coreclrpal)
+
+target_link_libraries(paltest_fflush_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fflush/test1/test1.c b/src/pal/tests/palsuite/c_runtime/fflush/test1/test1.c
new file mode 100644
index 0000000000..7baf9ba5b9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fflush/test1/test1.c
@@ -0,0 +1,80 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests to see that fflush is working properly. Flushes a couple
+** buffers and checks the return value. Can't figure out a way to test
+** and ensure it is really dropping the buffers, since the system
+** does this automatically most of the time ...
+**
+**
+**==========================================================================*/
+
+/* This function is really tough to test. Right now it just tests
+ a bunch of return values. No solid way to ensure that it is really
+ flushing a buffer or not -- might have to be a manual test someday.
+*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char **argv)
+{
+
+ int TheReturn;
+ FILE* TheFile;
+ FILE* AnotherFile = NULL;
+
+ PAL_Initialize(argc,argv);
+
+ TheFile = fopen("theFile","w+");
+
+ if(TheFile == NULL)
+ {
+ Fail("ERROR: fopen failed. Test depends on this function.");
+ }
+
+ TheReturn = fwrite("foo",3,3,TheFile);
+
+ if(TheReturn != 3)
+ {
+ Fail("ERROR: fwrite failed. Test depends on this function.");
+ }
+
+ /* Test to see that FlushFileBuffers returns a success value */
+ TheReturn = fflush(TheFile);
+
+ if(TheReturn != 0)
+ {
+ Fail("ERROR: The fflush function returned non-zero, which "
+ "indicates failure, when trying to flush a buffer.");
+ }
+
+ /* Test to see that FlushFileBuffers returns a success value */
+ TheReturn = fflush(NULL);
+
+ if(TheReturn != 0)
+ {
+ Fail("ERROR: The fflush function returned non-zero, which "
+ "indicates failure, when trying to flush all buffers.");
+ }
+
+ /* Test to see that FlushFileBuffers returns a success value */
+ TheReturn = fflush(AnotherFile);
+
+ if(TheReturn != 0)
+ {
+ Fail("ERROR: The fflush function returned non-zero, which "
+ "indicates failure, when trying to flush a stream not "
+ "associated with a file.");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/fflush/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fflush/test1/testinfo.dat
new file mode 100644
index 0000000000..1cff5a94a1
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fflush/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fflush
+Name = Positive Test for fflush
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests to see that fflush is working properly. Flushes a couple
+= buffers and checks the return value. Can't figure out a way to test
+= and ensure it is really dropping the buffers, since the system
+= does this automatically most of the time ...
diff --git a/src/pal/tests/palsuite/c_runtime/fgets/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fgets/CMakeLists.txt
new file mode 100644
index 0000000000..1962ade358
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fgets/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+
diff --git a/src/pal/tests/palsuite/c_runtime/fgets/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fgets/test1/CMakeLists.txt
new file mode 100644
index 0000000000..672d910c85
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fgets/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_fgets_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fgets_test1 coreclrpal)
+
+target_link_libraries(paltest_fgets_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fgets/test1/test1.c b/src/pal/tests/palsuite/c_runtime/fgets/test1/test1.c
new file mode 100644
index 0000000000..5e0e62dece
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fgets/test1/test1.c
@@ -0,0 +1,102 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Writes a simple file and calls fgets() to get a string shorter
+** than the first line of the file. Verifies that the correct
+** string is returned.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ const char outBuf1[] = "This is a test.\n";
+ const char outBuf2[] = "This is too.";
+ char inBuf[sizeof(outBuf1) + sizeof(outBuf2)];
+ const char filename[] = "testfile.tmp";
+ const int offset = 5; /* value chosen arbitrarily */
+ int actualLen;
+ int expectedLen;
+ FILE * fp;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /*write the file that we will use to test */
+ fp = fopen(filename, "w");
+ if (fp == NULL)
+ {
+ Fail("Unable to open file for write.\n");
+ }
+
+ fwrite(outBuf1, sizeof(outBuf1[0]), sizeof(outBuf1), fp);
+ fwrite(outBuf2, sizeof(outBuf2[0]), sizeof(outBuf2), fp);
+
+ if (fclose(fp) != 0)
+ {
+ Fail("Error closing a file opened for write.\n");
+ }
+
+
+ /*now read back the entire first string*/
+ fp = fopen(filename, "r");
+ if (fp == NULL)
+ {
+ Fail("Unable to open file for read.\n");
+ }
+
+ /*note: +1 because strlen() returns the length of a string _not_
+ including the NULL, while fgets() returns a string of specified
+ maximum length _including_ the NULL.*/
+ if (fgets(inBuf, strlen(outBuf1) - offset + 1, fp) != inBuf)
+ {
+ Fail("Error reading from file using fgets.\n");
+ }
+
+
+ expectedLen = strlen(outBuf1) - offset;
+ actualLen = strlen(inBuf);
+
+ if (actualLen < expectedLen)
+ {
+ Fail("fgets() was asked to read a one-line string and given the "
+ "length of the string as a parameter. The string it has "
+ "read is too short.\n");
+ }
+ if (actualLen > expectedLen)
+ {
+ Fail("fgets() was asked to read a one-line string and given the "
+ "length of the string as a parameter. The string it has "
+ "read is too long.\n");
+ }
+ if (memcmp(inBuf, outBuf1, actualLen) != 0)
+ {
+ /*We didn't read back exactly outBuf1*/
+ Fail("fgets() was asked to read a one-line string, and given the "
+ "length of the string as an parameter. It has returned a "
+ "string of the correct length, but the contents are not "
+ "correct.\n");
+ }
+
+ if (fclose(fp) != 0)
+ {
+ Fail("Error closing file after using fgets().\n");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/fgets/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fgets/test1/testinfo.dat
new file mode 100644
index 0000000000..70ea6690ca
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fgets/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fgets
+Name = Positive Test for fgets
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Writes a simple file and calls fgets() to get a string shorter than
+= the first line of the file. Verifies that the correct string is
+= returned.
+
diff --git a/src/pal/tests/palsuite/c_runtime/fgets/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fgets/test2/CMakeLists.txt
new file mode 100644
index 0000000000..d39401536b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fgets/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_fgets_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fgets_test2 coreclrpal)
+
+target_link_libraries(paltest_fgets_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fgets/test2/test2.c b/src/pal/tests/palsuite/c_runtime/fgets/test2/test2.c
new file mode 100644
index 0000000000..fa37cdbc13
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fgets/test2/test2.c
@@ -0,0 +1,97 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test2.c
+**
+** Purpose: Calls fgets to read a full line from a file. A maximum length
+** parameter greater than the length of the line is passed.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ const char outBuf1[] = "This is a test.\n";
+ const char outBuf2[] = "This is too.";
+
+ char inBuf[sizeof(outBuf1) + sizeof(outBuf2)];
+ const char filename[] = "testfile.tmp";
+ const int offset = 5; /*value chosen arbitrarily*/
+ int expectedLen;
+ int actualLen;
+
+ FILE * fp;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /*write the file that we will use to test */
+ fp = fopen(filename, "w");
+ if (fp == NULL)
+ {
+ Fail("Unable to open file for write.\n");
+ }
+
+ fwrite(outBuf1, sizeof(outBuf1[0]), sizeof(outBuf1), fp);
+ fwrite(outBuf2, sizeof(outBuf2[0]), sizeof(outBuf2), fp);
+
+ if (fclose(fp) != 0)
+ {
+ Fail("error closing stream opened for write.\n");
+ }
+
+ /*Read until the first linebreak*/
+ fp = fopen(filename, "r");
+ if (fp == NULL)
+ {
+ Fail("Unable to open file for read.\n");
+ }
+
+
+ if (fgets(inBuf, sizeof(outBuf1) + offset , fp) != inBuf)
+ {
+ Fail("Error reading from file using fgets.\n");
+ }
+
+ /*note: -1 because strlen returns the length of a string _not_
+ including the NULL, while fgets returns a string of specified
+ maximum length _including_ the NULL.*/
+ expectedLen = strlen(outBuf1);
+ actualLen = strlen(inBuf);
+ if (actualLen > expectedLen)
+ {
+ Fail("fgets() was asked to read the first line of a file, but did "
+ "not stop at the end of the line.\n");
+ }
+ else if (actualLen < expectedLen)
+ {
+ Fail("fgets() was asked to read the first line of a file, but did "
+ "not read the entire line.\n");
+ }
+ else if (memcmp(inBuf, outBuf1, actualLen) != 0)
+ {
+ /*We didn't read back exactly outBuf1*/
+ Fail("fgets() was asked to read the first line of a file. It "
+ "has read back a string of the correct length, but the"
+ " contents are not correct.\n");
+ }
+
+ if (fclose(fp) != 0)
+ {
+ Fail("Error closing file after using fgets().\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/fgets/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fgets/test2/testinfo.dat
new file mode 100644
index 0000000000..d282dbaa65
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fgets/test2/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fgets
+Name = Positive Test for fgets
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Calls fgets to read a full line from a file. A maximum length
+= parameter greater than the length of the line is passed.
+
diff --git a/src/pal/tests/palsuite/c_runtime/fgets/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fgets/test3/CMakeLists.txt
new file mode 100644
index 0000000000..50f0901ee1
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fgets/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_fgets_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fgets_test3 coreclrpal)
+
+target_link_libraries(paltest_fgets_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fgets/test3/test3.c b/src/pal/tests/palsuite/c_runtime/fgets/test3/test3.c
new file mode 100644
index 0000000000..525ba9327f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fgets/test3/test3.c
@@ -0,0 +1,73 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test3.c
+**
+** Purpose: Tries to read from an empty file using fgets(), to verify
+** handling of EOF condition.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ char inBuf[10];
+ const char filename[] = "testfile.tmp";
+
+ FILE * fp;
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /*write the empty file that we will use to test */
+ fp = fopen(filename, "w");
+ if (fp == NULL)
+ {
+ Fail("Unable to open file for write.\n");
+ }
+
+ /*Don't write anything*/
+
+ if (fclose(fp) != 0)
+ {
+ Fail("Error closing stream opened for write.\n");
+ }
+
+
+ /*Open the file and try to read.*/
+ fp = fopen(filename, "r");
+ if (fp == NULL)
+ {
+ Fail("Unable to open file for read.\n");
+ }
+
+
+ if (fgets(inBuf, sizeof(inBuf) , fp) != NULL)
+ {
+ /*NULL could also mean an error condition, but since the PAL
+ doesn't supply feof or ferror, we can't distinguish between
+ the two.*/
+ Fail("fgets doesn't handle EOF properly. When asked to read from "
+ "an empty file, it didn't return NULL as it should have.\n");
+ }
+
+ if (fclose(fp) != 0)
+ {
+ Fail("Error closing an empty file after trying to use fgets().\n");
+ }
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/fgets/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fgets/test3/testinfo.dat
new file mode 100644
index 0000000000..e10cf89968
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fgets/test3/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fgets
+Name = Positive Test for fgets
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Tries to read from an empty file using fgets(), to verify handling of
+= EOF condition.
+
diff --git a/src/pal/tests/palsuite/c_runtime/floor/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/floor/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/floor/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/floor/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/floor/test1/CMakeLists.txt
new file mode 100644
index 0000000000..dbc5abde5b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/floor/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_floor_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_floor_test1 coreclrpal)
+
+target_link_libraries(paltest_floor_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/floor/test1/test1.c b/src/pal/tests/palsuite/c_runtime/floor/test1/test1.c
new file mode 100644
index 0000000000..dba320919b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/floor/test1/test1.c
@@ -0,0 +1,132 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests floor with simple positive and negative values. Also tests
+** extreme cases like extremely small values and positive and
+** negative infinity. Makes sure that calling floor on NaN returns
+** NaN
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (15-17 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use
+// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx
+// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will
+// use PAL_EPSILON * 10.
+#define PAL_EPSILON 8.8817841970012523e-16
+
+#define PAL_NAN sqrt(-1.0)
+#define PAL_POSINF -log(0.0)
+#define PAL_NEGINF log(0.0)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ double value; /* value to test the function with */
+ double expected; /* expected result */
+ double variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(double value, double expected, double variance)
+{
+ double result = floor(value);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ double delta = fabs(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("floor(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(double value)
+{
+ double result = floor(value);
+
+ if (!_isnan(result))
+ {
+ Fail("floor(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char *argv[])
+{
+ struct test tests[] =
+ {
+ /* value expected variance */
+ { 0.31830988618379067, 0, PAL_EPSILON }, // value: 1 / pi
+ { 0.43429448190325183, 0, PAL_EPSILON }, // value: log10(e)
+ { 0.63661977236758134, 0, PAL_EPSILON }, // value: 2 / pi
+ { 0.69314718055994531, 0, PAL_EPSILON }, // value: ln(2)
+ { 0.70710678118654752, 0, PAL_EPSILON }, // value: 1 / sqrt(2)
+ { 0.78539816339744831, 0, PAL_EPSILON }, // value: pi / 4
+ { 1.1283791670955126, 1, PAL_EPSILON * 10 }, // value: 2 / sqrt(pi)
+ { 1.4142135623730950, 1, PAL_EPSILON * 10 }, // value: sqrt(2)
+ { 1.4426950408889634, 1, PAL_EPSILON * 10 }, // value: log2(e)
+ { 1.5707963267948966, 1, PAL_EPSILON * 10 }, // value: pi / 2
+ { 2.3025850929940457, 2, PAL_EPSILON * 10 }, // value: ln(10)
+ { 2.7182818284590452, 2, PAL_EPSILON * 10 }, // value: e
+ { 3.1415926535897932, 3, PAL_EPSILON * 10 }, // value: pi
+ { PAL_POSINF, PAL_POSINF, 0 }
+ };
+
+ /* PAL initialization */
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ validate( 0, 0, PAL_EPSILON);
+ validate(-0.0, 0, PAL_EPSILON);
+
+ validate( 1, 1, PAL_EPSILON * 10);
+ validate(-1.0, -1, PAL_EPSILON * 10);
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate( tests[i].value, tests[i].expected, tests[i].variance);
+ validate(-tests[i].value, -(tests[i].expected + 1), tests[i].variance);
+ }
+
+ validate_isnan(PAL_NAN);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/floor/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/floor/test1/testinfo.dat
new file mode 100644
index 0000000000..90543ea7af
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/floor/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = floor
+Name = Positive Test for floor
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes to floor() a series of value, checking that
+= each one return to correct value.
diff --git a/src/pal/tests/palsuite/c_runtime/fmod/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fmod/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fmod/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/fmod/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fmod/test1/CMakeLists.txt
new file mode 100644
index 0000000000..c76df1f0bf
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fmod/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_fmod_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fmod_test1 coreclrpal)
+
+target_link_libraries(paltest_fmod_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fmod/test1/test1.c b/src/pal/tests/palsuite/c_runtime/fmod/test1/test1.c
new file mode 100644
index 0000000000..fd69ca52cb
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fmod/test1/test1.c
@@ -0,0 +1,157 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test to ensure that fmod return the correct values
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** fabs
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (15-17 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use
+// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx
+// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will
+// use PAL_EPSILON * 10.
+#define PAL_EPSILON 8.8817841970012523e-16
+
+#define PAL_NAN sqrt(-1.0)
+#define PAL_POSINF -log(0.0)
+#define PAL_NEGINF log(0.0)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ double numerator; /* second component of the value to test the function with */
+ double denominator; /* first component of the value to test the function with */
+ double expected; /* expected result */
+ double variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(double numerator, double denominator, double expected, double variance)
+{
+ double result = fmod(numerator, denominator);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ double delta = fabs(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("fmod(%g, %g) returned %20.17g when it should have returned %20.17g",
+ numerator, denominator, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(double numerator, double denominator)
+{
+ double result = fmod(numerator, denominator);
+
+ if (!_isnan(result))
+ {
+ Fail("fmod(%g, %g) returned %20.17g when it should have returned %20.17g",
+ numerator, denominator, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+INT __cdecl main(INT argc, CHAR **argv)
+{
+ struct test tests[] =
+ {
+ /* numerator denominator expected variance */
+ { 0, PAL_POSINF, 0, PAL_EPSILON },
+ { 0.31296179620778659, 0.94976571538163866, 0.31296179620778658, PAL_EPSILON },
+ { 0.42077048331375735, 0.90716712923909839, 0.42077048331375733, PAL_EPSILON },
+ { 0.59448076852482208, 0.80410982822879171, 0.59448076852482212, PAL_EPSILON },
+ { 0.63896127631363480, 0.76923890136397213, 0.63896127631363475, PAL_EPSILON },
+ { 0.64963693908006244, 0.76024459707563015, 0.64963693908006248, PAL_EPSILON },
+ { 0.70710678118654752, 0.70710678118654752, 0, PAL_EPSILON },
+ { 1, 1, 0, PAL_EPSILON },
+ { 0.84147098480789651, 0.54030230586813972, 0.30116867893975674, PAL_EPSILON },
+ { 0.90371945743584630, 0.42812514788535792, 0.047469161665130377, PAL_EPSILON / 10 },
+ { 0.98776594599273553, 0.15594369476537447, 0.052103777400488605, PAL_EPSILON / 10 },
+ { 0.99180624439366372, 0.12775121753523991, 0.097547721646984359, PAL_EPSILON / 10 },
+ { 0.74398033695749319, -0.66820151019031295, 0.075778826767180285, PAL_EPSILON / 10 },
+ { 0.41078129050290870, -0.91173391478696510, 0.41078129050290868, PAL_EPSILON },
+ { 0, -1, 0, PAL_EPSILON },
+ { 1, PAL_POSINF, 1, PAL_EPSILON * 10 },
+ };
+
+
+ // PAL initialization
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate( tests[i].numerator, tests[i].denominator, tests[i].expected, tests[i].variance);
+ validate(-tests[i].numerator, tests[i].denominator, -tests[i].expected, tests[i].variance);
+ validate( tests[i].numerator, -tests[i].denominator, tests[i].expected, tests[i].variance);
+ validate(-tests[i].numerator, -tests[i].denominator, -tests[i].expected, tests[i].variance);
+ }
+
+ validate_isnan( 0, 0);
+ validate_isnan(-0.0, 0);
+ validate_isnan( 0, -0.0);
+ validate_isnan(-0.0, -0.0);
+
+ validate_isnan( 1, 0);
+ validate_isnan(-1.0, 0);
+ validate_isnan( 1, -0.0);
+ validate_isnan(-1.0, -0.0);
+
+ validate_isnan(PAL_POSINF, PAL_POSINF);
+ validate_isnan(PAL_NEGINF, PAL_POSINF);
+ validate_isnan(PAL_POSINF, PAL_NEGINF);
+ validate_isnan(PAL_NEGINF, PAL_NEGINF);
+
+ validate_isnan(PAL_POSINF, 0);
+ validate_isnan(PAL_NEGINF, 0);
+ validate_isnan(PAL_POSINF, -0.0);
+ validate_isnan(PAL_NEGINF, -0.0);
+
+ validate_isnan(PAL_POSINF, 1);
+ validate_isnan(PAL_NEGINF, 1);
+ validate_isnan(PAL_POSINF, -1.0);
+ validate_isnan(PAL_NEGINF, -1.0);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fmod/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fmod/test1/testinfo.dat
new file mode 100644
index 0000000000..0a81fd80e0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fmod/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fmod
+Name = Positive Test for fmod
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes to fmod() a series of values, checking that
+= each one return to correct value.
diff --git a/src/pal/tests/palsuite/c_runtime/fmodf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fmodf/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fmodf/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/fmodf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fmodf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..d1ea238a98
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fmodf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_fmodf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fmodf_test1 coreclrpal)
+
+target_link_libraries(paltest_fmodf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fmodf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/fmodf/test1/test1.c
new file mode 100644
index 0000000000..31b45d3606
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fmodf/test1/test1.c
@@ -0,0 +1,156 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test to ensure that fmodf return the correct values
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** fabsf
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (6-9 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON
+// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use
+// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10.
+#define PAL_EPSILON 4.76837158e-07
+
+#define PAL_NAN sqrt(-1.0)
+#define PAL_POSINF -log(0.0)
+#define PAL_NEGINF log(0.0)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ float numerator; /* second component of the value to test the function with */
+ float denominator; /* first component of the value to test the function with */
+ float expected; /* expected result */
+ float variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(float numerator, float denominator, float expected, float variance)
+{
+ float result = fmodf(numerator, denominator);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ float delta = fabsf(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("fmodf(%g, %g) returned %10.9g when it should have returned %10.9g",
+ numerator, denominator, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(float numerator, float denominator)
+{
+ float result = fmodf(numerator, denominator);
+
+ if (!_isnan(result))
+ {
+ Fail("fmodf(%g, %g) returned %10.9g when it should have returned %10.9g",
+ numerator, denominator, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+INT __cdecl main(INT argc, CHAR **argv)
+{
+ struct test tests[] =
+ {
+ /* numerator denominator expected variance */
+ { 0, PAL_POSINF, 0, PAL_EPSILON },
+ { 0.312961796f, 0.949765715f, 0.312961796f, PAL_EPSILON },
+ { 0.420770483f, 0.907167129f, 0.420770483f, PAL_EPSILON },
+ { 0.594480769f, 0.804109828f, 0.594480769f, PAL_EPSILON },
+ { 0.638961276f, 0.769238901f, 0.638961276f, PAL_EPSILON },
+ { 0.649636939f, 0.760244597f, 0.649636939f, PAL_EPSILON },
+ { 0.707106781f, 0.707106781f, 0, PAL_EPSILON },
+ { 1, 1, 0, PAL_EPSILON },
+ { 0.841470985f, 0.540302306f, 0.301168679f, PAL_EPSILON },
+ { 0.903719457f, 0.428125148f, 0.0474691617f, PAL_EPSILON / 10 },
+ { 0.987765946f, 0.155943695f, 0.0521037774f, PAL_EPSILON / 10 },
+ { 0.991806244f, 0.127751218f, 0.0975477216f, PAL_EPSILON / 10 },
+ { 0.743980337f, -0.668201510f, 0.0757788268f, PAL_EPSILON / 10 },
+ { 0.410781291f, -0.911733915f, 0.410781291f, PAL_EPSILON },
+ { 0, -1, 0, PAL_EPSILON },
+ { 1, PAL_POSINF, 1, PAL_EPSILON * 10 },
+ };
+
+
+ // PAL initialization
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate( tests[i].numerator, tests[i].denominator, tests[i].expected, tests[i].variance);
+ validate(-tests[i].numerator, tests[i].denominator, -tests[i].expected, tests[i].variance);
+ validate( tests[i].numerator, -tests[i].denominator, tests[i].expected, tests[i].variance);
+ validate(-tests[i].numerator, -tests[i].denominator, -tests[i].expected, tests[i].variance);
+ }
+
+ validate_isnan( 0, 0);
+ validate_isnan(-0.0f, 0);
+ validate_isnan( 0, -0.0f);
+ validate_isnan(-0.0f, -0.0f);
+
+ validate_isnan( 1, 0);
+ validate_isnan(-1, 0);
+ validate_isnan( 1, -0.0f);
+ validate_isnan(-1, -0.0f);
+
+ validate_isnan(PAL_POSINF, PAL_POSINF);
+ validate_isnan(PAL_NEGINF, PAL_POSINF);
+ validate_isnan(PAL_POSINF, PAL_NEGINF);
+ validate_isnan(PAL_NEGINF, PAL_NEGINF);
+
+ validate_isnan(PAL_POSINF, 0);
+ validate_isnan(PAL_NEGINF, 0);
+ validate_isnan(PAL_POSINF, -0.0f);
+ validate_isnan(PAL_NEGINF, -0.0f);
+
+ validate_isnan(PAL_POSINF, 1);
+ validate_isnan(PAL_NEGINF, 1);
+ validate_isnan(PAL_POSINF, -1);
+ validate_isnan(PAL_NEGINF, -1);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fmodf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fmodf/test1/testinfo.dat
new file mode 100644
index 0000000000..11c7978925
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fmodf/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fmodf
+Name = Positive Test for fmodf
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes to fmodf() a series of values, checking that
+= each one return to correct value.
diff --git a/src/pal/tests/palsuite/c_runtime/fopen/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fopen/CMakeLists.txt
new file mode 100644
index 0000000000..19ee487a6a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fopen/CMakeLists.txt
@@ -0,0 +1,10 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+add_subdirectory(test7)
+
diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fopen/test1/CMakeLists.txt
new file mode 100644
index 0000000000..6578c43659
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fopen/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_fopen_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fopen_test1 coreclrpal)
+
+target_link_libraries(paltest_fopen_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test1/test1.c b/src/pal/tests/palsuite/c_runtime/fopen/test1/test1.c
new file mode 100644
index 0000000000..565b4eb77d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fopen/test1/test1.c
@@ -0,0 +1,82 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests the PAL implementation of the fopen function.
+** This test simply attempts to open a number of files
+** with different modes. It checks to ensure a valid
+** file pointer is returned. It doesn't do any checking
+** to ensure the mode is really what it claims. And checks
+** for a NULL pointer when attempts to open a directory.
+**
+
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+struct testCase
+{
+ int CorrectResult;
+ char mode[20];
+};
+
+int __cdecl main(int argc, char **argv)
+{
+
+ FILE *fp;
+ char name[128];
+ int i;
+
+ struct testCase testCases[] =
+ {
+ {0, "r"}, {1, "w"}, {1, "a"},
+ {0, "r+"}, {1, "w+"}, {1, "a+"},
+ {1, "wt"}, {1, "wb"}, {1, "wS"},
+ {1, "w+c"}, {1, "w+n"}, {1, "wR"},
+ {1, "wT"}, {0, "tw"}
+ };
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+
+ for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++)
+ {
+ strcpy(name,"testfiles");
+ strcat(name,testCases[i].mode);
+
+ fp = fopen(name,testCases[i].mode);
+
+ if ((fp == 0 && testCases[i].CorrectResult != 0) ||
+ (testCases[i].CorrectResult == 0 && fp != 0) )
+ {
+ Fail("ERROR: fopen returned incorrectly "
+ "opening a file in %s mode. Perhaps it opened a "
+ "read only file which didn't exist and returned a correct "
+ "pointer?",testCases[i].mode);
+ }
+
+ memset(name, '\0', 128);
+
+ }
+
+ /* When attempt to open a directory fopen should returned NULL */
+ if ( fopen(".", "r") != NULL)
+ {
+ Fail("ERROR: fopen returned non-NULL when trying to open a directory"
+ " the returned value was %d\n", fp);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fopen/test1/testinfo.dat
new file mode 100644
index 0000000000..d9908549ea
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fopen/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fopen
+Name = Positive Test for fopen
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= This test simply attempts to open a number of files with different
+= modes. It checks to ensure a valid file pointer is returned. It
+= doesn't do any checking to ensure the mode is really what it claims.
+= Checks for returned value when attempts to open a directory.
diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fopen/test2/CMakeLists.txt
new file mode 100644
index 0000000000..4458ed21d8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fopen/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_fopen_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fopen_test2 coreclrpal)
+
+target_link_libraries(paltest_fopen_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test2/test2.c b/src/pal/tests/palsuite/c_runtime/fopen/test2/test2.c
new file mode 100644
index 0000000000..4026efe89a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fopen/test2/test2.c
@@ -0,0 +1,65 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test2.c
+**
+** Purpose: Tests the PAL implementation of the fopen function.
+** Test to ensure that you can write to a 'w' mode file.
+** And that you can't read from a 'w' mode file.
+**
+** Depends:
+** fprintf
+** fseek
+** fgets
+**
+
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+
+ FILE *fp;
+ char buffer[128];
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ if( (fp = fopen( "testfile", "w" )) == NULL )
+ {
+ Fail( "ERROR: The file failed to open with 'w' mode.\n" );
+ }
+
+ /* Test that you can write */
+ if(fprintf(fp,"%s","some text") <= 0)
+ {
+ Fail("ERROR: Attempted to WRITE to a file opened with 'w' mode "
+ "but fprintf failed. Either fopen or fprintf have problems.");
+ }
+
+ if(fseek(fp, 0, SEEK_SET))
+ {
+ Fail("ERROR: fseek failed, and this test depends on it.");
+ }
+
+ /* Test that you can't read */
+ if(fgets(buffer,10,fp) != NULL)
+ {
+ Fail("ERROR: Tried to READ from a file with only 'w' mode set. "
+ "This should fail, but fgets didn't return NULL. Either "
+ "fgets or fopen is broken.");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fopen/test2/testinfo.dat
new file mode 100644
index 0000000000..4c1a0095f8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fopen/test2/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fopen
+Name = Positive Test for fopen
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Test to ensure that you can write to a 'w' mode file. And that you can't
+= read from a 'w' mode file.
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fopen/test3/CMakeLists.txt
new file mode 100644
index 0000000000..2c80f72ae7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fopen/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_fopen_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fopen_test3 coreclrpal)
+
+target_link_libraries(paltest_fopen_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test3/test3.c b/src/pal/tests/palsuite/c_runtime/fopen/test3/test3.c
new file mode 100644
index 0000000000..f3af42dc8a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fopen/test3/test3.c
@@ -0,0 +1,66 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test3.c
+**
+** Purpose: Tests the PAL implementation of the fopen function.
+** Test to ensure that you can write to a 'w+' mode file.
+** And that you can read from a 'w+' mode file.
+**
+** Depends:
+** fprintf
+** fseek
+** fgets
+**
+
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+
+ FILE *fp;
+ char buffer[128];
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /* Open a file with 'w+' mode */
+ if( (fp = fopen( "testfile", "w+" )) == NULL )
+ {
+ Fail( "ERROR: The file failed to open with 'w+' mode.\n" );
+ }
+
+ /* Write some text to the file */
+ if(fprintf(fp,"%s","some text") <= 0)
+ {
+ Fail("ERROR: Attempted to WRITE to a file opened with 'w+' mode "
+ "but fprintf failed. Either fopen or fprintf have problems.");
+ }
+
+ if(fseek(fp, 0, SEEK_SET))
+ {
+ Fail("ERROR: fseek failed, and this test depends on it.");
+ }
+
+ /* Attempt to read from the 'w+' only file, should pass */
+ if(fgets(buffer,10,fp) == NULL)
+ {
+ Fail("ERROR: Tried to READ from a file with 'w+' mode set. "
+ "This should succeed, but fgets returned NULL. Either fgets "
+ "or fopen is broken.");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fopen/test3/testinfo.dat
new file mode 100644
index 0000000000..c458c1196a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fopen/test3/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fopen
+Name = Positive Test for fopen
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Test to ensure that you can write to a 'w+' mode file. And that you can
+= read from a 'w+' mode file.
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fopen/test4/CMakeLists.txt
new file mode 100644
index 0000000000..92e0ef0bd8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fopen/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_fopen_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fopen_test4 coreclrpal)
+
+target_link_libraries(paltest_fopen_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test4/test4.c b/src/pal/tests/palsuite/c_runtime/fopen/test4/test4.c
new file mode 100644
index 0000000000..04683d52c5
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fopen/test4/test4.c
@@ -0,0 +1,82 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test4.c
+**
+** Purpose: Tests the PAL implementation of the fopen function.
+** Test to ensure that you can't write to a 'r' mode file.
+** And that you can read from a 'r' mode file.
+**
+** Depends:
+** fprintf
+** fclose
+** fgets
+**
+
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+
+ FILE *fp;
+ char buffer[128];
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /* Open a file with 'w' mode */
+ if( (fp = fopen( "testfile", "w" )) == NULL )
+ {
+ Fail( "ERROR: The file failed to open with 'w' mode.\n" );
+ }
+
+ /* Write some text to the file */
+ if(fprintf(fp,"%s","some text") <= 0)
+ {
+ Fail("ERROR: Attempted to WRITE to a file opened with 'w' mode "
+ "but fprintf failed. Either fopen or fprintf have problems.");
+ }
+
+ if(fclose(fp))
+ {
+ Fail("ERROR: Attempted to close a file, but fclose failed. "
+ "This test depends upon it.");
+ }
+
+ /* Open a file with 'r' mode */
+ if( (fp = fopen( "testfile", "r" )) == NULL )
+ {
+ Fail( "ERROR: The file failed to open with 'r' mode.\n" );
+ }
+
+ /* Attempt to read from the 'r' only file, should pass */
+ if(fgets(buffer,10,fp) == NULL)
+ {
+ Fail("ERROR: Tried to READ from a file with 'r' mode set. "
+ "This should succeed, but fgets returned NULL. Either fgets "
+ "or fopen is broken.");
+ }
+
+ /* Write some text to the file */
+ if(fprintf(fp,"%s","some text") > 0)
+ {
+ Fail("ERROR: Attempted to WRITE to a file opened with 'r' mode "
+ "but fprintf succeeded It should have failed. "
+ "Either fopen or fprintf have problems.");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test4/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fopen/test4/testinfo.dat
new file mode 100644
index 0000000000..a1ecaf959b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fopen/test4/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fopen
+Name = Positive Test for fopen
+TYPE = DEFAULT
+EXE1 = test4
+Description
+= Test to ensure that you can't write to a 'r' mode file. And that you can
+= read from a 'r' mode file.
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fopen/test5/CMakeLists.txt
new file mode 100644
index 0000000000..82529b9aab
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fopen/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test5.c
+)
+
+add_executable(paltest_fopen_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fopen_test5 coreclrpal)
+
+target_link_libraries(paltest_fopen_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test5/test5.c b/src/pal/tests/palsuite/c_runtime/fopen/test5/test5.c
new file mode 100644
index 0000000000..0a760314e1
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fopen/test5/test5.c
@@ -0,0 +1,78 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test5.c
+**
+** Purpose: Tests the PAL implementation of the fopen function.
+** Test to ensure that you can write to a 'r+' mode file.
+** And that you can read from a 'r+' mode file.
+**
+** Depends:
+** fprintf
+** fclose
+** fgets
+** fseek
+**
+
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+
+ FILE *fp;
+ char buffer[128];
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /* Open a file with 'w' mode */
+ if( (fp = fopen( "testfile", "w" )) == NULL )
+ {
+ Fail( "ERROR: The file failed to open with 'w' mode.\n" );
+ }
+
+ if(fclose(fp))
+ {
+ Fail("ERROR: Attempted to close a file, but fclose failed. "
+ "This test depends upon it.");
+ }
+
+ if( (fp = fopen( "testfile", "r+" )) == NULL )
+ {
+ Fail( "ERROR: The file failed to open with 'r+' mode.\n" );
+ }
+
+ /* Write some text to the file */
+ if(fprintf(fp,"%s","some text") <= 0)
+ {
+ Fail("ERROR: Attempted to WRITE to a file opened with 'r+' mode "
+ "but fprintf failed. Either fopen or fprintf have problems.");
+ }
+
+ if(fseek(fp, 0, SEEK_SET))
+ {
+ Fail("ERROR: fseek failed, and this test depends on it.");
+ }
+
+ /* Attempt to read from the 'r+' only file, should pass */
+ if(fgets(buffer,10,fp) == NULL)
+ {
+ Fail("ERROR: Tried to READ from a file with 'r+' mode set. "
+ "This should succeed, but fgets returned NULL. Either fgets "
+ "or fopen is broken.");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test5/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fopen/test5/testinfo.dat
new file mode 100644
index 0000000000..8f8f5d950b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fopen/test5/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fopen
+Name = Positive Test for fopen
+TYPE = DEFAULT
+EXE1 = test5
+Description
+= Test to ensure that you can write to a 'r+' mode file. And that you can
+= read from a 'r+' mode file.
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fopen/test6/CMakeLists.txt
new file mode 100644
index 0000000000..9a01cfb9a8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fopen/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test6.c
+)
+
+add_executable(paltest_fopen_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fopen_test6 coreclrpal)
+
+target_link_libraries(paltest_fopen_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test6/test6.c b/src/pal/tests/palsuite/c_runtime/fopen/test6/test6.c
new file mode 100644
index 0000000000..03b6067fdd
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fopen/test6/test6.c
@@ -0,0 +1,131 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test6.c
+**
+** Purpose: Tests the PAL implementation of the fopen function.
+** Test to ensure that you can write to an 'a' mode file.
+** And that you can't read from a 'a' mode file. Also ensure
+** that you can use fseek and still write to the end of a file.
+**
+** Depends:
+** fprintf
+** fgets
+** fseek
+** fclose
+**
+
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+
+ FILE *fp;
+ char buffer[128];
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /* Open a file with 'a+' mode */
+ if( (fp = fopen( "testfile", "a" )) == NULL )
+ {
+ Fail( "ERROR: The file failed to open with 'a' mode.\n" );
+ }
+
+ /* Write some text to the file */
+ if(fprintf(fp,"%s","some text") <= 0)
+ {
+ Fail("ERROR: Attempted to WRITE to a file opened with 'a' mode "
+ "but fprintf failed. Either fopen or fprintf have problems.");
+ }
+
+ if(fseek(fp, 0, SEEK_SET))
+ {
+ Fail("ERROR: fseek failed, and this test depends on it.");
+ }
+
+ /* Attempt to read from the 'a' only file, should fail */
+ if(fgets(buffer,10,fp) != NULL)
+ {
+ Fail("ERROR: Tried to READ from a file with 'a' mode set. "
+ "This should fail, but fgets returned success. Either fgets "
+ "or fopen is broken.");
+ }
+
+
+ /* Attempt to write to a file after using 'a' and fseek */
+ fp = fopen("testfile2", "a");
+ if(fp == NULL)
+ {
+ Fail("ERROR: The file failed to be created with 'a' mode.\n");
+ }
+
+ /* write text to the file initially */
+ if(fprintf(fp,"%s","abcd") <= 0)
+ {
+ Fail("ERROR: Attempted to WRITE to a file opened with 'a' mode "
+ "but fprintf failed. Either fopen or fprintf have problems.\n");
+ }
+
+ /* set the pointer to the front of the file */
+ if(fseek(fp, 0, SEEK_SET))
+ {
+ Fail("ERROR: fseek failed, and this test depends on it.\n");
+ }
+
+ /* using 'a' should still write to the end of the file, not the front */
+ if(fputs("efgh",fp) < 0)
+ {
+ Fail("ERROR: Attempted to WRITE to a file opened with 'a' mode "
+ "but fputs failed.\n");
+ }
+
+ /* set the pointer to the front of the file */
+ if(fseek(fp, 0, SEEK_SET))
+ {
+ Fail("ERROR: fseek failed, and this test depends on it.\n");
+ }
+
+ /* a file with 'a' mode can only write, so close the file before reading */
+ if(fclose(fp))
+ {
+ Fail("ERROR: fclose failed when it should have succeeded.\n");
+ }
+
+ /* open the file again to read */
+ fp = fopen("testfile2","r");
+ if(fp == NULL)
+ {
+ Fail("ERROR: fopen failed to open the file using 'r' mode");
+ }
+
+ /* Attempt to read from the 'a' only file, should succeed */
+ if(fgets(buffer,10,fp) == NULL)
+ {
+ Fail("ERROR: Tried to READ from a file with 'a' mode set. "
+ "This should pass, but fgets returned failure. Either fgets "
+ "or fopen is broken.\n");
+ }
+
+ /* Compare what was read and what should have been in the file */
+ if(memcmp(buffer,"abcdefgh",8))
+ {
+ Fail("ERROR: The string read should have equaled 'abcdefgh' "
+ "but instead it is %s\n", buffer);
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test6/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fopen/test6/testinfo.dat
new file mode 100644
index 0000000000..5edd94416d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fopen/test6/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fopen
+Name = Positive Test for fopen
+TYPE = DEFAULT
+EXE1 = test6
+Description
+= Test to ensure that you can write to a 'a' mode file. And that you can't
+= read from a 'a' mode file.
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fopen/test7/CMakeLists.txt
new file mode 100644
index 0000000000..168a5aff53
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fopen/test7/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test7.c
+)
+
+add_executable(paltest_fopen_test7
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fopen_test7 coreclrpal)
+
+target_link_libraries(paltest_fopen_test7
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test7/test7.c b/src/pal/tests/palsuite/c_runtime/fopen/test7/test7.c
new file mode 100644
index 0000000000..3ef8602ddb
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fopen/test7/test7.c
@@ -0,0 +1,117 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test7.c
+**
+** Purpose: Tests the PAL implementation of the fopen function.
+** Test to ensure that you can write to an 'a+' mode file.
+** And that you can read from a 'a+' mode file. Also ensure
+** that you can use fseek and still write to the end of a file.
+**
+** Depends:
+** fprintf
+** fgets
+** fseek
+** fclose
+**
+
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+
+ FILE *fp;
+ char buffer[128];
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /* Open a file with 'a+' mode */
+ if( (fp = fopen( "testfile", "a+" )) == NULL )
+ {
+ Fail( "ERROR: The file failed to open with 'a+' mode.\n" );
+ }
+
+ /* Write some text to the file */
+ if(fprintf(fp,"%s","some text") <= 0)
+ {
+ Fail("ERROR: Attempted to WRITE to a file opened with 'a+' mode "
+ "but fprintf failed. Either fopen or fprintf have problems.\n");
+ }
+
+ if(fseek(fp, 0, SEEK_SET))
+ {
+ Fail("ERROR: fseek failed, and this test depends on it.\n");
+ }
+
+ /* Attempt to read from the 'a+' only file, should succeed */
+ if(fgets(buffer,10,fp) == NULL)
+ {
+ Fail("ERROR: Tried to READ from a file with 'a+' mode set. "
+ "This should pass, but fgets returned failure. Either fgets "
+ "or fopen is broken.\n");
+ }
+
+
+ /* Attempt to write to a file after using 'a+' and fseek */
+ fp = fopen("testfile2", "a+");
+ if(fp == NULL)
+ {
+ Fail("ERROR: The file failed to be created with 'a+' mode.\n");
+ }
+
+ /* write text to the file initially */
+ if(fprintf(fp,"%s","abcd") <= 0)
+ {
+ Fail("ERROR: Attempted to WRITE to a file opened with 'a+' mode "
+ "but fprintf failed. Either fopen or fprintf have problems.\n");
+ }
+
+ /* set the pointer to the front of the file */
+ if(fseek(fp, 0, SEEK_SET))
+ {
+ Fail("ERROR: fseek failed, and this test depends on it.\n");
+ }
+
+ /* using 'a+' should still write to the end of the file, not the front */
+ if(fputs("efgh",fp) < 0)
+ {
+ Fail("ERROR: Attempted to WRITE to a file opened with 'a+' mode "
+ "but fputs failed.\n");
+ }
+
+ /* set the pointer to the front of the file */
+ if(fseek(fp, 0, SEEK_SET))
+ {
+ Fail("ERROR: fseek failed, and this test depends on it.\n");
+ }
+
+ /* Attempt to read from the 'a+' only file, should succeed */
+ if(fgets(buffer,10,fp) == NULL)
+ {
+ Fail("ERROR: Tried to READ from a file with 'a+' mode set. "
+ "This should pass, but fgets returned failure. Either fgets "
+ "or fopen is broken.\n");
+ }
+
+ /* Compare what was read and what should have been in the file */
+ if(memcmp(buffer,"abcdefgh",8))
+ {
+ Fail("ERROR: The string read should have equaled 'abcdefgh' "
+ "but instead it is %s\n", buffer);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test7/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fopen/test7/testinfo.dat
new file mode 100644
index 0000000000..e4bc99c910
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fopen/test7/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fopen
+Name = Positive Test for fopen
+TYPE = DEFAULT
+EXE1 = test7
+Description
+= Test to ensure that you can write to a 'a+' mode file. And that you can
+= read from a 'a+' mode file.
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/CMakeLists.txt
new file mode 100644
index 0000000000..cafb9536b0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/CMakeLists.txt
@@ -0,0 +1,22 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test10)
+add_subdirectory(test11)
+add_subdirectory(test12)
+add_subdirectory(test13)
+add_subdirectory(test14)
+add_subdirectory(test15)
+add_subdirectory(test16)
+add_subdirectory(test17)
+add_subdirectory(test18)
+add_subdirectory(test19)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+add_subdirectory(test7)
+add_subdirectory(test8)
+add_subdirectory(test9)
+
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/fprintf.h b/src/pal/tests/palsuite/c_runtime/fprintf/fprintf.h
new file mode 100644
index 0000000000..380eb0a0b3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/fprintf.h
@@ -0,0 +1,177 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*NOTE:
+The creation of the test file within each function is because the FILE
+structure is not defined within pal.h. Therefore, unable to have
+function with this as a return type.
+*/
+
+#ifndef __FPRINTF_H__
+#define __FPRINTF_H__
+
+void DoStrTest(char *formatstr, char* param, char *checkstr)
+{
+ FILE *fp;
+ char buf[256] = { 0 };
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ Fail("ERROR: fopen failed to create testfile\n");
+ if ((fprintf(fp, formatstr, param)) < 0)
+ Fail("ERROR: fprintf failed\n");
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ Fail("ERROR: fseek failed\n");
+ if ((fgets(buf, 100, fp)) == NULL)
+ Fail("ERROR: fseek failed\n");
+
+ if (memcmp(buf, checkstr, strlen(buf) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert string \"%s\" into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ param, formatstr, checkstr, buf);
+ }
+ fclose(fp);
+}
+
+void DoWStrTest(char *formatstr, WCHAR* param, char *checkstr)
+{
+ FILE *fp;
+ char buf[256] = { 0 };
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ Fail("ERROR: fopen failed to create testfile\n");
+ if ((fprintf(fp, formatstr, param)) < 0)
+ Fail("ERROR: fprintf failed\n");
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ Fail("ERROR: fseek failed\n");
+ if ((fgets(buf, 100, fp)) == NULL)
+ Fail("ERROR: fseek failed\n");
+
+ if (memcmp(buf, checkstr, strlen(buf) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert wide string \"%s\" into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ convertC(param), formatstr, checkstr, buf);
+ }
+ fclose(fp);
+}
+
+
+void DoCharTest(char *formatstr, char param, char *checkstr)
+{
+ FILE *fp;
+ char buf[256] = { 0 };
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ Fail("ERROR: fopen failed to create testfile\n");
+ if ((fprintf(fp, formatstr, param)) < 0)
+ Fail("ERROR: fprintf failed\n");
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ Fail("ERROR: fseek failed\n");
+ if ((fgets(buf, 100, fp)) == NULL)
+ Fail("ERROR: fseek failed\n");
+
+ if (memcmp(buf, checkstr, strlen(buf) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert char \'%c\' (%d) into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ param, param, formatstr, checkstr, buf);
+ }
+ fclose(fp);
+}
+
+void DoWCharTest(char *formatstr, WCHAR param, char *checkstr)
+{
+ FILE *fp;
+ char buf[256] = { 0 };
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ Fail("ERROR: fopen failed to create testfile\n");
+ if ((fprintf(fp, formatstr, param)) < 0)
+ Fail("ERROR: fprintf failed\n");
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ Fail("ERROR: fseek failed\n");
+ if ((fgets(buf, 100, fp)) == NULL)
+ Fail("ERROR: fseek failed\n");
+
+ if (memcmp(buf, checkstr, strlen(buf) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert wide char \'%c\' (%d) into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ (char)param, param, formatstr, checkstr, buf);
+ }
+ fclose(fp);
+}
+
+void DoNumTest(char *formatstr, int value, char *checkstr)
+{
+ FILE *fp;
+ char buf[256] = { 0 };
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ Fail("ERROR: fopen failed to create testfile\n");
+ if ((fprintf(fp, formatstr, value)) < 0)
+ Fail("ERROR: fprintf failed\n");
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ Fail("ERROR: fseek failed\n");
+ if ((fgets(buf, 100, fp)) == NULL)
+ Fail("ERROR: fseek failed\n");
+
+ if (memcmp(buf, checkstr, strlen(buf) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %#x into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ value, formatstr, checkstr, buf);
+ }
+ fclose(fp);
+}
+
+void DoI64Test(char *formatstr, INT64 value, char *valuestr, char *checkstr1, char *checkstr2)
+{
+ FILE *fp;
+ char buf[256] = { 0 };
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ Fail("ERROR: fopen failed to create testfile\n");
+ if ((fprintf(fp, formatstr, value)) < 0)
+ Fail("ERROR: fprintf failed\n");
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ Fail("ERROR: fseek failed\n");
+ if ((fgets(buf, 100, fp)) == NULL)
+ Fail("ERROR: fseek failed\n");
+
+ if (memcmp(buf, checkstr1, strlen(buf) + 1) != 0 &&
+ memcmp(buf, checkstr2, strlen(buf) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %s into \"%s\"\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n",
+ valuestr, formatstr, checkstr1, checkstr2, buf);
+ }
+ fclose(fp);
+}
+
+void DoDoubleTest(char *formatstr, double value, char *checkstr1, char *checkstr2)
+{
+ FILE *fp;
+ char buf[256] = { 0 };
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ Fail("ERROR: fopen failed to create testfile\n");
+ if ((fprintf(fp, formatstr, value)) < 0)
+ Fail("ERROR: fprintf failed\n");
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ Fail("ERROR: fseek failed\n");
+ if ((fgets(buf, 100, fp)) == NULL)
+ Fail("ERROR: fseek failed\n");
+
+ if (memcmp(buf, checkstr1, strlen(buf) + 1) != 0 &&
+ memcmp(buf, checkstr2, strlen(buf) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %f into \"%s\"\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n",
+ value, formatstr, checkstr1, checkstr2, buf);
+ }
+ fclose(fp);
+}
+#endif
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..ab4176563d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_fprintf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fprintf_test1 coreclrpal)
+
+target_link_libraries(paltest_fprintf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/fprintf/test1/test1.c
new file mode 100644
index 0000000000..d55fc2534c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test1/test1.c
@@ -0,0 +1,80 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c (fprintf)
+**
+** Purpose: A single, basic, test case with no formatting.
+** Test modeled after the sprintf series.
+**
+
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+/*
+ * Depends on memcmp, strlen, fopen, fgets, fseek and fclose.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ FILE *fp;
+ char testfile[] = "testfile.txt";
+ char checkstr[] = "hello world";
+ char buf[256];
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ if ((fp = fopen(testfile, "w+")) == NULL)
+ {
+ Fail("ERROR: fopen failed to create \"%s\"\n", testfile);
+ }
+
+ if ((fprintf(fp, "hello world")) < 0)
+ {
+ Fail("ERROR: fprintf failed to print to \"%s\"\n", testfile);
+ }
+
+ if ((fseek( fp, 0, SEEK_SET)) != 0)
+
+ {
+
+ Fail("ERROR: Fseek failed to set pointer to beginning of file\n" );
+
+ }
+
+
+
+ if ((fgets( buf, 100, fp )) == NULL)
+
+ {
+
+ Fail("ERROR: fgets failed\n");
+
+ }
+
+
+ if (memcmp(checkstr, buf, strlen(checkstr)+1) != 0)
+ {
+ Fail("ERROR: expected %s, got %s\n", checkstr, buf);
+ }
+
+
+
+ if ((fclose( fp )) != 0)
+
+ {
+
+ Fail("ERROR: fclose failed to close \"%s\"\n", testfile);
+
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fprintf/test1/testinfo.dat
new file mode 100644
index 0000000000..be3bf4b78a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fprintf
+Name = Positive Test for fprintf
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= A single, basic, test case with no formatting.
+= Test modeled after the sprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test10/CMakeLists.txt
new file mode 100644
index 0000000000..f718ad7934
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test10/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test10.c
+)
+
+add_executable(paltest_fprintf_test10
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fprintf_test10 coreclrpal)
+
+target_link_libraries(paltest_fprintf_test10
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test10/test10.c b/src/pal/tests/palsuite/c_runtime/fprintf/test10/test10.c
new file mode 100644
index 0000000000..5988e8da74
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test10/test10.c
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test10.c (fprintf)
+**
+** Purpose: Tests the octal specifier (%o).
+** This test is modeled after the fprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoNumTest("foo %o", pos, "foo 52");
+ DoNumTest("foo %lo", 0xFFFF, "foo 177777");
+ DoNumTest("foo %ho", 0xFFFF, "foo 177777");
+ DoNumTest("foo %Lo", pos, "foo 52");
+ DoI64Test("foo %I64o", l, "42", "foo 52", "foo 52");
+ DoNumTest("foo %3o", pos, "foo 52");
+ DoNumTest("foo %-3o", pos, "foo 52 ");
+ DoNumTest("foo %.1o", pos, "foo 52");
+ DoNumTest("foo %.3o", pos, "foo 052");
+ DoNumTest("foo %03o", pos, "foo 052");
+ DoNumTest("foo %#o", pos, "foo 052");
+ DoNumTest("foo %+o", pos, "foo 52");
+ DoNumTest("foo % o", pos, "foo 52");
+ DoNumTest("foo %+o", neg, "foo 37777777726");
+ DoNumTest("foo % o", neg, "foo 37777777726");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test10/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fprintf/test10/testinfo.dat
new file mode 100644
index 0000000000..7afffeaf75
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test10/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fprintf
+Name = Positive Test for fprintf
+TYPE = DEFAULT
+EXE1 = test10
+Description
+= Tests the octal specifier (%o).
+= This test is modeled after the fprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test11/CMakeLists.txt
new file mode 100644
index 0000000000..6ccd58ddd2
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test11/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test11.c
+)
+
+add_executable(paltest_fprintf_test11
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fprintf_test11 coreclrpal)
+
+target_link_libraries(paltest_fprintf_test11
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test11/test11.c b/src/pal/tests/palsuite/c_runtime/fprintf/test11/test11.c
new file mode 100644
index 0000000000..01880552b7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test11/test11.c
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test11.c (fprintf)
+**
+** Purpose: Test the unsigned int specifier (%u).
+** This test is modeled after the fprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoNumTest("foo %u", pos, "foo 42");
+ DoNumTest("foo %lu", 0xFFFF, "foo 65535");
+ DoNumTest("foo %hu", 0xFFFF, "foo 65535");
+ DoNumTest("foo %Lu", pos, "foo 42");
+ DoI64Test("foo %I64u", l, "42", "foo 42", "foo 42");
+ DoNumTest("foo %3u", pos, "foo 42");
+ DoNumTest("foo %-3u", pos, "foo 42 ");
+ DoNumTest("foo %.1u", pos, "foo 42");
+ DoNumTest("foo %.3u", pos, "foo 042");
+ DoNumTest("foo %03u", pos, "foo 042");
+ DoNumTest("foo %#u", pos, "foo 42");
+ DoNumTest("foo %+u", pos, "foo 42");
+ DoNumTest("foo % u", pos, "foo 42");
+ DoNumTest("foo %+u", neg, "foo 4294967254");
+ DoNumTest("foo % u", neg, "foo 4294967254");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test11/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fprintf/test11/testinfo.dat
new file mode 100644
index 0000000000..8275f0f7ce
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test11/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fprintf
+Name = Positive Test for fprintf
+TYPE = DEFAULT
+EXE1 = test11
+Description
+= Test the unsigned int specifier (%u).
+= This test is modeled after the fprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test12/CMakeLists.txt
new file mode 100644
index 0000000000..17bc7f100b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test12/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test12.c
+)
+
+add_executable(paltest_fprintf_test12
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fprintf_test12 coreclrpal)
+
+target_link_libraries(paltest_fprintf_test12
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test12/test12.c b/src/pal/tests/palsuite/c_runtime/fprintf/test12/test12.c
new file mode 100644
index 0000000000..0292e15014
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test12/test12.c
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test12.c
+**
+** Purpose: Tests the (lowercase) hexadecimal specifier (%x).
+** This test is modeled after the fprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 0x1234ab;
+ INT64 l = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoNumTest("foo %x", pos, "foo 1234ab");
+ DoNumTest("foo %lx", pos, "foo 1234ab");
+ DoNumTest("foo %hx", pos, "foo 34ab");
+ DoNumTest("foo %Lx", pos, "foo 1234ab");
+ DoI64Test("foo %I64x", l, "0x1234567887654321",
+ "foo 1234567887654321", "foo 0x1234567887654321");
+ DoNumTest("foo %7x", pos, "foo 1234ab");
+ DoNumTest("foo %-7x", pos, "foo 1234ab ");
+ DoNumTest("foo %.1x", pos, "foo 1234ab");
+ DoNumTest("foo %.7x", pos, "foo 01234ab");
+ DoNumTest("foo %07x", pos, "foo 01234ab");
+ DoNumTest("foo %#x", pos, "foo 0x1234ab");
+ DoNumTest("foo %+x", pos, "foo 1234ab");
+ DoNumTest("foo % x", pos, "foo 1234ab");
+ DoNumTest("foo %+x", neg, "foo ffffffd6");
+ DoNumTest("foo % x", neg, "foo ffffffd6");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test12/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fprintf/test12/testinfo.dat
new file mode 100644
index 0000000000..4b44cfc313
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test12/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fprintf
+Name = Positive Test for fprintf
+TYPE = DEFAULT
+EXE1 = test12
+Description
+= Tests the (lowercase) hexadecimal specifier (%x).
+= This test is modeled after the fprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test13/CMakeLists.txt
new file mode 100644
index 0000000000..c6eb0f9075
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test13/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test13.c
+)
+
+add_executable(paltest_fprintf_test13
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fprintf_test13 coreclrpal)
+
+target_link_libraries(paltest_fprintf_test13
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test13/test13.c b/src/pal/tests/palsuite/c_runtime/fprintf/test13/test13.c
new file mode 100644
index 0000000000..e171aeacce
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test13/test13.c
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test13.c (fprintf)
+**
+** Purpose: Tests the (uppercase) hexadecimal specifier (%X).
+** This test is modeled after the fprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 0x1234AB;
+ INT64 l = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoNumTest("foo %X", pos, "foo 1234AB");
+ DoNumTest("foo %lX", pos, "foo 1234AB");
+ DoNumTest("foo %hX", pos, "foo 34AB");
+ DoNumTest("foo %LX", pos, "foo 1234AB");
+ DoI64Test("foo %I64X", l, "0x1234567887654321",
+ "foo 1234567887654321", "foo 0x1234567887654321");
+ DoNumTest("foo %7X", pos, "foo 1234AB");
+ DoNumTest("foo %-7X", pos, "foo 1234AB ");
+ DoNumTest("foo %.1X", pos, "foo 1234AB");
+ DoNumTest("foo %.7X", pos, "foo 01234AB");
+ DoNumTest("foo %07X", pos, "foo 01234AB");
+ DoNumTest("foo %#X", pos, "foo 0X1234AB");
+ DoNumTest("foo %+X", pos, "foo 1234AB");
+ DoNumTest("foo % X", pos, "foo 1234AB");
+ DoNumTest("foo %+X", neg, "foo FFFFFFD6");
+ DoNumTest("foo % X", neg, "foo FFFFFFD6");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test13/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fprintf/test13/testinfo.dat
new file mode 100644
index 0000000000..ae983ec78a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test13/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fprintf
+Name = Positive Test for fprintf
+TYPE = DEFAULT
+EXE1 = test13
+Description
+= Tests the (uppercase) hexadecimal specifier (%X).
+= This test is modeled after the fprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test14/CMakeLists.txt
new file mode 100644
index 0000000000..6bb281bc62
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test14/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test14.c
+)
+
+add_executable(paltest_fprintf_test14
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fprintf_test14 coreclrpal)
+
+target_link_libraries(paltest_fprintf_test14
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test14/test14.c b/src/pal/tests/palsuite/c_runtime/fprintf/test14/test14.c
new file mode 100644
index 0000000000..5d7d77387d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test14/test14.c
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test14.c (fprintf)
+**
+** Purpose: Tests the lowercase exponential
+** notation double specifier (%e).
+** This test is modeled after the fprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 256.0;
+ double neg = -256.0;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoDoubleTest("foo %e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %le", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %he", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %Le", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %I64e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %14e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %-14e", val, "foo 2.560000e+002 ", "foo 2.560000e+02 ");
+ DoDoubleTest("foo %.1e", val, "foo 2.6e+002", "foo 2.6e+02");
+ DoDoubleTest("foo %.8e", val, "foo 2.56000000e+002", "foo 2.56000000e+02");
+ DoDoubleTest("foo %014e", val, "foo 02.560000e+002", "foo 002.560000e+02");
+ DoDoubleTest("foo %#e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %+e", val, "foo +2.560000e+002", "foo +2.560000e+02");
+ DoDoubleTest("foo % e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %+e", neg, "foo -2.560000e+002", "foo -2.560000e+02");
+ DoDoubleTest("foo % e", neg, "foo -2.560000e+002", "foo -2.560000e+02");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test14/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fprintf/test14/testinfo.dat
new file mode 100644
index 0000000000..f0a843f480
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test14/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fprintf
+Name = Positive Test for fprintf
+TYPE = DEFAULT
+EXE1 = test14
+Description
+= Tests the lowercase exponential
+= notation double specifier (%e).
+= This test is modeled after the fprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test15/CMakeLists.txt
new file mode 100644
index 0000000000..ce1a8b6111
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test15/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test15.c
+)
+
+add_executable(paltest_fprintf_test15
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fprintf_test15 coreclrpal)
+
+target_link_libraries(paltest_fprintf_test15
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test15/test15.c b/src/pal/tests/palsuite/c_runtime/fprintf/test15/test15.c
new file mode 100644
index 0000000000..d024bdbd8a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test15/test15.c
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test15.c (fprintf)
+**
+** Purpose: Tests the uppercase exponential
+** notation double specifier (%E).
+** This test is modeled after the fprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 256.0;
+ double neg = -256.0;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoDoubleTest("foo %E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %lE", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %hE", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %LE", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %I64E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %14E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %-14E", val, "foo 2.560000E+002 ", "foo 2.560000E+02 ");
+ DoDoubleTest("foo %.1E", val, "foo 2.6E+002", "foo 2.6E+02");
+ DoDoubleTest("foo %.8E", val, "foo 2.56000000E+002", "foo 2.56000000E+02");
+ DoDoubleTest("foo %014E", val, "foo 02.560000E+002", "foo 002.560000E+02");
+ DoDoubleTest("foo %#E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %+E", val, "foo +2.560000E+002", "foo +2.560000E+02");
+ DoDoubleTest("foo % E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %+E", neg, "foo -2.560000E+002", "foo -2.560000E+02");
+ DoDoubleTest("foo % E", neg, "foo -2.560000E+002", "foo -2.560000E+02");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test15/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fprintf/test15/testinfo.dat
new file mode 100644
index 0000000000..fedabca3c6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test15/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fprintf
+Name = Positive Test for fprintf
+TYPE = DEFAULT
+EXE1 = test15
+Description
+= Tests the uppercase exponential
+= notation double specifier (%E).
+= This test is modeled after the fprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test16/CMakeLists.txt
new file mode 100644
index 0000000000..011cd13fb1
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test16/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test16.c
+)
+
+add_executable(paltest_fprintf_test16
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fprintf_test16 coreclrpal)
+
+target_link_libraries(paltest_fprintf_test16
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test16/test16.c b/src/pal/tests/palsuite/c_runtime/fprintf/test16/test16.c
new file mode 100644
index 0000000000..079faeaf59
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test16/test16.c
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test16.c (fprintf)
+**
+** Purpose: Tests the decimal notation double specifier (%f).
+** This test is modeled after the fprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoDoubleTest("foo %f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %lf", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %hf", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %Lf", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %I64f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %12f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %-12f", val, "foo 2560.001000 ", "foo 2560.001000 ");
+ DoDoubleTest("foo %.1f", val, "foo 2560.0", "foo 2560.0");
+ DoDoubleTest("foo %.8f", val, "foo 2560.00100000", "foo 2560.00100000");
+ DoDoubleTest("foo %012f", val, "foo 02560.001000", "foo 02560.001000");
+ DoDoubleTest("foo %#f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %+f", val, "foo +2560.001000", "foo +2560.001000");
+ DoDoubleTest("foo % f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %+f", neg, "foo -2560.001000", "foo -2560.001000");
+ DoDoubleTest("foo % f", neg, "foo -2560.001000", "foo -2560.001000");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test16/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fprintf/test16/testinfo.dat
new file mode 100644
index 0000000000..ef93c7c05d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test16/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fprintf
+Name = Positive Test for fprintf
+TYPE = DEFAULT
+EXE1 = test16
+Description
+= Tests the decimal notation double specifier (%f).
+= This test is modeled after the fprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test17/CMakeLists.txt
new file mode 100644
index 0000000000..4516f4b769
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test17/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test17.c
+)
+
+add_executable(paltest_fprintf_test17
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fprintf_test17 coreclrpal)
+
+target_link_libraries(paltest_fprintf_test17
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test17/test17.c b/src/pal/tests/palsuite/c_runtime/fprintf/test17/test17.c
new file mode 100644
index 0000000000..7bd817d7db
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test17/test17.c
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test17.c (fprintf)
+**
+** Purpose: Tests the lowercase shorthand notation double specifier (%g).
+** This test is modeled after the fprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoDoubleTest("foo %g", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %lg", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %hg", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %Lg", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %I64g", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %5g", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %-5g", val, "foo 2560 ", "foo 2560 ");
+ DoDoubleTest("foo %.1g", val, "foo 3e+003", "foo 3e+03");
+ DoDoubleTest("foo %.2g", val, "foo 2.6e+003", "foo 2.6e+03");
+ DoDoubleTest("foo %.12g", val, "foo 2560.001", "foo 2560.001");
+ DoDoubleTest("foo %06g", val, "foo 002560", "foo 002560");
+ DoDoubleTest("foo %#g", val, "foo 2560.00", "foo 2560.00");
+ DoDoubleTest("foo %+g", val, "foo +2560", "foo +2560");
+ DoDoubleTest("foo % g", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %+g", neg, "foo -2560", "foo -2560");
+ DoDoubleTest("foo % g", neg, "foo -2560", "foo -2560");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test17/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fprintf/test17/testinfo.dat
new file mode 100644
index 0000000000..420703c668
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test17/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fprintf
+Name = Positive Test for fprintf
+TYPE = DEFAULT
+EXE1 = test17
+Description
+= Tests the lowercase shorthand notation double specifier (%g).
+= This test is modeled after the fprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test18/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test18/CMakeLists.txt
new file mode 100644
index 0000000000..fc035020ca
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test18/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test18.c
+)
+
+add_executable(paltest_fprintf_test18
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fprintf_test18 coreclrpal)
+
+target_link_libraries(paltest_fprintf_test18
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test18/test18.c b/src/pal/tests/palsuite/c_runtime/fprintf/test18/test18.c
new file mode 100644
index 0000000000..6582c41e0f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test18/test18.c
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test18.c (fprintf)
+**
+** Purpose: Tests the uppercase shorthand notation double specifier (%G).
+** This test is modeled after the fprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoDoubleTest("foo %G", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %lG", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %hG", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %LG", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %I64G", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %5G", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %-5G", val, "foo 2560 ", "foo 2560 ");
+ DoDoubleTest("foo %.1G", val, "foo 3E+003", "foo 3E+03");
+ DoDoubleTest("foo %.2G", val, "foo 2.6E+003", "foo 2.6E+03");
+ DoDoubleTest("foo %.12G", val, "foo 2560.001", "foo 2560.001");
+ DoDoubleTest("foo %06G", val, "foo 002560", "foo 002560");
+ DoDoubleTest("foo %#G", val, "foo 2560.00", "foo 2560.00");
+ DoDoubleTest("foo %+G", val, "foo +2560", "foo +2560");
+ DoDoubleTest("foo % G", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %+G", neg, "foo -2560", "foo -2560");
+ DoDoubleTest("foo % G", neg, "foo -2560", "foo -2560");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test18/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fprintf/test18/testinfo.dat
new file mode 100644
index 0000000000..129febec27
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test18/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fprintf
+Name = Positive Test for fprintf
+TYPE = DEFAULT
+EXE1 = test18
+Description
+= Tests the uppercase shorthand notation double specifier (%G).
+= This test is modeled after the fprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test19/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test19/CMakeLists.txt
new file mode 100644
index 0000000000..3781b426f2
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test19/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test19.c
+)
+
+add_executable(paltest_fprintf_test19
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fprintf_test19 coreclrpal)
+
+target_link_libraries(paltest_fprintf_test19
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test19/test19.c b/src/pal/tests/palsuite/c_runtime/fprintf/test19/test19.c
new file mode 100644
index 0000000000..9d9a28c325
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test19/test19.c
@@ -0,0 +1,153 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test19.c (fprintf)
+**
+** Purpose: Tests the variable length precision argument.
+** This test is modeled after the fprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+#define DOTEST(a,b,c,d,e,f) DoTest(a,b,(void*)c,d,e,f)
+
+void DoTest(char *formatstr, int precision, void *param,
+ char *paramstr, char *checkstr1, char *checkstr2)
+{
+ FILE *fp;
+ char buf[256];
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ {
+ Fail("ERROR: fopen failed to create testfile\n");
+ }
+
+ if ((fprintf(fp, formatstr, precision, param)) < 0)
+ {
+ Fail("ERROR: fprintf failed\n");
+ }
+
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+
+ if ((fgets(buf, 100, fp)) == NULL)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+
+ if (memcmp(buf, checkstr1, strlen(buf) + 1) != 0 &&
+ memcmp(buf, checkstr2, strlen(buf) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n", paramstr, formatstr,
+ precision,
+ checkstr1, checkstr2, buf);
+ }
+
+ if ((fclose( fp )) != 0)
+
+ {
+ Fail("ERROR: fclose failed to close \"testfile.txt\"\n");
+ }
+
+}
+
+void DoublePrecTest(char *formatstr, int precision,
+ double param, char *checkstr1, char *checkstr2)
+{
+ FILE *fp;
+ char buf[256];
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ {
+ Fail("ERROR: fopen failed to create testfile\n");
+ }
+
+ if ((fprintf(fp, formatstr, precision, param)) < 0)
+ {
+ Fail("ERROR: fprintf failed\n");
+ }
+
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+
+ if ((fgets(buf, 100, fp)) == NULL)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+
+ if (memcmp(buf, checkstr1, strlen(buf) + 1) != 0 &&
+ memcmp(buf, checkstr2, strlen(buf) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n",
+ param, formatstr, precision, checkstr1, checkstr2, buf);
+ }
+
+ if ((fclose( fp )) != 0)
+ {
+ Fail("ERROR: fclose failed to close \"testfile.txt\"\n");
+ }
+
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DOTEST("%.*s", 2, "bar", "bar", "ba", "ba");
+ DOTEST("%.*S", 2, convert("bar"), "bar", "ba", "ba");
+
+ //DOTEST("%.*n", 4, 2, "2", "0002");
+ DOTEST("%.*c", 0, 'a', "a", "a", "a");
+ DOTEST("%.*c", 4, 'a', "a", "a", "a");
+ DOTEST("%.*C", 0, (WCHAR)'a', "a", "a", "a");
+ DOTEST("%.*C", 4, (WCHAR)'a', "a", "a", "a");
+ DOTEST("%.*d", 1, 42, "42", "42", "42");
+ DOTEST("%.*d", 3, 42, "42", "042", "042");
+ DOTEST("%.*i", 1, 42, "42", "42", "42");
+ DOTEST("%.*i", 3, 42, "42", "042", "042");
+ DOTEST("%.*o", 1, 42, "42", "52", "52");
+ DOTEST("%.*o", 3, 42, "42", "052", "052");
+ DOTEST("%.*u", 1, 42, "42", "42", "42");
+ DOTEST("%.*u", 3, 42, "42", "042", "042");
+ DOTEST("%.*x", 1, 0x42, "0x42", "42", "42");
+ DOTEST("%.*x", 3, 0x42, "0x42", "042", "042");
+ DOTEST("%.*X", 1, 0x42, "0x42", "42", "42");
+ DOTEST("%.*X", 3, 0x42, "0x42", "042", "042");
+
+
+ DoublePrecTest("%.*e", 1, 2.01, "2.0e+000", "2.0e+00");
+ DoublePrecTest("%.*e", 3, 2.01, "2.010e+000", "2.010e+00");
+ DoublePrecTest("%.*E", 1, 2.01, "2.0E+000", "2.0E+00");
+ DoublePrecTest("%.*E", 3, 2.01, "2.010E+000", "2.010E+00");
+ DoublePrecTest("%.*f", 1, 2.01, "2.0", "2.0");
+ DoublePrecTest("%.*f", 3, 2.01, "2.010", "2.010");
+ DoublePrecTest("%.*g", 1, 256.01, "3e+002", "3e+02");
+ DoublePrecTest("%.*g", 3, 256.01, "256", "256");
+ DoublePrecTest("%.*g", 4, 256.01, "256", "256");
+ DoublePrecTest("%.*g", 6, 256.01, "256.01", "256.01");
+ DoublePrecTest("%.*G", 1, 256.01, "3E+002", "3E+02");
+ DoublePrecTest("%.*G", 3, 256.01, "256", "256");
+ DoublePrecTest("%.*G", 4, 256.01, "256", "256");
+ DoublePrecTest("%.*G", 6, 256.01, "256.01", "256.01");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test19/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fprintf/test19/testinfo.dat
new file mode 100644
index 0000000000..25025b920a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test19/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fprintf
+Name = Positive Test for fprintf
+TYPE = DEFAULT
+EXE1 = test19
+Description
+= Tests the variable length precision argument.
+= This test is modeled after the fprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test2/CMakeLists.txt
new file mode 100644
index 0000000000..0ef44b6b7d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_fprintf_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fprintf_test2 coreclrpal)
+
+target_link_libraries(paltest_fprintf_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test2/test2.c b/src/pal/tests/palsuite/c_runtime/fprintf/test2/test2.c
new file mode 100644
index 0000000000..1ed7f3fd23
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test2/test2.c
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test2.c (fprintf)
+**
+** Purpose: Tests the string specifier (%s).
+** This test is modeled after the fprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoStrTest("foo %s", "bar", "foo bar");
+ DoStrTest("foo %hs", "bar", "foo bar");
+ DoWStrTest("foo %ls", convert("bar"), "foo bar");
+ DoWStrTest("foo %ws", convert("bar"), "foo bar");
+ DoStrTest("foo %Ls", "bar", "foo bar");
+ DoStrTest("foo %I64s", "bar", "foo bar");
+ DoStrTest("foo %5s", "bar", "foo bar");
+ DoStrTest("foo %.2s", "bar", "foo ba");
+ DoStrTest("foo %5.2s", "bar", "foo ba");
+ DoStrTest("foo %-5s", "bar", "foo bar ");
+ DoStrTest("foo %05s", "bar", "foo 00bar");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fprintf/test2/testinfo.dat
new file mode 100644
index 0000000000..d4c7dbff43
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fprintf
+Name = Positive Test for fprintf
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Tests the string specifier (%s).
+= This test is modeled after the fprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test3/CMakeLists.txt
new file mode 100644
index 0000000000..adfd36fce7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_fprintf_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fprintf_test3 coreclrpal)
+
+target_link_libraries(paltest_fprintf_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test3/test3.c b/src/pal/tests/palsuite/c_runtime/fprintf/test3/test3.c
new file mode 100644
index 0000000000..6185135581
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test3/test3.c
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test3.c (fprintf)
+**
+** Purpose: Tests the wide string specifier (%S).
+** This test is modeled after the fprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoWStrTest("foo %S", convert("bar"), "foo bar");
+ DoStrTest("foo %hS", "bar", "foo bar");
+ DoWStrTest("foo %lS", convert("bar"), "foo bar");
+ DoWStrTest("foo %wS", convert("bar"), "foo bar");
+ DoWStrTest("foo %LS", convert("bar"), "foo bar");
+ DoWStrTest("foo %I64S", convert("bar"), "foo bar");
+ DoWStrTest("foo %5S", convert("bar"), "foo bar");
+ DoWStrTest("foo %.2S", convert("bar"), "foo ba");
+ DoWStrTest("foo %5.2S", convert("bar"), "foo ba");
+ DoWStrTest("foo %-5S", convert("bar"), "foo bar ");
+ DoWStrTest("foo %05S", convert("bar"), "foo 00bar");
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fprintf/test3/testinfo.dat
new file mode 100644
index 0000000000..88a1b03a7f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test3/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fprintf
+Name = Positive Test for fprintf
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Tests the wide string specifier (%S).
+= This test is modeled after the fprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test4/CMakeLists.txt
new file mode 100644
index 0000000000..7d471b1b9c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_fprintf_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fprintf_test4 coreclrpal)
+
+target_link_libraries(paltest_fprintf_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test4/test4.c b/src/pal/tests/palsuite/c_runtime/fprintf/test4/test4.c
new file mode 100644
index 0000000000..51ec1f099c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test4/test4.c
@@ -0,0 +1,110 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test4.c (fprintf)
+**
+** Purpose: Tests the pointer specifier (%p).
+** This test is modeled after the fprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+static void DoTest(char *formatstr, void* param, char* paramstr,
+ char *checkstr1, char *checkstr2)
+{
+ FILE *fp;
+ char buf[256] = { 0 };
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ {
+ Fail("ERROR: fopen failed to create testfile\n");
+ }
+
+ if ((fprintf(fp, formatstr, param)) < 0)
+ {
+ Fail("ERROR: fprintf failed\n");
+ }
+
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+
+ if ((fgets(buf, 100, fp)) == NULL)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+
+ if (memcmp(buf, checkstr1, strlen(buf) + 1) != 0 &&
+ memcmp(buf, checkstr2, strlen(buf) + 1) != 0 )
+ {
+ Fail("ERROR: failed to insert %s into \"%s\"\n"
+ "Expected \"%s\" or \"%s\" got \"%s\".\n",
+ paramstr, formatstr, checkstr1, checkstr2, buf);
+ }
+
+ if ((fclose( fp )) != 0)
+
+ {
+
+ Fail("ERROR: fclose failed to close \"testfile.txt\"\n");
+
+ }
+}
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ void *ptr = (void*) 0x123456;
+ INT64 lptr = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+
+/*
+** Run only on 64 bit platforms
+*/
+#if defined(BIT64) && defined(PLATFORM_UNIX)
+ Trace("Testing for 64 Bit Platforms \n");
+ DoTest("%p", NULL, "NULL", "0000000000000000", "0x0");
+ DoTest("%p", ptr, "pointer to 0x123456", "0000000000123456", "0x123456");
+ DoTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456", " 0x123456");
+ DoTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456", "0x0123456");
+ DoTest("%-17p", ptr, "pointer to 0x123456", "0000000000123456 ", "0x123456 ");
+ DoTest("%+p", ptr, "pointer to 0x123456", "0000000000123456", "0x123456");
+ DoTest("%#p", ptr, "pointer to 0x123456", "0X0000000000123456", "0x123456");
+ DoTest("%lp", ptr, "pointer to 0x123456", "00123456", "0x123456");
+ DoTest("%hp", ptr, "pointer to 0x123456", "00003456", "0x3456");
+ DoTest("%Lp", ptr, "pointer to 0x123456", "00123456", "0x123456");
+ DoI64Test("%I64p", lptr, "pointer to 0x1234567887654321",
+ "1234567887654321", "0x1234567887654321");
+#else
+ Trace("Testing for Non 64 Bit Platforms \n");
+ DoTest("%p", NULL, "NULL", "00000000", "0x0");
+ DoTest("%p", ptr, "pointer to 0x123456", "00123456", "0x123456");
+ DoTest("%9p", ptr, "pointer to 0x123456", " 00123456", " 0x123456");
+ DoTest("%09p", ptr, "pointer to 0x123456", " 00123456", "0x0123456");
+ DoTest("%-9p", ptr, "pointer to 0x123456", "00123456 ", "0x123456 ");
+ DoTest("%+p", ptr, "pointer to 0x123456", "00123456", "0x123456");
+ DoTest("%#p", ptr, "pointer to 0x123456", "0X00123456", "0x123456");
+ DoTest("%lp", ptr, "pointer to 0x123456", "00123456", "0x123456");
+ DoTest("%hp", ptr, "pointer to 0x123456", "00003456", "0x3456");
+ DoTest("%Lp", ptr, "pointer to 0x123456", "00123456", "0x123456");
+ DoI64Test("%I64p", lptr, "pointer to 0x1234567887654321",
+ "1234567887654321", "0x1234567887654321");
+#endif
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test4/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fprintf/test4/testinfo.dat
new file mode 100644
index 0000000000..5f373ac230
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test4/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fprintf
+Name = Positive Test for fprintf
+TYPE = DEFAULT
+EXE1 = test4
+Description
+= Tests the pointer specifier (%p).
+= This test is modeled after the fprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test5/CMakeLists.txt
new file mode 100644
index 0000000000..1e3a568513
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test5.c
+)
+
+add_executable(paltest_fprintf_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fprintf_test5 coreclrpal)
+
+target_link_libraries(paltest_fprintf_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test5/test5.c b/src/pal/tests/palsuite/c_runtime/fprintf/test5/test5.c
new file mode 100644
index 0000000000..c53e3f45b4
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test5/test5.c
@@ -0,0 +1,131 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test5.c (fprintf)
+**
+** Purpose: Tests the count specifier (%n).
+** This test is modeled after the fprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+static void DoTest(char *formatstr, int param, char *checkstr)
+{
+ FILE *fp;
+ char buf[256] = { 0 };
+ int n = -1;
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ {
+ Fail("ERROR: fopen failed to create testfile\n");
+ }
+
+ if ((fprintf(fp, formatstr, &n)) < 0)
+ {
+ Fail("ERROR: fprintf failed\n");
+ }
+
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+
+ if ((fgets(buf, 100, fp)) == NULL)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+
+ if (n != param)
+ {
+ Fail("ERROR: Expected count parameter to resolve to %d, got %X\n",
+ param, n);
+ }
+
+ if (memcmp(buf, checkstr, strlen(buf) + 1) != 0)
+ {
+ Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf);
+ }
+
+
+ if ((fclose( fp )) != 0)
+
+ {
+
+ Fail("ERROR: fclose failed to close \"testfile.txt\"\n");
+
+ }
+}
+
+static void DoShortTest(char *formatstr, int param, char *checkstr)
+{
+ FILE *fp;
+ char buf[256] = { 0 };
+ short int n = -1;
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ {
+ Fail("ERROR: fopen failed to create testfile\n");
+ }
+
+ if ((fprintf(fp, formatstr, &n)) < 0)
+ {
+ Fail("ERROR: fprintf failed\n");
+ }
+
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+
+ if ((fgets(buf, 100, fp)) == NULL)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+
+ if (n != param)
+ {
+ Fail("ERROR: Expected count parameter to resolve to %d, got %X\n",
+ param, n);
+ }
+
+ if (memcmp(buf, checkstr, strlen(buf) + 1) != 0)
+ {
+ Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf);
+ }
+
+ if ((fclose( fp )) != 0)
+ {
+ Fail("ERROR: fclose failed to close \"testfile.txt\"\n");
+ }
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoTest("foo %n bar", 4, "foo bar");
+ DoTest("foo %#n bar", 4, "foo bar");
+ DoTest("foo % n bar", 4, "foo bar");
+ DoTest("foo %+n bar", 4, "foo bar");
+ DoTest("foo %-n bar", 4, "foo bar");
+ DoTest("foo %0n bar", 4, "foo bar");
+ DoShortTest("foo %hn bar", 4, "foo bar");
+ DoTest("foo %ln bar", 4, "foo bar");
+ DoTest("foo %Ln bar", 4, "foo bar");
+ DoTest("foo %I64n bar", 4, "foo bar");
+ DoTest("foo %20.3n bar", 4, "foo bar");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test5/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fprintf/test5/testinfo.dat
new file mode 100644
index 0000000000..b4d0e81777
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test5/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fprintf
+Name = Positive Test for fprintf
+TYPE = DEFAULT
+EXE1 = test5
+Description
+= Tests the count specifier (%n).
+= This test is modeled after the fprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test6/CMakeLists.txt
new file mode 100644
index 0000000000..89620dd453
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test6.c
+)
+
+add_executable(paltest_fprintf_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fprintf_test6 coreclrpal)
+
+target_link_libraries(paltest_fprintf_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test6/test6.c b/src/pal/tests/palsuite/c_runtime/fprintf/test6/test6.c
new file mode 100644
index 0000000000..0a8bc6b103
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test6/test6.c
@@ -0,0 +1,46 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test6.c (fprintf)
+**
+** Purpose: Tests the char specifier (%c).
+** This test is modeled after the fprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR wc = (WCHAR) 'c';
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoCharTest("foo %c", 'b', "foo b");
+ DoCharTest("foo %hc", 'b', "foo b");
+ DoWCharTest("foo %lc", wc, "foo c");
+ DoCharTest("foo %Lc", 'b', "foo b");
+ DoCharTest("foo %I64c", 'b', "foo b");
+ DoCharTest("foo %5c", 'b', "foo b");
+ DoCharTest("foo %.0c", 'b', "foo b");
+ DoCharTest("foo %-5c", 'b', "foo b ");
+ DoCharTest("foo %05c", 'b', "foo 0000b");
+ DoCharTest("foo % c", 'b', "foo b");
+ DoCharTest("foo %#c", 'b', "foo b");
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test6/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fprintf/test6/testinfo.dat
new file mode 100644
index 0000000000..a8a071ca21
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test6/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fprintf
+Name = Positive Test for fprintf
+TYPE = DEFAULT
+EXE1 = test6
+Description
+= Tests the char specifier (%c).
+= This test is modeled after the fprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test7/CMakeLists.txt
new file mode 100644
index 0000000000..3dc10dd6dc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test7/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test7.c
+)
+
+add_executable(paltest_fprintf_test7
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fprintf_test7 coreclrpal)
+
+target_link_libraries(paltest_fprintf_test7
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test7/test7.c b/src/pal/tests/palsuite/c_runtime/fprintf/test7/test7.c
new file mode 100644
index 0000000000..088e328de5
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test7/test7.c
@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test7.c (fprintf)
+**
+** Purpose: Tests the wide char specifier (%C).
+** This test is modeled after the fprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR wb = (WCHAR) 'b';
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoWCharTest("foo %C", wb, "foo b");
+ DoWCharTest("foo %hC", wb, "foo b");
+ DoCharTest("foo %lC", 'c', "foo c");
+ DoWCharTest("foo %LC", wb, "foo b");
+ DoWCharTest("foo %I64C", wb, "foo b");
+ DoWCharTest("foo %5C", wb, "foo b");
+ DoWCharTest("foo %.0C", wb, "foo b");
+ DoWCharTest("foo %-5C", wb, "foo b ");
+ DoWCharTest("foo %05C", wb, "foo 0000b");
+ DoWCharTest("foo % C", wb, "foo b");
+ DoWCharTest("foo %#C", wb, "foo b");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test7/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fprintf/test7/testinfo.dat
new file mode 100644
index 0000000000..fc12718063
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test7/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fprintf
+Name = Positive Test for fprintf
+TYPE = DEFAULT
+EXE1 = test7
+Description
+= Tests the wide char specifier (%C).
+= This test is modeled after the fprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test8/CMakeLists.txt
new file mode 100644
index 0000000000..f6dd984af9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test8/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test8.c
+)
+
+add_executable(paltest_fprintf_test8
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fprintf_test8 coreclrpal)
+
+target_link_libraries(paltest_fprintf_test8
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test8/test8.c b/src/pal/tests/palsuite/c_runtime/fprintf/test8/test8.c
new file mode 100644
index 0000000000..c781abc968
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test8/test8.c
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test8.c (fprintf)
+**
+** Purpose: Tests the decimal specifier (%d).
+** This test is modeled after the fprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoNumTest("foo %d", pos, "foo 42");
+ DoNumTest("foo %ld", 0xFFFF, "foo 65535");
+ DoNumTest("foo %hd", 0xFFFF, "foo -1");
+ DoNumTest("foo %Ld", pos, "foo 42");
+ DoI64Test("foo %I64d", l, "42", "foo 42", "foo 42");
+ DoNumTest("foo %3d", pos, "foo 42");
+ DoNumTest("foo %-3d", pos, "foo 42 ");
+ DoNumTest("foo %.1d", pos, "foo 42");
+ DoNumTest("foo %.3d", pos, "foo 042");
+ DoNumTest("foo %03d", pos, "foo 042");
+ DoNumTest("foo %#d", pos, "foo 42");
+ DoNumTest("foo %+d", pos, "foo +42");
+ DoNumTest("foo % d", pos, "foo 42");
+ DoNumTest("foo %+d", neg, "foo -42");
+ DoNumTest("foo % d", neg, "foo -42");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test8/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fprintf/test8/testinfo.dat
new file mode 100644
index 0000000000..2609260786
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test8/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fprintf
+Name = Positive Test for fprintf
+TYPE = DEFAULT
+EXE1 = test8
+Description
+= Tests the decimal specifier (%d).
+= This test is modeled after the fprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test9/CMakeLists.txt
new file mode 100644
index 0000000000..62aa85e6ff
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test9/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test9.c
+)
+
+add_executable(paltest_fprintf_test9
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fprintf_test9 coreclrpal)
+
+target_link_libraries(paltest_fprintf_test9
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test9/test9.c b/src/pal/tests/palsuite/c_runtime/fprintf/test9/test9.c
new file mode 100644
index 0000000000..3b06daec48
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test9/test9.c
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test9.c (fprintf)
+**
+** Purpose: Tests the integer specifier (%i).
+** This test is modeled after the fprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoNumTest("foo %i", pos, "foo 42");
+ DoNumTest("foo %li", 0xFFFF, "foo 65535");
+ DoNumTest("foo %hi", 0xFFFF, "foo -1");
+ DoNumTest("foo %Li", pos, "foo 42");
+ DoI64Test("foo %I64i", l, "42", "foo 42", "foo 42");
+ DoNumTest("foo %3i", pos, "foo 42");
+ DoNumTest("foo %-3i", pos, "foo 42 ");
+ DoNumTest("foo %.1i", pos, "foo 42");
+ DoNumTest("foo %.3i", pos, "foo 042");
+ DoNumTest("foo %03i", pos, "foo 042");
+ DoNumTest("foo %#i", pos, "foo 42");
+ DoNumTest("foo %+i", pos, "foo +42");
+ DoNumTest("foo % i", pos, "foo 42");
+ DoNumTest("foo %+i", neg, "foo -42");
+ DoNumTest("foo % i", neg, "foo -42");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test9/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fprintf/test9/testinfo.dat
new file mode 100644
index 0000000000..e502af70b2
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fprintf/test9/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fprintf
+Name = Positive Test for fprintf
+TYPE = DEFAULT
+EXE1 = test9
+Description
+= Tests the integer specifier (%i).
+= This test is modeled after the fprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fputs/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fputs/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fputs/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/c_runtime/fputs/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fputs/test1/CMakeLists.txt
new file mode 100644
index 0000000000..e4a92d5966
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fputs/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_fputs_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fputs_test1 coreclrpal)
+
+target_link_libraries(paltest_fputs_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fputs/test1/test1.c b/src/pal/tests/palsuite/c_runtime/fputs/test1/test1.c
new file mode 100644
index 0000000000..b90ea082e9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fputs/test1/test1.c
@@ -0,0 +1,100 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Call fputs twice and write two strings to a file. Then
+** call fread on the file and check that the data which was written is what
+** we expect it to be.
+**
+
+**
+**===================================================================*/
+
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char **argv)
+{
+
+ FILE* TheFile;
+ char* StringOne = "FooBar";
+ char* StringTwo = "BarFoo";
+ char* CompleteString = "FooBarBarFoo";
+ char ReadBuffer[64];
+ int ret;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Open the file that we'll be working with */
+
+ TheFile = fopen("TestFile", "w+");
+
+ if(TheFile == NULL)
+ {
+ Fail("ERROR: fopen failed to open the file 'TestFile' in read/write "
+ "mode.\n");
+ }
+
+ /* Call fputs twice to write two strings to the file stream */
+
+ if(fputs(StringOne, TheFile) < 0)
+ {
+ Fail("ERROR: fputs returned a negative value when attempting to "
+ "put the string '%s' to the file.\n",StringOne);
+ }
+
+ if(fputs(StringTwo, TheFile) < 0)
+ {
+ Fail("ERROR: fputs returned a negative value when attempting to "
+ "put the string '%s' to the file.\n",StringTwo);
+ }
+
+ /* Flush the buffers */
+ if(fflush(TheFile) != 0)
+ {
+ Fail("ERROR: fflush failed to properly flush the buffers.\n");
+ }
+
+ /* Now read from the file to ensure the data was written correctly.
+ Note: We read more than what was written to make sure nothing extra
+ was written.
+ */
+
+ if(fseek(TheFile, 0, SEEK_SET) != 0)
+ {
+ Fail("ERROR: fseek failed to set the file pointer back to the start "
+ "of the file.\n");
+ }
+
+
+ if((ret = fread(ReadBuffer, 1, 20, TheFile)) != 12)
+ {
+ Fail("ERROR: fread should have returned that it read in 12 characters "
+ "from the file, but instead it returned %d.\n", ret);
+ }
+
+ ReadBuffer[ret] = '\0';
+
+ if(strcmp(ReadBuffer, CompleteString) != 0)
+ {
+ Fail("ERROR: The data read back from the file is not exactly the same "
+ "as the data that was written by fputs. The file contains '%s' "
+ "instead of '%s'.\n",ReadBuffer, CompleteString);
+ }
+
+ if(fclose(TheFile) != 0)
+ {
+ Fail("ERROR: fclose failed to close the file stream.\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fputs/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fputs/test1/testinfo.dat
new file mode 100644
index 0000000000..bdef09c60f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fputs/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fputs
+Name = Check that fputs writes correctly to a valid stream
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Call fputs twice and write two strings to a file. Then
+= call fread on the file and check that the data which was written is what
+= we expect it to be.
diff --git a/src/pal/tests/palsuite/c_runtime/fputs/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fputs/test2/CMakeLists.txt
new file mode 100644
index 0000000000..6e939f3346
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fputs/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_fputs_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fputs_test2 coreclrpal)
+
+target_link_libraries(paltest_fputs_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fputs/test2/test2.c b/src/pal/tests/palsuite/c_runtime/fputs/test2/test2.c
new file mode 100644
index 0000000000..b8e2f410bb
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fputs/test2/test2.c
@@ -0,0 +1,88 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test2.c
+**
+** Purpose: Check to see that fputs fails and returns EOF when called on
+** a closed file stream and a read-only file stream.
+**
+
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+
+ FILE* TheFile;
+ char* StringOne = "FooBar";
+ int ret;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Create a file with read/write access */
+
+ TheFile = fopen("TestFile", "w+");
+
+ if(TheFile == NULL)
+ {
+ Fail("ERROR: fopen failed to open the file 'TestFile' in read/write "
+ "mode.\n");
+ }
+
+ /* Then close that file we just opened */
+
+ if(fclose(TheFile) != 0)
+ {
+ Fail("ERROR: fclose failed to close the file.\n");
+ }
+
+ /* Check that calling fputs on this closed file stream fails. */
+
+ if((ret = fputs(StringOne, TheFile)) >= 0)
+ {
+ Fail("ERROR: fputs should have failed to write to a closed "
+ "file stream, but it didn't return a negative value.\n");
+ }
+
+ if(ret != EOF)
+ {
+ Fail("ERROR: fputs should have returned EOF on an error, but instead "
+ "returned %d.\n",ret);
+ }
+
+ /* Open a file as Readonly */
+
+ TheFile = fopen("TestFile", "r");
+
+ if(TheFile == NULL)
+ {
+ Fail("ERROR: fopen failed to open the file 'TestFile' in read/write "
+ "mode.\n");
+ }
+
+ /* Check that fputs fails when trying to write to a read-only stream */
+
+ if((ret = fputs(StringOne, TheFile)) >= 0)
+ {
+ Fail("ERROR: fputs should have failed to write to a read-only "
+ "file stream, but it didn't return a negative value.\n");
+ }
+
+ if(ret != EOF)
+ {
+ Fail("ERROR: fputs should have returned EOF when writing to a "
+ "read-only filestream, but instead "
+ "returned %d.\n",ret);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fputs/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fputs/test2/testinfo.dat
new file mode 100644
index 0000000000..0e2abbdc30
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fputs/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fputs
+Name = Check that fputs returns EOF when called on closed/readonly streams
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Check to see that fputs fails and returns EOF when called on
+= a closed file stream and a read-only file stream.
diff --git a/src/pal/tests/palsuite/c_runtime/fread/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fread/CMakeLists.txt
new file mode 100644
index 0000000000..1962ade358
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fread/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+
diff --git a/src/pal/tests/palsuite/c_runtime/fread/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fread/test1/CMakeLists.txt
new file mode 100644
index 0000000000..a2e09579b1
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fread/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_fread_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fread_test1 coreclrpal)
+
+target_link_libraries(paltest_fread_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fread/test1/test1.c b/src/pal/tests/palsuite/c_runtime/fread/test1/test1.c
new file mode 100644
index 0000000000..b706b2e91c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fread/test1/test1.c
@@ -0,0 +1,135 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests the PAL implementation of the fread function.
+** Open a file in READ mode, and then try to read all
+** the characters, more than all the characters,
+** 0 characters and 0 sized characters and check that
+** the return values are correct.
+**
+** Depends:
+** fopen
+** fseek
+** fclose
+**
+**
+**===================================================================*/
+
+/* Note: testfile should exist in the directory with 15 characters
+ in it ... something got lost if it isn't here.
+*/
+
+/* Note: Under win32, fread() crashes when passed NULL. The test to ensure that
+ it returns 0 has been removed to reflect this.
+*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ const char filename[] = "testfile";
+ char buffer[128];
+ FILE * fp = NULL;
+ int result;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Open a file in READ mode */
+
+ if((fp = fopen(filename, "r")) == NULL)
+ {
+ Fail("Unable to open a file for reading. Is the file "
+ "in the directory? It should be.");
+ }
+
+ /* Read 15 characters from the file. The file has exactly this many
+ in it.
+ */
+ if((result = fread(buffer,1,15,fp)) == 0)
+ {
+ Fail("ERROR: Zero characters read from the file. It should have "
+ "15 characters in it.");
+ }
+
+ if(result != 15)
+ {
+ Fail("ERROR: The fread function should have returned that it read "
+ "in 15 characters from the file. But it indicates having "
+ "read %i characters.",result);
+ }
+
+ /* Go back to the start of the file */
+
+ if(fseek(fp, 0, SEEK_SET))
+ {
+ Fail("ERROR: fseek failed, and this test depends on it.");
+ }
+
+ /* Attempt to read 17 characters, the return should still be 15 */
+
+ if((result = fread(buffer,1,17,fp)) == 0)
+ {
+ Fail("ERROR: Zero characters read from the file. It should have "
+ "15 characters in it. Though, it attempted to read 17.");
+ }
+
+ if(result != 15)
+ {
+ Fail("ERROR: The fread function should have returned that it read "
+ "in 15 characters from the file. "
+ "But it indicates having read %i characters.",result);
+ }
+
+ /* Back to the start of the file */
+
+ if(fseek(fp, 0, SEEK_SET))
+ {
+ Fail("ERROR: fseek failed, and this test depends on it.");
+ }
+
+ /* Read 0 characters and ensure the function returns 0 */
+
+ if((result = fread(buffer,1,0,fp)) != 0)
+ {
+ Fail("ERROR: The return value should be 0, as we attempted to "
+ "read 0 characters.");
+ }
+
+ /* Read characters of 0 size and ensure the return value is 0 */
+
+ if((result = fread(buffer,0,5,fp)) != 0)
+ {
+ Fail("ERROR: The return value should be 0, as we attempted to "
+ "read 0 sized data.");
+ }
+
+ /* Close the file */
+
+ if(fclose(fp))
+ {
+ Fail("ERROR: fclose failed. Test depends on it.");
+ }
+
+ /* Read 5 characters of 1 size from a closed file pointer
+ and ensure the return value is 0
+ */
+
+ if((result = fread(buffer,1,5,fp)) != 0)
+ {
+ Fail("ERROR: The return value should be 0, as we attempted to "
+ "read data from a closed file pointer.");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/fread/test1/testfile b/src/pal/tests/palsuite/c_runtime/fread/test1/testfile
new file mode 100644
index 0000000000..273c1a9ffd
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fread/test1/testfile
@@ -0,0 +1 @@
+This is a test. \ No newline at end of file
diff --git a/src/pal/tests/palsuite/c_runtime/fread/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fread/test1/testinfo.dat
new file mode 100644
index 0000000000..0f8b860616
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fread/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fread
+Name = Positive Test for fread
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests the PAL implementation of the fread function.
+= Open a file in READ mode, and then try to read all the characters,
+= more than all the characters, 0 characters and 0 sized characters and
+= check that the return values are correct.
diff --git a/src/pal/tests/palsuite/c_runtime/fread/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fread/test2/CMakeLists.txt
new file mode 100644
index 0000000000..0538e0c3af
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fread/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_fread_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fread_test2 coreclrpal)
+
+target_link_libraries(paltest_fread_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fread/test2/test2.c b/src/pal/tests/palsuite/c_runtime/fread/test2/test2.c
new file mode 100644
index 0000000000..d7262a9321
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fread/test2/test2.c
@@ -0,0 +1,143 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test2.c
+**
+** Purpose: Tests the PAL implementation of the fread function.
+** Open a file in READ mode, and then try to read all
+** the characters, more than all the characters,
+** 0 characters and 0 sized characters and check that
+** the strings read in are correct.
+**
+** Depends:
+** fopen
+** fseek
+** fclose
+** strcmp
+** memset
+**
+**
+**===================================================================*/
+
+/* Note: testfile should exist in the directory with 15 characters
+ in it ... something got lost if it isn't here.
+*/
+
+/* Note: The behaviour in win32 is to crash if a NULL pointer is passed to
+ fread, so the test to check that it returns 0 has been removed.
+*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ const char filename[] = "testfile";
+ char buffer[128];
+ FILE * fp = NULL;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Open a file in READ mode */
+
+ if((fp = fopen(filename, "r")) == NULL)
+ {
+ Fail("Unable to open a file for reading. Is the file "
+ "in the directory? It should be.");
+ }
+
+ /* Read 15 characters from the file. The file has exactly this many
+ in it. Then check to see that the data read in is correct.
+ Note: The 'testfile' should have "This is a test." written in it.
+ */
+ memset(buffer,'\0',128);
+ fread(buffer,1,15,fp);
+
+ if(strcmp(buffer,"This is a test.") != 0)
+ {
+ Fail("ERROR: The data read in should have been "
+ "'This is a test.' but, the buffer contains '%s'.",
+ buffer);
+ }
+
+ /* Go back to the start of the file */
+
+ if(fseek(fp, 0, SEEK_SET))
+ {
+ Fail("ERROR: fseek failed, and this test depends on it.");
+ }
+
+ /* Attempt to read 17 characters. The same 15 characters should
+ be in the buffer.
+ */
+
+ memset(buffer,'\0',128);
+ fread(buffer,1,17,fp);
+
+ if(strcmp(buffer,"This is a test.") != 0)
+ {
+ Fail("ERROR: The data read in should have been "
+ "'This is a test.' but, the buffer contains '%s'.",
+ buffer);
+ }
+
+ /* Back to the start of the file */
+
+ if(fseek(fp, 0, SEEK_SET))
+ {
+ Fail("ERROR: fseek failed, and this test depends on it.");
+ }
+
+ /* Read 0 characters and ensure the buffer is empty */
+
+ memset(buffer,'\0',128);
+ fread(buffer,1,0,fp);
+
+ if(strcmp(buffer,"\0") != 0)
+ {
+ Fail("ERROR: The data read in should have been "
+ "NULL but, the buffer contains '%s'.",
+ buffer);
+ }
+
+ /* Read characters of 0 size and ensure the buffer is empty */
+
+ memset(buffer,'\0',128);
+ fread(buffer,0,5,fp);
+
+ if(strcmp(buffer,"\0") != 0)
+ {
+ Fail("ERROR: The data read in should have been "
+ "NULL but, the buffer contains '%s'.",
+ buffer);
+ }
+
+ /* Close the file */
+
+ if(fclose(fp))
+ {
+ Fail("ERROR: fclose failed. Test depends on it.");
+ }
+
+ /* Read 5 characters of 1 size from a closed file pointer
+ and ensure the buffer is empty
+ */
+ memset(buffer,'\0',128);
+ fread(buffer,1,5,fp);
+ if(strcmp(buffer,"\0") != 0)
+ {
+ Fail("ERROR: The data read in should have been "
+ "NULL but, the buffer contains '%s'.",
+ buffer);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/fread/test2/testfile b/src/pal/tests/palsuite/c_runtime/fread/test2/testfile
new file mode 100644
index 0000000000..273c1a9ffd
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fread/test2/testfile
@@ -0,0 +1 @@
+This is a test. \ No newline at end of file
diff --git a/src/pal/tests/palsuite/c_runtime/fread/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fread/test2/testinfo.dat
new file mode 100644
index 0000000000..a73c0ecf9e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fread/test2/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fread
+Name = Positive Test for fread
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Tests the PAL implementation of the fread function.
+= Open a file in READ mode, and then try to read all
+= the characters, more than all the characters,
+= 0 characters and 0 sized characters and check that
+= the strings read in are correct.
diff --git a/src/pal/tests/palsuite/c_runtime/fread/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fread/test3/CMakeLists.txt
new file mode 100644
index 0000000000..f3c636f3df
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fread/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_fread_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fread_test3 coreclrpal)
+
+target_link_libraries(paltest_fread_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fread/test3/test3.c b/src/pal/tests/palsuite/c_runtime/fread/test3/test3.c
new file mode 100644
index 0000000000..8c79bee582
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fread/test3/test3.c
@@ -0,0 +1,131 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test3.c
+**
+** Purpose: Tests the PAL implementation of the fread function.
+** Open a file in READ mode, then try to read from the file with
+** different 'size' params. Check to ensure the return values and
+** the text in the buffer is correct.
+**
+** Depends:
+** fopen
+** fseek
+** strcmp
+** memset
+**
+**
+**===================================================================*/
+
+/* Note: testfile should exist in the directory with 15 characters
+ in it ... something got lost if it isn't here.
+*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ const char filename[] = "testfile";
+ char buffer[128];
+ FILE * fp = NULL;
+ int result;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Open a file in READ mode */
+
+ if((fp = fopen(filename, "r")) == NULL)
+ {
+ Fail("Unable to open a file for reading. Is the file "
+ "in the directory? It should be.");
+ }
+
+ memset(buffer,'x',128);
+
+ /* Put the null one character past the end of the text that was read
+ in, to ensure that it wasn't reading in 0
+ */
+
+ buffer[16] = '\0';
+
+ /* Attempt to read in 5 bytes at a time. This should return 3 and
+ contain the full string in the buffer.
+ */
+
+ if((result = fread(buffer,5,3,fp)) != 3)
+ {
+ Fail("ERROR: Attempted to read in data of size 5. The file has "
+ "15 bytes in it so 3 items should have been read. But the value "
+ "returned was %d.",result);
+ }
+
+ if(strcmp(buffer, "This is a test.x") != 0)
+ {
+ Fail("ERROR: The buffer should have contained the text "
+ "'This is a test.x' but instead contained '%s'.",buffer);
+ }
+
+ memset(buffer,'x',128);
+
+ if(fseek(fp, 0, SEEK_SET))
+ {
+ Fail("ERROR: fseek failed, and this test depends on it.");
+ }
+
+ buffer[16] = '\0';
+
+ /* Attempt to read in 6 bytes at a time. The return should be 2. The
+ full string should still be in the buffer.
+ */
+
+ if((result = fread(buffer,6,3,fp)) != 2)
+ {
+ Fail("ERROR: Attempted to read in data of size 6. The file has "
+ "15 bytes in it, so 2 items should have been read. But the "
+ "value returned was %d.",result);
+ }
+
+ if(strcmp(buffer, "This is a test.x") != 0)
+ {
+ Fail("ERROR: The buffer should have contained the text "
+ "'This is a test.x' but instead contained '%s'.",buffer);
+ }
+
+ memset(buffer,'x',128);
+
+ buffer[7] = '\0';
+
+ if(fseek(fp, 0, SEEK_SET))
+ {
+ Fail("ERROR: fseek failed, and this test depends on it.");
+ }
+
+ /* Attempt to read in 6 bytes at a time but only one item max.
+ The return should be 1. The first 6 characters should be in the
+ buffer.
+ */
+
+ if((result = fread(buffer,6,1,fp)) != 1)
+ {
+ Fail("ERROR: Attempted to read in data of size 6 with a max count "
+ "of 1. Thus, one item should have been read, but the "
+ "value returned was %d.",result);
+ }
+
+ if(strcmp(buffer, "This ix") != 0)
+ {
+ Fail("ERROR: The buffer should have contained the text "
+ "'This ix.' but instead contained '%s'.",buffer);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/fread/test3/testfile b/src/pal/tests/palsuite/c_runtime/fread/test3/testfile
new file mode 100644
index 0000000000..273c1a9ffd
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fread/test3/testfile
@@ -0,0 +1 @@
+This is a test. \ No newline at end of file
diff --git a/src/pal/tests/palsuite/c_runtime/fread/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fread/test3/testinfo.dat
new file mode 100644
index 0000000000..95bc30ebcf
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fread/test3/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fread
+Name = Positive Test for fread
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Tests the PAL implementation of the fread function.
+= Open a file in READ mode, then try to read from the file with
+= different 'size' params. Check to ensure the return values and
+= the text in the buffer is correct
diff --git a/src/pal/tests/palsuite/c_runtime/free/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/free/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/free/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/free/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/free/test1/CMakeLists.txt
new file mode 100644
index 0000000000..bd94cb5733
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/free/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_free_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_free_test1 coreclrpal)
+
+target_link_libraries(paltest_free_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/free/test1/test1.c b/src/pal/tests/palsuite/c_runtime/free/test1/test1.c
new file mode 100644
index 0000000000..4ff8dfb094
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/free/test1/test1.c
@@ -0,0 +1,62 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Repeatedly allocates and frees a chunk of memory, to verify
+** that free is really returning memory to the heap
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+
+ char *testA;
+
+ long i;
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /* check that free really returns memory to the heap. */
+ for(i=1; i<1000000; i++)
+ {
+ testA = (char *)malloc(1000*sizeof(char));
+ if (testA==NULL)
+ {
+ Fail("Either free is failing to return memory to the heap, or"
+ " the system is running out of memory for some other "
+ "reason.\n");
+ }
+ free(testA);
+ }
+
+ free(NULL); /*should do nothing*/
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/free/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/free/test1/testinfo.dat
new file mode 100644
index 0000000000..5bf400ce27
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/free/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = free
+Name = Positive Test for free
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Repeatedly allocates and frees a chunk of memory, to verify that free
+= is really returning memory to the heap
+
diff --git a/src/pal/tests/palsuite/c_runtime/fseek/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fseek/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fseek/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/fseek/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fseek/test1/CMakeLists.txt
new file mode 100644
index 0000000000..fb55bd1051
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fseek/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_fseek_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fseek_test1 coreclrpal)
+
+target_link_libraries(paltest_fseek_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fseek/test1/test1.c b/src/pal/tests/palsuite/c_runtime/fseek/test1/test1.c
new file mode 100644
index 0000000000..8496289a01
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fseek/test1/test1.c
@@ -0,0 +1,193 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Call fseek to move a file pointer to the start of a file,
+** a position offset from the start, a position offset from the
+** current position, and a position offset from the end of the
+** file. Check that the file pointer is at the correct position
+** after each seek.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+const char filename[] = "testfile.txt";
+
+static BOOL Cleanup(HANDLE hFile)
+{
+ BOOL result= TRUE;
+
+ if (fclose(hFile))
+ {
+ Trace("fseek: ERROR -> Unable to close file \"%s\".\n",
+ filename);
+ result= FALSE;
+ }
+ if (!DeleteFileA(filename))
+ {
+ result= FALSE;
+ Trace("fseek: ERROR -> Unable to delete file \"%s\". ",
+ "GetLastError returned %u.\n",
+ filename,
+ GetLastError());
+ }
+ return result;
+}
+
+int __cdecl main(int argc, char **argv)
+{
+ char outBuf[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ char inBuf[20];
+ FILE * fp;
+ int size = ( sizeof(outBuf)/sizeof(char) ) - 1;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /*create the file*/
+ fp = fopen(filename, "w");
+ if (fp == NULL)
+ {
+ Fail("Unable to open a file for write.\n");
+ }
+ if(fprintf(fp, outBuf) != size)
+ {
+ Trace("Unable to write to %s.\n", filename);
+ Cleanup(fp);
+ Fail("");
+ }
+
+ if (fclose(fp) != 0)
+ {
+ Trace("Unable to close newly written file.\n");
+ if (!DeleteFileA(filename))
+ {
+ Trace("fseek: ERROR -> Unable to delete file \"%s\". ",
+ "GetLastError returned %u.\n",
+ filename,
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ fp = fopen(filename, "r");
+ if (fp == NULL)
+ {
+ if (!DeleteFileA(filename))
+ {
+ Trace("_putw: ERROR -> Unable to delete file \"%s\". ",
+ "GetLastError returned %u.\n",
+ filename,
+ GetLastError());
+ }
+ Fail("Unable to open a file for read.\n");
+ }
+
+ /*seek to the start*/
+ if (fseek(fp, 0, SEEK_SET) != 0)
+ {
+ Cleanup(fp);
+ Fail("fseek failed when seeking the start of a file.\n");
+ }
+ if (fgets(inBuf, 11, fp) != inBuf)
+ {
+ Cleanup(fp);
+ Fail("Unable to read from file after using fseek to move to the start.\n");
+ }
+ if (strncmp(inBuf, outBuf, 10) != 0)
+ {
+ Cleanup(fp);
+ Fail("fseek was asked to seek the start of a file,"
+ "but didn't get there.\n");
+ }
+
+ /*Seek with an offset from the start*/
+
+ if (fseek(fp, 10, SEEK_SET) != 0)
+ {
+ Cleanup(fp);
+ Fail("fseek failed when called with SEEK_SET and a positive offset.\n");
+ }
+
+ if (fgets(inBuf, 6, fp) != inBuf)
+ {
+ Cleanup(fp);
+ Fail("fgets failed after feek was called with SEEK_SET"
+ "and a positive offset.\n");
+ }
+
+
+ if (strncmp(inBuf, "ABCDE", 5) != 0)
+ {
+ Cleanup(fp);
+ Fail("fseek did not move to the correct position when passed SEEK_SET"
+ " and a positive offset.\n");
+ }
+
+ /*now move backwards and read the same string*/
+ if (fseek(fp, -5, SEEK_CUR) != 0)
+ {
+ Cleanup(fp);
+ Fail("fseek failed when passed SEEK_CUR and a negative offset.\n");
+ }
+
+ if (fgets(inBuf, 6, fp) != inBuf)
+ {
+ Cleanup(fp);
+ Fail("fgets failed after fseek was called with SEEK_CUR and a "
+ "negative offset.\n");
+ }
+
+ if (strncmp(inBuf, "ABCDE", 5) != 0)
+ {
+ Cleanup(fp);
+ Fail("fseek did not move to the correct position when called with"
+ " SEEK_CUR and a negative offset.\n");
+ }
+
+ /*Try seeking relative to the end of the file.*/
+ if (fseek(fp, -10, SEEK_END) != 0)
+ {
+ Cleanup(fp);
+ Fail("fseek failed when called with SEEK_END and a negative"
+ " offset.\n");
+ }
+ if (fgets(inBuf, 2, fp) != inBuf)
+ {
+ Cleanup(fp);
+ Fail("fgets failed after fseek was called with SEEK_END and a "
+ "negative offset\n");
+ }
+
+ if (strncmp(inBuf, "Q", 1) != 0)
+ {
+ Cleanup(fp);
+ Fail("fseek did not move to the correct position when called with "
+ "SEEK_END and a negative offset.\n");
+ }
+
+
+ /*close the file*/
+ if(!Cleanup(fp))
+ {
+ Fail("");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/fseek/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fseek/test1/testinfo.dat
new file mode 100644
index 0000000000..788f8d4bea
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fseek/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fseek
+Name = Positive Test for fseek
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Call seek to move a file pointer to the start of a file, a position
+= offset from the start, a position offset from the current position, and
+= a position offset from the end of the file. Check that the file
+= pointer is at the correct position after each seek.
diff --git a/src/pal/tests/palsuite/c_runtime/ftell/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/ftell/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ftell/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/ftell/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/ftell/test1/CMakeLists.txt
new file mode 100644
index 0000000000..7ea9a51111
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ftell/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ ftell.c
+)
+
+add_executable(paltest_ftell_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_ftell_test1 coreclrpal)
+
+target_link_libraries(paltest_ftell_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/ftell/test1/ftell.c b/src/pal/tests/palsuite/c_runtime/ftell/test1/ftell.c
new file mode 100644
index 0000000000..66e0854847
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ftell/test1/ftell.c
@@ -0,0 +1,145 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: ftell.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the ftell function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+FILE* pFile;
+struct TESTS
+{
+ long lDist;
+ int nFrom;
+ long lPosition;
+};
+
+
+/*************************************************
+**
+** Validate
+**
+** Purpose:
+** Tests whether the move was successful. If
+** it passes, it returns TRUE. If it fails
+** it outputs some error messages and returns
+** FALSE.
+**
+*************************************************/
+BOOL Validate(long lExpected)
+{
+ long lPos = -2;
+
+ if (((lPos = ftell(pFile)) == -1) || (lPos != lExpected))
+ {
+ Trace("ftell: ERROR -> ftell returned %ld when expecting %ld.\n",
+ lPos,
+ lExpected);
+ if (fclose(pFile) != 0)
+ {
+ Trace("ftell: ERROR -> fclose failed to close the file.\n");
+ }
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+/*************************************************
+**
+** MovePointer
+**
+** Purpose:
+** Accepts the distance to move and the
+** distance and calls fseek to move the file
+** pointer. If the fseek fails, error messages
+** are displayed and FALSE is returned. TRUE
+** is returned on a successful fseek.
+**
+*************************************************/
+BOOL MovePointer(long lDist, int nFrom)
+{
+ /* move the file pointer*/
+ if (fseek(pFile, lDist, nFrom) != 0)
+ {
+ Trace("ftell: ERROR -> fseek failed to move the file pointer "
+ "%l characters.\n",
+ lDist);
+ if (fclose(pFile) != 0)
+ {
+ Trace("ftell: ERROR -> fclose failed to close the file.\n");
+ }
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ const char szFileName[] = {"testfile.txt"};
+ long lPos = -1;
+ int i;
+ char szTempBuffer[256];
+ struct TESTS testCase[] =
+ {
+ {0, SEEK_SET, 0},
+ {10, SEEK_CUR, 10},
+ {-5, SEEK_CUR, 5},
+ {-2, SEEK_END, 50}
+ };
+
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ memset(szTempBuffer, 0, 256);
+
+
+ /* open the test file */
+ pFile = fopen(szFileName, "r");
+ if (pFile == NULL)
+ {
+ Fail("ftell: ERROR -> fopen failed to open the file \"%s\".\n");
+ }
+
+ /* loop through the test cases */
+ for (i = 0; i < (sizeof(testCase)/sizeof(struct TESTS)); i++)
+ {
+ if (MovePointer(testCase[i].lDist, testCase[i].nFrom) != TRUE)
+ {
+ Fail("");
+ }
+ else if (Validate(testCase[i].lPosition) != TRUE)
+ {
+ Fail("");
+ }
+ }
+
+ if (fclose(pFile) != 0)
+ {
+ Fail("ftell: ERROR -> fclose failed to close the file.\n");
+ }
+
+ /* lets just see if we can find out where we are in a closed stream... */
+ if ((lPos = ftell(pFile)) != -1)
+ {
+ Fail("ftell: ERROR -> ftell returned a valid position (%ld) on a "
+ "closed file handle\n",
+ lPos);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/ftell/test1/testfile.txt b/src/pal/tests/palsuite/c_runtime/ftell/test1/testfile.txt
new file mode 100644
index 0000000000..dd0fe15fe1
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ftell/test1/testfile.txt
@@ -0,0 +1 @@
+The quick brown fox jumped over the lazy dog's back. \ No newline at end of file
diff --git a/src/pal/tests/palsuite/c_runtime/ftell/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/ftell/test1/testinfo.dat
new file mode 100644
index 0000000000..c17ec9ad99
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ftell/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = c_runtime
+Function = ftell
+Name = test for ftell (test 1)
+Type = DEFAULT
+EXE1 = ftell
+Description
+= Use fseek and a static list of distances to move, direction
+= to move and expected results to test the ftell function. A typical
+= test will move the file pointer with fseek then call ftell. The
+= results from ftell will then be compared to the expected result to
+= determine whether the test passed or failed.
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/CMakeLists.txt
new file mode 100644
index 0000000000..cafb9536b0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/CMakeLists.txt
@@ -0,0 +1,22 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test10)
+add_subdirectory(test11)
+add_subdirectory(test12)
+add_subdirectory(test13)
+add_subdirectory(test14)
+add_subdirectory(test15)
+add_subdirectory(test16)
+add_subdirectory(test17)
+add_subdirectory(test18)
+add_subdirectory(test19)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+add_subdirectory(test7)
+add_subdirectory(test8)
+add_subdirectory(test9)
+
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/fwprintf.h b/src/pal/tests/palsuite/c_runtime/fwprintf/fwprintf.h
new file mode 100644
index 0000000000..36756636cf
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/fwprintf.h
@@ -0,0 +1,453 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: fwprintf.h
+**
+** Purpose: Containts common testing functions for fwprintf
+**
+**
+**==========================================================================*/
+
+#ifndef __fwprintf_H__
+#define __fwprintf_H__
+
+void DoStrTest(WCHAR *formatstr, char* param, char *checkstr)
+{
+ FILE *fp;
+ char buf[256] = { 0 };
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ {
+ Fail("ERROR: fopen failed to create testfile\n");
+ }
+ if ((fwprintf(fp, formatstr, param)) < 0)
+ {
+ Fail("ERROR: fwprintf failed\n");
+ }
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+ if ((fgets(buf, 100, fp)) == NULL)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+
+ if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert string \"%\" into \"%S\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ param, formatstr, checkstr, buf);
+ }
+ fclose(fp);
+}
+
+void DoWStrTest(WCHAR *formatstr, WCHAR* param, char *checkstr)
+{
+ FILE *fp;
+ char buf[256] = { 0 };
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ {
+ Fail("ERROR: fopen failed to create testfile\n");
+ }
+ if ((fwprintf(fp, formatstr, param)) < 0)
+ {
+ Fail("ERROR: fwprintf failed\n");
+ }
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+ if ((fgets(buf, 100, fp)) == NULL)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+
+ if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert wide string \"%s\" into \"%S\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ convertC(param), formatstr, checkstr, buf);
+ }
+ fclose(fp);
+}
+
+
+void DoPointerTest(WCHAR *formatstr, void* param, char* paramstr,
+ char *checkstr1, char *checkstr2)
+{
+ FILE *fp;
+ char buf[256] = { 0 };
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ {
+ Fail("ERROR: fopen failed to create testfile\n");
+ }
+
+ if ((fwprintf(fp, formatstr, param)) < 0)
+ {
+ Fail("ERROR: fwprintf failed\n");
+ }
+
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+
+ if ((fgets(buf, 100, fp)) == NULL)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+
+ if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 &&
+ memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0 )
+ {
+ Fail("ERROR: failed to insert %s into \"%s\"\n"
+ "Expected \"%s\" or \"%s\" got \"%s\".\n",
+ paramstr, formatstr, checkstr1, checkstr2, buf);
+ }
+
+ if ((fclose( fp )) != 0)
+ {
+ Fail("ERROR: fclose failed to close \"testfile.txt\"\n");
+ }
+}
+
+
+
+void DoCountTest(WCHAR *formatstr, int param, char *checkstr)
+{
+ FILE *fp;
+ char buf[512] = { 0 };
+ int n = -1;
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ {
+ Fail("ERROR: fopen failed to create testfile\n");
+ }
+
+ if ((fwprintf(fp, formatstr, &n)) < 0)
+ {
+ Fail("ERROR: fwprintf failed\n");
+ }
+
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+
+ if ((fgets(buf, sizeof(buf), fp)) == NULL)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+
+ if (n != param)
+ {
+ Fail("ERROR: Expected count parameter to resolve to %d, got %X\n",
+ param, n);
+ }
+
+ if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0)
+ {
+ Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf);
+ }
+
+ if ((fclose( fp )) != 0)
+ {
+ Fail("ERROR: fclose failed to close \"testfile.txt\"\n");
+ }
+}
+
+void DoShortCountTest(WCHAR *formatstr, int param, char *checkstr)
+{
+ FILE *fp;
+ char buf[512] = { 0 };
+ short int n = -1;
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ {
+ Fail("ERROR: fopen failed to create testfile\n");
+ }
+
+ if ((fwprintf(fp, formatstr, &n)) < 0)
+ {
+ Fail("ERROR: fwprintf failed\n");
+ }
+
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+
+ if ((fgets(buf, 100, fp)) == NULL)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+
+ if (n != param)
+ {
+ Fail("ERROR: Expected count parameter to resolve to %d, got %X\n",
+ param, n);
+ }
+
+ if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0)
+ {
+ Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf);
+ }
+
+ if ((fclose( fp )) != 0)
+ {
+ Fail("ERROR: fclose failed to close \"testfile.txt\"\n");
+ }
+}
+
+
+void DoCharTest(WCHAR *formatstr, char param, char *checkstr)
+{
+ FILE *fp;
+ char buf[256] = { 0 };
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ {
+ Fail("ERROR: fopen failed to create testfile\n");
+ }
+ if ((fwprintf(fp, formatstr, param)) < 0)
+ {
+ Fail("ERROR: fwprintf failed\n");
+ }
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+ if ((fgets(buf, 100, fp)) == NULL)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+
+ if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert char \'%c\' (%d) into \"%S\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ param, param, formatstr, checkstr, buf);
+ }
+ fclose(fp);
+}
+
+void DoWCharTest(WCHAR *formatstr, WCHAR param, char *checkstr)
+{
+ FILE *fp;
+ char buf[256] = { 0 };
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ {
+ Fail("ERROR: fopen failed to create testfile\n");
+ }
+ if ((fwprintf(fp, formatstr, param)) < 0)
+ {
+ Fail("ERROR: fwprintf failed\n");
+ }
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+ if ((fgets(buf, 100, fp)) == NULL)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+
+ if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert wide char \'%c\' (%d) into \"%S\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ (char)param, param, formatstr, checkstr, buf);
+ }
+ fclose(fp);
+}
+
+void DoNumTest(WCHAR *formatstr, int value, char *checkstr)
+{
+ FILE *fp;
+ char buf[256] = { 0 };
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ {
+ Fail("ERROR: fopen failed to create testfile\n");
+ }
+ if ((fwprintf(fp, formatstr, value)) < 0)
+ {
+ Fail("ERROR: fwprintf failed\n");
+ }
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+ if ((fgets(buf, 100, fp)) == NULL)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+
+ if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %#x into \"%S\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ value, formatstr, checkstr, buf);
+ }
+ fclose(fp);
+}
+
+void DoI64Test(WCHAR *formatstr, INT64 value, char *valuestr, char *checkstr1,
+ char *checkstr2)
+{
+ FILE *fp;
+ char buf[256] = { 0 };
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ {
+ Fail("ERROR: fopen failed to create testfile\n");
+ }
+ if ((fwprintf(fp, formatstr, value)) < 0)
+ {
+ Fail("ERROR: fwprintf failed\n");
+ }
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+ if ((fgets(buf, 100, fp)) == NULL)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+
+ if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 &&
+ memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %s into \"%S\"\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n",
+ valuestr, formatstr, checkstr1, checkstr2, buf);
+ }
+ fclose(fp);
+}
+
+void DoDoubleTest(WCHAR *formatstr, double value, char *checkstr1,
+ char *checkstr2)
+{
+ FILE *fp;
+ char buf[256] = { 0 };
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ {
+ Fail("ERROR: fopen failed to create testfile\n");
+ }
+
+ if ((fwprintf(fp, formatstr, value)) < 0)
+ {
+ Fail("ERROR: fwprintf failed\n");
+ }
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+ if ((fgets(buf, 100, fp)) == NULL)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+
+ if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 &&
+ memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %f into \"%S\"\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n",
+ value, formatstr, checkstr1, checkstr2, buf);
+ }
+ fclose(fp);
+}
+
+
+void DoArgumentPrecTest(WCHAR *formatstr, int precision, void *param,
+ char *paramstr, char *checkstr1, char *checkstr2)
+{
+ FILE *fp;
+ char buf[256];
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ {
+ Fail("ERROR: fopen failed to create testfile\n");
+ }
+
+ if ((fwprintf(fp, formatstr, precision, param)) < 0)
+ {
+ Fail("ERROR: fwprintf failed\n");
+ }
+
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+
+ if ((fgets(buf, 100, fp)) == NULL)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+
+ if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 &&
+ memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n", paramstr, formatstr,
+ precision, checkstr1, checkstr2, buf);
+ }
+
+
+ if ((fclose( fp )) != 0)
+ {
+ Fail("ERROR: fclose failed to close \"testfile.txt\"\n");
+ }
+
+}
+
+void DoArgumentPrecDoubleTest(WCHAR *formatstr, int precision, double param,
+ char *checkstr1, char *checkstr2)
+{
+ FILE *fp;
+ char buf[256];
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ {
+ Fail("ERROR: fopen failed to create testfile\n");
+ }
+
+ if ((fwprintf(fp, formatstr, precision, param)) < 0)
+ {
+ Fail("ERROR: fwprintf failed\n");
+ }
+
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+
+ if ((fgets(buf, 100, fp)) == NULL)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+
+ if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 &&
+ memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n", param, formatstr,
+ precision, checkstr1, checkstr2, buf);
+ }
+
+ if ((fclose( fp )) != 0)
+ {
+ Fail("ERROR: fclose failed to close \"testfile.txt\"\n");
+ }
+
+}
+
+#endif
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..ce4271edb2
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_fwprintf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fwprintf_test1 coreclrpal)
+
+target_link_libraries(paltest_fwprintf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test1/test1.c
new file mode 100644
index 0000000000..8a171db52a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test1/test1.c
@@ -0,0 +1,71 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: A single, basic, test case with no formatting.
+** Test modeled after the sprintf series.
+**
+
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+/*
+ * Depends on memcmp, strlen, fopen, fgets, fseek and fclose.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ FILE *fp;
+ char testfile[] = "testfile.txt";
+
+ WCHAR *outstr;
+ char checkstr[] = "hello world";
+ char buf[256];
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ outstr = convert(checkstr);
+ if ((fp = fopen(testfile, "w+")) == NULL)
+ {
+ Fail("ERROR: fopen failed to create \"%s\"\n", testfile);
+ }
+
+ if ((fwprintf(fp, outstr)) < 0)
+ {
+ Fail("ERROR: fwprintf failed to print to \"%s\"\n", testfile);
+ }
+
+ if ((fseek( fp, 0, SEEK_SET)) != 0)
+ {
+ Fail("ERROR: Fseek failed to set pointer to beginning of file\n" );
+ }
+
+
+ if ((fgets( buf, 100, fp )) == NULL)
+ {
+ Fail("ERROR: fgets failed\n");
+ }
+
+ if (memcmp(checkstr, buf, strlen(checkstr)+1) != 0)
+ {
+ Fail("ERROR: expected %s, got %s\n", checkstr, buf);
+ }
+
+
+ if ((fclose( fp )) != 0)
+ {
+ Fail("ERROR: fclose failed to close \"%s\"\n", testfile);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fwprintf/test1/testinfo.dat
new file mode 100644
index 0000000000..3bef5c6384
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fwprintf
+Name = Positive Test for fwprintf
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= A single, basic, test case with no formatting.
+= Test modeled after the sprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test10/CMakeLists.txt
new file mode 100644
index 0000000000..a8323b4fc7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test10/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test10.c
+)
+
+add_executable(paltest_fwprintf_test10
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fwprintf_test10 coreclrpal)
+
+target_link_libraries(paltest_fwprintf_test10
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test10/test10.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test10/test10.c
new file mode 100644
index 0000000000..3aa2c45c7c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test10/test10.c
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test10.c
+**
+** Purpose: Tests the octal specifier (%o).
+** This test is modeled after the sprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fwprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoNumTest(convert("foo %o"), pos, "foo 52");
+ DoNumTest(convert("foo %lo"), 0xFFFF, "foo 177777");
+ DoNumTest(convert("foo %ho"), 0xFFFF, "foo 177777");
+ DoNumTest(convert("foo %Lo"), pos, "foo 52");
+ DoI64Test(convert("foo %I64o"), l, "42", "foo 52", "foo 52");
+ DoNumTest(convert("foo %3o"), pos, "foo 52");
+ DoNumTest(convert("foo %-3o"), pos, "foo 52 ");
+ DoNumTest(convert("foo %.1o"), pos, "foo 52");
+ DoNumTest(convert("foo %.3o"), pos, "foo 052");
+ DoNumTest(convert("foo %03o"), pos, "foo 052");
+ DoNumTest(convert("foo %#o"), pos, "foo 052");
+ DoNumTest(convert("foo %+o"), pos, "foo 52");
+ DoNumTest(convert("foo % o"), pos, "foo 52");
+ DoNumTest(convert("foo %+o"), neg, "foo 37777777726");
+ DoNumTest(convert("foo % o"), neg, "foo 37777777726");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test10/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fwprintf/test10/testinfo.dat
new file mode 100644
index 0000000000..17902cb7fc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test10/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fwprintf
+Name = Positive Test for fwprintf
+TYPE = DEFAULT
+EXE1 = test10
+Description
+= Tests the octal specifier (%o).
+= This test is modeled after the sprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test11/CMakeLists.txt
new file mode 100644
index 0000000000..1b7987400a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test11/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test11.c
+)
+
+add_executable(paltest_fwprintf_test11
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fwprintf_test11 coreclrpal)
+
+target_link_libraries(paltest_fwprintf_test11
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test11/test11.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test11/test11.c
new file mode 100644
index 0000000000..5867cd64fb
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test11/test11.c
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test11.c
+**
+** Purpose: Test the unsigned int specifier (%u).
+** This test is modeled after the sprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fwprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoNumTest(convert("foo %u"), pos, "foo 42");
+ DoNumTest(convert("foo %lu"), 0xFFFF, "foo 65535");
+ DoNumTest(convert("foo %hu"), 0xFFFF, "foo 65535");
+ DoNumTest(convert("foo %Lu"), pos, "foo 42");
+ DoI64Test(convert("foo %I64u"), l, "42", "foo 42", "foo 42");
+ DoNumTest(convert("foo %3u"), pos, "foo 42");
+ DoNumTest(convert("foo %-3u"), pos, "foo 42 ");
+ DoNumTest(convert("foo %.1u"), pos, "foo 42");
+ DoNumTest(convert("foo %.3u"), pos, "foo 042");
+ DoNumTest(convert("foo %03u"), pos, "foo 042");
+ DoNumTest(convert("foo %#u"), pos, "foo 42");
+ DoNumTest(convert("foo %+u"), pos, "foo 42");
+ DoNumTest(convert("foo % u"), pos, "foo 42");
+ DoNumTest(convert("foo %+u"), neg, "foo 4294967254");
+ DoNumTest(convert("foo % u"), neg, "foo 4294967254");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test11/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fwprintf/test11/testinfo.dat
new file mode 100644
index 0000000000..beda0cc3ab
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test11/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fwprintf
+Name = Positive Test for fwprintf
+TYPE = DEFAULT
+EXE1 = test11
+Description
+= Test the unsigned int specifier (%u).
+= This test is modeled after the sprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test12/CMakeLists.txt
new file mode 100644
index 0000000000..1e43a4c906
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test12/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test12.c
+)
+
+add_executable(paltest_fwprintf_test12
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fwprintf_test12 coreclrpal)
+
+target_link_libraries(paltest_fwprintf_test12
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test12/test12.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test12/test12.c
new file mode 100644
index 0000000000..48a6123423
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test12/test12.c
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test12.c
+**
+** Purpose: Tests the (lowercase) hexadecimal specifier (%x).
+** This test is modeled after the sprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fwprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 0x1234ab;
+ INT64 l = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoNumTest(convert("foo %x"), pos, "foo 1234ab");
+ DoNumTest(convert("foo %lx"), pos, "foo 1234ab");
+ DoNumTest(convert("foo %hx"), pos, "foo 34ab");
+ DoNumTest(convert("foo %Lx"), pos, "foo 1234ab");
+ DoI64Test(convert("foo %I64x"), l, "0x1234567887654321",
+ "foo 1234567887654321", "foo 0x1234567887654321");
+ DoNumTest(convert("foo %7x"), pos, "foo 1234ab");
+ DoNumTest(convert("foo %-7x"), pos, "foo 1234ab ");
+ DoNumTest(convert("foo %.1x"), pos, "foo 1234ab");
+ DoNumTest(convert("foo %.7x"), pos, "foo 01234ab");
+ DoNumTest(convert("foo %07x"), pos, "foo 01234ab");
+ DoNumTest(convert("foo %#x"), pos, "foo 0x1234ab");
+ DoNumTest(convert("foo %+x"), pos, "foo 1234ab");
+ DoNumTest(convert("foo % x"), pos, "foo 1234ab");
+ DoNumTest(convert("foo %+x"), neg, "foo ffffffd6");
+ DoNumTest(convert("foo % x"), neg, "foo ffffffd6");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test12/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fwprintf/test12/testinfo.dat
new file mode 100644
index 0000000000..3d0bf4c8f8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test12/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fwprintf
+Name = Positive Test for fwprintf
+TYPE = DEFAULT
+EXE1 = test12
+Description
+= Tests the (lowercase) hexadecimal specifier (%x).
+= This test is modeled after the sprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test13/CMakeLists.txt
new file mode 100644
index 0000000000..c84dc3ea41
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test13/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test13.c
+)
+
+add_executable(paltest_fwprintf_test13
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fwprintf_test13 coreclrpal)
+
+target_link_libraries(paltest_fwprintf_test13
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test13/test13.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test13/test13.c
new file mode 100644
index 0000000000..6eabec6c77
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test13/test13.c
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test13.c
+**
+** Purpose: Tests the (uppercase) hexadecimal specifier (%X).
+** This test is modeled after the sprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fwprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 0x1234AB;
+ INT64 l = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoNumTest(convert("foo %X"), pos, "foo 1234AB");
+ DoNumTest(convert("foo %lX"), pos, "foo 1234AB");
+ DoNumTest(convert("foo %hX"), pos, "foo 34AB");
+ DoNumTest(convert("foo %LX"), pos, "foo 1234AB");
+ DoI64Test(convert("foo %I64X"), l, "0x1234567887654321",
+ "foo 1234567887654321", "foo 0x1234567887654321");
+ DoNumTest(convert("foo %7X"), pos, "foo 1234AB");
+ DoNumTest(convert("foo %-7X"), pos, "foo 1234AB ");
+ DoNumTest(convert("foo %.1X"), pos, "foo 1234AB");
+ DoNumTest(convert("foo %.7X"), pos, "foo 01234AB");
+ DoNumTest(convert("foo %07X"), pos, "foo 01234AB");
+ DoNumTest(convert("foo %#X"), pos, "foo 0X1234AB");
+ DoNumTest(convert("foo %+X"), pos, "foo 1234AB");
+ DoNumTest(convert("foo % X"), pos, "foo 1234AB");
+ DoNumTest(convert("foo %+X"), neg, "foo FFFFFFD6");
+ DoNumTest(convert("foo % X"), neg, "foo FFFFFFD6");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test13/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fwprintf/test13/testinfo.dat
new file mode 100644
index 0000000000..c3222e7c9e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test13/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fwprintf
+Name = Positive Test for fwprintf
+TYPE = DEFAULT
+EXE1 = test13
+Description
+= Tests the (uppercase) hexadecimal specifier (%X).
+= This test is modeled after the sprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test14/CMakeLists.txt
new file mode 100644
index 0000000000..97824c76b7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test14/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test14.c
+)
+
+add_executable(paltest_fwprintf_test14
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fwprintf_test14 coreclrpal)
+
+target_link_libraries(paltest_fwprintf_test14
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test14/test14.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test14/test14.c
new file mode 100644
index 0000000000..001cf72689
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test14/test14.c
@@ -0,0 +1,66 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test14.c
+**
+** Purpose: Tests the lowercase exponential
+** notation double specifier (%e).
+** This test is modeled after the sprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fwprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 256.0;
+ double neg = -256.0;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoDoubleTest(convert("foo %e"), val, "foo 2.560000e+002",
+ "foo 2.560000e+02");
+ DoDoubleTest(convert("foo %le"), val, "foo 2.560000e+002",
+ "foo 2.560000e+02");
+ DoDoubleTest(convert("foo %he"), val, "foo 2.560000e+002",
+ "foo 2.560000e+02");
+ DoDoubleTest(convert("foo %Le"), val, "foo 2.560000e+002",
+ "foo 2.560000e+02");
+ DoDoubleTest(convert("foo %I64e"), val, "foo 2.560000e+002",
+ "foo 2.560000e+02");
+ DoDoubleTest(convert("foo %14e"), val, "foo 2.560000e+002",
+ "foo 2.560000e+02");
+ DoDoubleTest(convert("foo %-14e"), val, "foo 2.560000e+002 ",
+ "foo 2.560000e+02 ");
+ DoDoubleTest(convert("foo %.1e"), val, "foo 2.6e+002",
+ "foo 2.6e+02");
+ DoDoubleTest(convert("foo %.8e"), val, "foo 2.56000000e+002",
+ "foo 2.56000000e+02");
+ DoDoubleTest(convert("foo %014e"), val, "foo 02.560000e+002",
+ "foo 002.560000e+02");
+ DoDoubleTest(convert("foo %#e"), val, "foo 2.560000e+002",
+ "foo 2.560000e+02");
+ DoDoubleTest(convert("foo %+e"), val, "foo +2.560000e+002",
+ "foo +2.560000e+02");
+ DoDoubleTest(convert("foo % e"), val, "foo 2.560000e+002",
+ "foo 2.560000e+02");
+ DoDoubleTest(convert("foo %+e"), neg, "foo -2.560000e+002",
+ "foo -2.560000e+02");
+ DoDoubleTest(convert("foo % e"), neg, "foo -2.560000e+002",
+ "foo -2.560000e+02");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test14/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fwprintf/test14/testinfo.dat
new file mode 100644
index 0000000000..a723f76083
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test14/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fwprintf
+Name = Positive Test for fwprintf
+TYPE = DEFAULT
+EXE1 = test14
+Description
+= Tests the lowercase exponential
+= notation double specifier (%e).
+= This test is modeled after the sprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test15/CMakeLists.txt
new file mode 100644
index 0000000000..6786c5b774
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test15/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test15.c
+)
+
+add_executable(paltest_fwprintf_test15
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fwprintf_test15 coreclrpal)
+
+target_link_libraries(paltest_fwprintf_test15
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test15/test15.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test15/test15.c
new file mode 100644
index 0000000000..9dfe82eccc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test15/test15.c
@@ -0,0 +1,66 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test15.c
+**
+** Purpose: Tests the uppercase exponential
+** notation double specifier (%E).
+** This test is modeled after the sprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fwprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 256.0;
+ double neg = -256.0;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoDoubleTest(convert("foo %E"), val, "foo 2.560000E+002",
+ "foo 2.560000E+02");
+ DoDoubleTest(convert("foo %lE"), val, "foo 2.560000E+002",
+ "foo 2.560000E+02");
+ DoDoubleTest(convert("foo %hE"), val, "foo 2.560000E+002",
+ "foo 2.560000E+02");
+ DoDoubleTest(convert("foo %LE"), val, "foo 2.560000E+002",
+ "foo 2.560000E+02");
+ DoDoubleTest(convert("foo %I64E"), val, "foo 2.560000E+002",
+ "foo 2.560000E+02");
+ DoDoubleTest(convert("foo %14E"), val, "foo 2.560000E+002",
+ "foo 2.560000E+02");
+ DoDoubleTest(convert("foo %-14E"), val, "foo 2.560000E+002 ",
+ "foo 2.560000E+02 ");
+ DoDoubleTest(convert("foo %.1E"), val, "foo 2.6E+002",
+ "foo 2.6E+02");
+ DoDoubleTest(convert("foo %.8E"), val, "foo 2.56000000E+002",
+ "foo 2.56000000E+02");
+ DoDoubleTest(convert("foo %014E"), val, "foo 02.560000E+002",
+ "foo 002.560000E+02");
+ DoDoubleTest(convert("foo %#E"), val, "foo 2.560000E+002",
+ "foo 2.560000E+02");
+ DoDoubleTest(convert("foo %+E"), val, "foo +2.560000E+002",
+ "foo +2.560000E+02");
+ DoDoubleTest(convert("foo % E"), val, "foo 2.560000E+002",
+ "foo 2.560000E+02");
+ DoDoubleTest(convert("foo %+E"), neg, "foo -2.560000E+002",
+ "foo -2.560000E+02");
+ DoDoubleTest(convert("foo % E"), neg, "foo -2.560000E+002",
+ "foo -2.560000E+02");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test15/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fwprintf/test15/testinfo.dat
new file mode 100644
index 0000000000..246072f797
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test15/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fwprintf
+Name = Positive Test for fwprintf
+TYPE = DEFAULT
+EXE1 = test15
+Description
+= Tests the uppercase exponential
+= notation double specifier (%E).
+= This test is modeled after the sprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test16/CMakeLists.txt
new file mode 100644
index 0000000000..be14870863
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test16/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test16.c
+)
+
+add_executable(paltest_fwprintf_test16
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fwprintf_test16 coreclrpal)
+
+target_link_libraries(paltest_fwprintf_test16
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test16/test16.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test16/test16.c
new file mode 100644
index 0000000000..1969be1824
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test16/test16.c
@@ -0,0 +1,65 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test16.c
+**
+** Purpose: Tests the decimal notation double specifier (%f).
+** This test is modeled after the sprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fwprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoDoubleTest(convert("foo %f"), val, "foo 2560.001000",
+ "foo 2560.001000");
+ DoDoubleTest(convert("foo %lf"), val, "foo 2560.001000",
+ "foo 2560.001000");
+ DoDoubleTest(convert("foo %hf"), val, "foo 2560.001000",
+ "foo 2560.001000");
+ DoDoubleTest(convert("foo %Lf"), val, "foo 2560.001000",
+ "foo 2560.001000");
+ DoDoubleTest(convert("foo %I64f"), val, "foo 2560.001000",
+ "foo 2560.001000");
+ DoDoubleTest(convert("foo %12f"), val, "foo 2560.001000",
+ "foo 2560.001000");
+ DoDoubleTest(convert("foo %-12f"), val, "foo 2560.001000 ",
+ "foo 2560.001000 ");
+ DoDoubleTest(convert("foo %.1f"), val, "foo 2560.0",
+ "foo 2560.0");
+ DoDoubleTest(convert("foo %.8f"), val, "foo 2560.00100000",
+ "foo 2560.00100000");
+ DoDoubleTest(convert("foo %012f"), val, "foo 02560.001000",
+ "foo 02560.001000");
+ DoDoubleTest(convert("foo %#f"), val, "foo 2560.001000",
+ "foo 2560.001000");
+ DoDoubleTest(convert("foo %+f"), val, "foo +2560.001000",
+ "foo +2560.001000");
+ DoDoubleTest(convert("foo % f"), val, "foo 2560.001000",
+ "foo 2560.001000");
+ DoDoubleTest(convert("foo %+f"), neg, "foo -2560.001000",
+ "foo -2560.001000");
+ DoDoubleTest(convert("foo % f"), neg, "foo -2560.001000",
+ "foo -2560.001000");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test16/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fwprintf/test16/testinfo.dat
new file mode 100644
index 0000000000..9e5faf9baf
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test16/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fwprintf
+Name = Positive Test for fwprintf
+TYPE = DEFAULT
+EXE1 = test16
+Description
+= Tests the decimal notation double specifier (%f).
+= This test is modeled after the sprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test17/CMakeLists.txt
new file mode 100644
index 0000000000..b390d15620
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test17/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test17.c
+)
+
+add_executable(paltest_fwprintf_test17
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fwprintf_test17 coreclrpal)
+
+target_link_libraries(paltest_fwprintf_test17
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test17/test17.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test17/test17.c
new file mode 100644
index 0000000000..66b12716d0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test17/test17.c
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test17.c
+**
+** Purpose: Tests the lowercase shorthand notation double specifier (%g).
+** This test is modeled after the sprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fwprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoDoubleTest(convert("foo %g"), val, "foo 2560", "foo 2560");
+ DoDoubleTest(convert("foo %lg"), val, "foo 2560", "foo 2560");
+ DoDoubleTest(convert("foo %hg"), val, "foo 2560", "foo 2560");
+ DoDoubleTest(convert("foo %Lg"), val, "foo 2560", "foo 2560");
+ DoDoubleTest(convert("foo %I64g"), val, "foo 2560", "foo 2560");
+ DoDoubleTest(convert("foo %5g"), val, "foo 2560", "foo 2560");
+ DoDoubleTest(convert("foo %-5g"), val, "foo 2560 ", "foo 2560 ");
+ DoDoubleTest(convert("foo %.1g"), val, "foo 3e+003", "foo 3e+03");
+ DoDoubleTest(convert("foo %.2g"), val, "foo 2.6e+003", "foo 2.6e+03");
+ DoDoubleTest(convert("foo %.12g"), val, "foo 2560.001", "foo 2560.001");
+ DoDoubleTest(convert("foo %06g"), val, "foo 002560", "foo 002560");
+ DoDoubleTest(convert("foo %#g"), val, "foo 2560.00", "foo 2560.00");
+ DoDoubleTest(convert("foo %+g"), val, "foo +2560", "foo +2560");
+ DoDoubleTest(convert("foo % g"), val, "foo 2560", "foo 2560");
+ DoDoubleTest(convert("foo %+g"), neg, "foo -2560", "foo -2560");
+ DoDoubleTest(convert("foo % g"), neg, "foo -2560", "foo -2560");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test17/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fwprintf/test17/testinfo.dat
new file mode 100644
index 0000000000..fe637d744c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test17/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fwprintf
+Name = Positive Test for fwprintf
+TYPE = DEFAULT
+EXE1 = test17
+Description
+= Tests the lowercase shorthand notation double specifier (%g).
+= This test is modeled after the sprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test18/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test18/CMakeLists.txt
new file mode 100644
index 0000000000..6f6d79bce5
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test18/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test18.c
+)
+
+add_executable(paltest_fwprintf_test18
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fwprintf_test18 coreclrpal)
+
+target_link_libraries(paltest_fwprintf_test18
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test18/test18.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test18/test18.c
new file mode 100644
index 0000000000..a33dea39b3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test18/test18.c
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test18.c
+**
+** Purpose: Tests the uppercase shorthand notation double specifier (%G).
+** This test is modeled after the sprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fwprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoDoubleTest(convert("foo %G"), val, "foo 2560", "foo 2560");
+ DoDoubleTest(convert("foo %lG"), val, "foo 2560", "foo 2560");
+ DoDoubleTest(convert("foo %hG"), val, "foo 2560", "foo 2560");
+ DoDoubleTest(convert("foo %LG"), val, "foo 2560", "foo 2560");
+ DoDoubleTest(convert("foo %I64G"), val, "foo 2560", "foo 2560");
+ DoDoubleTest(convert("foo %5G"), val, "foo 2560", "foo 2560");
+ DoDoubleTest(convert("foo %-5G"), val, "foo 2560 ", "foo 2560 ");
+ DoDoubleTest(convert("foo %.1G"), val, "foo 3E+003", "foo 3E+03");
+ DoDoubleTest(convert("foo %.2G"), val, "foo 2.6E+003", "foo 2.6E+03");
+ DoDoubleTest(convert("foo %.12G"), val, "foo 2560.001", "foo 2560.001");
+ DoDoubleTest(convert("foo %06G"), val, "foo 002560", "foo 002560");
+ DoDoubleTest(convert("foo %#G"), val, "foo 2560.00", "foo 2560.00");
+ DoDoubleTest(convert("foo %+G"), val, "foo +2560", "foo +2560");
+ DoDoubleTest(convert("foo % G"), val, "foo 2560", "foo 2560");
+ DoDoubleTest(convert("foo %+G"), neg, "foo -2560", "foo -2560");
+ DoDoubleTest(convert("foo % G"), neg, "foo -2560", "foo -2560");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test18/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fwprintf/test18/testinfo.dat
new file mode 100644
index 0000000000..23f621733b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test18/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fwprintf
+Name = Positive Test for fwprintf
+TYPE = DEFAULT
+EXE1 = test18
+Description
+= Tests the uppercase shorthand notation double specifier (%G).
+= This test is modeled after the sprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test19/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test19/CMakeLists.txt
new file mode 100644
index 0000000000..bc10825ce1
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test19/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test19.c
+)
+
+add_executable(paltest_fwprintf_test19
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fwprintf_test19 coreclrpal)
+
+target_link_libraries(paltest_fwprintf_test19
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test19/test19.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test19/test19.c
new file mode 100644
index 0000000000..4600de7fa9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test19/test19.c
@@ -0,0 +1,81 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test19.c
+**
+** Purpose: Tests the variable length precision argument.
+** This test is modeled after the sprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fwprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int n = -1;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoArgumentPrecTest(convert("%.*s"), 2, convert("bar"), "bar", "ba", "ba");
+ DoArgumentPrecTest(convert("%.*S"), 2, "bar", "bar", "ba", "ba");
+ DoArgumentPrecTest(convert("foo %.*n"), 3, &n, "pointer to int", "foo ",
+ "foo ");
+ if (n != 4)
+ {
+ Fail("ERROR: Expected count parameter to resolve to %d, got %X\n",
+ 4, n);
+ }
+
+ DoArgumentPrecTest(convert("%.*c"), 0, (void*)'a', "a", "a", "a");
+ DoArgumentPrecTest(convert("%.*c"), 4, (void*)'a', "a", "a", "a");
+ DoArgumentPrecTest(convert("%.*C"), 0, (void*)'a', "a", "a", "a");
+ DoArgumentPrecTest(convert("%.*C"), 4, (void*)'a', "a", "a", "a");
+ DoArgumentPrecTest(convert("%.*d"), 1, (void*)42, "42", "42", "42");
+ DoArgumentPrecTest(convert("%.*d"), 3, (void*)42, "42", "042", "042");
+ DoArgumentPrecTest(convert("%.*i"), 1, (void*)42, "42", "42", "42");
+ DoArgumentPrecTest(convert("%.*i"), 3, (void*)42, "42", "042", "042");
+ DoArgumentPrecTest(convert("%.*o"), 1, (void*)42, "42", "52", "52");
+ DoArgumentPrecTest(convert("%.*o"), 3, (void*)42, "42", "052", "052");
+ DoArgumentPrecTest(convert("%.*u"), 1, (void*)42, "42", "42", "42");
+ DoArgumentPrecTest(convert("%.*u"), 3, (void*)42, "42", "042", "042");
+ DoArgumentPrecTest(convert("%.*x"), 1, (void*)0x42, "0x42", "42", "42");
+ DoArgumentPrecTest(convert("%.*x"), 3, (void*)0x42, "0x42", "042", "042");
+ DoArgumentPrecTest(convert("%.*X"), 1, (void*)0x42, "0x42", "42", "42");
+ DoArgumentPrecTest(convert("%.*X"), 3, (void*)0x42, "0x42", "042", "042");
+
+
+ DoArgumentPrecDoubleTest(convert("%.*e"), 1, 2.01, "2.0e+000", "2.0e+00");
+ DoArgumentPrecDoubleTest(convert("%.*e"), 3, 2.01, "2.010e+000",
+ "2.010e+00");
+ DoArgumentPrecDoubleTest(convert("%.*E"), 1, 2.01, "2.0E+000", "2.0E+00");
+ DoArgumentPrecDoubleTest(convert("%.*E"), 3, 2.01, "2.010E+000",
+ "2.010E+00");
+ DoArgumentPrecDoubleTest(convert("%.*f"), 1, 2.01, "2.0", "2.0");
+ DoArgumentPrecDoubleTest(convert("%.*f"), 3, 2.01, "2.010", "2.010");
+ DoArgumentPrecDoubleTest(convert("%.*g"), 1, 256.01, "3e+002", "3e+02");
+ DoArgumentPrecDoubleTest(convert("%.*g"), 3, 256.01, "256", "256");
+ DoArgumentPrecDoubleTest(convert("%.*g"), 4, 256.01, "256", "256");
+ DoArgumentPrecDoubleTest(convert("%.*g"), 6, 256.01, "256.01", "256.01");
+ DoArgumentPrecDoubleTest(convert("%.*G"), 1, 256.01, "3E+002", "3E+02");
+ DoArgumentPrecDoubleTest(convert("%.*G"), 3, 256.01, "256", "256");
+ DoArgumentPrecDoubleTest(convert("%.*G"), 4, 256.01, "256", "256");
+ DoArgumentPrecDoubleTest(convert("%.*G"), 6, 256.01, "256.01", "256.01");
+
+ PAL_Terminate();
+
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test19/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fwprintf/test19/testinfo.dat
new file mode 100644
index 0000000000..24aa8778c3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test19/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fwprintf
+Name = Positive Test for fwprintf
+TYPE = DEFAULT
+EXE1 = test19
+Description
+= Tests the variable length precision argument.
+= This test is modeled after the sprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test2/CMakeLists.txt
new file mode 100644
index 0000000000..64314651c0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_fwprintf_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fwprintf_test2 coreclrpal)
+
+target_link_libraries(paltest_fwprintf_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test2/test2.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test2/test2.c
new file mode 100644
index 0000000000..ecd3c513df
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test2/test2.c
@@ -0,0 +1,45 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test2.c
+**
+** Purpose: Tests the string specifier (%s).
+** This test is modeled after the sprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fwprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoWStrTest(convert("foo %s"), convert("bar"), "foo bar");
+ DoStrTest(convert("foo %hs"), "bar", "foo bar");
+ DoWStrTest(convert("foo %ls"), convert("bar"), "foo bar");
+ DoWStrTest(convert("foo %ws"), convert("bar"), "foo bar");
+ DoWStrTest(convert("foo %Ls"), convert("bar"), "foo bar");
+ DoWStrTest(convert("foo %I64s"), convert("bar"), "foo bar");
+ DoWStrTest(convert("foo %5s"), convert("bar"), "foo bar");
+ DoWStrTest(convert("foo %.2s"), convert("bar"), "foo ba");
+ DoWStrTest(convert("foo %5.2s"), convert("bar"), "foo ba");
+ DoWStrTest(convert("foo %-5s"), convert("bar"), "foo bar ");
+ DoWStrTest(convert("foo %05s"), convert("bar"), "foo 00bar");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fwprintf/test2/testinfo.dat
new file mode 100644
index 0000000000..1933682f24
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fwprintf
+Name = Positive Test for fwprintf
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Tests the string specifier (%s).
+= This test is modeled after the sprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test3/CMakeLists.txt
new file mode 100644
index 0000000000..6906722cde
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_fwprintf_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fwprintf_test3 coreclrpal)
+
+target_link_libraries(paltest_fwprintf_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test3/test3.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test3/test3.c
new file mode 100644
index 0000000000..d718a19067
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test3/test3.c
@@ -0,0 +1,45 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test3.c
+**
+** Purpose: Tests the wide string specifier (%S).
+** This test is modeled after the sprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fwprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoStrTest(convert("foo %S"), "bar", "foo bar");
+ DoStrTest(convert("foo %hS"), "bar", "foo bar");
+ DoWStrTest(convert("foo %lS"), convert("bar"), "foo bar");
+ DoWStrTest(convert("foo %wS"), convert("bar"), "foo bar");
+ DoStrTest(convert("foo %LS"), "bar", "foo bar");
+ DoStrTest(convert("foo %I64S"), "bar", "foo bar");
+ DoStrTest(convert("foo %5S"), "bar", "foo bar");
+ DoStrTest(convert("foo %.2S"), "bar", "foo ba");
+ DoStrTest(convert("foo %5.2S"),"bar", "foo ba");
+ DoStrTest(convert("foo %-5S"), "bar", "foo bar ");
+ DoStrTest(convert("foo %05S"), "bar", "foo 00bar");
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fwprintf/test3/testinfo.dat
new file mode 100644
index 0000000000..fa8a0bcf75
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test3/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fwprintf
+Name = Positive Test for fwprintf
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Tests the wide string specifier (%S).
+= This test is modeled after the sprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test4/CMakeLists.txt
new file mode 100644
index 0000000000..b91bc87195
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_fwprintf_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fwprintf_test4 coreclrpal)
+
+target_link_libraries(paltest_fwprintf_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test4/test4.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test4/test4.c
new file mode 100644
index 0000000000..96fb472c3e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test4/test4.c
@@ -0,0 +1,85 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test4.c
+**
+** Purpose: Tests the pointer specifier (%p).
+** This test is modeled after the sprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fwprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ void *ptr = (void*) 0x123456;
+ INT64 lptr = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+/*
+** Run only on 64 bit platforms
+*/
+#if defined(BIT64) && defined(PLATFORM_UNIX)
+ Trace("Testing for 64 Bit Platforms \n");
+ DoPointerTest(convert("%p"), NULL, "NULL", "0000000000000000", "0x0");
+ DoPointerTest(convert("%p"), ptr, "pointer to 0x123456", "0000000000123456",
+ "0x123456");
+ DoPointerTest(convert("%17p"), ptr, "pointer to 0x123456", " 0000000000123456",
+ " 0x123456");
+ DoPointerTest(convert("%17p"), ptr, "pointer to 0x123456", " 0000000000123456",
+ "0x0123456");
+ DoPointerTest(convert("%-17p"), ptr, "pointer to 0x123456", "0000000000123456 ",
+ "0x123456 ");
+ DoPointerTest(convert("%+p"), ptr, "pointer to 0x123456", "0000000000123456",
+ "0x123456");
+ DoPointerTest(convert("%#p"), ptr, "pointer to 0x123456", "0X0000000000123456",
+ "0x123456");
+ DoPointerTest(convert("%lp"), ptr, "pointer to 0x123456", "00123456",
+ "0x123456");
+ DoPointerTest(convert("%hp"), ptr, "pointer to 0x123456", "00003456",
+ "0x3456");
+ DoPointerTest(convert("%Lp"), ptr, "pointer to 0x123456", "00123456",
+ "0x123456");
+ DoI64Test(convert("%I64p"), lptr, "pointer to 0x1234567887654321",
+ "1234567887654321", "0x1234567887654321");
+#else
+ Trace("Testing for Non 64 Bit Platforms \n");
+ DoPointerTest(convert("%p"), NULL, "NULL", "00000000", "0x0");
+ DoPointerTest(convert("%p"), ptr, "pointer to 0x123456", "00123456",
+ "0x123456");
+ DoPointerTest(convert("%9p"), ptr, "pointer to 0x123456", " 00123456",
+ " 0x123456");
+ DoPointerTest(convert("%09p"), ptr, "pointer to 0x123456", " 00123456",
+ "0x0123456");
+ DoPointerTest(convert("%-9p"), ptr, "pointer to 0x123456", "00123456 ",
+ "0x123456 ");
+ DoPointerTest(convert("%+p"), ptr, "pointer to 0x123456", "00123456",
+ "0x123456");
+ DoPointerTest(convert("%#p"), ptr, "pointer to 0x123456", "0X00123456",
+ "0x123456");
+ DoPointerTest(convert("%lp"), ptr, "pointer to 0x123456", "00123456",
+ "0x123456");
+ DoPointerTest(convert("%hp"), ptr, "pointer to 0x123456", "00003456",
+ "0x3456");
+ DoPointerTest(convert("%Lp"), ptr, "pointer to 0x123456", "00123456",
+ "0x123456");
+ DoI64Test(convert("%I64p"), lptr, "pointer to 0x1234567887654321",
+ "1234567887654321", "0x1234567887654321");
+#endif
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test4/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fwprintf/test4/testinfo.dat
new file mode 100644
index 0000000000..92140c29bb
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test4/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fwprintf
+Name = Positive Test for fwprintf
+TYPE = DEFAULT
+EXE1 = test4
+Description
+= Tests the pointer specifier (%p).
+= This test is modeled after the sprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test5/CMakeLists.txt
new file mode 100644
index 0000000000..53bf482b6f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test5.c
+)
+
+add_executable(paltest_fwprintf_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fwprintf_test5 coreclrpal)
+
+target_link_libraries(paltest_fwprintf_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test5/test5.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test5/test5.c
new file mode 100644
index 0000000000..9d95989090
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test5/test5.c
@@ -0,0 +1,63 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test5.c
+**
+** Purpose: Tests the count specifier (%n).
+** This test is modeled after the sprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fwprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR *longStr;
+ char *longResult =
+ "really-long-string-that-just-keeps-going-on-and-on-and-on.."
+ "..................useless-filler.................................."
+ "..................useless-filler.................................."
+ "..................useless-filler.................................."
+ " bar";
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ longStr =
+ convert("really-long-string-that-just-keeps-going-on-and-on-and-on.."
+ "..................useless-filler.................................."
+ "..................useless-filler.................................."
+ "..................useless-filler.................................."
+ "%n bar");
+ DoCountTest(convert("foo %n bar"), 4, "foo bar");
+ DoCountTest(longStr, 257, longResult);
+ DoCountTest(convert("fo%n bar"), 2, "fo bar");
+ DoCountTest(convert("%n foo"), 0, " foo");
+ DoCountTest(convert("foo %#n bar"), 4, "foo bar");
+ DoCountTest(convert("foo % n bar"), 4, "foo bar");
+ DoCountTest(convert("foo %+n bar"), 4, "foo bar");
+ DoCountTest(convert("foo %-n bar"), 4, "foo bar");
+ DoCountTest(convert("foo %0n bar"), 4, "foo bar");
+ DoShortCountTest(convert("foo %hn bar"), 4, "foo bar");
+ DoCountTest(convert("foo %ln bar"), 4, "foo bar");
+ DoCountTest(convert("foo %Ln bar"), 4, "foo bar");
+ DoCountTest(convert("foo %I64n bar"), 4, "foo bar");
+ DoCountTest(convert("foo %20.3n bar"), 4, "foo bar");
+
+ PAL_Terminate();
+
+ free(longStr);
+
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test5/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fwprintf/test5/testinfo.dat
new file mode 100644
index 0000000000..152f56334b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test5/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fwprintf
+Name = Positive Test for fwprintf
+TYPE = DEFAULT
+EXE1 = test5
+Description
+= Tests the count specifier (%n).
+= This test is modeled after the sprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test6/CMakeLists.txt
new file mode 100644
index 0000000000..bf7d7cccb8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test6.c
+)
+
+add_executable(paltest_fwprintf_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fwprintf_test6 coreclrpal)
+
+target_link_libraries(paltest_fwprintf_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test6/test6.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test6/test6.c
new file mode 100644
index 0000000000..160ff524e0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test6/test6.c
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test6.c
+**
+** Purpose: Tests the char specifier (%c).
+** This test is modeled after the sprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fwprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR wb = (WCHAR) 'b';
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoWCharTest(convert("foo %c"), wb, "foo b");
+ DoCharTest(convert("foo %hc"), 'c', "foo c");
+ DoWCharTest(convert("foo %lc"), wb, "foo b");
+ DoWCharTest(convert("foo %Lc"), wb, "foo b");
+ DoWCharTest(convert("foo %I64c"), wb, "foo b");
+ DoWCharTest(convert("foo %5c"), wb, "foo b");
+ DoWCharTest(convert("foo %.0c"), wb, "foo b");
+ DoWCharTest(convert("foo %-5c"), wb, "foo b ");
+ DoWCharTest(convert("foo %05c"), wb, "foo 0000b");
+ DoWCharTest(convert("foo % c"), wb, "foo b");
+ DoWCharTest(convert("foo %#c"), wb, "foo b");
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test6/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fwprintf/test6/testinfo.dat
new file mode 100644
index 0000000000..cc968bdf7f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test6/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fwprintf
+Name = Positive Test for fwprintf
+TYPE = DEFAULT
+EXE1 = test6
+Description
+= Tests the char specifier (%c).
+= This test is modeled after the sprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test7/CMakeLists.txt
new file mode 100644
index 0000000000..68bcc9ca65
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test7/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test7.c
+)
+
+add_executable(paltest_fwprintf_test7
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fwprintf_test7 coreclrpal)
+
+target_link_libraries(paltest_fwprintf_test7
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test7/test7.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test7/test7.c
new file mode 100644
index 0000000000..c5515a8640
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test7/test7.c
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test7.c
+**
+** Purpose: Tests the wide char specifier (%C).
+** This test is modeled after the sprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fwprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR wb = (WCHAR) 'b';
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoCharTest(convert("foo %C"), 'c', "foo c");
+ DoWCharTest(convert("foo %hc"), wb, "foo b");
+ DoCharTest(convert("foo %lC"), 'c', "foo c");
+ DoCharTest(convert("foo %LC"), 'c', "foo c");
+ DoCharTest(convert("foo %I64C"), 'c', "foo c");
+ DoCharTest(convert("foo %5C"), 'c', "foo c");
+ DoCharTest(convert("foo %.0C"), 'c', "foo c");
+ DoCharTest(convert("foo %-5C"), 'c', "foo c ");
+ DoCharTest(convert("foo %05C"), 'c', "foo 0000c");
+ DoCharTest(convert("foo % C"), 'c', "foo c");
+ DoCharTest(convert("foo %#C"), 'c', "foo c");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test7/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fwprintf/test7/testinfo.dat
new file mode 100644
index 0000000000..46cb35cf4b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test7/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fwprintf
+Name = Positive Test for fwprintf
+TYPE = DEFAULT
+EXE1 = test7
+Description
+= Tests the wide char specifier (%C).
+= This test is modeled after the sprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test8/CMakeLists.txt
new file mode 100644
index 0000000000..e07cbb9119
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test8/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test8.c
+)
+
+add_executable(paltest_fwprintf_test8
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fwprintf_test8 coreclrpal)
+
+target_link_libraries(paltest_fwprintf_test8
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test8/test8.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test8/test8.c
new file mode 100644
index 0000000000..efc81a954a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test8/test8.c
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test8.c
+**
+** Purpose: Tests the decimal specifier (%d).
+** This test is modeled after the sprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fwprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoNumTest(convert("foo %d"), pos, "foo 42");
+ DoNumTest(convert("foo %ld"), 0xFFFF, "foo 65535");
+ DoNumTest(convert("foo %hd"), 0xFFFF, "foo -1");
+ DoNumTest(convert("foo %Ld"), pos, "foo 42");
+ DoI64Test(convert("foo %I64d"), l, "42", "foo 42", "foo 42");
+ DoNumTest(convert("foo %3d"), pos, "foo 42");
+ DoNumTest(convert("foo %-3d"), pos, "foo 42 ");
+ DoNumTest(convert("foo %.1d"), pos, "foo 42");
+ DoNumTest(convert("foo %.3d"), pos, "foo 042");
+ DoNumTest(convert("foo %03d"), pos, "foo 042");
+ DoNumTest(convert("foo %#d"), pos, "foo 42");
+ DoNumTest(convert("foo %+d"), pos, "foo +42");
+ DoNumTest(convert("foo % d"), pos, "foo 42");
+ DoNumTest(convert("foo %+d"), neg, "foo -42");
+ DoNumTest(convert("foo % d"), neg, "foo -42");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test8/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fwprintf/test8/testinfo.dat
new file mode 100644
index 0000000000..c8ce33acb9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test8/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fwprintf
+Name = Positive Test for fwprintf
+TYPE = DEFAULT
+EXE1 = test8
+Description
+= Tests the decimal specifier (%d).
+= This test is modeled after the sprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test9/CMakeLists.txt
new file mode 100644
index 0000000000..898da1a64f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test9/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test9.c
+)
+
+add_executable(paltest_fwprintf_test9
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fwprintf_test9 coreclrpal)
+
+target_link_libraries(paltest_fwprintf_test9
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test9/test9.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test9/test9.c
new file mode 100644
index 0000000000..23db2d8971
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test9/test9.c
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test9.c
+**
+** Purpose: Tests the integer specifier (%i).
+** This test is modeled after the sprintf series.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+#include "../fwprintf.h"
+
+/*
+ * Depends on memcmp, strlen, fopen, fseek and fgets.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoNumTest(convert("foo %i"), pos, "foo 42");
+ DoNumTest(convert("foo %li"), 0xFFFF, "foo 65535");
+ DoNumTest(convert("foo %hi"), 0xFFFF, "foo -1");
+ DoNumTest(convert("foo %Li"), pos, "foo 42");
+ DoI64Test(convert("foo %I64i"), l, "42", "foo 42", "foo 42");
+ DoNumTest(convert("foo %3i"), pos, "foo 42");
+ DoNumTest(convert("foo %-3i"), pos, "foo 42 ");
+ DoNumTest(convert("foo %.1i"), pos, "foo 42");
+ DoNumTest(convert("foo %.3i"), pos, "foo 042");
+ DoNumTest(convert("foo %03i"), pos, "foo 042");
+ DoNumTest(convert("foo %#i"), pos, "foo 42");
+ DoNumTest(convert("foo %+i"), pos, "foo +42");
+ DoNumTest(convert("foo % i"), pos, "foo 42");
+ DoNumTest(convert("foo %+i"), neg, "foo -42");
+ DoNumTest(convert("foo % i"), neg, "foo -42");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test9/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fwprintf/test9/testinfo.dat
new file mode 100644
index 0000000000..5c2ec25ab5
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test9/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fwprintf
+Name = Positive Test for fwprintf
+TYPE = DEFAULT
+EXE1 = test9
+Description
+= Tests the integer specifier (%i).
+= This test is modeled after the sprintf series.
diff --git a/src/pal/tests/palsuite/c_runtime/fwrite/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwrite/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwrite/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/fwrite/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwrite/test1/CMakeLists.txt
new file mode 100644
index 0000000000..701e56acb5
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwrite/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_fwrite_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_fwrite_test1 coreclrpal)
+
+target_link_libraries(paltest_fwrite_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/fwrite/test1/test1.c b/src/pal/tests/palsuite/c_runtime/fwrite/test1/test1.c
new file mode 100644
index 0000000000..392522879f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwrite/test1/test1.c
@@ -0,0 +1,104 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Write a short string to a file and check that it was written
+** properly.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ const char filename[] = "testfile.tmp";
+ const char outBuffer[] = "This is a test.";
+ char inBuffer[sizeof(outBuffer) + 10];
+ int itemsExpected;
+ int itemsWritten;
+ FILE * fp = NULL;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ if((fp = fopen(filename, "w")) == NULL)
+ {
+ Fail("Unable to open a file for write.\n");
+ }
+
+ itemsExpected = sizeof(outBuffer);
+ itemsWritten = fwrite(outBuffer,
+ sizeof(outBuffer[0]),
+ sizeof(outBuffer),
+ fp);
+
+ if (itemsWritten == 0)
+ {
+ if(fclose(fp) != 0)
+ {
+ Fail("fwrite: Error occurred during the closing of a file.\n");
+ }
+
+ Fail("fwrite() couldn't write to a stream at all\n");
+ }
+ else if (itemsWritten != itemsExpected)
+ {
+ if(fclose(fp) != 0)
+ {
+ Fail("fwrite: Error occurred during the closing of a file.\n");
+ }
+
+ Fail("fwrite() produced errors writing to a stream.\n");
+ }
+
+ if(fclose(fp) != 0)
+ {
+ Fail("fwrite: Error occurred during the closing of a file.\n");
+ }
+
+ /* open the file to verify what was written to the file */
+ if ((fp = fopen(filename, "r")) == NULL)
+ {
+ Fail("Couldn't open newly written file for read.\n");
+ }
+
+ if (fgets(inBuffer, sizeof(inBuffer), fp) == NULL)
+ {
+ if(fclose(fp) != 0)
+ {
+ Fail("fwrite: Error occurred during the closing of a file.\n");
+ }
+
+ Fail("We wrote something to a file using fwrite() and got errors"
+ " when we tried to read it back using fgets(). Either "
+ "fwrite() or fgets() is broken.\n");
+ }
+
+ if (strcmp(inBuffer, outBuffer) != 0)
+ {
+ if(fclose(fp) != 0)
+ {
+ Fail("fwrite: Error occurred during the closing of a file.\n");
+ }
+
+ Fail("fwrite() (or fgets()) is broken. The string read back from"
+ " the file does not match the string written.\n");
+ }
+
+ if(fclose(fp) != 0)
+ {
+ Fail("fwrite: Error occurred during the closing of a file.\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/fwrite/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/fwrite/test1/testinfo.dat
new file mode 100644
index 0000000000..75ad9ed05d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/fwrite/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = fwrite
+Name = Positive Test for fwrite
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Write a short string to a file and check that it was written properly.
diff --git a/src/pal/tests/palsuite/c_runtime/getc/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/getc/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/getc/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/getc/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/getc/test1/CMakeLists.txt
new file mode 100644
index 0000000000..2a29e8af0a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/getc/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ getc.c
+)
+
+add_executable(paltest_getc_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getc_test1 coreclrpal)
+
+target_link_libraries(paltest_getc_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/getc/test1/getc.c b/src/pal/tests/palsuite/c_runtime/getc/test1/getc.c
new file mode 100644
index 0000000000..dfe10d6160
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/getc/test1/getc.c
@@ -0,0 +1,152 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: getc.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the getc function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ const char szFileName[] = {"testfile.tmp"};
+ const char szTestString[] =
+ {"The quick brown fox jumped over the lazy dog's back."};
+ FILE* pFile = NULL;
+ int nCount = 0;
+ int nChar = 0;
+ char szBuiltString[256];
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ memset(szBuiltString, 0, 256);
+
+
+ /* create/open a file for read and write */
+ pFile = fopen(szFileName, "w+");
+ if (pFile == NULL)
+ {
+ Fail("getc: ERROR -> fopen failed to create the file %s with the "
+ "error code %ld\n",
+ szFileName,
+ GetLastError());
+ }
+
+ /* try reading from an empty file */
+ if ((nChar = getc(pFile)) != EOF)
+ {
+ Trace("getc: ERROR -> getc returned \"%c\" when run on "
+ "an empty file.\n", nChar);
+ if (fclose(pFile) != 0)
+ {
+ Trace("getc: ERROR -> fclose failed to close the file. "
+ "GetLastError returned %ld\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ // Move the file pointer back to the beginning of the file. Some
+ // platforms require an fseek() between a getc() that returns EOF
+ // and any subsequent output to the file.
+ if (fseek(pFile, 0, SEEK_SET) != 0)
+ {
+ Trace("getc: ERROR -> fseek failed to move the file pointer to the "
+ "beginning of the file. GetLastError returned %ld\n",
+ GetLastError());
+ if (fclose(pFile) != 0)
+ {
+ Trace("getc: ERROR -> fclose failed to close the file. "
+ "GetLastError returned %ld\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ /* populate the file with a known string */
+ nCount = fprintf(pFile, szTestString);
+ if (nCount != strlen(szTestString))
+ {
+ Fail("getc: ERROR -> fprintf failed to write %s. The string is %d "
+ "characters long but fprintf apparently only wrote %d characters."
+ " GetLastError returned %ld\n",
+ szTestString,
+ strlen(szTestString),
+ nCount,
+ GetLastError());
+ }
+
+ /* move the file pointer back to the beginning of the file */
+ if (fseek(pFile, 0, SEEK_SET) != 0)
+ {
+ Trace("getc: ERROR -> fseek failed to move the file pointer to the "
+ "beginning of the file. GetLastError returned %ld\n",
+ GetLastError());
+ if (fclose(pFile) != 0)
+ {
+ Trace("getc: ERROR -> fclose failed to close the file. "
+ "GetLastError returned %ld\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ /* now get the characters one at a time */
+ nCount = 0;
+ while ((nChar = getc(pFile)) != EOF)
+ {
+ szBuiltString[nCount++] = nChar;
+ }
+
+ /* now, let's see if it worked */
+ if (strcmp(szBuiltString, szTestString) != 0)
+ {
+ Trace("getc: ERROR -> Reading one char at a time, getc built \"%s\" "
+ "however it should have built \"%s\".\n",
+ szBuiltString,
+ szTestString);
+ if (fclose(pFile) != 0)
+ {
+ Trace("getc: ERROR -> fclose failed to close the file. "
+ "GetLastError returned %ld\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ /* with the file pointer at EOF, try reading past EOF*/
+ if ((nChar = getc(pFile)) != EOF)
+ {
+ Trace("getc: ERROR -> getc returned \"%c\" when reading past "
+ "the end of the file.\n", nChar);
+ if (fclose(pFile) != 0)
+ {
+ Trace("getc: ERROR -> fclose failed to close the file. "
+ "GetLastError returned %ld\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ if (fclose(pFile) != 0)
+ {
+ Fail("getc: ERROR -> fclose failed to close the file. "
+ "GetLastError returned %ld\n",
+ GetLastError());
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/getc/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/getc/test1/testinfo.dat
new file mode 100644
index 0000000000..19a0c1ee1a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/getc/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = getc
+Name = test for getc (test 1)
+Type = DEFAULT
+EXE1 = getc
+Description
+= Write a string to a file, read it in one character
+= at a time with getc and compare with the original string.
+= It also verifies that getc can't read past EOF.
diff --git a/src/pal/tests/palsuite/c_runtime/getenv/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/getenv/CMakeLists.txt
new file mode 100644
index 0000000000..1962ade358
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/getenv/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+
diff --git a/src/pal/tests/palsuite/c_runtime/getenv/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/getenv/test1/CMakeLists.txt
new file mode 100644
index 0000000000..6243c032ab
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/getenv/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_getenv_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getenv_test1 coreclrpal)
+
+target_link_libraries(paltest_getenv_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/getenv/test1/test1.c b/src/pal/tests/palsuite/c_runtime/getenv/test1/test1.c
new file mode 100644
index 0000000000..0fb9025c8f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/getenv/test1/test1.c
@@ -0,0 +1,78 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Create an environment variable and then use getenv to get
+** a pointer to it. Check that the pointer is valid and that the string
+** is what we expected. Also check that searching for a non-existent
+** variable will cause getenv to return NULL. Also check that function
+** passes when the parameter has it's casing changed (e.g upper case)
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+
+ const char* SetVariable = "PalTestingEnvironmentVariable=The value";
+ const char* VariableName = "PalTestingEnvironmentVariable";
+ const char* VariableValue = "The value";
+ char* result;
+
+
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Use _putenv to set an environment variable. This ensures that the
+ variable we're testing on is always present.
+ */
+
+ if(_putenv(SetVariable) == -1)
+ {
+ Fail("ERROR: _putenv failed to set an environment variable that "
+ "getenv will be using for testing.\n");
+ }
+
+ /* Call getenv -- ensure it doesn't return NULL and the string it returns
+ is the value we set above.
+ */
+
+ result = getenv(VariableName);
+ if(result == NULL)
+ {
+ Fail("ERROR: The result of getenv on a valid Environment Variable "
+ "was NULL, which indicates the environment varaible was not "
+ "found.\n");
+ }
+
+ if(strcmp(result, VariableValue) != 0)
+ {
+ Fail("ERROR: The value obtained by getenv() was not equal to the "
+ "correct value of the environment variable. The correct "
+ "value is '%s' and the function returned '%s'.\n",
+ VariableValue,
+ result);
+ }
+
+ /* Try calling getenv on an environment variable which doesn't
+ exist.
+ */
+ result = getenv("SomeEnvironmentVariableThatReallyDoesNotExist");
+
+ if(result != NULL)
+ {
+ Fail("ERROR: Called getenv on an environment variable which "
+ "doesn't exist and it returned '%s' instead of NULL.\n",result);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/getenv/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/getenv/test1/testinfo.dat
new file mode 100644
index 0000000000..b9cbf71986
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/getenv/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = getenv
+Name = Test retrieval of variables correctly, and failure if they don't exist
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Create an environment variable and then use getenv to get
+= a pointer to it. Check that the pointer is valid and that the string
+= is what we expected. Also check that searching for a non-existent
+= variable will cause getenv to return NULL. Also check that changing
+= the case (upper or lower) of a variable does not effect functionality.
diff --git a/src/pal/tests/palsuite/c_runtime/getenv/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/getenv/test2/CMakeLists.txt
new file mode 100644
index 0000000000..7a301a5ca6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/getenv/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_getenv_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getenv_test2 coreclrpal)
+
+target_link_libraries(paltest_getenv_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/getenv/test2/test2.c b/src/pal/tests/palsuite/c_runtime/getenv/test2/test2.c
new file mode 100644
index 0000000000..26f245fcce
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/getenv/test2/test2.c
@@ -0,0 +1,101 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test2.c
+**
+** Purpose: Create environment variables that differ only in Case, and
+** verify that the BSD operating system treats the variables
+** differently.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+#if WIN32
+
+ return PASS;
+
+#else
+
+ const char* FirstVariable = "PalTestingEnvironmentVariable=The value";
+ const char* SecondVariable = "PALTESTINGEnvironmentVariable=Different value";
+ const char* FirstVarName = "PalTestingEnvironmentVariable";
+ const char* SecondVarName = "PALTESTINGEnvironmentVariable";
+ const char* FirstVarValue = "The value";
+ const char* SecondVarValue = "Different value";
+ char* result;
+
+
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Use _putenv to set the environment variables. This ensures that the
+ variables we're testing with are always present.
+ */
+ if(_putenv(FirstVariable) != 0)
+ {
+ Fail("ERROR: _putenv failed to set an environment variable that "
+ "getenv will be using for testing.\n");
+ }
+
+ if(_putenv(SecondVariable) != 0)
+ {
+ Fail("ERROR: _putenv failed to set an environment variable that "
+ "getenv will be using for testing.\n");
+ }
+
+
+ /* Call getenv -- ensure it doesn't return NULL and the string it returns
+ is the value we set above. Also make sure that each environment variable,
+ differing only by case, returns it's own value.
+ */
+
+ result = getenv(FirstVarName);
+ if(result == NULL)
+ {
+ Fail("ERROR: The result of getenv on a valid Environment Variable "
+ "was NULL, which indicates the environment varaible was not "
+ "found.\n");
+ }
+
+ if(strcmp(result, FirstVarValue) != 0)
+ {
+ Fail("ERROR: The value obtained by getenv() was not equal to the "
+ "correct value of the environment variable. The correct "
+ "value is '%s' and the function returned '%s'.\n",
+ FirstVarValue,
+ result);
+ }
+
+
+ result = getenv(SecondVarName);
+ if(result == NULL)
+ {
+ Fail("ERROR: The result of getenv on a valid Environment Variable "
+ "was NULL, which indicates the environment varaible was not "
+ "found.\n");
+ }
+
+ if(strcmp(result, SecondVarValue) != 0)
+ {
+ Fail("ERROR: The value obtained by getenv() was not equal to the "
+ "correct value of the environment variable. The correct "
+ "value is '%s' and the function returned '%s'.\n",
+ SecondVarValue,
+ result);
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+#endif
+}
diff --git a/src/pal/tests/palsuite/c_runtime/getenv/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/getenv/test2/testinfo.dat
new file mode 100644
index 0000000000..90a4ac5aff
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/getenv/test2/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = getenv
+Name = Test retrieval of variables differing only by case.
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Check that environment variables differing only by their
+= case are interpreted as separate variables by the BSD Operationg
+= System.
diff --git a/src/pal/tests/palsuite/c_runtime/getenv/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/getenv/test3/CMakeLists.txt
new file mode 100644
index 0000000000..2cbe472221
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/getenv/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_getenv_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getenv_test3 coreclrpal)
+
+target_link_libraries(paltest_getenv_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/getenv/test3/test3.c b/src/pal/tests/palsuite/c_runtime/getenv/test3/test3.c
new file mode 100644
index 0000000000..1eefd9d40c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/getenv/test3/test3.c
@@ -0,0 +1,75 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test3.c
+**
+** Purpose: Create an environment variable and try to retrieve
+** it using the same name but with different case. This
+** is to show that the Win32 representation of getenv
+** is case insensitive.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+#if WIN32
+
+ const char* FirstVariable = "PalTestingEnvironmentVariable=The value";
+ const char* ModifiedName = "PALTESTINGEnvironmentVariable";
+ const char* FirstVarValue = "The value";
+ char* result;
+
+
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Use _putenv to set an environment variable. This ensures that the
+ variable we're testing on is always present.
+ */
+
+ if(_putenv(FirstVariable) != 0)
+ {
+ Fail("ERROR: _putenv failed to set an environment variable that "
+ "getenv will be using for testing.\n");
+ }
+
+
+ /* Call getenv -- ensure it doesn't return NULL and the string it returns
+ is the value we set above. Also make sure that each environment variable,
+ differing only by case, doesn't affect the return value.
+ */
+
+ result = getenv(ModifiedName);
+ if(result == NULL)
+ {
+ Fail("ERROR: The result of getenv on a valid Environment Variable "
+ "was NULL, which indicates the environment varaible was not "
+ "found.\n");
+ }
+
+ if(strcmp(result, FirstVarValue) != 0)
+ {
+ Fail("ERROR: The value obtained by getenv() was not equal to the "
+ "correct value of the environment variable. The correct "
+ "value is '%s' and the function returned '%s'.\n",
+ FirstVarValue,
+ result);
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+#else
+ return PASS;
+
+#endif
+}
diff --git a/src/pal/tests/palsuite/c_runtime/getenv/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/getenv/test3/testinfo.dat
new file mode 100644
index 0000000000..6e12fc4385
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/getenv/test3/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = getenv
+Name = Test retrieval of variables differing only by case.
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Check that environment variables differing only by their
+= case are interpreted as the same variables in the WIN32
+= platform.
diff --git a/src/pal/tests/palsuite/c_runtime/isalnum/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/isalnum/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/isalnum/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/isalnum/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/isalnum/test1/CMakeLists.txt
new file mode 100644
index 0000000000..3879bb7902
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/isalnum/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_isalnum_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_isalnum_test1 coreclrpal)
+
+target_link_libraries(paltest_isalnum_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/isalnum/test1/test1.c b/src/pal/tests/palsuite/c_runtime/isalnum/test1/test1.c
new file mode 100644
index 0000000000..d9cdfcadf6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/isalnum/test1/test1.c
@@ -0,0 +1,88 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests the PAL implementation of the isalnum function
+** Check that a number of characters return the correct
+** values for whether they are alpha/numeric or not.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+struct testCase
+{
+ int CorrectResult;
+ int character;
+};
+
+int __cdecl main(int argc, char **argv)
+{
+
+ int result;
+ int i;
+
+ struct testCase testCases[] =
+ {
+ {1, 'a'},
+ {1, 'z'},
+ {1, 'B'},
+ {1, '5'},
+ {1, '0'},
+ {0, '?'},
+ {0, 230}
+ };
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /* Loop through each case. Check to see if each is alpha/numeric or
+ not.
+ */
+
+ for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++)
+ {
+
+ result = isalnum(testCases[i].character);
+
+ /* The return value is 'non-zero' for success. This if condition
+ * will still work if that non-zero isn't just 1
+ */
+ if ( ((testCases[i].CorrectResult == 1) && (result == 0)) ||
+ ( (testCases[i].CorrectResult == 0) && (result != 0) ))
+ {
+ Fail("ERROR: isalnum returned %i instead of %i for character "
+ " %c.\n",
+ result,
+ testCases[i].CorrectResult,
+ testCases[i].character);
+ }
+
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/isalnum/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/isalnum/test1/testinfo.dat
new file mode 100644
index 0000000000..ba8f07a722
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/isalnum/test1/testinfo.dat
@@ -0,0 +1,19 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = isalnum
+Name = Positive Test for isalnum
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests the PAL implementation of the isalnum function
+= Check that a number of characters return the correct values for whether
+= they are alpha/numeric or not.
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/isalpha/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/isalpha/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/isalpha/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/isalpha/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/isalpha/test1/CMakeLists.txt
new file mode 100644
index 0000000000..44fb72d7fe
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/isalpha/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_isalpha_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_isalpha_test1 coreclrpal)
+
+target_link_libraries(paltest_isalpha_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/isalpha/test1/test1.c b/src/pal/tests/palsuite/c_runtime/isalpha/test1/test1.c
new file mode 100644
index 0000000000..b494d14a92
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/isalpha/test1/test1.c
@@ -0,0 +1,86 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests the PAL implementation of the isalpha function
+** Check that a number of characters return the correct
+** values for whether they are alpha or not.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+struct testCase
+{
+ int CorrectResult;
+ int character;
+};
+
+int __cdecl main(int argc, char **argv)
+{
+
+ int result;
+ int i;
+
+ struct testCase testCases[] =
+ {
+ {1, 'a'},
+ {1, 'z'},
+ {1, 'B'},
+ {0, '5'},
+ {0, '?'},
+ {0, 230}
+ };
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /* Loop through each case. Check to see if each is alpha or
+ not.
+ */
+
+ for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++)
+ {
+
+ result = isalpha(testCases[i].character);
+
+ /* The return value is 'non-zero' for success. This if condition
+ * will still work if that non-zero isn't just 1
+ */
+ if ( ((testCases[i].CorrectResult == 1) && (result == 0)) ||
+ ( (testCases[i].CorrectResult == 0) && (result != 0) ))
+ {
+ Fail("ERROR: isalpha returned %i instead of %i for character "
+ "%c.\n",
+ result,
+ testCases[i].CorrectResult,
+ testCases[i].character);
+ }
+
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/isalpha/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/isalpha/test1/testinfo.dat
new file mode 100644
index 0000000000..7d508366e8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/isalpha/test1/testinfo.dat
@@ -0,0 +1,19 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = isalpha
+Name = Positive Test for isalpha
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests the PAL implementation of the isalpha function
+= Check that a number of characters return the correct values for whether
+= they are alpha or not.
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/isdigit/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/isdigit/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/isdigit/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/isdigit/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/isdigit/test1/CMakeLists.txt
new file mode 100644
index 0000000000..dd03b238e1
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/isdigit/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_isdigit_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_isdigit_test1 coreclrpal)
+
+target_link_libraries(paltest_isdigit_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/isdigit/test1/test1.c b/src/pal/tests/palsuite/c_runtime/isdigit/test1/test1.c
new file mode 100644
index 0000000000..ad2344827f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/isdigit/test1/test1.c
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Checks every character against the known range of digits.
+**
+**
+**==========================================================================*/
+
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int i;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ for (i=0; i<256; i++)
+ {
+ if (isdigit(i))
+ {
+ if (i < '0' || i > '9')
+ {
+ Fail("ERROR: isdigit returned true for '%c' (%d)!\n", i, i);
+ }
+ }
+ else
+ {
+ if (i >= '0' && i <= '9')
+ {
+ Fail("ERROR: isdigit returned false for '%c' (%d)!\n", i, i);
+ }
+ }
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/isdigit/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/isdigit/test1/testinfo.dat
new file mode 100644
index 0000000000..eb23739164
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/isdigit/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = isdigit
+Name = Test #1 for isdigit
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Checks every character against the known range of digits.
diff --git a/src/pal/tests/palsuite/c_runtime/islower/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/islower/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/islower/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/islower/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/islower/test1/CMakeLists.txt
new file mode 100644
index 0000000000..b7f5ad069f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/islower/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_islower_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_islower_test1 coreclrpal)
+
+target_link_libraries(paltest_islower_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/islower/test1/test1.c b/src/pal/tests/palsuite/c_runtime/islower/test1/test1.c
new file mode 100644
index 0000000000..c8e877b705
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/islower/test1/test1.c
@@ -0,0 +1,85 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests the PAL implementation of the islower function
+** Check that a number of characters return the correct
+** values for whether they are lower case or not.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+struct testCase
+{
+ int CorrectResult;
+ int character;
+};
+
+int __cdecl main(int argc, char **argv)
+{
+
+ int result;
+ int i;
+
+ struct testCase testCases[] =
+ {
+ {1, 'a'}, /* Basic cases */
+ {1, 'z'},
+ {0, 'B'}, /* Lower case */
+ {0, '?'}, /* Characters without case */
+ {0, 230},
+ {0, '5'}
+ };
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /* Loop through each case. Check to see if each is lower case or
+ not.
+ */
+
+ for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++)
+ {
+
+ result = islower(testCases[i].character);
+
+ /* The return value is 'non-zero' for success. This if condition
+ * will still work if that non-zero isn't just 1
+ */
+ if ( ((testCases[i].CorrectResult == 1) && (result == 0)) ||
+ ( (testCases[i].CorrectResult == 0) && (result != 0) ))
+ {
+ Fail("ERROR: islower returned %i instead of %i for "
+ "character %c.\n",
+ result, testCases[i].CorrectResult,
+ testCases[i].character);
+ }
+
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/islower/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/islower/test1/testinfo.dat
new file mode 100644
index 0000000000..49a6fb761d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/islower/test1/testinfo.dat
@@ -0,0 +1,19 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = islower
+Name = Positive Test for islower
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests the PAL implementation of the islower function
+= Check that a number of characters return the correct values for whether
+= they are lower case or not.
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/isprint/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/isprint/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/isprint/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/c_runtime/isprint/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/isprint/test1/CMakeLists.txt
new file mode 100644
index 0000000000..365777ab5a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/isprint/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ isprint.c
+)
+
+add_executable(paltest_isprint_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_isprint_test1 coreclrpal)
+
+target_link_libraries(paltest_isprint_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/isprint/test1/isprint.c b/src/pal/tests/palsuite/c_runtime/isprint/test1/isprint.c
new file mode 100644
index 0000000000..54db666bf2
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/isprint/test1/isprint.c
@@ -0,0 +1,42 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: isprint.c
+**
+** Purpose: Positive test the isprint API.
+** Call isprint to test if a character is printable
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ int index;
+
+ /*Initialize the PAL environment*/
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+ /*check if the character is printable*/
+ for(index = 0x20; index<=0x7E;index++)
+ {
+ err = isprint(index);
+ if(0 == err)
+ {
+ Fail("\nFailed to call isprint API to check "
+ "printable character from 0x20 to 0x7E!\n");
+ }
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/isprint/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/isprint/test1/testinfo.dat
new file mode 100644
index 0000000000..c9b9ec07ea
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/isprint/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = miscellaneous
+Function = isprint
+Name = Positive test for isprint API to check if a character is printable
+TYPE = DEFAULT
+EXE1 = isprint
+Description
+=Test the isprint to check if a character is printable
diff --git a/src/pal/tests/palsuite/c_runtime/isprint/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/isprint/test2/CMakeLists.txt
new file mode 100644
index 0000000000..a7ad75cc04
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/isprint/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_isprint_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_isprint_test2 coreclrpal)
+
+target_link_libraries(paltest_isprint_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/isprint/test2/test2.c b/src/pal/tests/palsuite/c_runtime/isprint/test2/test2.c
new file mode 100644
index 0000000000..2170c47a14
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/isprint/test2/test2.c
@@ -0,0 +1,59 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: isprint.c
+**
+** Purpose: Negative test for the isprint API. Call isprint
+** to test if out of range characters are
+** not printable.
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+
+ /*Initialize the PAL environment*/
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+ /*check that function fails for values that are not printable*/
+ err = isprint(0x15);
+ if(err)
+ {
+ Fail("\nSucceeded when it should have failed because 0x15 "
+ "is not in the range of printable characters\n");
+ }
+
+ err = isprint(0xAA);
+ if(err)
+ {
+ Fail("\nSucceeded when it should have failed because 0xAA "
+ "is not in the range of printable characters\n");
+ }
+
+ /* check carriage return */
+ if(0 != isprint(0x0d))
+ {
+ Fail("\nSucceeded when it should have failed because 0x0d "
+ "is not in the range of printable characters\n");
+ }
+
+ /* check line feed */
+ if(0 != isprint(0x0a))
+ {
+ Fail("\nSucceeded when it should have failed because 0x0a "
+ "is not in the range of printable characters\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/isprint/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/isprint/test2/testinfo.dat
new file mode 100644
index 0000000000..e115278edb
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/isprint/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = miscellaneous
+Function = isprint
+Name = Test isprint API to check if out of range characters are not printable.
+TYPE = DEFAULT
+EXE1 = test2
+Description
+=Test the isprint function to verify that out of range characters
+=are not printable.
diff --git a/src/pal/tests/palsuite/c_runtime/isspace/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/isspace/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/isspace/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/isspace/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/isspace/test1/CMakeLists.txt
new file mode 100644
index 0000000000..34ad70d328
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/isspace/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_isspace_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_isspace_test1 coreclrpal)
+
+target_link_libraries(paltest_isspace_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/isspace/test1/test1.c b/src/pal/tests/palsuite/c_runtime/isspace/test1/test1.c
new file mode 100644
index 0000000000..6cd1ce878b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/isspace/test1/test1.c
@@ -0,0 +1,82 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test #1 for the isspace function
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+
+struct testCase
+{
+ long result;
+ char avalue;
+};
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int i=0;
+ long result = 0;
+
+ /*
+ * A structures of the testcases to be tested with
+ * isspace function
+ */
+ struct testCase testCases[] =
+ {
+ {1,'\n'},
+ {1,'\t'},
+ {1,'\r'},
+ {1,'\v'},
+ {1,'\f'},
+ {1,' '},
+ {0,'a'},
+ {0,'A'},
+ {0,'z'},
+ {0,'Z'},
+ {0,'r'},
+ {0,'R'},
+ {0,'0'},
+ {0,'*'},
+ {0,3}
+ };
+
+ /*
+ * Initialize the PAL
+ */
+ if ( 0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /* Loop through the testcases */
+ for (i=0; i<sizeof(testCases)/sizeof(struct testCase); i++)
+ {
+ result = isspace(testCases[i].avalue);
+ if ( ((testCases[i].result == 1) && (result==0)) ||
+ ((testCases[i].result ==0) && (result !=0)) )
+ {
+ Fail("ERROR: isspace() returned %d for %c instead of %d\n",
+ result,
+ testCases[i].avalue,
+ testCases[i].result );
+ }
+ }
+
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/isspace/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/isspace/test1/testinfo.dat
new file mode 100644
index 0000000000..fe9926e8c8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/isspace/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = isspace
+Name = Positive Test for isspace
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Run through every possible character. For each time that isspace returns
+= >0, check through a list of the known space characters to ensure that it
+= is really a space. Also, when it returns <=0, ensure that that character
+= isn't a space.
diff --git a/src/pal/tests/palsuite/c_runtime/isupper/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/isupper/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/isupper/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/isupper/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/isupper/test1/CMakeLists.txt
new file mode 100644
index 0000000000..c7fc71c43b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/isupper/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_isupper_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_isupper_test1 coreclrpal)
+
+target_link_libraries(paltest_isupper_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/isupper/test1/test1.c b/src/pal/tests/palsuite/c_runtime/isupper/test1/test1.c
new file mode 100644
index 0000000000..b88bcc4a7e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/isupper/test1/test1.c
@@ -0,0 +1,88 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests the PAL implementation of the isupper function
+** Check that a number of characters return the correct
+** values for whether they are upper case or not.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+struct testCase
+{
+ int CorrectResult;
+ int character;
+};
+
+int __cdecl main(int argc, char **argv)
+{
+
+ int result;
+ int i;
+
+ /* Note: 1 iff char = A..Z
+ 0 iff char =~ A..Z
+ */
+
+ struct testCase testCases[] =
+ {
+ {1, 'A'}, /* Basic cases */
+ {1, 'Z'},
+ {0, 'b'}, /* Lower case */
+ {0, '?'}, /* Characters without case */
+ {0, 230},
+ {0, '5'}
+ };
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /* Loop through each case. Check to see if each is upper case or
+ not.
+ */
+
+ for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++)
+ {
+ result = isupper(testCases[i].character);
+
+ /* The return value is 'non-zero' for success. This if condition
+ * will still work if that non-zero isn't just 1
+ */
+ if ( ((testCases[i].CorrectResult == 1) && (result == 0)) ||
+ ( (testCases[i].CorrectResult == 0) && (result != 0) ))
+ {
+ Fail("ERROR: isupper returned %i instead of %i for "
+ "character %c.\n",
+ result,testCases[i].CorrectResult,
+ testCases[i].character);
+ }
+
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/isupper/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/isupper/test1/testinfo.dat
new file mode 100644
index 0000000000..fb2648a526
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/isupper/test1/testinfo.dat
@@ -0,0 +1,19 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = isupper
+Name = Positive Test for isupper
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests the PAL implementation of the isupper function
+= Check that a number of characters return the correct values for whether
+= they are upper case or not.
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/iswdigit/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/iswdigit/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/iswdigit/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/iswdigit/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/iswdigit/test1/CMakeLists.txt
new file mode 100644
index 0000000000..b35dd5ed6d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/iswdigit/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_iswdigit_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_iswdigit_test1 coreclrpal)
+
+target_link_libraries(paltest_iswdigit_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/iswdigit/test1/test1.c b/src/pal/tests/palsuite/c_runtime/iswdigit/test1/test1.c
new file mode 100644
index 0000000000..1cf94c5d13
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/iswdigit/test1/test1.c
@@ -0,0 +1,69 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c (iswdigit)
+**
+** Purpose: Tests the PAL implementation of the iswdigit function.
+** Tests the passed parameter to iswdigit for being a
+** digit ('0' - '9'). Also passes non-digits to make sure
+** iswdigit picks them up.
+** NOTE: There are three ASCII values that under Windows,
+** iswdigit will return non-zero, indicating a digit.
+** These values are quite apparently not digits:
+** 178, 179, 185.
+** These are not tested.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+
+ int result;
+ int i;
+
+ wchar_t passTestCases[] = {'1','2','3','4','5','6','7','8','9'};
+ wchar_t failTestCases[] = {'a','b','p','$','?',234};
+
+ if ((PAL_Initialize(argc, argv)) != 0)
+ {
+ return (FAIL);
+ }
+
+ /* Loop through each case. Testing if each is a digit. */
+ for(i = 0; i < sizeof(passTestCases) / sizeof(wchar_t); i++)
+ {
+ result = iswdigit(passTestCases[i]);
+
+ /* The return value is 'non-zero' indicates digit*/
+ if (result == 0)
+ {
+ Fail("ERROR: iswdigit returned \"%d\" instead indicating"
+ " \"%c\" is not a digit\n",
+ result,
+ passTestCases[i]);
+ }
+ }
+
+ /* Loop through each case. Testing if each is a not a digit. */
+ for(i = 0; i < sizeof(failTestCases) / sizeof(wchar_t); i++)
+ {
+ result = iswdigit(failTestCases[i]);
+
+ /* The return value is 'zero' indicates non-digit*/
+ if (result != 0)
+ {
+ Fail("ERROR: iswdigit returned \"%d\", indicating"
+ " \"%c\" is a digit\n",
+ result,
+ failTestCases[i]);
+ }
+ }
+ PAL_Terminate();
+ return (PASS);
+}
diff --git a/src/pal/tests/palsuite/c_runtime/iswdigit/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/iswdigit/test1/testinfo.dat
new file mode 100644
index 0000000000..345c9d5661
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/iswdigit/test1/testinfo.dat
@@ -0,0 +1,19 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = iswdigit
+Name = Positive Test for iswdigit
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests the PAL implementation of the iswdigit function.
+= Tests the passed parameter to iswdigit for being a
+= digit ('0' - '9'). Also passes non-digits to make sure
+= iswdigit picks them up.
+= NOTE: There are three ASCII values that under Windows,
+= iswdigit will return non-zero, indicating a digit.
+= These values are quite apparently not digits:
+= 178, 179, 185. These are not tested.
diff --git a/src/pal/tests/palsuite/c_runtime/iswprint/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/iswprint/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/iswprint/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/iswprint/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/iswprint/test1/CMakeLists.txt
new file mode 100644
index 0000000000..5e436c3ca2
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/iswprint/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_iswprint_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_iswprint_test1 coreclrpal)
+
+target_link_libraries(paltest_iswprint_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/iswprint/test1/test1.c b/src/pal/tests/palsuite/c_runtime/iswprint/test1/test1.c
new file mode 100644
index 0000000000..08a985b2d6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/iswprint/test1/test1.c
@@ -0,0 +1,59 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests iswprint with all wide characters, ensuring they are
+** consistent with GetStringTypeExW.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ WORD Info;
+ int ret;
+ int i;
+ WCHAR ch;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ for (i=0; i<=0xFFFF; i++)
+ {
+ ch = i;
+ ret = GetStringTypeExW(LOCALE_USER_DEFAULT, CT_CTYPE1, &ch, 1, &Info);
+ if (!ret)
+ {
+ Fail("GetStringTypeExW failed to get information for %#X!\n", ch);
+ }
+
+ ret = iswprint(ch);
+ if (Info & (C1_BLANK|C1_PUNCT|C1_ALPHA|C1_DIGIT))
+ {
+ if (!ret)
+ {
+ Fail("iswprint returned incorrect results for %#X: "
+ "expected printable\n", ch);
+ }
+ }
+ else
+ {
+ if (ret)
+ {
+ Fail("iswprint returned incorrect results for %#X: "
+ "expected non-printable\n", ch);
+ }
+ }
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/iswprint/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/iswprint/test1/testinfo.dat
new file mode 100644
index 0000000000..c425967b97
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/iswprint/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = iswprint
+Name = Positive Test for iswprint
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Tests iswprint with all wide characters, ensuring they are
+=consistent with GetStringTypeExW.
diff --git a/src/pal/tests/palsuite/c_runtime/iswspace/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/iswspace/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/iswspace/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/iswspace/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/iswspace/test1/CMakeLists.txt
new file mode 100644
index 0000000000..1368e55ccc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/iswspace/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_iswspace_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_iswspace_test1 coreclrpal)
+
+target_link_libraries(paltest_iswspace_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/iswspace/test1/test1.c b/src/pal/tests/palsuite/c_runtime/iswspace/test1/test1.c
new file mode 100644
index 0000000000..c58997812e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/iswspace/test1/test1.c
@@ -0,0 +1,78 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests iswspace with a range of wide characters.
+**
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int ret;
+ int i;
+
+ struct testChars
+ {
+ WCHAR charValue;
+ int result;
+ };
+
+ /* create an array of chars that test the range of possible characters */
+ struct testChars testChars1[] =
+ {
+ {0x00,0}, /* null */
+ {0x09,1}, /* open circle */
+ {0x0D,1}, /* musical note */
+ {0x20,1}, /* space */
+ {0x3F,0}, /* ? */
+ {0x5E,0}, /* ^ */
+ {0x7B,0}, /* { */
+ {0x86,0}, /* a with circle on top */
+ {0x9F,0}, /* slanted f */
+ {0xC4,0}, /* long dash */
+ {0xE5,0} /* sigma */
+ };
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ for (i = 0; i < (sizeof(testChars1) / sizeof(struct testChars)); i++)
+ {
+
+ ret = iswspace(testChars1[i].charValue);
+
+ if((ret==0) && (testChars1[i].result != 0))
+ {
+ Fail("ERROR: wide character %#X IS considered a space, "
+ "but iswspace did NOT indicate it was one with error %u.\n",
+ testChars1[i].charValue,
+ GetLastError());
+ }
+
+ if((ret!=0) && (testChars1[i].result == 0))
+ {
+ Fail("ERROR: wide character %#X is NOT considered a space, "
+ "but iswspace DID indicate it was a space with error %u.\n",
+ testChars1[i].charValue,
+ GetLastError());
+ }
+ }
+
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/iswspace/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/iswspace/test1/testinfo.dat
new file mode 100644
index 0000000000..0368052b91
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/iswspace/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = iswspace
+Name = Positive Test for iswspace
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Tests iswspace with a range of wide characters.
diff --git a/src/pal/tests/palsuite/c_runtime/iswupper/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/iswupper/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/iswupper/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/iswupper/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/iswupper/test1/CMakeLists.txt
new file mode 100644
index 0000000000..8b8fae6d72
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/iswupper/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_iswupper_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_iswupper_test1 coreclrpal)
+
+target_link_libraries(paltest_iswupper_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/iswupper/test1/test1.c b/src/pal/tests/palsuite/c_runtime/iswupper/test1/test1.c
new file mode 100644
index 0000000000..a01686be44
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/iswupper/test1/test1.c
@@ -0,0 +1,91 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests the PAL implementation of the iswupper function
+** Check that a number of characters return the correct
+** values for whether they are upper case or not.
+**
+**
+**===================================================================*/
+
+#define UNICODE
+#include <palsuite.h>
+
+
+struct testCase
+{
+ int CorrectResult;
+ WCHAR character;
+};
+
+int __cdecl main(int argc, char **argv)
+{
+
+ int result;
+ int i;
+
+ /* Note: 1 iff char = A..Z
+ 0 iff char =~ A..Z
+ */
+
+ struct testCase testCases[] =
+ {
+ {1, 'A'}, /* Basic cases */
+ {1, 'Z'},
+ {0, 'b'}, /* Lower case */
+ {0, '?'}, /* Characters without case */
+ {0, 230}
+ };
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /* Loop through each case. Check to see if each is upper case or
+ not.
+ */
+
+ for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++)
+ {
+
+ result = iswupper(testCases[i].character);
+
+ /* The return value is 'non-zero' for success. This if condition
+ * will still work if that non-zero isn't just 1
+ */
+ if ( ((testCases[i].CorrectResult == 1) && (result == 0)) ||
+ ( (testCases[i].CorrectResult == 0) && (result != 0) ))
+ {
+ Fail("ERROR: iswupper returned %i instead of %i for "
+ "character %c.\n",
+ result,
+ testCases[i].CorrectResult,
+ testCases[i].character);
+ }
+
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/iswupper/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/iswupper/test1/testinfo.dat
new file mode 100644
index 0000000000..22131e40ac
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/iswupper/test1/testinfo.dat
@@ -0,0 +1,19 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = isupper
+Name = Positive Test for iswupper
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests the PAL implementation of the iswupper function
+= Check that a number of characters return the correct values for whether
+= they are upper case or not.
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/iswxdigit/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/iswxdigit/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/iswxdigit/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/iswxdigit/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/iswxdigit/test1/CMakeLists.txt
new file mode 100644
index 0000000000..3a726eced9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/iswxdigit/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_iswxdigit_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_iswxdigit_test1 coreclrpal)
+
+target_link_libraries(paltest_iswxdigit_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/iswxdigit/test1/test1.c b/src/pal/tests/palsuite/c_runtime/iswxdigit/test1/test1.c
new file mode 100644
index 0000000000..73ad495856
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/iswxdigit/test1/test1.c
@@ -0,0 +1,61 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests iswxdigit with every possible wide character, ensuring it
+** returns the correct results.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+/*
+ * These are the only wide characters Win2000 recogonizes as valid hex digits.
+ */
+WCHAR ValidHexDigits[] =
+{
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 97, 98, 99, 100,
+ 101, 102, 65296, 65297, 65298, 65299, 65300, 65301, 65302, 65303, 65304, 65305,
+ 65313, 65314, 65315, 65316, 65317, 65318, 65345, 65346, 65347, 65348, 65349, 65350,
+ 0
+};
+
+int __cdecl main(int argc, char **argv)
+{
+ int i;
+ WCHAR c;
+ int ret;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ for (i=0; i<=0xFFFF; i++)
+ {
+ ret = iswxdigit(i);
+ c = (WCHAR) i;
+
+ if (ret)
+ {
+ if (wcschr(ValidHexDigits, c) == NULL)
+ {
+ /* iswxdigit says its a hex digit. We know better */
+ Fail("iswxdigit incorrectly found %#x to be a hex digit!\n", c);
+ }
+ }
+ else if (wcschr(ValidHexDigits, c) != NULL && c != 0)
+ {
+ /* iswxdigit says it isn't a hex digit. We know better */
+ Fail("iswxdigit failed to find %#x to be a hex digit!\n", c);
+ }
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/iswxdigit/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/iswxdigit/test1/testinfo.dat
new file mode 100644
index 0000000000..2b683c4eb7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/iswxdigit/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = iswxdigit
+Name = iswxdigit test #1
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Tests iswxdigit with every possible wide character, ensuring it
+=returns the correct results.
+
diff --git a/src/pal/tests/palsuite/c_runtime/isxdigit/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/isxdigit/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/isxdigit/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/isxdigit/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/isxdigit/test1/CMakeLists.txt
new file mode 100644
index 0000000000..8919b36e42
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/isxdigit/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_isxdigit_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_isxdigit_test1 coreclrpal)
+
+target_link_libraries(paltest_isxdigit_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/isxdigit/test1/test1.c b/src/pal/tests/palsuite/c_runtime/isxdigit/test1/test1.c
new file mode 100644
index 0000000000..be25af233c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/isxdigit/test1/test1.c
@@ -0,0 +1,58 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Run through every possible character. For each time that
+** isxdigit returns:
+** 1, check through a list of the known hex characters to ensure that it
+** is really a hex char. Also, when it returns 0, ensure that that character
+** isn't a hex character.
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int i;
+
+ /* Initialize the PAL */
+ if ( 0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /* Loop through each character and call isxdigit for each character */
+ for (i=1; i<256; i++)
+ {
+
+ if (isxdigit(i) == 0)
+ {
+ if( ((i>=48) && (i<=57)) || ((i>=97) && (i<=102)) ||
+ ((i>=65) && (i<=70)) )
+ {
+ Fail("ERROR: isxdigit() returns true for '%c' (%d)\n", i, i);
+ }
+ }
+ else
+ {
+ if( ((i<48) && (i>58)) || ((i<97) && (i>102)) ||
+ ((i<65) && (i>70)) )
+ {
+ Fail("ERROR: isxdigit() returns false for '%c' (%d)\n", i, i);
+ }
+ }
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/isxdigit/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/isxdigit/test1/testinfo.dat
new file mode 100644
index 0000000000..fd031f0768
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/isxdigit/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = isxdigit
+Name = Positive Test for isxdigit
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Run through every possible character. For each time that isxdigit returns
+= 1, check through a list of the known hex characters to ensure that it
+= is really a hex char. Also, when it returns 0, ensure that that character
+= isn't a hex character.
diff --git a/src/pal/tests/palsuite/c_runtime/labs/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/labs/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/labs/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/labs/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/labs/test1/CMakeLists.txt
new file mode 100644
index 0000000000..cf0f0999a9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/labs/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_labs_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_labs_test1 coreclrpal)
+
+target_link_libraries(paltest_labs_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/labs/test1/test1.c b/src/pal/tests/palsuite/c_runtime/labs/test1/test1.c
new file mode 100644
index 0000000000..41f85226e1
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/labs/test1/test1.c
@@ -0,0 +1,65 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Call labs on a series of values -- negative, positive, zero,
+** and the largest negative value of a LONG. Ensure that they are all
+** changed properly to their absoulte value.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+struct testCase
+{
+ LONG LongValue;
+ LONG AbsoluteLongValue;
+};
+
+int __cdecl main(int argc, char **argv)
+{
+
+ LONG result=0;
+ int i=0;
+
+ struct testCase testCases[] =
+ {
+ {1234, 1234},
+ {-1234, 1234},
+ {0, 0},
+ {-2147483647, 2147483647}, /* Max value to abs */
+ {2147483647, 2147483647}
+ };
+
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Loop through each case. Call labs on each LONG and ensure that
+ the resulting value is correct.
+ */
+
+ for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++)
+ {
+ /* Absolute value on a LONG */
+ result = labs(testCases[i].LongValue);
+
+ if (testCases[i].AbsoluteLongValue != result)
+ {
+ Fail("ERROR: labs took the absoulte value of '%d' to be '%d' "
+ "instead of %d.\n",
+ testCases[i].LongValue,
+ result,
+ testCases[i].AbsoluteLongValue);
+ }
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/labs/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/labs/test1/testinfo.dat
new file mode 100644
index 0000000000..c385aa76b6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/labs/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = labs
+Name = Series of tests for labs: positive, negative, zero, maximum long value.
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Call labs on a series of values -- negative, positive, zero,
+= and the largest negative value of a long. Ensure that they are all
+= changed properly to their absoulte value.
diff --git a/src/pal/tests/palsuite/c_runtime/llabs/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/llabs/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/llabs/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/llabs/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/llabs/test1/CMakeLists.txt
new file mode 100644
index 0000000000..8f5bdbe097
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/llabs/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_llabs_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_llabs_test1 coreclrpal)
+
+target_link_libraries(paltest_llabs_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/llabs/test1/test1.c b/src/pal/tests/palsuite/c_runtime/llabs/test1/test1.c
new file mode 100644
index 0000000000..044e22f134
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/llabs/test1/test1.c
@@ -0,0 +1,65 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Call llabs on a series of values -- negative, positive,
+** zero, and the largest negative value of an __int64. Ensure that
+** they are all changed properly to their absoulte value.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+struct testCase
+{
+ __int64 LongLongValue;
+ __int64 AbsoluteLongLongValue;
+};
+
+int __cdecl main(int argc, char **argv)
+{
+
+ __int64 result=0;
+ int i=0;
+
+ struct testCase testCases[] =
+ {
+ {1234, 1234},
+ {-1234, 1234},
+ {0, 0},
+ {-9223372036854775807LL, 9223372036854775807LL}, /* Max value to abs */
+ {9223372036854775807LL, 9223372036854775807LL}
+ };
+
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Loop through each case. Call llabs on each __int64 and ensure that
+ the resulting value is correct.
+ */
+
+ for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++)
+ {
+ /* Absolute value on an __int64 */
+ result = llabs(testCases[i].LongLongValue);
+
+ if (testCases[i].AbsoluteLongLongValue != result)
+ {
+ Fail("ERROR: llabs took the absoulte value of '%d' to be '%d' "
+ "instead of %d.\n",
+ testCases[i].LongLongValue,
+ result,
+ testCases[i].AbsoluteLongLongValue);
+ }
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/llabs/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/llabs/test1/testinfo.dat
new file mode 100644
index 0000000000..b1b76377bf
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/llabs/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = labs
+Name = Series of tests for labs: positive, negative, zero, maximum __int64 value.
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Call llabs on a series of values -- negative, positive, zero,
+= and the largest negative value of an __int64. Ensure that they are all
+= changed properly to their absoulte value.
diff --git a/src/pal/tests/palsuite/c_runtime/localtime/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/localtime/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/localtime/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/localtime/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/localtime/test1/CMakeLists.txt
new file mode 100644
index 0000000000..25acf48749
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/localtime/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_localtime_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_localtime_test1 coreclrpal)
+
+target_link_libraries(paltest_localtime_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/localtime/test1/test1.c b/src/pal/tests/palsuite/c_runtime/localtime/test1/test1.c
new file mode 100644
index 0000000000..a993a17f69
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/localtime/test1/test1.c
@@ -0,0 +1,69 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c (localtime)
+**
+** Purpose: Tests the PAL implementation of the localtime function.
+** localtime() is passed a date in seconds, since January 01
+** 1970 midnight, UTC. localtime() converts the time to the
+** tm struct, those values are tested for validity.
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ time_t dates[] ={1003327482, // Oct 17, 2001 10:04:42 am
+ 701307301, // March 22, 1992 6:35:01 pm
+ 973620900, // Nov 07, 2000 1:15:00 pm
+ 924632589, // April 20, 1999 2:23:09 pm
+ 951934989}; // March 01, 2000 1:23:09 pm
+ struct tm * converted_date;
+ int i;
+
+ if (PAL_Initialize(argc, argv) != 0)
+
+ return (FAIL);
+
+ /*Convert from time_t to struct tm*/
+ for ( i=0; i < (sizeof(dates)/sizeof(time_t)); i++)
+ {
+ converted_date = localtime(&dates[i]);
+
+ if ((converted_date->tm_hour < 0) || (converted_date->tm_hour > 23))
+ {
+ Fail("ERROR: localtime returned %d for tm_hour\n", converted_date->tm_hour);
+ }
+ if ((converted_date->tm_mday < 1) || (converted_date->tm_mday > 31))
+ {
+ Fail("ERROR: localtime returned %d for tm_mday\n",converted_date->tm_mday);
+ }
+ if ((converted_date->tm_min < 0) || (converted_date->tm_min > 59))
+ {
+ Fail("ERROR: localtime returned %d for tm_min\n",converted_date->tm_min);
+ }
+ if ((converted_date->tm_mon < 0) || (converted_date->tm_mon > 11))
+ {
+ Fail("ERROR: localtime returned %d for tm_mon\n",converted_date->tm_mon);
+ }
+ if ((converted_date->tm_sec < 0) || (converted_date->tm_sec > 59))
+ {
+ Fail("ERROR: localtime returned %d for tm_sec\n",converted_date->tm_sec);
+ }
+ if ((converted_date->tm_wday < 0) || (converted_date->tm_wday > 6 ))
+ {
+ Fail("ERROR: localtime returned %d for tm_wday\n",converted_date->tm_wday);
+ }
+ if ((converted_date->tm_yday < 0) || (converted_date->tm_yday > 365))
+ {
+ Fail("ERROR: localtime returned %d for tm_yday\n",converted_date->tm_yday);
+ }
+ }
+
+ PAL_Terminate();
+ return (PASS);
+}
diff --git a/src/pal/tests/palsuite/c_runtime/localtime/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/localtime/test1/testinfo.dat
new file mode 100644
index 0000000000..63f7fcda93
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/localtime/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = localtime
+Name = Positive Test for localtime
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests the PAL implementation of the localtime function.
+= localtime() is passed a date in seconds, since January 01
+= 1970 midnight, UTC. localtime() converts the time to the
+= tm struct, those values are tested for validity.
diff --git a/src/pal/tests/palsuite/c_runtime/log/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/log/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/log/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/log/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/log/test1/CMakeLists.txt
new file mode 100644
index 0000000000..dd19002904
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/log/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_log_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_log_test1 coreclrpal)
+
+target_link_libraries(paltest_log_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/log/test1/test1.c b/src/pal/tests/palsuite/c_runtime/log/test1/test1.c
new file mode 100644
index 0000000000..eea592dd45
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/log/test1/test1.c
@@ -0,0 +1,140 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests log with a normal set of values.
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (15-17 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use
+// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx
+// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will
+// use PAL_EPSILON * 10.
+#define PAL_EPSILON 8.8817841970012523e-16
+
+#define PAL_NAN sqrt(-1.0)
+#define PAL_POSINF -log(0.0)
+#define PAL_NEGINF log(0.0)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ double value; /* value to test the function with */
+ double expected; /* expected result */
+ double variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(double value, double expected, double variance)
+{
+ double result = log(value);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ double delta = fabs(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("log(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(double value)
+{
+ double result = log(value);
+
+ if (!_isnan(result))
+ {
+ Fail("log(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char **argv)
+{
+ struct test tests[] =
+ {
+ /* value expected variance */
+ { 0, PAL_NEGINF, 0 },
+ { 0.043213918263772250, -3.1415926535897932, PAL_EPSILON * 10 }, // expected: -(pi)
+ { 0.065988035845312537, -2.7182818284590452, PAL_EPSILON * 10 }, // expected: -(e)
+ { 0.1, -2.3025850929940457, PAL_EPSILON * 10 }, // expected: -(ln(10))
+ { 0.20787957635076191, -1.5707963267948966, PAL_EPSILON * 10 }, // expected: -(pi / 2)
+ { 0.23629008834452270, -1.4426950408889634, PAL_EPSILON * 10 }, // expected: -(log2(e))
+ { 0.24311673443421421, -1.4142135623730950, PAL_EPSILON * 10 }, // expected: -(sqrt(2))
+ { 0.32355726390307110, -1.1283791670955126, PAL_EPSILON * 10 }, // expected: -(2 / sqrt(pi))
+ { 0.36787944117144232, -1, PAL_EPSILON * 10 }, // expected: -(1)
+ { 0.45593812776599624, -0.78539816339744831, PAL_EPSILON }, // expected: -(pi / 4)
+ { 0.49306869139523979, -0.70710678118654752, PAL_EPSILON }, // expected: -(1 / sqrt(2))
+ { 0.5, -0.69314718055994531, PAL_EPSILON }, // expected: -(ln(2))
+ { 0.52907780826773535, -0.63661977236758134, PAL_EPSILON }, // expected: -(2 / pi)
+ { 0.64772148514180065, -0.43429448190325183, PAL_EPSILON }, // expected: -(log10(e))
+ { 0.72737734929521647, -0.31830988618379067, PAL_EPSILON }, // expected: -(1 / pi)
+ { 1, 0, PAL_EPSILON },
+ { 1.3748022274393586, 0.31830988618379067, PAL_EPSILON }, // expected: 1 / pi
+ { 1.5438734439711811, 0.43429448190325183, PAL_EPSILON }, // expected: log10(e)
+ { 1.8900811645722220, 0.63661977236758134, PAL_EPSILON }, // expected: 2 / pi
+ { 2, 0.69314718055994531, PAL_EPSILON }, // expected: ln(2)
+ { 2.0281149816474725, 0.70710678118654752, PAL_EPSILON }, // expected: 1 / sqrt(2)
+ { 2.1932800507380155, 0.78539816339744831, PAL_EPSILON }, // expected: pi / 4
+ { 2.7182818284590452, 1, PAL_EPSILON * 10 }, // value: e
+ { 3.0906430223107976, 1.1283791670955126, PAL_EPSILON * 10 }, // expected: 2 / sqrt(pi)
+ { 4.1132503787829275, 1.4142135623730950, PAL_EPSILON * 10 }, // expected: sqrt(2)
+ { 4.2320861065570819, 1.4426950408889634, PAL_EPSILON * 10 }, // expected: log2(e)
+ { 4.8104773809653517, 1.5707963267948966, PAL_EPSILON * 10 }, // expected: pi / 2
+ { 10, 2.3025850929940457, PAL_EPSILON * 10 }, // expected: ln(10)
+ { 15.154262241479264, 2.7182818284590452, PAL_EPSILON * 10 }, // expected: e
+ { 23.140692632779269, 3.1415926535897932, PAL_EPSILON * 10 }, // expected: pi
+ { PAL_POSINF, PAL_POSINF, 0 },
+ };
+
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate(tests[i].value, tests[i].expected, tests[i].variance);
+ }
+
+ validate_isnan(PAL_NEGINF);
+ validate_isnan(PAL_NAN);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/log/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/log/test1/testinfo.dat
new file mode 100644
index 0000000000..6b984f6eba
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/log/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = log
+Name = Positive Test for log
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes a series of values to the log() function,
+= checking each for the expected result. Also checks
+= for proper handling of out-of-range values.
diff --git a/src/pal/tests/palsuite/c_runtime/log10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/log10/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/log10/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/log10/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/log10/test1/CMakeLists.txt
new file mode 100644
index 0000000000..31e750df3e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/log10/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_log10_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_log10_test1 coreclrpal)
+
+target_link_libraries(paltest_log10_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/log10/test1/test1.c b/src/pal/tests/palsuite/c_runtime/log10/test1/test1.c
new file mode 100644
index 0000000000..13711a752e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/log10/test1/test1.c
@@ -0,0 +1,146 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test to ensure that log10 returns correct values.
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** fabs
+** _isnan
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (15-17 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use
+// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx
+// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will
+// use PAL_EPSILON * 10.
+#define PAL_EPSILON 8.8817841970012523e-16
+
+#define PAL_NAN sqrt(-1.0)
+#define PAL_POSINF -log(0.0)
+#define PAL_NEGINF log(0.0)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ double value; /* value to test the function with */
+ double expected; /* expected result */
+ double variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(double value, double expected, double variance)
+{
+ double result = log10(value);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ double delta = fabs(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("log10(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(double value)
+{
+ double result = log10(value);
+
+ if (!_isnan(result))
+ {
+ Fail("log10(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char **argv)
+{
+ struct test tests[] =
+ {
+ /* value expected variance */
+ { 0, PAL_NEGINF, 0 },
+ { 0.00072178415907472774, -3.1415926535897932, PAL_EPSILON * 10 }, // expected: -(pi)
+ { 0.0019130141022243176, -2.7182818284590452, PAL_EPSILON * 10 }, // expected: -(e)
+ { 0.0049821282964407206, -2.3025850929940457, PAL_EPSILON * 10 }, // expected: -(ln(10))
+ { 0.026866041001136132, -1.5707963267948966, PAL_EPSILON * 10 }, // expected: -(pi / 2)
+ { 0.036083192820787210, -1.4426950408889634, PAL_EPSILON * 10 }, // expected: -(log2(e))
+ { 0.038528884700322026, -1.4142135623730950, PAL_EPSILON * 10 }, // expected: -(sqrt(2))
+ { 0.074408205860642723, -1.1283791670955126, PAL_EPSILON * 10 }, // expected: -(2 / sqrt(pi))
+ { 0.1, -1, PAL_EPSILON * 10 }, // expected: -(1)
+ { 0.16390863613957665, -0.78539816339744831, PAL_EPSILON }, // expected: -(pi / 4)
+ { 0.19628775993505562, -0.70710678118654752, PAL_EPSILON }, // expected: -(1 / sqrt(2))
+ { 0.20269956628651730, -0.69314718055994531, PAL_EPSILON }, // expected: -(ln(2))
+ { 0.23087676451600055, -0.63661977236758134, PAL_EPSILON }, // expected: -(2 / pi)
+ { 0.36787944117144232, -0.43429448190325183, PAL_EPSILON }, // expected: -(log10(e))
+ { 0.48049637305186868, -0.31830988618379067, PAL_EPSILON }, // expected: -(1 / pi)
+ { 1, 0, PAL_EPSILON },
+ { 2.0811811619898573, 0.31830988618379067, PAL_EPSILON }, // expected: 1 / pi
+ { 2.7182818284590452, 0.43429448190325183, PAL_EPSILON }, // expected: log10(e) value: e
+ { 4.3313150290214525, 0.63661977236758134, PAL_EPSILON }, // expected: 2 / pi
+ { 4.9334096679145963, 0.69314718055994531, PAL_EPSILON }, // expected: ln(2)
+ { 5.0945611704512962, 0.70710678118654752, PAL_EPSILON }, // expected: 1 / sqrt(2)
+ { 6.1009598002416937, 0.78539816339744831, PAL_EPSILON }, // expected: pi / 4
+ { 10, 1, PAL_EPSILON * 10 },
+ { 13.439377934644400, 1.1283791670955126, PAL_EPSILON * 10 }, // expected: 2 / sqrt(pi)
+ { 25.954553519470081, 1.4142135623730950, PAL_EPSILON * 10 }, // expected: sqrt(2)
+ { 27.713733786437790, 1.4426950408889634, PAL_EPSILON * 10 }, // expected: log2(e)
+ { 37.221710484165167, 1.5707963267948966, PAL_EPSILON * 10 }, // expected: pi / 2
+ { 200.71743249053009, 2.3025850929940457, PAL_EPSILON * 10 }, // expected: ln(10)
+ { 522.73529967043665, 2.7182818284590452, PAL_EPSILON * 10 }, // expected: e
+ { 1385.4557313670111, 3.1415926535897932, PAL_EPSILON * 10 }, // expected: pi
+ { PAL_POSINF, PAL_POSINF, 0 },
+ };
+
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate(tests[i].value, tests[i].expected, tests[i].variance);
+ }
+
+ validate_isnan(PAL_NEGINF);
+ validate_isnan(PAL_NAN);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/log10/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/log10/test1/testinfo.dat
new file mode 100644
index 0000000000..887bace692
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/log10/test1/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = log10
+Name = Positive Test for log10
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes a series of values to the log10() function,
+= checking each for the expected result. Also checks
+= for proper handling of out-of-range values.
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/malloc/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/malloc/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/malloc/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/c_runtime/malloc/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/malloc/test1/CMakeLists.txt
new file mode 100644
index 0000000000..4a388ad3d7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/malloc/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_malloc_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_malloc_test1 coreclrpal)
+
+target_link_libraries(paltest_malloc_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/malloc/test1/test1.c b/src/pal/tests/palsuite/c_runtime/malloc/test1/test1.c
new file mode 100644
index 0000000000..7ea4dd068f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/malloc/test1/test1.c
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test that malloc returns useable memory
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char **argv)
+{
+
+ char *testA;
+ int i;
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* check that malloc really gives us addressable memory */
+ testA = (char *)malloc(20 * sizeof(char));
+ if (testA == NULL)
+ {
+ Fail("Call to malloc failed.\n");
+ }
+ for (i = 0; i < 20; i++)
+ {
+ testA[i] = 'a';
+ }
+ for (i = 0; i < 20; i++)
+ {
+ if (testA[i] != 'a')
+ {
+ Fail("The memory doesn't seem to be properly allocated.\n");
+ }
+ }
+ free(testA);
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/malloc/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/malloc/test1/testinfo.dat
new file mode 100644
index 0000000000..9060bc6284
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/malloc/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = malloc
+Name = Positive Test for malloc
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests that malloc properly allocates memory.
diff --git a/src/pal/tests/palsuite/c_runtime/malloc/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/malloc/test2/CMakeLists.txt
new file mode 100644
index 0000000000..abbed2aa62
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/malloc/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_malloc_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_malloc_test2 coreclrpal)
+
+target_link_libraries(paltest_malloc_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/malloc/test2/test2.c b/src/pal/tests/palsuite/c_runtime/malloc/test2/test2.c
new file mode 100644
index 0000000000..5deee0eddb
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/malloc/test2/test2.c
@@ -0,0 +1,41 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test2.c
+**
+** Purpose: Test that malloc(0) returns non-zero value
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char **argv)
+{
+
+ char *testA;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* check that malloc(0) returns non-zero value */
+ testA = (char *)malloc(0);
+ if (testA == NULL)
+ {
+ Fail("Call to malloc(0) failed.\n");
+ }
+
+ free(testA);
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/malloc/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/malloc/test2/testinfo.dat
new file mode 100644
index 0000000000..1212a8f8f9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/malloc/test2/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = malloc
+Name = Positive Test for malloc
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Test that malloc(0) returns non-zero value
diff --git a/src/pal/tests/palsuite/c_runtime/memchr/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/memchr/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/memchr/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/memchr/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/memchr/test1/CMakeLists.txt
new file mode 100644
index 0000000000..4e33a8fc04
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/memchr/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_memchr_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_memchr_test1 coreclrpal)
+
+target_link_libraries(paltest_memchr_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/memchr/test1/test1.c b/src/pal/tests/palsuite/c_runtime/memchr/test1/test1.c
new file mode 100644
index 0000000000..043a6789d8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/memchr/test1/test1.c
@@ -0,0 +1,122 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests the PAL implementation of the memchr function.
+** Create a string buffer, and check for a number of
+** characters in it. Test to ensure it returns NULL if
+** it can't find the character, and that the size argument
+** works properly.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+struct testCase
+{
+ char *result;
+ char string[50];
+ int character;
+ int length;
+};
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int i = 0;
+ char *result = NULL;
+
+ /*
+ * this structure includes several strings to be tested with
+ * memchr function and the expected results
+ */
+
+ struct testCase testCases[]=
+ {
+ {"st","corn cup cat cream coast",'s',23},
+ /* single instance of char */
+ {"st","corn cup cat cream coast",'s',24},
+ /* single inst, inst< exact length */
+ {"q","corn cup cat cream coastq",'q',25},
+ /* single inst at end, inst=exact length */
+ {"q","corn cup cat cream coastq",'q',26},
+ /* single inst at end, inst<length,
+ length>len(string) */
+ {"st","corn cup cat cream coast",115,24},
+ /* single int inst, inst<exact length */
+ {"corn cup cat cream coast","corn cup cat cream coast",'c',24},
+ /* multi-inst, inst=1, exact length */
+ {"corn cup cat cream coast","corn cup cat cream coast",'c',1},
+ /* multi-inst, inst = length, length=1 */
+ {"is is a test","This is a test",105,14},
+ /* single int inst, exact length */
+ {"is is a test","This is a test",'i',14},
+ /* double inst, exact length */
+ {"a test","This is a test",'a',9},
+ /* single instance instance = length */
+ {NULL,"This is a test",'b',14},
+ /* no instance exact length */
+ {NULL,"This is a test",'a',8},
+ /* single instance - < length */
+ {NULL,"This is a test",121,14},
+ /* single instance - exact length */
+ {" is a test of the function","This is a test of the function",
+ ' ',17} /* single inst<length, len(string)>length */
+ };
+
+
+ /* Initialize the PAL */
+ if ( 0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Loop through the testcases in the structure */
+ for (i=0; i< sizeof(testCases)/sizeof(struct testCase); i++)
+ {
+ /* Need to type cast function in order to compare the result */
+ result = (char *)memchr(testCases[i].string,
+ testCases[i].character,testCases[i].length);
+
+ if (result==NULL)
+ {
+ if (testCases[i].result != NULL)
+ {
+ Fail("ERROR: Expected memcmp to return \"%s\" instead of"
+ " NULL\n", testCases[i].result);
+ }
+ }
+ else
+ {
+ if (strcmp(result,testCases[i].result)!=0 )
+
+ {
+ Fail("ERROR: Expected memcmp to return \"%s\" instead of"
+ " \"%s\"\n", testCases[i].result, result);
+ }
+
+ }
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/memchr/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/memchr/test1/testinfo.dat
new file mode 100644
index 0000000000..fc2a8e95dc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/memchr/test1/testinfo.dat
@@ -0,0 +1,19 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = memchr
+Name = Positive Test for memchr
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Create a string buffer, and check for a number of characters in it.
+= Test to ensure it returns NULL if it can't find the character, and that
+= the size argument works properly.
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/memcmp/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/memcmp/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/memcmp/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/memcmp/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/memcmp/test1/CMakeLists.txt
new file mode 100644
index 0000000000..b61f208f34
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/memcmp/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_memcmp_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_memcmp_test1 coreclrpal)
+
+target_link_libraries(paltest_memcmp_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/memcmp/test1/test1.c b/src/pal/tests/palsuite/c_runtime/memcmp/test1/test1.c
new file mode 100644
index 0000000000..7b63173e22
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/memcmp/test1/test1.c
@@ -0,0 +1,57 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Check that memcmp find identical buffers to be identical,
+** and that it correctly orders different buffers.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+
+ char testA[] = "aaaaaaaaaaaaaaaaaaaa";
+ char testB[] = "aaaaaaaaaaaaaaaaaaaa";
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ if (!(memcmp(testA, testB, 20) == 0))
+ {
+ Fail("memcmp compared two identical buffers and found them to "
+ "differ.\n");
+ }
+ testB[3] = 'b';
+
+ if (!(memcmp(testA, testB, 20) < 0)
+ || !(memcmp(testB, testA, 20) >0 ))
+ {
+ Fail("memcmp compared two buffers with different contents, and"
+ " did not order them correctly.\n");
+ }
+
+ if (memcmp(testA, testB, 0) != 0)
+ {
+ Fail("memcmp didn't return 0 when comparing buffers of length 0.\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/memcmp/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/memcmp/test1/testinfo.dat
new file mode 100644
index 0000000000..2de36b2dd6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/memcmp/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = memcmp
+Name = Positive Test for memcmp
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Check that memcmp find identical buffers to be identical,
+= and that it correctly orders different buffers.
diff --git a/src/pal/tests/palsuite/c_runtime/memcpy/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/memcpy/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/memcpy/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/memcpy/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/memcpy/test1/CMakeLists.txt
new file mode 100644
index 0000000000..d846bfc62d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/memcpy/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_memcpy_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_memcpy_test1 coreclrpal)
+
+target_link_libraries(paltest_memcpy_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/memcpy/test1/test1.c b/src/pal/tests/palsuite/c_runtime/memcpy/test1/test1.c
new file mode 100644
index 0000000000..9da98d6573
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/memcpy/test1/test1.c
@@ -0,0 +1,87 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Calls memcpy and verifies that the buffer was copied correctly.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ char testA[20];
+ char testB[20];
+ void *retVal;
+ long i;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ memset(testA, 'a', 20);
+ memset(testB, 'b', 20);
+
+ retVal = (char *)memcpy(testB, testA, 0);
+ if (retVal != testB)
+ {
+ Fail("memcpy should return a pointer to the destination buffer, "
+ "but doesn't.\n");
+ }
+ for(i = 0; i<20; i++)
+ {
+ if (testB[i]!= 'b')
+ {
+ Fail("The destination buffer overflowed by memcpy.\n");
+ }
+ }
+
+ retVal = (char *)memcpy(testB+1, testA, 18);
+ if (retVal != testB+1)
+ {
+ Fail("memcpy should return a pointer to the destination buffer, "
+ "but doesn't.\n");
+ }
+
+ if (testB[0] != 'b' || testB[19] != 'b')
+ {
+ Fail("The destination buffer was written out of bounds by memcpy!\n");
+ }
+
+ for(i = 1; i<19; i++)
+ {
+ if (testB[i]!= 'a')
+ {
+ Fail("The destination buffer copied to by memcpy doesn't match "
+ "the source buffer.\n");
+ }
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/memcpy/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/memcpy/test1/testinfo.dat
new file mode 100644
index 0000000000..157da6cf87
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/memcpy/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = memcpy
+Name = Positive Test for memcpy
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Calls memcpy and verifies that the buffer was copied correctly.
diff --git a/src/pal/tests/palsuite/c_runtime/memmove/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/memmove/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/memmove/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/memmove/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/memmove/test1/CMakeLists.txt
new file mode 100644
index 0000000000..cf50ec01b7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/memmove/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_memmove_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_memmove_test1 coreclrpal)
+
+target_link_libraries(paltest_memmove_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/memmove/test1/test1.c b/src/pal/tests/palsuite/c_runtime/memmove/test1/test1.c
new file mode 100644
index 0000000000..c1af871f4a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/memmove/test1/test1.c
@@ -0,0 +1,116 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test that memmove correctly copies text from one buffer
+** to another even when the buffers overlap.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ char testA[11] = "abcdefghij";
+ char testB[15] = "aabbccddeeffgg";
+ char testC[15] = "aabbccddeeffgg";
+ char testD[15] = "aabbccddeeffgg";
+ char insString[3] = "zzz";
+ char *retVal;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* move a string onto itself */
+ retVal = (char *)memmove(testA + 2, testA, 8);
+ if (retVal != testA + 2)
+ {
+ Fail("The return value should have been the value of the destination"
+ "pointer, but wasn't\n");
+ }
+
+ /*Check the most likely error*/
+ if (memcmp(testA, "ababababab", 11) == 0)
+ {
+ Fail("memmove should have saved the characters in the region of"
+ " overlap between source and destination, but didn't.\n");
+ }
+
+ if (memcmp(testA, "ababcdefgh", 11) != 0)
+ {
+ /* not sure what exactly went wrong. */
+ Fail("memmove was called on a region containing the characters"
+ " \"abcdefghij\". It was to move the first 8 positions to"
+ " the last 8 positions, giving the result \"ababcdefgh\". "
+ " Instead, it gave the result \"%s\".\n", testA);
+ }
+
+ /* move a string to the front of testB */
+ retVal = (char *)memmove(testB, insString, 3);
+ if(retVal != testB)
+ {
+ Fail("memmove: The function did not return the correct "
+ "string.\n");
+ }
+
+ if(memcmp(testB, "zzzbccddeeffgg",15) != 0)
+ {
+ Fail("memmove: The function failed to move the string "
+ "correctly.\n");
+ }
+
+
+ /* move a string to the middle of testC */
+ retVal = memmove(testC+5, insString, 3);
+ if(retVal != testC+5)
+ {
+ Fail("memmove: The function did not return the correct "
+ "string.\n");
+ }
+
+ if(memcmp(testC, "aabbczzzeeffgg",15) != 0)
+ {
+ Fail("memmove: The function failed to move the string "
+ "correctly.\n");
+ }
+
+
+ /* move a string to the end of testD */
+ retVal = memmove(testD+11, insString, 3);
+ if(retVal != testD+11)
+ {
+ Fail("memmove: The function did not return the correct "
+ "string.\n");
+ }
+
+ if(memcmp(testD, "aabbccddeefzzz",15) != 0)
+ {
+ Fail("memmove: The function failed to move the string "
+ "correctly.\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/memmove/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/memmove/test1/testinfo.dat
new file mode 100644
index 0000000000..d8d4c0ead9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/memmove/test1/testinfo.dat
@@ -0,0 +1,19 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = memmove
+Name = Positive Test for memmove
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Test that memmove correctly copies text from one buffer to another
+= even when the buffers overlap.
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/memset/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/memset/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/memset/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/memset/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/memset/test1/CMakeLists.txt
new file mode 100644
index 0000000000..78b5a6bc00
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/memset/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_memset_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_memset_test1 coreclrpal)
+
+target_link_libraries(paltest_memset_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/memset/test1/test1.c b/src/pal/tests/palsuite/c_runtime/memset/test1/test1.c
new file mode 100644
index 0000000000..67cde8756b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/memset/test1/test1.c
@@ -0,0 +1,60 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Check that memset correctly fills a destination buffer
+** without overflowing it.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+
+ char testA[22] = "bbbbbbbbbbbbbbbbbbbbb";
+ char *retVal;
+
+ int i;
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ retVal = (char *)memset(testA, 'a', 20);
+ if (retVal != testA)
+ {
+ Fail("memset should have returned the value of the destination"
+ "pointer, but didn't");
+ }
+
+ for(i = 0; i<20; i++)
+ {
+ if (testA[i]!= 'a')
+ {
+ Fail("memset didn't set the destination bytes.\n");
+ }
+ }
+ if (testA[20] == 'a')
+ {
+ Fail("memset overfilled the destination buffer.\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/memset/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/memset/test1/testinfo.dat
new file mode 100644
index 0000000000..cab02fb4b7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/memset/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = memset
+Name = Positive Test for memset
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Check that memset correctly fills a destination buffer without overflowing it.
+
diff --git a/src/pal/tests/palsuite/c_runtime/modf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/modf/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/modf/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/modf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/modf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..4b65ba7a6f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/modf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_modf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_modf_test1 coreclrpal)
+
+target_link_libraries(paltest_modf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/modf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/modf/test1/test1.c
new file mode 100644
index 0000000000..389d079253
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/modf/test1/test1.c
@@ -0,0 +1,136 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c (modf)
+**
+** Purpose: Test to ensure that modf return the correct values
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** fabs
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (15-17 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use
+// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx
+// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will
+// use PAL_EPSILON * 10.
+#define PAL_EPSILON 8.8817841970012523e-16
+
+#define PAL_NAN sqrt(-1.0)
+#define PAL_POSINF -log(0.0)
+#define PAL_NEGINF log(0.0)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ double value; /* value to test the function with */
+ double expected; /* expected result */
+ double variance; /* maximum delta between the expected and actual result */
+ double expected_intpart; /* expected result */
+ double variance_intpart; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(double value, double expected, double variance, double expected_intpart, double variance_intpart)
+{
+ double result_intpart;
+ double result = modf(value, &result_intpart);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ double delta = fabs(result - expected);
+ double delta_intpart = fabs(result_intpart - expected_intpart);
+
+ if ((delta > variance) || (delta_intpart > variance_intpart))
+ {
+ Fail("modf(%g) returned %20.17g with an intpart of %20.17g when it should have returned %20.17g with an intpart of %20.17g",
+ value, result, result_intpart, expected, expected_intpart);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(double value)
+{
+ double result_intpart;
+ double result = modf(value, &result_intpart);
+
+ if (!_isnan(result) || !_isnan(result_intpart))
+ {
+ Fail("modf(%g) returned %20.17g with an intpart of %20.17g when it should have returned %20.17g with an intpart of %20.17g",
+ value, result, result_intpart, PAL_NAN, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char **argv)
+{
+ struct test tests[] =
+ {
+ /* value expected variance expected_intpart variance_intpart */
+ { 0, 0, PAL_EPSILON, 0, PAL_EPSILON },
+ { 0.31830988618379067, 0.31830988618379067, PAL_EPSILON, 0, PAL_EPSILON }, // value: 1 / pi
+ { 0.43429448190325183, 0.43429448190325183, PAL_EPSILON, 0, PAL_EPSILON }, // value: log10(e)
+ { 0.63661977236758134, 0.63661977236758134, PAL_EPSILON, 0, PAL_EPSILON }, // value: 2 / pi
+ { 0.69314718055994531, 0.69314718055994531, PAL_EPSILON, 0, PAL_EPSILON }, // value: ln(2)
+ { 0.70710678118654752, 0.70710678118654752, PAL_EPSILON, 0, PAL_EPSILON }, // value: 1 / sqrt(2)
+ { 0.78539816339744831, 0.78539816339744831, PAL_EPSILON, 0, PAL_EPSILON }, // value: pi / 4
+ { 1, 0, PAL_EPSILON, 1, PAL_EPSILON * 10 },
+ { 1.1283791670955126, 0.1283791670955126, PAL_EPSILON, 1, PAL_EPSILON * 10 }, // value: 2 / sqrt(pi)
+ { 1.4142135623730950, 0.4142135623730950, PAL_EPSILON, 1, PAL_EPSILON * 10 }, // value: sqrt(2)
+ { 1.4426950408889634, 0.4426950408889634, PAL_EPSILON, 1, PAL_EPSILON * 10 }, // value: log2(e)
+ { 1.5707963267948966, 0.5707963267948966, PAL_EPSILON, 1, PAL_EPSILON * 10 }, // value: pi / 2
+ { 2.3025850929940457, 0.3025850929940457, PAL_EPSILON, 2, PAL_EPSILON * 10 }, // value: ln(10)
+ { 2.7182818284590452, 0.7182818284590452, PAL_EPSILON, 2, PAL_EPSILON * 10 }, // value: e
+ { 3.1415926535897932, 0.1415926535897932, PAL_EPSILON, 3, PAL_EPSILON * 10 }, // value: pi
+ { PAL_POSINF, 0, PAL_EPSILON, PAL_POSINF, 0 }
+
+ };
+
+ /* PAL initialization */
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate( tests[i].value, tests[i].expected, tests[i].variance, tests[i].expected_intpart, tests[i].variance_intpart);
+ validate(-tests[i].value, -tests[i].expected, tests[i].variance, -tests[i].expected_intpart, tests[i].variance_intpart);
+ }
+
+ validate_isnan(PAL_NAN);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/modf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/modf/test1/testinfo.dat
new file mode 100644
index 0000000000..203b553e20
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/modf/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = modf
+Name = Positive Test for modf
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes to modf() a series of values, checking that
+= each one return to correct value.
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/modff/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/modff/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/modff/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/modff/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/modff/test1/CMakeLists.txt
new file mode 100644
index 0000000000..812cd1c47b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/modff/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_modff_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_modff_test1 coreclrpal)
+
+target_link_libraries(paltest_modff_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/modff/test1/test1.c b/src/pal/tests/palsuite/c_runtime/modff/test1/test1.c
new file mode 100644
index 0000000000..6b7a50be39
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/modff/test1/test1.c
@@ -0,0 +1,135 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c (modf)
+**
+** Purpose: Test to ensure that modf return the correct values
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** fabs
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (6-9 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON
+// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use
+// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10.
+#define PAL_EPSILON 4.76837158e-07
+
+#define PAL_NAN sqrt(-1.0)
+#define PAL_POSINF -log(0.0)
+#define PAL_NEGINF log(0.0)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ float value; /* value to test the function with */
+ float expected; /* expected result */
+ float variance; /* maximum delta between the expected and actual result */
+ float expected_intpart; /* expected result */
+ float variance_intpart; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(float value, float expected, float variance, float expected_intpart, float variance_intpart)
+{
+ float result_intpart;
+ float result = modff(value, &result_intpart);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ float delta = fabsf(result - expected);
+ float delta_intpart = fabsf(result_intpart - expected_intpart);
+
+ if ((delta > variance) || (delta_intpart > variance_intpart))
+ {
+ Fail("modff(%g) returned %10.9g with an intpart of %10.9g when it should have returned %10.9g with an intpart of %10.9g",
+ value, result, result_intpart, expected, expected_intpart);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(float value)
+{
+ float result_intpart;
+ float result = modff(value, &result_intpart);
+
+ if (!_isnan(result) || !_isnan(result_intpart))
+ {
+ Fail("modff(%g) returned %10.9g with an intpart of %10.9g when it should have returned %10.9g with an intpart of %10.9g",
+ value, result, result_intpart, PAL_NAN, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char **argv)
+{
+ struct test tests[] =
+ {
+ /* value expected variance expected_intpart variance_intpart */
+ { 0, 0, PAL_EPSILON, 0, PAL_EPSILON },
+ { 0.318309886f, 0.318309886f, PAL_EPSILON, 0, PAL_EPSILON }, // value: 1 / pi
+ { 0.434294482f, 0.434294482f, PAL_EPSILON, 0, PAL_EPSILON }, // value: log10(e)
+ { 0.636619772f, 0.636619772f, PAL_EPSILON, 0, PAL_EPSILON }, // value: 2 / pi
+ { 0.693147181f, 0.693147181f, PAL_EPSILON, 0, PAL_EPSILON }, // value: ln(2)
+ { 0.707106781f, 0.707106781f, PAL_EPSILON, 0, PAL_EPSILON }, // value: 1 / sqrt(2)
+ { 0.785398163f, 0.785398163f, PAL_EPSILON, 0, PAL_EPSILON }, // value: pi / 4
+ { 1, 0, PAL_EPSILON, 1, PAL_EPSILON * 10 },
+ { 1.12837917f, 0.128379167f, PAL_EPSILON, 1, PAL_EPSILON * 10 }, // value: 2 / sqrt(pi)
+ { 1.41421356f, 0.414213562f, PAL_EPSILON, 1, PAL_EPSILON * 10 }, // value: sqrt(2)
+ { 1.44269504f, 0.442695041f, PAL_EPSILON, 1, PAL_EPSILON * 10 }, // value: log2(e)
+ { 1.57079633f, 0.570796327f, PAL_EPSILON, 1, PAL_EPSILON * 10 }, // value: pi / 2
+ { 2.30258509f, 0.302585093f, PAL_EPSILON, 2, PAL_EPSILON * 10 }, // value: ln(10)
+ { 2.71828183f, 0.718281828f, PAL_EPSILON, 2, PAL_EPSILON * 10 }, // value: e
+ { 3.14159265f, 0.141592654f, PAL_EPSILON, 3, PAL_EPSILON * 10 }, // value: pi
+ { PAL_POSINF, 0, PAL_EPSILON, PAL_POSINF, 0 }
+
+ };
+
+ /* PAL initialization */
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate( tests[i].value, tests[i].expected, tests[i].variance, tests[i].expected_intpart, tests[i].variance_intpart);
+ validate(-tests[i].value, -tests[i].expected, tests[i].variance, -tests[i].expected_intpart, tests[i].variance_intpart);
+ }
+
+ validate_isnan(PAL_NAN);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/modff/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/modff/test1/testinfo.dat
new file mode 100644
index 0000000000..392491e3be
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/modff/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = modff
+Name = Positive Test for modff
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes to modff() a series of values, checking that
+= each one return to correct value.
diff --git a/src/pal/tests/palsuite/c_runtime/pow/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/pow/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/pow/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/pow/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/pow/test1/CMakeLists.txt
new file mode 100644
index 0000000000..69ba02af17
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/pow/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_pow_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pow_test1 coreclrpal)
+
+target_link_libraries(paltest_pow_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/pow/test1/test1.c b/src/pal/tests/palsuite/c_runtime/pow/test1/test1.c
new file mode 100644
index 0000000000..0a05cd5a47
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/pow/test1/test1.c
@@ -0,0 +1,230 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests that atan2 returns correct values for a subset of values.
+** Tests with positive and negative values of x and y to ensure
+** atan2 is returning results from the correct quadrant.
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (15-17 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use
+// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx
+// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will
+// use PAL_EPSILON * 10.
+#define PAL_EPSILON 8.8817841970012523e-16
+
+#define PAL_NAN sqrt(-1.0)
+#define PAL_POSINF -log(0.0)
+#define PAL_NEGINF log(0.0)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ double x; /* first component of the value to test the function with */
+ double y; /* second component of the value to test the function with */
+ double expected; /* expected result */
+ double variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(double x, double y, double expected, double variance)
+{
+ double result = pow(x, y);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ double delta = fabs(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("pow(%g, %g) returned %20.17g when it should have returned %20.17g",
+ x, y, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(double x, double y)
+{
+ double result = pow(x, y);
+
+ if (!_isnan(result))
+ {
+ Fail("pow(%g, %g) returned %20.17g when it should have returned %20.17g",
+ x, y, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char **argv)
+{
+ struct test tests[] =
+ {
+ /* x y expected variance */
+ { PAL_NEGINF, PAL_NEGINF, 0, PAL_EPSILON },
+ { PAL_NEGINF, PAL_POSINF, PAL_POSINF, 0 },
+
+ { -10, PAL_NEGINF, 0, PAL_EPSILON },
+ { -10, -1, -0.1, PAL_EPSILON },
+ { -10, 0, 1, PAL_EPSILON * 10 },
+ { -10, 1, -10, PAL_EPSILON * 100 },
+ { -10, PAL_POSINF, PAL_POSINF, 0 },
+
+ { -2.7182818284590452, PAL_NEGINF, 0, PAL_EPSILON }, // x: -(e)
+ { -2.7182818284590452, -1, -0.36787944117144232, PAL_EPSILON }, // x: -(e)
+ { -2.7182818284590452, 0, 1, PAL_EPSILON * 10 }, // x: -(e)
+ { -2.7182818284590452, 1, -2.7182818284590452, PAL_EPSILON * 10 }, // x: -(e) expected: e
+ { -2.7182818284590452, PAL_POSINF, PAL_POSINF, 0 }, // x: -(e)
+
+ { -0.0, PAL_NEGINF, PAL_POSINF, 0 },
+ { -0.0, -1, PAL_NEGINF, 0 },
+ { -0.0, -0.0, 1, PAL_EPSILON * 10 },
+ { -0.0, 0, 1, PAL_EPSILON * 10 },
+ { -0.0, 1, -0.0, PAL_EPSILON },
+ { -0.0, PAL_POSINF, 0, PAL_EPSILON },
+
+ { 0.0, PAL_NEGINF, PAL_POSINF, 0 },
+ { 0.0, -1, PAL_POSINF, 0 },
+ { 0, -0.0, 1, PAL_EPSILON * 10 },
+ { 0, 0, 1, PAL_EPSILON * 10 },
+ { 0.0, 1, 0, PAL_EPSILON },
+ { 0.0, PAL_POSINF, 0, PAL_EPSILON },
+
+ { 1, PAL_NEGINF, 1, PAL_EPSILON * 10 },
+ { 1, PAL_POSINF, 1, PAL_EPSILON * 10 },
+
+ { 2.7182818284590452, PAL_NEGINF, 0, PAL_EPSILON },
+ { 2.7182818284590452, -3.1415926535897932, 0.043213918263772250, PAL_EPSILON / 10 }, // x: e y: -(pi)
+ { 2.7182818284590452, -2.7182818284590452, 0.065988035845312537, PAL_EPSILON / 10 }, // x: e y: -(e)
+ { 2.7182818284590452, -2.3025850929940457, 0.1, PAL_EPSILON }, // x: e y: -(ln(10))
+ { 2.7182818284590452, -1.5707963267948966, 0.20787957635076191, PAL_EPSILON }, // x: e y: -(pi / 2)
+ { 2.7182818284590452, -1.4426950408889634, 0.23629008834452270, PAL_EPSILON }, // x: e y: -(log2(e))
+ { 2.7182818284590452, -1.4142135623730950, 0.24311673443421421, PAL_EPSILON }, // x: e y: -(sqrt(2))
+ { 2.7182818284590452, -1.1283791670955126, 0.32355726390307110, PAL_EPSILON }, // x: e y: -(2 / sqrt(pi))
+ { 2.7182818284590452, -1, 0.36787944117144232, PAL_EPSILON }, // x: e y: -(1)
+ { 2.7182818284590452, -0.78539816339744831, 0.45593812776599624, PAL_EPSILON }, // x: e y: -(pi / 4)
+ { 2.7182818284590452, -0.70710678118654752, 0.49306869139523979, PAL_EPSILON }, // x: e y: -(1 / sqrt(2))
+ { 2.7182818284590452, -0.69314718055994531, 0.5, PAL_EPSILON }, // x: e y: -(ln(2))
+ { 2.7182818284590452, -0.63661977236758134, 0.52907780826773535, PAL_EPSILON }, // x: e y: -(2 / pi)
+ { 2.7182818284590452, -0.43429448190325183, 0.64772148514180065, PAL_EPSILON }, // x: e y: -(log10(e))
+ { 2.7182818284590452, -0.31830988618379067, 0.72737734929521647, PAL_EPSILON }, // x: e y: -(1 / pi)
+ { 2.7182818284590452, 0, 1, PAL_EPSILON * 10 }, // x: e
+ { 2.7182818284590452, 0.31830988618379067, 1.3748022274393586, PAL_EPSILON * 10 }, // x: e y: 1 / pi
+ { 2.7182818284590452, 0.43429448190325183, 1.5438734439711811, PAL_EPSILON * 10 }, // x: e y: log10(e)
+ { 2.7182818284590452, 0.63661977236758134, 1.8900811645722220, PAL_EPSILON * 10 }, // x: e y: 2 / pi
+ { 2.7182818284590452, 0.69314718055994531, 2, PAL_EPSILON * 10 }, // x: e y: ln(2)
+ { 2.7182818284590452, 0.70710678118654752, 2.0281149816474725, PAL_EPSILON * 10 }, // x: e y: 1 / sqrt(2)
+ { 2.7182818284590452, 0.78539816339744831, 2.1932800507380155, PAL_EPSILON * 10 }, // x: e y: pi / 4
+ { 2.7182818284590452, 1, 2.7182818284590452, PAL_EPSILON * 10 }, // x: e expected: e
+ { 2.7182818284590452, 1.1283791670955126, 3.0906430223107976, PAL_EPSILON * 10 }, // x: e y: 2 / sqrt(pi)
+ { 2.7182818284590452, 1.4142135623730950, 4.1132503787829275, PAL_EPSILON * 10 }, // x: e y: sqrt(2)
+ { 2.7182818284590452, 1.4426950408889634, 4.2320861065570819, PAL_EPSILON * 10 }, // x: e y: log2(e)
+ { 2.7182818284590452, 1.5707963267948966, 4.8104773809653517, PAL_EPSILON * 10 }, // x: e y: pi / 2
+ { 2.7182818284590452, 2.3025850929940457, 10, PAL_EPSILON * 100 }, // x: e y: ln(10)
+ { 2.7182818284590452, 2.7182818284590452, 15.154262241479264, PAL_EPSILON * 100 }, // x: e y: e
+ { 2.7182818284590452, 3.1415926535897932, 23.140692632779269, PAL_EPSILON * 100 }, // x: e y: pi
+ { 2.7182818284590452, PAL_POSINF, PAL_POSINF, 0 }, // x: e
+
+ { 10, PAL_NEGINF, 0, 0 },
+ { 10, -3.1415926535897932, 0.00072178415907472774, PAL_EPSILON / 1000 }, // y: -(pi)
+ { 10, -2.7182818284590452, 0.0019130141022243176, PAL_EPSILON / 100 }, // y: -(e)
+ { 10, -2.3025850929940457, 0.0049821282964407206, PAL_EPSILON / 100 }, // y: -(ln(10))
+ { 10, -1.5707963267948966, 0.026866041001136132, PAL_EPSILON / 10 }, // y: -(pi / 2)
+ { 10, -1.4426950408889634, 0.036083192820787210, PAL_EPSILON / 10 }, // y: -(log2(e))
+ { 10, -1.4142135623730950, 0.038528884700322026, PAL_EPSILON / 10 }, // y: -(sqrt(2))
+ { 10, -1.1283791670955126, 0.074408205860642723, PAL_EPSILON / 10 }, // y: -(2 / sqrt(pi))
+ { 10, -1, 0.1, PAL_EPSILON }, // y: -(1)
+ { 10, -0.78539816339744831, 0.16390863613957665, PAL_EPSILON }, // y: -(pi / 4)
+ { 10, -0.70710678118654752, 0.19628775993505562, PAL_EPSILON }, // y: -(1 / sqrt(2))
+ { 10, -0.69314718055994531, 0.20269956628651730, PAL_EPSILON }, // y: -(ln(2))
+ { 10, -0.63661977236758134, 0.23087676451600055, PAL_EPSILON }, // y: -(2 / pi)
+ { 10, -0.43429448190325183, 0.36787944117144232, PAL_EPSILON }, // y: -(log10(e))
+ { 10, -0.31830988618379067, 0.48049637305186868, PAL_EPSILON }, // y: -(1 / pi)
+ { 10, 0, 1, PAL_EPSILON * 10 },
+ { 10, 0.31830988618379067, 2.0811811619898573, PAL_EPSILON * 10 }, // y: 1 / pi
+ { 10, 0.43429448190325183, 2.7182818284590452, PAL_EPSILON * 10 }, // y: log10(e) expected: e
+ { 10, 0.63661977236758134, 4.3313150290214525, PAL_EPSILON * 10 }, // y: 2 / pi
+ { 10, 0.69314718055994531, 4.9334096679145963, PAL_EPSILON * 10 }, // y: ln(2)
+ { 10, 0.70710678118654752, 5.0945611704512962, PAL_EPSILON * 10 }, // y: 1 / sqrt(2)
+ { 10, 0.78539816339744831, 6.1009598002416937, PAL_EPSILON * 10 }, // y: pi / 4
+ { 10, 1, 10, PAL_EPSILON * 100 },
+ { 10, 1.1283791670955126, 13.439377934644400, PAL_EPSILON * 100 }, // y: 2 / sqrt(pi)
+ { 10, 1.4142135623730950, 25.954553519470081, PAL_EPSILON * 100 }, // y: sqrt(2)
+ { 10, 1.4426950408889634, 27.713733786437790, PAL_EPSILON * 100 }, // y: log2(e)
+ { 10, 1.5707963267948966, 37.221710484165167, PAL_EPSILON * 100 }, // y: pi / 2
+ { 10, 2.3025850929940457, 200.71743249053009, PAL_EPSILON * 1000 }, // y: ln(10)
+ { 10, 2.7182818284590452, 522.73529967043665, PAL_EPSILON * 1000 }, // y: e
+ { 10, 3.1415926535897932, 1385.4557313670111, PAL_EPSILON * 10000 }, // y: pi
+ { 10, PAL_POSINF, PAL_POSINF, 0 },
+
+ { PAL_POSINF, PAL_NEGINF, 0, PAL_EPSILON },
+ { PAL_POSINF, PAL_POSINF, PAL_POSINF, 0 },
+ };
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate(tests[i].x, tests[i].y, tests[i].expected, tests[i].variance);
+ }
+
+ validate_isnan(-10, -1.5707963267948966); // y: -(pi / 2)
+ validate_isnan(-10, -0.78539816339744828); // y: -(pi / 4)
+ validate_isnan(-10, 0.78539816339744828); // y: pi / 4
+ validate_isnan(-10, 1.5707963267948966); // y: pi / 2
+
+ validate_isnan(-2.7182818284590452, -1.5707963267948966); // x: -(e) y: -(pi / 2)
+ validate_isnan(-2.7182818284590452, -0.78539816339744828); // x: -(e) y: -(pi / 4)
+ validate_isnan(-2.7182818284590452, 0.78539816339744828); // x: -(e) y: pi / 4
+ validate_isnan(-2.7182818284590452, 1.5707963267948966); // x: -(e) y: pi / 2
+
+ validate_isnan(-1, PAL_NEGINF);
+ validate_isnan(-1, PAL_POSINF);
+
+ validate_isnan(PAL_NAN, -0.0);
+ validate_isnan(PAL_NAN, 0);
+
+ validate_isnan(PAL_NEGINF, PAL_NAN);
+ validate_isnan(PAL_NAN, PAL_NEGINF);
+
+ validate_isnan(PAL_POSINF, PAL_NAN);
+ validate_isnan(PAL_NAN, PAL_POSINF);
+
+ validate_isnan(PAL_NAN, PAL_NAN);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/pow/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/pow/test1/testinfo.dat
new file mode 100644
index 0000000000..cf106d90ed
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/pow/test1/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = pow
+Name = Call pow with some std input/output.
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Call the pow function with various num/exponent pairs
+= that should produce std answers.
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/printf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/CMakeLists.txt
new file mode 100644
index 0000000000..cafb9536b0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/CMakeLists.txt
@@ -0,0 +1,22 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test10)
+add_subdirectory(test11)
+add_subdirectory(test12)
+add_subdirectory(test13)
+add_subdirectory(test14)
+add_subdirectory(test15)
+add_subdirectory(test16)
+add_subdirectory(test17)
+add_subdirectory(test18)
+add_subdirectory(test19)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+add_subdirectory(test7)
+add_subdirectory(test8)
+add_subdirectory(test9)
+
diff --git a/src/pal/tests/palsuite/c_runtime/printf/printf.h b/src/pal/tests/palsuite/c_runtime/printf/printf.h
new file mode 100644
index 0000000000..2eaa984bad
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/printf.h
@@ -0,0 +1,182 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: printf.h
+**
+** Purpose: Containts common testing functions for printf
+**
+**
+**==========================================================================*/
+
+#ifndef __printf_H__
+#define __printf_H__
+
+void DoStrTest(char *formatstr, char* param, char *checkstr)
+{
+ int ret;
+
+ ret = printf(formatstr, param);
+ if (ret != strlen(checkstr))
+ {
+ Fail("Expected printf to return %d, got %d.\n",
+ strlen(checkstr), ret);
+ }
+}
+
+void DoWStrTest(char *formatstr, WCHAR* param, char *checkstr)
+{
+ int ret;
+
+ ret = printf(formatstr, param);
+ if (ret != strlen(checkstr))
+ {
+ Fail("Expected printf to return %d, got %d.\n",
+ strlen(checkstr), ret);
+ }
+}
+
+void DoPointerTest(char *formatstr, void* param, char* paramstr,
+ char *checkstr1)
+{
+ int ret;
+
+ ret = printf(formatstr, param);
+ if (ret != strlen(checkstr1))
+ {
+ Fail("Expected printf to return %d, got %d.\n",
+ strlen(checkstr1), ret);
+ }
+}
+
+void DoCountTest(char *formatstr, int param, char *checkstr)
+{
+ int ret;
+ int n = -1;
+
+ ret = printf(formatstr, &n);
+
+ if (n != param)
+ {
+ Fail("Expected count parameter to resolve to %d, got %d\n", param, n);
+ }
+
+ if (ret != strlen(checkstr))
+ {
+ Fail("Expected printf to return %d, got %d.\n",
+ strlen(checkstr), ret);
+ }
+}
+
+void DoShortCountTest(char *formatstr, int param, char *checkstr)
+{
+ int ret;
+ short int n = -1;
+
+ ret = printf(formatstr, &n);
+
+ if (n != param)
+ {
+ Fail("Expected count parameter to resolve to %d, got %d\n", param, n);
+ }
+
+ if (ret != strlen(checkstr))
+ {
+ Fail("Expected printf to return %d, got %d.\n",
+ strlen(checkstr), ret);
+ }
+}
+
+
+void DoCharTest(char *formatstr, char param, char *checkstr)
+{
+ int ret;
+
+ ret = printf(formatstr, param);
+ if (ret != strlen(checkstr))
+ {
+ Fail("Expected printf to return %d, got %d.\n",
+ strlen(checkstr), ret);
+ }
+}
+
+void DoWCharTest(char *formatstr, WCHAR param, char *checkstr)
+{
+ int ret;
+
+ ret = printf(formatstr, param);
+ if (ret != strlen(checkstr))
+ {
+ Fail("Expected printf to return %d, got %d.\n",
+ strlen(checkstr), ret);
+ }
+}
+
+void DoNumTest(char *formatstr, int param, char *checkstr)
+{
+ int ret;
+
+ ret = printf(formatstr, param);
+ if (ret != strlen(checkstr))
+ {
+ Fail("Expected printf to return %d, got %d.\n",
+ strlen(checkstr), ret);
+ }
+}
+
+void DoI64Test(char *formatstr, INT64 param, char *valuestr,
+ char *checkstr1)
+{
+ int ret;
+
+ ret = printf(formatstr, param);
+ if (ret != strlen(checkstr1))
+ {
+ Fail("Expected printf to return %d, got %d.\n",
+ strlen(checkstr1), ret);
+ }
+}
+
+void DoDoubleTest(char *formatstr, double param,
+ char *checkstr1, char *checkstr2)
+{
+ int ret;
+
+ ret = printf(formatstr, param);
+ if (ret != strlen(checkstr1) && ret != strlen(checkstr2))
+ {
+ Fail("Expected printf to return %d or %d, got %d.\n",
+ strlen(checkstr1), strlen(checkstr2), ret);
+ }
+}
+
+void DoArgumentPrecTest(char *formatstr, int precision, void *param,
+ char *paramstr, char *checkstr1, char *checkstr2)
+{
+ int ret;
+
+ ret = printf(formatstr, precision, param);
+ if (ret != strlen(checkstr1) && ret != strlen(checkstr2))
+ {
+ Fail("Expected printf to return %d or %d, got %d.\n",
+ strlen(checkstr1), strlen(checkstr2), ret);
+ }
+}
+
+void DoArgumentPrecDoubleTest(char *formatstr, int precision, double param,
+ char *checkstr1, char *checkstr2)
+{
+ int ret;
+
+ ret = printf(formatstr, precision, param);
+ if (ret != strlen(checkstr1) && ret != strlen(checkstr2))
+ {
+ Fail("Expected printf to return %d or %d, got %d.\n",
+ strlen(checkstr1), strlen(checkstr2), ret);
+ }
+}
+
+#endif
+
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..bea9151ed7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_printf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_printf_test1 coreclrpal)
+
+target_link_libraries(paltest_printf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/printf/test1/test1.c
new file mode 100644
index 0000000000..31b7014343
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test1/test1.c
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test #1 for the printf function. A single, basic, test
+** case with no formatting.
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../printf.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+ char checkstr[] = "hello world";
+ int ret;
+
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ ret = printf("hello world");
+
+ if (ret != strlen(checkstr))
+ {
+ Fail("Expected printf to return %d, got %d.\n",
+ strlen(checkstr), ret);
+
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/printf/test1/testinfo.dat
new file mode 100644
index 0000000000..fe8bee680e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = printf
+Name = Positive Test for printf
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= General test to see if printf works correctly
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test10/CMakeLists.txt
new file mode 100644
index 0000000000..89ff2e0190
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test10/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test10.c
+)
+
+add_executable(paltest_printf_test10
+ ${SOURCES}
+)
+
+add_dependencies(paltest_printf_test10 coreclrpal)
+
+target_link_libraries(paltest_printf_test10
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test10/test10.c b/src/pal/tests/palsuite/c_runtime/printf/test10/test10.c
new file mode 100644
index 0000000000..5e69175b07
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test10/test10.c
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test10.c
+**
+** Purpose: Test #10 for the printf function. Tests the octal specifier
+** (%o).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../printf.h"
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest("foo %o", pos, "foo 52");
+ DoNumTest("foo %lo", 0xFFFF, "foo 177777");
+ DoNumTest("foo %ho", 0xFFFF, "foo 177777");
+ DoNumTest("foo %Lo", pos, "foo 52");
+ DoI64Test("foo %I64o", l, "42", "foo 52");
+ DoNumTest("foo %3o", pos, "foo 52");
+ DoNumTest("foo %-3o", pos, "foo 52 ");
+ DoNumTest("foo %.1o", pos, "foo 52");
+ DoNumTest("foo %.3o", pos, "foo 052");
+ DoNumTest("foo %03o", pos, "foo 052");
+ DoNumTest("foo %#o", pos, "foo 052");
+ DoNumTest("foo %+o", pos, "foo 52");
+ DoNumTest("foo % o", pos, "foo 52");
+ DoNumTest("foo %+o", neg, "foo 37777777726");
+ DoNumTest("foo % o", neg, "foo 37777777726");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test10/testinfo.dat b/src/pal/tests/palsuite/c_runtime/printf/test10/testinfo.dat
new file mode 100644
index 0000000000..7667a0f461
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test10/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = printf
+Name = Positive Test for printf
+TYPE = DEFAULT
+EXE1 = test10
+Description
+= Tests printf with octal numbers
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test11/CMakeLists.txt
new file mode 100644
index 0000000000..349f154a8d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test11/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test11.c
+)
+
+add_executable(paltest_printf_test11
+ ${SOURCES}
+)
+
+add_dependencies(paltest_printf_test11 coreclrpal)
+
+target_link_libraries(paltest_printf_test11
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test11/test11.c b/src/pal/tests/palsuite/c_runtime/printf/test11/test11.c
new file mode 100644
index 0000000000..788be8b2db
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test11/test11.c
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test11.c
+**
+** Purpose: Test #11 for the printf function. Test the unsigned int
+** specifier (%u).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../printf.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest("foo %u", pos, "foo 42");
+ DoNumTest("foo %lu", 0xFFFF, "foo 65535");
+ DoNumTest("foo %hu", 0xFFFF, "foo 65535");
+ DoNumTest("foo %Lu", pos, "foo 42");
+ DoI64Test("foo %I64u", l, "42", "foo 42");
+ DoNumTest("foo %3u", pos, "foo 42");
+ DoNumTest("foo %-3u", pos, "foo 42 ");
+ DoNumTest("foo %.1u", pos, "foo 42");
+ DoNumTest("foo %.3u", pos, "foo 042");
+ DoNumTest("foo %03u", pos, "foo 042");
+ DoNumTest("foo %#u", pos, "foo 42");
+ DoNumTest("foo %+u", pos, "foo 42");
+ DoNumTest("foo % u", pos, "foo 42");
+ DoNumTest("foo %+u", neg, "foo 4294967254");
+ DoNumTest("foo % u", neg, "foo 4294967254");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test11/testinfo.dat b/src/pal/tests/palsuite/c_runtime/printf/test11/testinfo.dat
new file mode 100644
index 0000000000..a88e0d8fcb
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test11/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = printf
+Name = Positive Test for printf
+TYPE = DEFAULT
+EXE1 = test11
+Description
+= Tests printf with unsigned numbers
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test12/CMakeLists.txt
new file mode 100644
index 0000000000..0d32ee1690
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test12/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test12.c
+)
+
+add_executable(paltest_printf_test12
+ ${SOURCES}
+)
+
+add_dependencies(paltest_printf_test12 coreclrpal)
+
+target_link_libraries(paltest_printf_test12
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test12/test12.c b/src/pal/tests/palsuite/c_runtime/printf/test12/test12.c
new file mode 100644
index 0000000000..b4006f2405
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test12/test12.c
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test12.c
+**
+** Purpose: Test #12 for the printf function. Tests the (lowercase)
+** hexadecimal specifier (%x)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../printf.h"
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 0x1234ab;
+ INT64 l = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest("foo %x", pos, "foo 1234ab");
+ DoNumTest("foo %lx", pos, "foo 1234ab");
+ DoNumTest("foo %hx", pos, "foo 34ab");
+ DoNumTest("foo %Lx", pos, "foo 1234ab");
+ DoI64Test("foo %I64x", l, "0x1234567887654321",
+ "foo 1234567887654321");
+ DoNumTest("foo %7x", pos, "foo 1234ab");
+ DoNumTest("foo %-7x", pos, "foo 1234ab ");
+ DoNumTest("foo %.1x", pos, "foo 1234ab");
+ DoNumTest("foo %.7x", pos, "foo 01234ab");
+ DoNumTest("foo %07x", pos, "foo 01234ab");
+ DoNumTest("foo %#x", pos, "foo 0x1234ab");
+ DoNumTest("foo %+x", pos, "foo 1234ab");
+ DoNumTest("foo % x", pos, "foo 1234ab");
+ DoNumTest("foo %+x", neg, "foo ffffffd6");
+ DoNumTest("foo % x", neg, "foo ffffffd6");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test12/testinfo.dat b/src/pal/tests/palsuite/c_runtime/printf/test12/testinfo.dat
new file mode 100644
index 0000000000..a6e317f905
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test12/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = printf
+Name = Positive Test for printf
+TYPE = DEFAULT
+EXE1 = test12
+Description
+= Tests printf with hex numbers (lowercase)
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test13/CMakeLists.txt
new file mode 100644
index 0000000000..348d25b22d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test13/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test13.c
+)
+
+add_executable(paltest_printf_test13
+ ${SOURCES}
+)
+
+add_dependencies(paltest_printf_test13 coreclrpal)
+
+target_link_libraries(paltest_printf_test13
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test13/test13.c b/src/pal/tests/palsuite/c_runtime/printf/test13/test13.c
new file mode 100644
index 0000000000..ccd16b50d2
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test13/test13.c
@@ -0,0 +1,54 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test13.c
+**
+** Purpose: Test #13 for the printf function. Tests the (uppercase)
+** hexadecimal specifier (%X)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../printf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 0x1234AB;
+ INT64 l = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest("foo %X", pos, "foo 1234AB");
+ DoNumTest("foo %lX", pos, "foo 1234AB");
+ DoNumTest("foo %hX", pos, "foo 34AB");
+ DoNumTest("foo %LX", pos, "foo 1234AB");
+ DoI64Test("foo %I64X", l, "0x1234567887654321",
+ "foo 1234567887654321");
+ DoNumTest("foo %7X", pos, "foo 1234AB");
+ DoNumTest("foo %-7X", pos, "foo 1234AB ");
+ DoNumTest("foo %.1X", pos, "foo 1234AB");
+ DoNumTest("foo %.7X", pos, "foo 01234AB");
+ DoNumTest("foo %07X", pos, "foo 01234AB");
+ DoNumTest("foo %#X", pos, "foo 0X1234AB");
+ DoNumTest("foo %+X", pos, "foo 1234AB");
+ DoNumTest("foo % X", pos, "foo 1234AB");
+ DoNumTest("foo %+X", neg, "foo FFFFFFD6");
+ DoNumTest("foo % X", neg, "foo FFFFFFD6");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test13/testinfo.dat b/src/pal/tests/palsuite/c_runtime/printf/test13/testinfo.dat
new file mode 100644
index 0000000000..e814040b37
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test13/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = printf
+Name = Positive Test for printf
+TYPE = DEFAULT
+EXE1 = test13
+Description
+= Tests printf with hex numbers (uppercase)
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test14/CMakeLists.txt
new file mode 100644
index 0000000000..659ea78cc6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test14/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test14.c
+)
+
+add_executable(paltest_printf_test14
+ ${SOURCES}
+)
+
+add_dependencies(paltest_printf_test14 coreclrpal)
+
+target_link_libraries(paltest_printf_test14
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test14/test14.c b/src/pal/tests/palsuite/c_runtime/printf/test14/test14.c
new file mode 100644
index 0000000000..10577db67d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test14/test14.c
@@ -0,0 +1,54 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test14.c
+**
+** Purpose: Test #14 for the printf function. Tests the lowercase
+** exponential notation double specifier (%e)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../printf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 256.0;
+ double neg = -256.0;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest("foo %e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %le", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %he", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %Le", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %I64e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %14e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %-14e", val, "foo 2.560000e+002 ",
+ "foo 2.560000e+02 ");
+ DoDoubleTest("foo %.1e", val, "foo 2.6e+002", "foo 2.6e+02");
+ DoDoubleTest("foo %.8e", val, "foo 2.56000000e+002",
+ "foo 2.56000000e+02");
+ DoDoubleTest("foo %014e", val, "foo 02.560000e+002",
+ "foo 002.560000e+02");
+ DoDoubleTest("foo %#e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %+e", val, "foo +2.560000e+002", "foo +2.560000e+02");
+ DoDoubleTest("foo % e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %+e", neg, "foo -2.560000e+002", "foo -2.560000e+02");
+ DoDoubleTest("foo % e", neg, "foo -2.560000e+002", "foo -2.560000e+02");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test14/testinfo.dat b/src/pal/tests/palsuite/c_runtime/printf/test14/testinfo.dat
new file mode 100644
index 0000000000..5cb22c1fcc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test14/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = printf
+Name = Positive Test for printf
+TYPE = DEFAULT
+EXE1 = test14
+Description
+= Tests printf with exponential format doubles (lowercase)
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test15/CMakeLists.txt
new file mode 100644
index 0000000000..9e4e310304
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test15/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test15.c
+)
+
+add_executable(paltest_printf_test15
+ ${SOURCES}
+)
+
+add_dependencies(paltest_printf_test15 coreclrpal)
+
+target_link_libraries(paltest_printf_test15
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test15/test15.c b/src/pal/tests/palsuite/c_runtime/printf/test15/test15.c
new file mode 100644
index 0000000000..2acfc436a3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test15/test15.c
@@ -0,0 +1,54 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test15.c
+**
+** Purpose: Test #15 for the printf function. Tests the uppercase
+** exponential notation double specifier (%E)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../printf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 256.0;
+ double neg = -256.0;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest("foo %E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %lE", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %hE", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %LE", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %I64E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %14E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %-14E", val, "foo 2.560000E+002 ",
+ "foo 2.560000E+02 ");
+ DoDoubleTest("foo %.1E", val, "foo 2.6E+002", "foo 2.6E+02");
+ DoDoubleTest("foo %.8E", val, "foo 2.56000000E+002",
+ "foo 2.56000000E+02");
+ DoDoubleTest("foo %014E", val, "foo 02.560000E+002",
+ "foo 002.560000E+02");
+ DoDoubleTest("foo %#E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %+E", val, "foo +2.560000E+002", "foo +2.560000E+02");
+ DoDoubleTest("foo % E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %+E", neg, "foo -2.560000E+002", "foo -2.560000E+02");
+ DoDoubleTest("foo % E", neg, "foo -2.560000E+002", "foo -2.560000E+02");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test15/testinfo.dat b/src/pal/tests/palsuite/c_runtime/printf/test15/testinfo.dat
new file mode 100644
index 0000000000..bdfa2cc3b5
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test15/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = printf
+Name = Positive Test for printf
+TYPE = DEFAULT
+EXE1 = test15
+Description
+= Tests printf with exponential format doubles (uppercase)
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test16/CMakeLists.txt
new file mode 100644
index 0000000000..7e477a3059
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test16/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test16.c
+)
+
+add_executable(paltest_printf_test16
+ ${SOURCES}
+)
+
+add_dependencies(paltest_printf_test16 coreclrpal)
+
+target_link_libraries(paltest_printf_test16
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test16/test16.c b/src/pal/tests/palsuite/c_runtime/printf/test16/test16.c
new file mode 100644
index 0000000000..50c952f959
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test16/test16.c
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test16.c
+**
+** Purpose: Test #16 for the printf function. Tests the decimal notation
+** double specifier (%f)
+**
+**
+**==========================================================================*/
+
+
+#include <palsuite.h>
+#include "../printf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest("foo %f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %lf", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %hf", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %Lf", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %I64f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %12f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %-12f", val, "foo 2560.001000 ", "foo 2560.001000 ");
+ DoDoubleTest("foo %.1f", val, "foo 2560.0", "foo 2560.0");
+ DoDoubleTest("foo %.8f", val, "foo 2560.00100000", "foo 2560.00100000");
+ DoDoubleTest("foo %012f", val, "foo 02560.001000", "foo 02560.001000");
+ DoDoubleTest("foo %#f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %+f", val, "foo +2560.001000", "foo +2560.001000");
+ DoDoubleTest("foo % f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %+f", neg, "foo -2560.001000", "foo -2560.001000");
+ DoDoubleTest("foo % f", neg, "foo -2560.001000", "foo -2560.001000");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test16/testinfo.dat b/src/pal/tests/palsuite/c_runtime/printf/test16/testinfo.dat
new file mode 100644
index 0000000000..afb9a21b3b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test16/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = printf
+Name = Positive Test for printf
+TYPE = DEFAULT
+EXE1 = test16
+Description
+= Tests printf with decimal point format doubles
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test17/CMakeLists.txt
new file mode 100644
index 0000000000..c18450c2aa
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test17/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test17.c
+)
+
+add_executable(paltest_printf_test17
+ ${SOURCES}
+)
+
+add_dependencies(paltest_printf_test17 coreclrpal)
+
+target_link_libraries(paltest_printf_test17
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test17/test17.c b/src/pal/tests/palsuite/c_runtime/printf/test17/test17.c
new file mode 100644
index 0000000000..96ddd5c1e4
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test17/test17.c
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test17.c
+**
+** Purpose: Test #17 for the printf function. Tests the lowercase
+** shorthand notation double specifier (%g)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../printf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest("foo %g", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %lg", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %hg", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %Lg", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %I64g", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %5g", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %-5g", val, "foo 2560 ", "foo 2560 ");
+ DoDoubleTest("foo %.1g", val, "foo 3e+003", "foo 3e+03");
+ DoDoubleTest("foo %.2g", val, "foo 2.6e+003", "foo 2.6e+03");
+ DoDoubleTest("foo %.12g", val, "foo 2560.001", "foo 2560.001");
+ DoDoubleTest("foo %06g", val, "foo 002560", "foo 002560");
+ DoDoubleTest("foo %#g", val, "foo 2560.00", "foo 2560.00");
+ DoDoubleTest("foo %+g", val, "foo +2560", "foo +2560");
+ DoDoubleTest("foo % g", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %+g", neg, "foo -2560", "foo -2560");
+ DoDoubleTest("foo % g", neg, "foo -2560", "foo -2560");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test17/testinfo.dat b/src/pal/tests/palsuite/c_runtime/printf/test17/testinfo.dat
new file mode 100644
index 0000000000..a8545d9542
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test17/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = printf
+Name = Positive Test for printf
+TYPE = DEFAULT
+EXE1 = test17
+Description
+= Tests printf with compact format doubles (lowercase)
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test18/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test18/CMakeLists.txt
new file mode 100644
index 0000000000..b0468314a3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test18/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test18.c
+)
+
+add_executable(paltest_printf_test18
+ ${SOURCES}
+)
+
+add_dependencies(paltest_printf_test18 coreclrpal)
+
+target_link_libraries(paltest_printf_test18
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test18/test18.c b/src/pal/tests/palsuite/c_runtime/printf/test18/test18.c
new file mode 100644
index 0000000000..6c05e40f42
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test18/test18.c
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test18.c
+**
+** Purpose: Test #18 for the printf function. Tests the uppercase
+** shorthand notation double specifier (%G)
+**
+**
+**==========================================================================*/
+
+
+#include <palsuite.h>
+#include "../printf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest("foo %G", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %lG", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %hG", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %LG", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %I64G", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %5G", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %-5G", val, "foo 2560 ", "foo 2560 ");
+ DoDoubleTest("foo %.1G", val, "foo 3E+003", "foo 3E+03");
+ DoDoubleTest("foo %.2G", val, "foo 2.6E+003", "foo 2.6E+03");
+ DoDoubleTest("foo %.12G", val, "foo 2560.001", "foo 2560.001");
+ DoDoubleTest("foo %06G", val, "foo 002560", "foo 002560");
+ DoDoubleTest("foo %#G", val, "foo 2560.00", "foo 2560.00");
+ DoDoubleTest("foo %+G", val, "foo +2560", "foo +2560");
+ DoDoubleTest("foo % G", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %+G", neg, "foo -2560", "foo -2560");
+ DoDoubleTest("foo % G", neg, "foo -2560", "foo -2560");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test18/testinfo.dat b/src/pal/tests/palsuite/c_runtime/printf/test18/testinfo.dat
new file mode 100644
index 0000000000..bd5c90b0c3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test18/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = printf
+Name = Positive Test for printf
+TYPE = DEFAULT
+EXE1 = test18
+Description
+= Tests printf with compact format doubles (uppercase)
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test19/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test19/CMakeLists.txt
new file mode 100644
index 0000000000..efd47563d4
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test19/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test19.c
+)
+
+add_executable(paltest_printf_test19
+ ${SOURCES}
+)
+
+add_dependencies(paltest_printf_test19 coreclrpal)
+
+target_link_libraries(paltest_printf_test19
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test19/test19.c b/src/pal/tests/palsuite/c_runtime/printf/test19/test19.c
new file mode 100644
index 0000000000..1e09398f7c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test19/test19.c
@@ -0,0 +1,76 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test19.c
+**
+** Purpose: Test #19 for the printf function. Tests the variable length
+** precision argument.
+**
+**
+**==========================================================================*/
+
+
+#include <palsuite.h>
+#include "../printf.h"
+
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int n = -1;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoArgumentPrecTest("%.*s", 2, "bar", "bar", "ba", "ba");
+ DoArgumentPrecTest("%.*S", 2, convert("bar"), "bar", "ba", "ba");
+
+ DoArgumentPrecTest("%.*n", 3, &n, "pointer to int", "", "");
+ if (n != 0)
+ {
+ Fail("ERROR: Expected count parameter to resolve to %d, got %X\n",
+ 0, n);
+ }
+
+ DoArgumentPrecTest("%.*c", 0, (void*)'a', "a", "a", "a");
+ DoArgumentPrecTest("%.*c", 4, (void*)'a', "a", "a", "a");
+ DoArgumentPrecTest("%.*C", 0, (void*)'a', "a", "a", "a");
+ DoArgumentPrecTest("%.*C", 4, (void*)'a', "a", "a", "a");
+ DoArgumentPrecTest("%.*d", 1, (void*)42, "42", "42", "42");
+ DoArgumentPrecTest("%.*d", 3, (void*)42, "42", "042", "042");
+ DoArgumentPrecTest("%.*i", 1, (void*)42, "42", "42", "42");
+ DoArgumentPrecTest("%.*i", 3, (void*)42, "42", "042", "042");
+ DoArgumentPrecTest("%.*o", 1, (void*)42, "42", "52", "52");
+ DoArgumentPrecTest("%.*o", 3, (void*)42, "42", "052", "052");
+ DoArgumentPrecTest("%.*u", 1, (void*)42, "42", "42", "42");
+ DoArgumentPrecTest("%.*u", 3, (void*)42, "42", "042", "042");
+ DoArgumentPrecTest("%.*x", 1, (void*)0x42, "0x42", "42", "42");
+ DoArgumentPrecTest("%.*x", 3, (void*)0x42, "0x42", "042", "042");
+ DoArgumentPrecTest("%.*X", 1, (void*)0x42, "0x42", "42", "42");
+ DoArgumentPrecTest("%.*X", 3, (void*)0x42, "0x42", "042", "042");
+
+
+ DoArgumentPrecDoubleTest("%.*e", 1, 2.01, "2.0e+000", "2.0e+00");
+ DoArgumentPrecDoubleTest("%.*e", 3, 2.01, "2.010e+000", "2.010e+00");
+ DoArgumentPrecDoubleTest("%.*E", 1, 2.01, "2.0E+000", "2.0E+00");
+ DoArgumentPrecDoubleTest("%.*E", 3, 2.01, "2.010E+000", "2.010E+00");
+ DoArgumentPrecDoubleTest("%.*f", 1, 2.01, "2.0", "2.0");
+ DoArgumentPrecDoubleTest("%.*f", 3, 2.01, "2.010", "2.010");
+ DoArgumentPrecDoubleTest("%.*g", 1, 256.01, "3e+002", "3e+02");
+ DoArgumentPrecDoubleTest("%.*g", 3, 256.01, "256", "256");
+ DoArgumentPrecDoubleTest("%.*g", 4, 256.01, "256", "256");
+ DoArgumentPrecDoubleTest("%.*g", 6, 256.01, "256.01", "256.01");
+ DoArgumentPrecDoubleTest("%.*G", 1, 256.01, "3E+002", "3E+02");
+ DoArgumentPrecDoubleTest("%.*G", 3, 256.01, "256", "256");
+ DoArgumentPrecDoubleTest("%.*G", 4, 256.01, "256", "256");
+ DoArgumentPrecDoubleTest("%.*G", 6, 256.01, "256.01", "256.01");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test19/testinfo.dat b/src/pal/tests/palsuite/c_runtime/printf/test19/testinfo.dat
new file mode 100644
index 0000000000..6ad18f7591
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test19/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = printf
+Name = Positive Test for printf
+TYPE = DEFAULT
+EXE1 = test19
+Description
+= Tests printf with argument specified precision
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test2/CMakeLists.txt
new file mode 100644
index 0000000000..c303a69134
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_printf_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_printf_test2 coreclrpal)
+
+target_link_libraries(paltest_printf_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test2/test2.c b/src/pal/tests/palsuite/c_runtime/printf/test2/test2.c
new file mode 100644
index 0000000000..e766ef4a90
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test2/test2.c
@@ -0,0 +1,45 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test2.c
+**
+** Purpose: Test #2 for the printf function. Tests the string specifier
+** (%s).
+**
+**
+**==========================================================================*/
+
+
+#include <palsuite.h>
+#include "../printf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoStrTest("foo %s", "bar", "foo bar");
+ DoStrTest("foo %hs", "bar", "foo bar");
+ DoWStrTest("foo %ls", convert("bar"), "foo bar");
+ DoWStrTest("foo %ws", convert("bar"), "foo bar");
+ DoStrTest("foo %Ls", "bar", "foo bar");
+ DoStrTest("foo %I64s", "bar", "foo bar");
+ DoStrTest("foo %5s", "bar", "foo bar");
+ DoStrTest("foo %.2s", "bar", "foo ba");
+ DoStrTest("foo %5.2s", "bar", "foo ba");
+ DoStrTest("foo %-5s", "bar", "foo bar ");
+ DoStrTest("foo %05s", "bar", "foo 00bar");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/printf/test2/testinfo.dat
new file mode 100644
index 0000000000..3ff71c7496
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test2/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = printf
+Name = Positive Test for printf
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Tests printf with strings
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test3/CMakeLists.txt
new file mode 100644
index 0000000000..8bc7479797
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_printf_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_printf_test3 coreclrpal)
+
+target_link_libraries(paltest_printf_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test3/test3.c b/src/pal/tests/palsuite/c_runtime/printf/test3/test3.c
new file mode 100644
index 0000000000..5cc530948c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test3/test3.c
@@ -0,0 +1,45 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test3.c
+**
+** Purpose: Test #3 for the printf function. Tests the wide string
+** specifier (%S).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../printf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoWStrTest("foo %S", convert("bar"), "foo bar");
+ DoStrTest("foo %hS", "bar", "foo bar");
+ DoWStrTest("foo %lS", convert("bar"), "foo bar");
+ DoWStrTest("foo %wS", convert("bar"), "foo bar");
+ DoWStrTest("foo %LS", convert("bar"), "foo bar");
+ DoWStrTest("foo %I64S", convert("bar"), "foo bar");
+ DoWStrTest("foo %5S", convert("bar"), "foo bar");
+ DoWStrTest("foo %.2S", convert("bar"), "foo ba");
+ DoWStrTest("foo %5.2S", convert("bar"), "foo ba");
+ DoWStrTest("foo %-5S", convert("bar"), "foo bar ");
+ DoWStrTest("foo %05S", convert("bar"), "foo 00bar");
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/printf/test3/testinfo.dat
new file mode 100644
index 0000000000..295c172f09
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test3/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = printf
+Name = Positive Test for printf
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Tests printf with wide strings
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test4/CMakeLists.txt
new file mode 100644
index 0000000000..55e5700fe3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_printf_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_printf_test4 coreclrpal)
+
+target_link_libraries(paltest_printf_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test4/test4.c b/src/pal/tests/palsuite/c_runtime/printf/test4/test4.c
new file mode 100644
index 0000000000..bcdc201d4f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test4/test4.c
@@ -0,0 +1,66 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test4.c
+**
+** Purpose: Test #4 for the printf function. Tests the pointer
+** specifier (%p).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../printf.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+ void *ptr = (void*) 0x123456;
+ INT64 lptr = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+/*
+** Run only on 64 bit platforms
+*/
+#if defined(BIT64) && defined(PLATFORM_UNIX)
+ Trace("Testing for 64 Bit Platforms \n");
+ DoPointerTest("%p", NULL, "NULL", "0000000000000000");
+ DoPointerTest("%p", ptr, "pointer to 0x123456", "0000000000123456");
+ DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456");
+ DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456");
+ DoPointerTest("%-17p", ptr, "pointer to 0x123456", "0000000000123456 ");
+ DoPointerTest("%+p", ptr, "pointer to 0x123456", "0000000000123456");
+ DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X0000000000123456");
+ DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456");
+ DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456");
+ DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456");
+ DoI64Test("%I64p", lptr, "pointer to 0x1234567887654321",
+ "1234567887654321");
+#else
+ Trace("Testing for Non 64 Bit Platforms \n");
+ DoPointerTest("%p", NULL, "NULL", "00000000");
+ DoPointerTest("%p", ptr, "pointer to 0x123456", "00123456");
+ DoPointerTest("%9p", ptr, "pointer to 0x123456", " 00123456");
+ DoPointerTest("%09p", ptr, "pointer to 0x123456", " 00123456");
+ DoPointerTest("%-9p", ptr, "pointer to 0x123456", "00123456 ");
+ DoPointerTest("%+p", ptr, "pointer to 0x123456", "00123456");
+ DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X00123456");
+ DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456");
+ DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456");
+ DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456");
+ DoI64Test("%I64p", lptr, "pointer to 0x1234567887654321",
+ "1234567887654321");
+
+#endif
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test4/testinfo.dat b/src/pal/tests/palsuite/c_runtime/printf/test4/testinfo.dat
new file mode 100644
index 0000000000..0c55e0ed39
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test4/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = printf
+Name = Positive Test for printf
+TYPE = DEFAULT
+EXE1 = test4
+Description
+= Tests printf with pointers
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test5/CMakeLists.txt
new file mode 100644
index 0000000000..d091bca2dc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test5.c
+)
+
+add_executable(paltest_printf_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_printf_test5 coreclrpal)
+
+target_link_libraries(paltest_printf_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test5/test5.c b/src/pal/tests/palsuite/c_runtime/printf/test5/test5.c
new file mode 100644
index 0000000000..9f8baa74da
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test5/test5.c
@@ -0,0 +1,60 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test5.c
+**
+** Purpose: Test #5 for the printf function. Tests the count specifier (%n).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../printf.h"
+
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ char *longStr =
+ "really-long-string-that-just-keeps-going-on-and-on-and-on.."
+ "..................useless-filler.................................."
+ "..................useless-filler.................................."
+ "..................useless-filler.................................."
+ "%n bar";
+ char *longResult =
+ "really-long-string-that-just-keeps-going-on-and-on-and-on.."
+ "..................useless-filler.................................."
+ "..................useless-filler.................................."
+ "..................useless-filler.................................."
+ " bar";
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoCountTest("foo %n bar", 4, "foo bar");
+ DoCountTest(longStr, 257, longResult);
+ DoCountTest("fo%n bar", 2, "fo bar");
+ DoCountTest("%n", 0, "");
+ DoCountTest("foo %#n bar", 4, "foo bar");
+ DoCountTest("foo % n bar", 4, "foo bar");
+ DoCountTest("foo %+n bar", 4, "foo bar");
+ DoCountTest("foo %-n bar", 4, "foo bar");
+ DoCountTest("foo %0n bar", 4, "foo bar");
+ DoShortCountTest("foo %hn bar", 4, "foo bar");
+ DoCountTest("foo %ln bar", 4, "foo bar");
+ DoCountTest("foo %Ln bar", 4, "foo bar");
+ DoCountTest("foo %I64n bar", 4, "foo bar");
+ DoCountTest("foo %20.3n bar", 4, "foo bar");
+
+ PAL_Terminate();
+
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test5/testinfo.dat b/src/pal/tests/palsuite/c_runtime/printf/test5/testinfo.dat
new file mode 100644
index 0000000000..a7c7400f58
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test5/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = printf
+Name = Positive Test for printf
+TYPE = DEFAULT
+EXE1 = test5
+Description
+= Tests printf with the count specifier
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test6/CMakeLists.txt
new file mode 100644
index 0000000000..c004e353e9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test6.c
+)
+
+add_executable(paltest_printf_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_printf_test6 coreclrpal)
+
+target_link_libraries(paltest_printf_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test6/test6.c b/src/pal/tests/palsuite/c_runtime/printf/test6/test6.c
new file mode 100644
index 0000000000..edc65b6b9b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test6/test6.c
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test6.c
+**
+** Purpose: Test #6 for the printf function. Tests the char specifier (%c).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../printf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR wc = (WCHAR) 'c';
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoCharTest("foo %c", 'b', "foo b");
+ DoCharTest("foo %hc", 'b', "foo b");
+ DoWCharTest("foo %lc", wc, "foo c");
+ DoCharTest("foo %Lc", 'b', "foo b");
+ DoCharTest("foo %I64c", 'b', "foo b");
+ DoCharTest("foo %5c", 'b', "foo b");
+ DoCharTest("foo %.0c", 'b', "foo b");
+ DoCharTest("foo %-5c", 'b', "foo b ");
+ DoCharTest("foo %05c", 'b', "foo 0000b");
+ DoCharTest("foo % c", 'b', "foo b");
+ DoCharTest("foo %#c", 'b', "foo b");
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test6/testinfo.dat b/src/pal/tests/palsuite/c_runtime/printf/test6/testinfo.dat
new file mode 100644
index 0000000000..fd8a985291
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test6/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = printf
+Name = Positive Test for printf
+TYPE = DEFAULT
+EXE1 = test6
+Description
+= Tests printf with characters
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test7/CMakeLists.txt
new file mode 100644
index 0000000000..ff6b647ccd
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test7/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test7.c
+)
+
+add_executable(paltest_printf_test7
+ ${SOURCES}
+)
+
+add_dependencies(paltest_printf_test7 coreclrpal)
+
+target_link_libraries(paltest_printf_test7
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test7/test7.c b/src/pal/tests/palsuite/c_runtime/printf/test7/test7.c
new file mode 100644
index 0000000000..3aeb58f7dc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test7/test7.c
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test7.c
+**
+** Purpose: Test #7 for the printf function. Tests the wide char
+** specifier (%C).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../printf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR wb = (WCHAR) 'b';
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoWCharTest("foo %C", wb, "foo b");
+ DoWCharTest("foo %hC", wb, "foo b");
+ DoCharTest("foo %lC", 'c', "foo c");
+ DoWCharTest("foo %LC", wb, "foo b");
+ DoWCharTest("foo %I64C", wb, "foo b");
+ DoWCharTest("foo %5C", wb, "foo b");
+ DoWCharTest("foo %.0C", wb, "foo b");
+ DoWCharTest("foo %-5C", wb, "foo b ");
+ DoWCharTest("foo %05C", wb, "foo 0000b");
+ DoWCharTest("foo % C", wb, "foo b");
+ DoWCharTest("foo %#C", wb, "foo b");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test7/testinfo.dat b/src/pal/tests/palsuite/c_runtime/printf/test7/testinfo.dat
new file mode 100644
index 0000000000..6d2b1cf84e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test7/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = printf
+Name = Positive Test for printf
+TYPE = DEFAULT
+EXE1 = test7
+Description
+= Tests printf with wide characters
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test8/CMakeLists.txt
new file mode 100644
index 0000000000..5ee387f5b8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test8/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test8.c
+)
+
+add_executable(paltest_printf_test8
+ ${SOURCES}
+)
+
+add_dependencies(paltest_printf_test8 coreclrpal)
+
+target_link_libraries(paltest_printf_test8
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test8/test8.c b/src/pal/tests/palsuite/c_runtime/printf/test8/test8.c
new file mode 100644
index 0000000000..daa4674b92
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test8/test8.c
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test8.c
+**
+** Purpose: Test #8 for the printf function. Tests the decimal
+** specifier (%d).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../printf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest("foo %d", pos, "foo 42");
+ DoNumTest("foo %ld", 0xFFFF, "foo 65535");
+ DoNumTest("foo %hd", 0xFFFF, "foo -1");
+ DoNumTest("foo %Ld", pos, "foo 42");
+ DoI64Test("foo %I64d", l, "42", "foo 42");
+ DoNumTest("foo %3d", pos, "foo 42");
+ DoNumTest("foo %-3d", pos, "foo 42 ");
+ DoNumTest("foo %.1d", pos, "foo 42");
+ DoNumTest("foo %.3d", pos, "foo 042");
+ DoNumTest("foo %03d", pos, "foo 042");
+ DoNumTest("foo %#d", pos, "foo 42");
+ DoNumTest("foo %+d", pos, "foo +42");
+ DoNumTest("foo % d", pos, "foo 42");
+ DoNumTest("foo %+d", neg, "foo -42");
+ DoNumTest("foo % d", neg, "foo -42");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test8/testinfo.dat b/src/pal/tests/palsuite/c_runtime/printf/test8/testinfo.dat
new file mode 100644
index 0000000000..6367235aa5
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test8/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = printf
+Name = Positive Test for printf
+TYPE = DEFAULT
+EXE1 = test8
+Description
+= Tests printf with decimal numbers
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test9/CMakeLists.txt
new file mode 100644
index 0000000000..baf46c1065
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test9/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test9.c
+)
+
+add_executable(paltest_printf_test9
+ ${SOURCES}
+)
+
+add_dependencies(paltest_printf_test9 coreclrpal)
+
+target_link_libraries(paltest_printf_test9
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test9/test9.c b/src/pal/tests/palsuite/c_runtime/printf/test9/test9.c
new file mode 100644
index 0000000000..22c60d04f2
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test9/test9.c
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test9.c
+**
+** Purpose: Test #9 for the printf function. Tests the integer
+** specifier (%i).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../printf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest("foo %i", pos, "foo 42");
+ DoNumTest("foo %li", 0xFFFF, "foo 65535");
+ DoNumTest("foo %hi", 0xFFFF, "foo -1");
+ DoNumTest("foo %Li", pos, "foo 42");
+ DoI64Test("foo %I64i", l, "42", "foo 42");
+ DoNumTest("foo %3i", pos, "foo 42");
+ DoNumTest("foo %-3i", pos, "foo 42 ");
+ DoNumTest("foo %.1i", pos, "foo 42");
+ DoNumTest("foo %.3i", pos, "foo 042");
+ DoNumTest("foo %03i", pos, "foo 042");
+ DoNumTest("foo %#i", pos, "foo 42");
+ DoNumTest("foo %+i", pos, "foo +42");
+ DoNumTest("foo % i", pos, "foo 42");
+ DoNumTest("foo %+i", neg, "foo -42");
+ DoNumTest("foo % i", neg, "foo -42");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/printf/test9/testinfo.dat b/src/pal/tests/palsuite/c_runtime/printf/test9/testinfo.dat
new file mode 100644
index 0000000000..3208cb44a5
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/printf/test9/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = printf
+Name = Positive Test for printf
+TYPE = DEFAULT
+EXE1 = test9
+Description
+= Tests printf with integer numbers
diff --git a/src/pal/tests/palsuite/c_runtime/qsort/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/qsort/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/qsort/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/c_runtime/qsort/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/qsort/test1/CMakeLists.txt
new file mode 100644
index 0000000000..105a727e91
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/qsort/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_qsort_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_qsort_test1 coreclrpal)
+
+target_link_libraries(paltest_qsort_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/qsort/test1/test1.c b/src/pal/tests/palsuite/c_runtime/qsort/test1/test1.c
new file mode 100644
index 0000000000..c65fb18e68
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/qsort/test1/test1.c
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Calls qsort to sort a buffer, and verifies that it has done
+** the job correctly.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl charcmp(const void *pa, const void *pb)
+{
+ return memcmp(pa, pb, 1);
+}
+
+int __cdecl main(int argc, char **argv)
+{
+ char before[] = "cgaiehdbjf";
+ const char after[] = "abcdefghij";
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ qsort(before, sizeof(before) - 1, sizeof(char), charcmp);
+
+ if (memcmp(before, after, sizeof(before)) != 0)
+ {
+ Fail("qsort did not correctly sort an array of characters.\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/qsort/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/qsort/test1/testinfo.dat
new file mode 100644
index 0000000000..7e3b4b87c3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/qsort/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = qsort
+Name = Positive Test for qsort
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Calls qsort to sort a buffer, and verifies that it has done the job correctly.
diff --git a/src/pal/tests/palsuite/c_runtime/qsort/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/qsort/test2/CMakeLists.txt
new file mode 100644
index 0000000000..09e3f6db1e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/qsort/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_qsort_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_qsort_test2 coreclrpal)
+
+target_link_libraries(paltest_qsort_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/qsort/test2/test2.c b/src/pal/tests/palsuite/c_runtime/qsort/test2/test2.c
new file mode 100644
index 0000000000..8110dcd2c2
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/qsort/test2/test2.c
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test2.c
+**
+** Purpose: Calls qsort to sort a buffer, and verifies that it has done
+** the job correctly.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl twocharcmp(const void *pa, const void *pb)
+{
+ return memcmp(pa, pb, 2);
+}
+
+int __cdecl main(int argc, char **argv)
+{
+ char before[] = "ccggaaiieehhddbbjjff";
+ const char after[] = "aabbccddeeffgghhiijj";
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ qsort(before, (sizeof(before) - 1) / 2, 2 * sizeof(char), twocharcmp);
+
+ if (memcmp(before, after, sizeof(before)) != 0)
+ {
+ Fail("qsort did not correctly sort an array of 2-character "
+ "buffers.\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/qsort/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/qsort/test2/testinfo.dat
new file mode 100644
index 0000000000..35f5f06076
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/qsort/test2/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = qsort
+Name = Positive Test for qsort
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Calls qsort to sort a buffer, and verifies that it has done the job correctly.
diff --git a/src/pal/tests/palsuite/c_runtime/rand_srand/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/rand_srand/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/rand_srand/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/rand_srand/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/rand_srand/test1/CMakeLists.txt
new file mode 100644
index 0000000000..939914662a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/rand_srand/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_rand_srand_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_rand_srand_test1 coreclrpal)
+
+target_link_libraries(paltest_rand_srand_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/rand_srand/test1/test1.c b/src/pal/tests/palsuite/c_runtime/rand_srand/test1/test1.c
new file mode 100644
index 0000000000..34154cb6d2
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/rand_srand/test1/test1.c
@@ -0,0 +1,100 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test to ensure that srand provide random
+** number to rand. Also make sure that rand result from a
+** srand with seed 1 and no call to srand are the same.
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** srand()
+**
+
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char **argv)
+{
+ int RandNumber[10];
+ int TempRandNumber;
+ int i;
+ int SRAND_SEED;
+ int SRAND_REINIT = 1;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ SRAND_SEED = time(NULL);
+
+ /* does not initialize srand and call rand. */
+ for (i=0; i<10; i++)
+ {
+ /* keep the value in a array */
+ RandNumber[i]=rand();
+ if (RandNumber[i] < 0 || RandNumber[i] > RAND_MAX)
+ {
+ Fail("1) ERROR: random generated an invalid value: %d", RandNumber[i]);
+ }
+ }
+
+
+ /* initialize random generator */
+ srand(SRAND_SEED);
+
+
+ /* choose 10 numbers with a different seed.
+ the numbers should be different than
+ those the previously generated one */
+ for(i = 0; i < 10; i++)
+ {
+ TempRandNumber=rand();
+ if (TempRandNumber < 0 || TempRandNumber > RAND_MAX)
+ {
+ Fail("2) ERROR: random generated an invalid value: %d", TempRandNumber);
+ }
+ }
+
+
+
+ /* renitialize the srand with 1 */
+ srand(SRAND_REINIT);
+
+
+
+ /* choose 10 numbers with seed 1,
+ the number should be the same as those we kept in the array. */
+ for( i = 0; i < 10;i++ )
+ {
+ /* pick the random number*/
+ TempRandNumber=rand();
+ /* test if it is the same number generated in the first sequences*/
+ if(RandNumber[i]!=TempRandNumber)
+ {
+ Fail ("ERROR: rand should return the same value when srand "
+ "is initialized with 1 or not initialized at all");
+ }
+ if (TempRandNumber < 0 || TempRandNumber > RAND_MAX)
+ {
+ Fail("3) ERROR: random generated an invalid value: %d", TempRandNumber);
+ }
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/rand_srand/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/rand_srand/test1/testinfo.dat
new file mode 100644
index 0000000000..cf1b42dbf0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/rand_srand/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = rand and srand
+Name = Positive Test for rand and srand
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Call rand without srand and get 10 random number batch 1.
+= call srand with seed 2, get 10 other random number and verify
+= that numbers are different from the batch 1.
+= Set the seed to 1, get 10 other random number and verify
+= that the generated number are the same as batch 1.
diff --git a/src/pal/tests/palsuite/c_runtime/realloc/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/realloc/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/realloc/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/realloc/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/realloc/test1/CMakeLists.txt
new file mode 100644
index 0000000000..0a9f34fc3b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/realloc/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_realloc_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_realloc_test1 coreclrpal)
+
+target_link_libraries(paltest_realloc_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/realloc/test1/test1.c b/src/pal/tests/palsuite/c_runtime/realloc/test1/test1.c
new file mode 100644
index 0000000000..d0dd128cc1
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/realloc/test1/test1.c
@@ -0,0 +1,66 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Uses realloc to allocate and realloate memory, checking
+** that memory contents are copied when the memory is reallocated.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ char *testA;
+ const int len1 = 10;
+ const char str1[] = "aaaaaaaaaa";
+
+ const int len2 = 20;
+ const char str2[] = "bbbbbbbbbbbbbbbbbbbb";
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* this should work like malloc */
+ testA = (char *)realloc(NULL, len1*sizeof(char));
+ memcpy(testA, str1, len1);
+ if (testA == NULL)
+ {
+ Fail("We ran out of memory (unlikely), or realloc is broken.\n");
+ }
+
+ if (memcmp(testA, str1, len1) != 0)
+ {
+ Fail("realloc doesn't properly allocate new memory.\n");
+ }
+
+ testA = (char *)realloc(testA, len2*sizeof(char));
+ if (memcmp(testA, str1, len1) != 0)
+ {
+ Fail("realloc doesn't move the contents of the original memory "
+ "block to the newly allocated block.\n");
+ }
+
+ memcpy(testA, str2, len2);
+ if (memcmp(testA, str2, len2) != 0)
+ {
+ Fail("Couldn't write to memory allocated by realloc.\n");
+ }
+
+ /* free the buffer */
+ testA = realloc(testA, 0);
+ if (testA != NULL)
+ {
+ Fail("Realloc didn't return NULL when called with a length "
+ "of zero.\n");
+ }
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/realloc/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/realloc/test1/testinfo.dat
new file mode 100644
index 0000000000..5d2a32224e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/realloc/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = realloc
+Name = Positive Test for realloc
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Uses realloc to allocate and realloate memory, checking that memory
+= contents are copied when the memory is reallocated.
+
diff --git a/src/pal/tests/palsuite/c_runtime/sin/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sin/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sin/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/sin/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sin/test1/CMakeLists.txt
new file mode 100644
index 0000000000..e074337452
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sin/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_sin_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sin_test1 coreclrpal)
+
+target_link_libraries(paltest_sin_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sin/test1/test1.c b/src/pal/tests/palsuite/c_runtime/sin/test1/test1.c
new file mode 100644
index 0000000000..bec58d4dd9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sin/test1/test1.c
@@ -0,0 +1,131 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test to ensure that sin return the correct values
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** fabs
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (15-17 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use
+// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx
+// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will
+// use PAL_EPSILON * 10.
+#define PAL_EPSILON 8.8817841970012523e-16
+
+#define PAL_NAN sqrt(-1.0)
+#define PAL_POSINF -log(0.0)
+#define PAL_NEGINF log(0.0)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ double value; /* value to test the function with */
+ double expected; /* expected result */
+ double variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(double value, double expected, double variance)
+{
+ double result = sin(value);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ double delta = fabs(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("sin(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(double value)
+{
+ double result = sin(value);
+
+ if (!_isnan(result))
+ {
+ Fail("sin(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char **argv)
+{
+ struct test tests[] =
+ {
+ /* value expected variance */
+ { 0, 0, PAL_EPSILON },
+ { 0.31830988618379067, 0.31296179620778659, PAL_EPSILON }, // value: 1 / pi
+ { 0.43429448190325183, 0.42077048331375735, PAL_EPSILON }, // value: log10(e)
+ { 0.63661977236758134, 0.59448076852482208, PAL_EPSILON }, // value: 2 / pi
+ { 0.69314718055994531, 0.63896127631363480, PAL_EPSILON }, // value: ln(2)
+ { 0.70710678118654752, 0.64963693908006244, PAL_EPSILON }, // value: 1 / sqrt(2)
+ { 0.78539816339744831, 0.70710678118654752, PAL_EPSILON }, // value: pi / 4, expected: 1 / sqrt(2)
+ { 1, 0.84147098480789651, PAL_EPSILON },
+ { 1.1283791670955126, 0.90371945743584630, PAL_EPSILON }, // value: 2 / sqrt(pi)
+ { 1.4142135623730950, 0.98776594599273553, PAL_EPSILON }, // value: sqrt(2)
+ { 1.4426950408889634, 0.99180624439366372, PAL_EPSILON }, // value: log2(e)
+ { 1.5707963267948966, 1, PAL_EPSILON * 10 }, // value: pi / 2
+ { 2.3025850929940457, 0.74398033695749319, PAL_EPSILON }, // value: ln(10)
+ { 2.7182818284590452, 0.41078129050290870, PAL_EPSILON }, // value: e
+ { 3.1415926535897932, 0, PAL_EPSILON }, // value: pi
+ };
+
+ /* PAL initialization */
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate( tests[i].value, tests[i].expected, tests[i].variance);
+ validate(-tests[i].value, -tests[i].expected, tests[i].variance);
+ }
+
+ validate_isnan(PAL_NEGINF);
+ validate_isnan(PAL_NAN);
+ validate_isnan(PAL_POSINF);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/sin/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sin/test1/testinfo.dat
new file mode 100644
index 0000000000..57eae6bfd1
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sin/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sin
+Name = Positive Test for sin
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes to sin() a series of angle value, checking that
+= each one return to correct value.
diff --git a/src/pal/tests/palsuite/c_runtime/sinh/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sinh/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sinh/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/sinh/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sinh/test1/CMakeLists.txt
new file mode 100644
index 0000000000..66cc691d92
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sinh/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_sinh_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sinh_test1 coreclrpal)
+
+target_link_libraries(paltest_sinh_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sinh/test1/test1.c b/src/pal/tests/palsuite/c_runtime/sinh/test1/test1.c
new file mode 100644
index 0000000000..e790b16fb4
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sinh/test1/test1.c
@@ -0,0 +1,130 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test to ensure that sinh return the correct values
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** fabs
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (15-17 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use
+// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx
+// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will
+// use PAL_EPSILON * 10.
+#define PAL_EPSILON 8.8817841970012523e-16
+
+#define PAL_NAN sqrt(-1.0)
+#define PAL_POSINF -log(0.0)
+#define PAL_NEGINF log(0.0)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ double value; /* value to test the function with */
+ double expected; /* expected result */
+ double variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(double value, double expected, double variance)
+{
+ double result = sinh(value);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ double delta = fabs(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("sinh(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(double value)
+{
+ double result = sinh(value);
+
+ if (!_isnan(result))
+ {
+ Fail("sinh(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char **argv)
+{
+ struct test tests[] =
+ {
+ /* value expected variance */
+ { 0, 0, PAL_EPSILON },
+ { 0.31830988618379067, 0.32371243907207108, PAL_EPSILON }, // value: 1 / pi
+ { 0.43429448190325183, 0.44807597941469025, PAL_EPSILON }, // value: log10(e)
+ { 0.63661977236758134, 0.68050167815224332, PAL_EPSILON }, // value: 2 / pi
+ { 0.69314718055994531, 0.75, PAL_EPSILON }, // value: ln(2)
+ { 0.70710678118654752, 0.76752314512611633, PAL_EPSILON }, // value: 1 / sqrt(2)
+ { 0.78539816339744831, 0.86867096148600961, PAL_EPSILON }, // value: pi / 4
+ { 1, 1.1752011936438015, PAL_EPSILON * 10 },
+ { 1.1283791670955126, 1.3835428792038633, PAL_EPSILON * 10 }, // value: 2 / sqrt(pi)
+ { 1.4142135623730950, 1.9350668221743567, PAL_EPSILON * 10 }, // value: sqrt(2)
+ { 1.4426950408889634, 1.9978980091062796, PAL_EPSILON * 10 }, // value: log2(e)
+ { 1.5707963267948966, 2.3012989023072949, PAL_EPSILON * 10 }, // value: pi / 2
+ { 2.3025850929940457, 4.95, PAL_EPSILON * 10 }, // value: ln(10)
+ { 2.7182818284590452, 7.5441371028169758, PAL_EPSILON * 10 }, // value: e
+ { 3.1415926535897932, 11.548739357257748, PAL_EPSILON * 100 }, // value: pi
+ { PAL_POSINF, PAL_POSINF, 0 },
+ };
+
+ /* PAL initialization */
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate( tests[i].value, tests[i].expected, tests[i].variance);
+ validate(-tests[i].value, -tests[i].expected, tests[i].variance);
+ }
+
+ validate_isnan(PAL_NAN);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/sinh/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sinh/test1/testinfo.dat
new file mode 100644
index 0000000000..f7aee40201
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sinh/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sinh
+Name = Positive Test for sinh
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes to sinh() a series of angle value, checking that
+= each one return to correct value.
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/CMakeLists.txt
new file mode 100644
index 0000000000..cafb9536b0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/CMakeLists.txt
@@ -0,0 +1,22 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test10)
+add_subdirectory(test11)
+add_subdirectory(test12)
+add_subdirectory(test13)
+add_subdirectory(test14)
+add_subdirectory(test15)
+add_subdirectory(test16)
+add_subdirectory(test17)
+add_subdirectory(test18)
+add_subdirectory(test19)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+add_subdirectory(test7)
+add_subdirectory(test8)
+add_subdirectory(test9)
+
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/sprintf.h b/src/pal/tests/palsuite/c_runtime/sprintf/sprintf.h
new file mode 100644
index 0000000000..411ae66d54
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/sprintf.h
@@ -0,0 +1,195 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: sprintf.h
+**
+** Purpose: Containts common testing functions for sprintf
+**
+**
+**==========================================================================*/
+
+#ifndef __SPRINTF_H__
+#define __SPRINTF_H__
+
+void DoStrTest(char *formatstr, char* param, char *checkstr)
+{
+ char buf[256] = { 0 };
+
+ sprintf(buf, formatstr, param);
+ if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert string \"%s\" into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ param, formatstr, checkstr, buf);
+ }
+}
+
+void DoWStrTest(char *formatstr, WCHAR* param, char *checkstr)
+{
+ char buf[256] = { 0 };
+
+ sprintf(buf, formatstr, param);
+ if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert wide string \"%s\" into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ convertC(param), formatstr, checkstr, buf);
+ }
+}
+
+void DoPointerTest(char *formatstr, void* param, char* paramstr,
+ char *checkstr1)
+{
+ char buf[256] = { 0 };
+
+ sprintf(buf, formatstr, param);
+ if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %s into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ paramstr, formatstr, checkstr1, buf);
+ }
+}
+
+void DoCountTest(char *formatstr, int param, char *checkstr)
+{
+ char buf[512] = { 0 };
+ int n = -1;
+
+ sprintf(buf, formatstr, &n);
+
+ if (n != param)
+ {
+ Fail("ERROR: Expected count parameter to resolve to %d, got %X\n",
+ param, n);
+ }
+ if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0)
+ {
+ Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf);
+ }
+}
+
+void DoShortCountTest(char *formatstr, int param, char *checkstr)
+{
+ char buf[256] = { 0 };
+ short int n = -1;
+
+ sprintf(buf, formatstr, &n);
+
+ if (n != param)
+ {
+ Fail("ERROR: Expected count parameter to resolve to %d, got %X\n",
+ param, n);
+ }
+ if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0)
+ {
+ Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf);
+ }
+}
+
+
+void DoCharTest(char *formatstr, char param, char *checkstr)
+{
+ char buf[256] = { 0 };
+
+ sprintf(buf, formatstr, param);
+ if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert char \'%c\' (%d) into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ param, param, formatstr, checkstr, buf);
+ }
+}
+
+void DoWCharTest(char *formatstr, WCHAR param, char *checkstr)
+{
+ char buf[256] = { 0 };
+
+ sprintf(buf, formatstr, param);
+ if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert wide char \'%c\' (%d) into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ (char)param, param, formatstr, checkstr, buf);
+ }
+}
+
+void DoNumTest(char *formatstr, int value, char *checkstr)
+{
+ char buf[256] = { 0 };
+
+ sprintf(buf, formatstr, value);
+ if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %#x into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ value, formatstr, checkstr, buf);
+ }
+}
+
+void DoI64Test(char *formatstr, INT64 value, char *valuestr, char *checkstr1)
+{
+ char buf[256] = { 0 };
+
+ sprintf(buf, formatstr, value);
+ if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %s into \"%s\"\n"
+ "Expected \"%s\", got \"%s\".\n",
+ valuestr, formatstr, checkstr1, buf);
+ }
+}
+
+void DoDoubleTest(char *formatstr, double value, char *checkstr1,
+ char *checkstr2)
+{
+ char buf[256] = { 0 };
+
+ sprintf(buf, formatstr, value);
+ if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 &&
+ memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %f into \"%s\"\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n",
+ value, formatstr, checkstr1, checkstr2, buf);
+ }
+}
+
+void DoArgumentPrecTest(char *formatstr, int precision, void *param,
+ char *paramstr, char *checkstr1, char *checkstr2)
+{
+ char buf[256];
+
+ sprintf(buf, formatstr, precision, param);
+ if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 &&
+ memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n", paramstr, formatstr,
+ precision, checkstr1, checkstr2, buf);
+ }
+
+}
+
+void DoArgumentPrecDoubleTest(char *formatstr, int precision, double param,
+ char *checkstr1, char *checkstr2)
+{
+ char buf[256];
+
+ sprintf(buf, formatstr, precision, param);
+ if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 &&
+ memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n", param, formatstr,
+ precision, checkstr1, checkstr2, buf);
+ }
+
+}
+
+#endif
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..bdec045af9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_sprintf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sprintf_test1 coreclrpal)
+
+target_link_libraries(paltest_sprintf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/sprintf/test1/test1.c
new file mode 100644
index 0000000000..42e27f263b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test1/test1.c
@@ -0,0 +1,45 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test #1 for the sprintf function. A single, basic, test
+** case with no formatting.
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../sprintf.h"
+
+/*
+ * Depends on memcmp and strlen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ char checkstr[] = "hello world";
+ char buf[256];
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ sprintf(buf, "hello world");
+
+ if (memcmp(checkstr, buf, strlen(checkstr)+1) != 0)
+ {
+ Fail("ERROR: expected %s, got %s\n", checkstr, buf);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test1/testinfo.dat
new file mode 100644
index 0000000000..abe07445cc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sprintf
+Name = Positive Test for sprintf
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= General test to see if sprintf works correctly
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test10/CMakeLists.txt
new file mode 100644
index 0000000000..91e9db8ccc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test10/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test10.c
+)
+
+add_executable(paltest_sprintf_test10
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sprintf_test10 coreclrpal)
+
+target_link_libraries(paltest_sprintf_test10
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test10/test10.c b/src/pal/tests/palsuite/c_runtime/sprintf/test10/test10.c
new file mode 100644
index 0000000000..ae7dbfb177
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test10/test10.c
@@ -0,0 +1,55 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test10.c
+**
+** Purpose: Test #10 for the sprintf function. Tests the octal specifier
+** (%o).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../sprintf.h"
+
+/*
+ * Depends on memcmp and strlen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest("foo %o", pos, "foo 52");
+ DoNumTest("foo %lo", 0xFFFF, "foo 177777");
+ DoNumTest("foo %ho", 0xFFFF, "foo 177777");
+ DoNumTest("foo %Lo", pos, "foo 52");
+ DoI64Test("foo %I64o", l, "42", "foo 52");
+ DoNumTest("foo %3o", pos, "foo 52");
+ DoNumTest("foo %-3o", pos, "foo 52 ");
+ DoNumTest("foo %.1o", pos, "foo 52");
+ DoNumTest("foo %.3o", pos, "foo 052");
+ DoNumTest("foo %03o", pos, "foo 052");
+ DoNumTest("foo %#o", pos, "foo 052");
+ DoNumTest("foo %+o", pos, "foo 52");
+ DoNumTest("foo % o", pos, "foo 52");
+ DoNumTest("foo %+o", neg, "foo 37777777726");
+ DoNumTest("foo % o", neg, "foo 37777777726");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test10/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test10/testinfo.dat
new file mode 100644
index 0000000000..70b7f3ab75
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test10/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sprintf
+Name = Positive Test for sprintf
+TYPE = DEFAULT
+EXE1 = test10
+Description
+= Tests sprintf with octal numbers
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test11/CMakeLists.txt
new file mode 100644
index 0000000000..b14c8be04d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test11/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test11.c
+)
+
+add_executable(paltest_sprintf_test11
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sprintf_test11 coreclrpal)
+
+target_link_libraries(paltest_sprintf_test11
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test11/test11.c b/src/pal/tests/palsuite/c_runtime/sprintf/test11/test11.c
new file mode 100644
index 0000000000..0b5b5ab93d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test11/test11.c
@@ -0,0 +1,55 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test11.c
+**
+** Purpose: Test #11 for the sprintf function. Test the unsigned int
+** specifier (%u).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../sprintf.h"
+
+/*
+ * Depends on memcmp and strlen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest("foo %u", pos, "foo 42");
+ DoNumTest("foo %lu", 0xFFFF, "foo 65535");
+ DoNumTest("foo %hu", 0xFFFF, "foo 65535");
+ DoNumTest("foo %Lu", pos, "foo 42");
+ DoI64Test("foo %I64u", l, "42", "foo 42");
+ DoNumTest("foo %3u", pos, "foo 42");
+ DoNumTest("foo %-3u", pos, "foo 42 ");
+ DoNumTest("foo %.1u", pos, "foo 42");
+ DoNumTest("foo %.3u", pos, "foo 042");
+ DoNumTest("foo %03u", pos, "foo 042");
+ DoNumTest("foo %#u", pos, "foo 42");
+ DoNumTest("foo %+u", pos, "foo 42");
+ DoNumTest("foo % u", pos, "foo 42");
+ DoNumTest("foo %+u", neg, "foo 4294967254");
+ DoNumTest("foo % u", neg, "foo 4294967254");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test11/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test11/testinfo.dat
new file mode 100644
index 0000000000..852bd3e7b6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test11/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sprintf
+Name = Positive Test for sprintf
+TYPE = DEFAULT
+EXE1 = test11
+Description
+= Tests sprintf with unsigned numbers
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test12/CMakeLists.txt
new file mode 100644
index 0000000000..1e517495bd
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test12/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test12.c
+)
+
+add_executable(paltest_sprintf_test12
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sprintf_test12 coreclrpal)
+
+target_link_libraries(paltest_sprintf_test12
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test12/test12.c b/src/pal/tests/palsuite/c_runtime/sprintf/test12/test12.c
new file mode 100644
index 0000000000..c2e778e494
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test12/test12.c
@@ -0,0 +1,56 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test12.c
+**
+** Purpose: Test #12 for the sprintf function. Tests the (lowercase)
+** hexadecimal specifier (%x)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../sprintf.h"
+
+/*
+ * Depends on memcmp and strlen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 0x1234ab;
+ INT64 l = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest("foo %x", pos, "foo 1234ab");
+ DoNumTest("foo %lx", pos, "foo 1234ab");
+ DoNumTest("foo %hx", pos, "foo 34ab");
+ DoNumTest("foo %Lx", pos, "foo 1234ab");
+ DoI64Test("foo %I64x", l, "0x1234567887654321",
+ "foo 1234567887654321");
+ DoNumTest("foo %7x", pos, "foo 1234ab");
+ DoNumTest("foo %-7x", pos, "foo 1234ab ");
+ DoNumTest("foo %.1x", pos, "foo 1234ab");
+ DoNumTest("foo %.7x", pos, "foo 01234ab");
+ DoNumTest("foo %07x", pos, "foo 01234ab");
+ DoNumTest("foo %#x", pos, "foo 0x1234ab");
+ DoNumTest("foo %+x", pos, "foo 1234ab");
+ DoNumTest("foo % x", pos, "foo 1234ab");
+ DoNumTest("foo %+x", neg, "foo ffffffd6");
+ DoNumTest("foo % x", neg, "foo ffffffd6");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test12/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test12/testinfo.dat
new file mode 100644
index 0000000000..5df91d0e6a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test12/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sprintf
+Name = Positive Test for sprintf
+TYPE = DEFAULT
+EXE1 = test12
+Description
+= Tests sprintf with hex numbers (lowercase)
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test13/CMakeLists.txt
new file mode 100644
index 0000000000..25b033fe82
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test13/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test13.c
+)
+
+add_executable(paltest_sprintf_test13
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sprintf_test13 coreclrpal)
+
+target_link_libraries(paltest_sprintf_test13
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test13/test13.c b/src/pal/tests/palsuite/c_runtime/sprintf/test13/test13.c
new file mode 100644
index 0000000000..0b4b7ed9ae
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test13/test13.c
@@ -0,0 +1,56 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test13.c
+**
+** Purpose: Test #13 for the sprintf function. Tests the (uppercase)
+** hexadecimal specifier (%X)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../sprintf.h"
+
+/*
+ * Depends on memcmp and strlen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 0x1234AB;
+ INT64 l = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest("foo %X", pos, "foo 1234AB");
+ DoNumTest("foo %lX", pos, "foo 1234AB");
+ DoNumTest("foo %hX", pos, "foo 34AB");
+ DoNumTest("foo %LX", pos, "foo 1234AB");
+ DoI64Test("foo %I64X", l, "0x1234567887654321",
+ "foo 1234567887654321");
+ DoNumTest("foo %7X", pos, "foo 1234AB");
+ DoNumTest("foo %-7X", pos, "foo 1234AB ");
+ DoNumTest("foo %.1X", pos, "foo 1234AB");
+ DoNumTest("foo %.7X", pos, "foo 01234AB");
+ DoNumTest("foo %07X", pos, "foo 01234AB");
+ DoNumTest("foo %#X", pos, "foo 0X1234AB");
+ DoNumTest("foo %+X", pos, "foo 1234AB");
+ DoNumTest("foo % X", pos, "foo 1234AB");
+ DoNumTest("foo %+X", neg, "foo FFFFFFD6");
+ DoNumTest("foo % X", neg, "foo FFFFFFD6");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test13/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test13/testinfo.dat
new file mode 100644
index 0000000000..634817a791
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test13/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sprintf
+Name = Positive Test for sprintf
+TYPE = DEFAULT
+EXE1 = test13
+Description
+= Tests sprintf with hex numbers (uppercase)
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test14/CMakeLists.txt
new file mode 100644
index 0000000000..5eae306e16
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test14/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test14.c
+)
+
+add_executable(paltest_sprintf_test14
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sprintf_test14 coreclrpal)
+
+target_link_libraries(paltest_sprintf_test14
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test14/test14.c b/src/pal/tests/palsuite/c_runtime/sprintf/test14/test14.c
new file mode 100644
index 0000000000..20e986a9c3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test14/test14.c
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test14.c
+**
+** Purpose: Test #14 for the sprintf function. Tests the lowercase
+** exponential notation double specifier (%e)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../sprintf.h"
+
+/*
+ * Depends on memcmp and strlen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 256.0;
+ double neg = -256.0;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest("foo %e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %le", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %he", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %Le", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %I64e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %14e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %-14e", val, "foo 2.560000e+002 ", "foo 2.560000e+02 ");
+ DoDoubleTest("foo %.1e", val, "foo 2.6e+002", "foo 2.6e+02");
+ DoDoubleTest("foo %.8e", val, "foo 2.56000000e+002", "foo 2.56000000e+02");
+ DoDoubleTest("foo %014e", val, "foo 02.560000e+002", "foo 002.560000e+02");
+ DoDoubleTest("foo %#e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %+e", val, "foo +2.560000e+002", "foo +2.560000e+02");
+ DoDoubleTest("foo % e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %+e", neg, "foo -2.560000e+002", "foo -2.560000e+02");
+ DoDoubleTest("foo % e", neg, "foo -2.560000e+002", "foo -2.560000e+02");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test14/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test14/testinfo.dat
new file mode 100644
index 0000000000..c7086efdbc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test14/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sprintf
+Name = Positive Test for sprintf
+TYPE = DEFAULT
+EXE1 = test14
+Description
+= Tests sprintf with exponential format doubles (lowercase)
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test15/CMakeLists.txt
new file mode 100644
index 0000000000..1fff23fc89
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test15/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test15.c
+)
+
+add_executable(paltest_sprintf_test15
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sprintf_test15 coreclrpal)
+
+target_link_libraries(paltest_sprintf_test15
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test15/test15.c b/src/pal/tests/palsuite/c_runtime/sprintf/test15/test15.c
new file mode 100644
index 0000000000..34199b2eb3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test15/test15.c
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test15.c
+**
+** Purpose: Test #15 for the sprintf function. Tests the uppercase
+** exponential notation double specifier (%E)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../sprintf.h"
+
+/*
+ * Depends on memcmp and strlen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 256.0;
+ double neg = -256.0;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest("foo %E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %lE", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %hE", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %LE", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %I64E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %14E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %-14E", val, "foo 2.560000E+002 ", "foo 2.560000E+02 ");
+ DoDoubleTest("foo %.1E", val, "foo 2.6E+002", "foo 2.6E+02");
+ DoDoubleTest("foo %.8E", val, "foo 2.56000000E+002", "foo 2.56000000E+02");
+ DoDoubleTest("foo %014E", val, "foo 02.560000E+002", "foo 002.560000E+02");
+ DoDoubleTest("foo %#E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %+E", val, "foo +2.560000E+002", "foo +2.560000E+02");
+ DoDoubleTest("foo % E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %+E", neg, "foo -2.560000E+002", "foo -2.560000E+02");
+ DoDoubleTest("foo % E", neg, "foo -2.560000E+002", "foo -2.560000E+02");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test15/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test15/testinfo.dat
new file mode 100644
index 0000000000..0a47c5321a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test15/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sprintf
+Name = Positive Test for sprintf
+TYPE = DEFAULT
+EXE1 = test15
+Description
+= Tests sprintf with exponential format doubles (uppercase)
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test16/CMakeLists.txt
new file mode 100644
index 0000000000..2065c576d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test16/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test16.c
+)
+
+add_executable(paltest_sprintf_test16
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sprintf_test16 coreclrpal)
+
+target_link_libraries(paltest_sprintf_test16
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test16/test16.c b/src/pal/tests/palsuite/c_runtime/sprintf/test16/test16.c
new file mode 100644
index 0000000000..c93b68bc2d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test16/test16.c
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test16.c
+**
+** Purpose: Test #16 for the sprintf function. Tests the decimal notation
+** double specifier (%f)
+**
+**
+**==========================================================================*/
+
+
+#include <palsuite.h>
+#include "../sprintf.h"
+
+/*
+ * Depends on memcmp and strlen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest("foo %f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %lf", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %hf", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %Lf", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %I64f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %12f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %-12f", val, "foo 2560.001000 ", "foo 2560.001000 ");
+ DoDoubleTest("foo %.1f", val, "foo 2560.0", "foo 2560.0");
+ DoDoubleTest("foo %.8f", val, "foo 2560.00100000", "foo 2560.00100000");
+ DoDoubleTest("foo %012f", val, "foo 02560.001000", "foo 02560.001000");
+ DoDoubleTest("foo %#f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %+f", val, "foo +2560.001000", "foo +2560.001000");
+ DoDoubleTest("foo % f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %+f", neg, "foo -2560.001000", "foo -2560.001000");
+ DoDoubleTest("foo % f", neg, "foo -2560.001000", "foo -2560.001000");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test16/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test16/testinfo.dat
new file mode 100644
index 0000000000..e18fab1ad8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test16/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sprintf
+Name = Positive Test for sprintf
+TYPE = DEFAULT
+EXE1 = test16
+Description
+= Tests sprintf with decimal point format doubles
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test17/CMakeLists.txt
new file mode 100644
index 0000000000..ce3a8ad048
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test17/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test17.c
+)
+
+add_executable(paltest_sprintf_test17
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sprintf_test17 coreclrpal)
+
+target_link_libraries(paltest_sprintf_test17
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test17/test17.c b/src/pal/tests/palsuite/c_runtime/sprintf/test17/test17.c
new file mode 100644
index 0000000000..643215b8f5
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test17/test17.c
@@ -0,0 +1,54 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test17.c
+**
+** Purpose: Test #17 for the sprintf function. Tests the lowercase
+** shorthand notation double specifier (%g)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../sprintf.h"
+
+/*
+ * Depends on memcmp and strlen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest("foo %g", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %lg", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %hg", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %Lg", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %I64g", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %5g", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %-5g", val, "foo 2560 ", "foo 2560 ");
+ DoDoubleTest("foo %.1g", val, "foo 3e+003", "foo 3e+03");
+ DoDoubleTest("foo %.2g", val, "foo 2.6e+003", "foo 2.6e+03");
+ DoDoubleTest("foo %.12g", val, "foo 2560.001", "foo 2560.001");
+ DoDoubleTest("foo %06g", val, "foo 002560", "foo 002560");
+ DoDoubleTest("foo %#g", val, "foo 2560.00", "foo 2560.00");
+ DoDoubleTest("foo %+g", val, "foo +2560", "foo +2560");
+ DoDoubleTest("foo % g", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %+g", neg, "foo -2560", "foo -2560");
+ DoDoubleTest("foo % g", neg, "foo -2560", "foo -2560");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test17/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test17/testinfo.dat
new file mode 100644
index 0000000000..a723103e02
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test17/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sprintf
+Name = Positive Test for sprintf
+TYPE = DEFAULT
+EXE1 = test17
+Description
+= Tests sprintf with compact format doubles (lowercase)
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test18/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test18/CMakeLists.txt
new file mode 100644
index 0000000000..6f69e1c7c2
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test18/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test18.c
+)
+
+add_executable(paltest_sprintf_test18
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sprintf_test18 coreclrpal)
+
+target_link_libraries(paltest_sprintf_test18
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test18/test18.c b/src/pal/tests/palsuite/c_runtime/sprintf/test18/test18.c
new file mode 100644
index 0000000000..fa88152479
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test18/test18.c
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test18.c
+**
+** Purpose: Test #18 for the sprintf function. Tests the uppercase
+** shorthand notation double specifier (%G)
+**
+**
+**==========================================================================*/
+
+
+#include <palsuite.h>
+#include "../sprintf.h"
+
+/*
+ * Depends on memcmp and strlen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest("foo %G", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %lG", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %hG", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %LG", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %I64G", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %5G", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %-5G", val, "foo 2560 ", "foo 2560 ");
+ DoDoubleTest("foo %.1G", val, "foo 3E+003", "foo 3E+03");
+ DoDoubleTest("foo %.2G", val, "foo 2.6E+003", "foo 2.6E+03");
+ DoDoubleTest("foo %.12G", val, "foo 2560.001", "foo 2560.001");
+ DoDoubleTest("foo %06G", val, "foo 002560", "foo 002560");
+ DoDoubleTest("foo %#G", val, "foo 2560.00", "foo 2560.00");
+ DoDoubleTest("foo %+G", val, "foo +2560", "foo +2560");
+ DoDoubleTest("foo % G", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %+G", neg, "foo -2560", "foo -2560");
+ DoDoubleTest("foo % G", neg, "foo -2560", "foo -2560");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test18/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test18/testinfo.dat
new file mode 100644
index 0000000000..dfafa4bcf4
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test18/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sprintf
+Name = Positive Test for sprintf
+TYPE = DEFAULT
+EXE1 = test18
+Description
+= Tests sprintf with compact format doubles (uppercase)
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test19/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test19/CMakeLists.txt
new file mode 100644
index 0000000000..a2917b27dc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test19/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test19.c
+)
+
+add_executable(paltest_sprintf_test19
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sprintf_test19 coreclrpal)
+
+target_link_libraries(paltest_sprintf_test19
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test19/test19.c b/src/pal/tests/palsuite/c_runtime/sprintf/test19/test19.c
new file mode 100644
index 0000000000..aee731cb74
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test19/test19.c
@@ -0,0 +1,78 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test19.c
+**
+** Purpose: Test #19 for the sprintf function. Tests the variable length
+** precision argument.
+**
+**
+**==========================================================================*/
+
+
+#include <palsuite.h>
+#include "../sprintf.h"
+
+/*
+ * Depends on memcmp and strlen
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int n = -1;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ DoArgumentPrecTest("%.*s", 2, "bar", "bar", "ba", "ba");
+ DoArgumentPrecTest("%.*S", 2, convert("bar"), "bar", "ba", "ba");
+
+ DoArgumentPrecTest("%.*n", 3, &n, "pointer to int", "", "");
+ if (n != 0)
+ {
+ Fail("ERROR: Expected count parameter to resolve to %d, got %X\n",
+ 0, n);
+ }
+
+ DoArgumentPrecTest("%.*c", 0, (void*)'a', "a", "a", "a");
+ DoArgumentPrecTest("%.*c", 4, (void*)'a', "a", "a", "a");
+ DoArgumentPrecTest("%.*C", 0, (void*)'a', "a", "a", "a");
+ DoArgumentPrecTest("%.*C", 4, (void*)'a', "a", "a", "a");
+ DoArgumentPrecTest("%.*d", 1, (void*)42, "42", "42", "42");
+ DoArgumentPrecTest("%.*d", 3, (void*)42, "42", "042", "042");
+ DoArgumentPrecTest("%.*i", 1, (void*)42, "42", "42", "42");
+ DoArgumentPrecTest("%.*i", 3, (void*)42, "42", "042", "042");
+ DoArgumentPrecTest("%.*o", 1, (void*)42, "42", "52", "52");
+ DoArgumentPrecTest("%.*o", 3, (void*)42, "42", "052", "052");
+ DoArgumentPrecTest("%.*u", 1, (void*)42, "42", "42", "42");
+ DoArgumentPrecTest("%.*u", 3, (void*)42, "42", "042", "042");
+ DoArgumentPrecTest("%.*x", 1, (void*)0x42, "0x42", "42", "42");
+ DoArgumentPrecTest("%.*x", 3, (void*)0x42, "0x42", "042", "042");
+ DoArgumentPrecTest("%.*X", 1, (void*)0x42, "0x42", "42", "42");
+ DoArgumentPrecTest("%.*X", 3, (void*)0x42, "0x42", "042", "042");
+
+
+ DoArgumentPrecDoubleTest("%.*e", 1, 2.01, "2.0e+000", "2.0e+00");
+ DoArgumentPrecDoubleTest("%.*e", 3, 2.01, "2.010e+000", "2.010e+00");
+ DoArgumentPrecDoubleTest("%.*E", 1, 2.01, "2.0E+000", "2.0E+00");
+ DoArgumentPrecDoubleTest("%.*E", 3, 2.01, "2.010E+000", "2.010E+00");
+ DoArgumentPrecDoubleTest("%.*f", 1, 2.01, "2.0", "2.0");
+ DoArgumentPrecDoubleTest("%.*f", 3, 2.01, "2.010", "2.010");
+ DoArgumentPrecDoubleTest("%.*g", 1, 256.01, "3e+002", "3e+02");
+ DoArgumentPrecDoubleTest("%.*g", 3, 256.01, "256", "256");
+ DoArgumentPrecDoubleTest("%.*g", 4, 256.01, "256", "256");
+ DoArgumentPrecDoubleTest("%.*g", 6, 256.01, "256.01", "256.01");
+ DoArgumentPrecDoubleTest("%.*G", 1, 256.01, "3E+002", "3E+02");
+ DoArgumentPrecDoubleTest("%.*G", 3, 256.01, "256", "256");
+ DoArgumentPrecDoubleTest("%.*G", 4, 256.01, "256", "256");
+ DoArgumentPrecDoubleTest("%.*G", 6, 256.01, "256.01", "256.01");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test19/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test19/testinfo.dat
new file mode 100644
index 0000000000..ebd13025f6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test19/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sprintf
+Name = Positive Test for sprintf
+TYPE = DEFAULT
+EXE1 = test19
+Description
+= Tests sprintf with argument specified precision
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test2/CMakeLists.txt
new file mode 100644
index 0000000000..8af1c53a30
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_sprintf_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sprintf_test2 coreclrpal)
+
+target_link_libraries(paltest_sprintf_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test2/test2.c b/src/pal/tests/palsuite/c_runtime/sprintf/test2/test2.c
new file mode 100644
index 0000000000..d50679a5a3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test2/test2.c
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test2.c
+**
+** Purpose: Test #2 for the sprintf function. Tests the string specifier
+** (%s).
+**
+**
+**==========================================================================*/
+
+
+#include <palsuite.h>
+#include "../sprintf.h"
+
+/*
+ * Depends on memcmp and strlen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoStrTest("foo %s", "bar", "foo bar");
+ DoStrTest("foo %hs", "bar", "foo bar");
+ DoWStrTest("foo %ls", convert("bar"), "foo bar");
+ DoWStrTest("foo %ws", convert("bar"), "foo bar");
+ DoStrTest("foo %Ls", "bar", "foo bar");
+ DoStrTest("foo %I64s", "bar", "foo bar");
+ DoStrTest("foo %5s", "bar", "foo bar");
+ DoStrTest("foo %.2s", "bar", "foo ba");
+ DoStrTest("foo %5.2s", "bar", "foo ba");
+ DoStrTest("foo %-5s", "bar", "foo bar ");
+ DoStrTest("foo %05s", "bar", "foo 00bar");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test2/testinfo.dat
new file mode 100644
index 0000000000..e8d0f53ff3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test2/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sprintf
+Name = Positive Test for sprintf
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Tests sprintf with strings
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test3/CMakeLists.txt
new file mode 100644
index 0000000000..b7b7e0a579
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_sprintf_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sprintf_test3 coreclrpal)
+
+target_link_libraries(paltest_sprintf_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test3/test3.c b/src/pal/tests/palsuite/c_runtime/sprintf/test3/test3.c
new file mode 100644
index 0000000000..ae52dbed08
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test3/test3.c
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test3.c
+**
+** Purpose: Test #3 for the sprintf function. Tests the wide string
+** specifier (%S).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../sprintf.h"
+
+/*
+ * Depends on memcmp and strlen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ DoWStrTest("foo %S", convert("bar"), "foo bar");
+ DoStrTest("foo %hS", "bar", "foo bar");
+ DoWStrTest("foo %lS", convert("bar"), "foo bar");
+ DoWStrTest("foo %wS", convert("bar"), "foo bar");
+ DoWStrTest("foo %LS", convert("bar"), "foo bar");
+ DoWStrTest("foo %I64S", convert("bar"), "foo bar");
+ DoWStrTest("foo %5S", convert("bar"), "foo bar");
+ DoWStrTest("foo %.2S", convert("bar"), "foo ba");
+ DoWStrTest("foo %5.2S", convert("bar"), "foo ba");
+ DoWStrTest("foo %-5S", convert("bar"), "foo bar ");
+ DoWStrTest("foo %05S", convert("bar"), "foo 00bar");
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test3/testinfo.dat
new file mode 100644
index 0000000000..12e0a9cfb0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test3/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sprintf
+Name = Positive Test for sprintf
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Tests sprintf with wide strings
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test4/CMakeLists.txt
new file mode 100644
index 0000000000..3478867b7c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_sprintf_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sprintf_test4 coreclrpal)
+
+target_link_libraries(paltest_sprintf_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test4/test4.c b/src/pal/tests/palsuite/c_runtime/sprintf/test4/test4.c
new file mode 100644
index 0000000000..9660ffaa3a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test4/test4.c
@@ -0,0 +1,69 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test4.c
+**
+** Purpose: Test #4 for the sprintf function. Tests the pointer
+** specifier (%p).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../sprintf.h"
+/*
+ * Depends on memcmp and strlen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ void *ptr = (void*) 0x123456;
+ INT64 lptr = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+/*
+** Run only on 64 bit platforms
+*/
+#if defined(BIT64) && defined(PLATFORM_UNIX)
+ Trace("Testing for 64 Bit Platforms \n");
+ DoPointerTest("%p", NULL, "NULL", "0000000000000000");
+ DoPointerTest("%p", ptr, "pointer to 0x123456", "0000000000123456");
+ DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456");
+ DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456");
+ DoPointerTest("%-17p", ptr, "pointer to 0x123456", "0000000000123456 ");
+ DoPointerTest("%+p", ptr, "pointer to 0x123456", "0000000000123456");
+ DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X0000000000123456");
+ DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456");
+ DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456");
+ DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456");
+ DoI64Test("%I64p", lptr, "pointer to 0x1234567887654321",
+ "1234567887654321");
+#else
+ Trace("Testing for Non 64 Bit Platforms \n");
+ DoPointerTest("%p", NULL, "NULL", "00000000");
+ DoPointerTest("%p", ptr, "pointer to 0x123456", "00123456");
+ DoPointerTest("%9p", ptr, "pointer to 0x123456", " 00123456");
+ DoPointerTest("%09p", ptr, "pointer to 0x123456", " 00123456");
+ DoPointerTest("%-9p", ptr, "pointer to 0x123456", "00123456 ");
+ DoPointerTest("%+p", ptr, "pointer to 0x123456", "00123456");
+ DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X00123456");
+ DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456");
+ DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456");
+ DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456");
+ DoI64Test("%I64p", lptr, "pointer to 0x1234567887654321",
+ "1234567887654321");
+#endif
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test4/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test4/testinfo.dat
new file mode 100644
index 0000000000..bf7236dc32
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test4/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sprintf
+Name = Positive Test for sprintf
+TYPE = DEFAULT
+EXE1 = test4
+Description
+= Tests sprintf with pointers
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test5/CMakeLists.txt
new file mode 100644
index 0000000000..dfa7583766
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test5.c
+)
+
+add_executable(paltest_sprintf_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sprintf_test5 coreclrpal)
+
+target_link_libraries(paltest_sprintf_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test5/test5.c b/src/pal/tests/palsuite/c_runtime/sprintf/test5/test5.c
new file mode 100644
index 0000000000..1b52da77b6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test5/test5.c
@@ -0,0 +1,62 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test5.c
+**
+** Purpose: Test #5 for the sprintf function. Tests the count specifier (%n).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../sprintf.h"
+
+/*
+ * Depends on memcmp and strlen
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ char *longStr =
+ "really-long-string-that-just-keeps-going-on-and-on-and-on.."
+ "..................useless-filler.................................."
+ "..................useless-filler.................................."
+ "..................useless-filler.................................."
+ "%n bar";
+ char *longResult =
+ "really-long-string-that-just-keeps-going-on-and-on-and-on.."
+ "..................useless-filler.................................."
+ "..................useless-filler.................................."
+ "..................useless-filler.................................."
+ " bar";
+
+ if (PAL_Initialize(argc, argv)!= 0)
+ {
+ return FAIL;
+ }
+
+ DoCountTest("foo %n bar", 4, "foo bar");
+ DoCountTest(longStr, 257, longResult);
+ DoCountTest("fo%n bar", 2, "fo bar");
+ DoCountTest("%n", 0, "");
+ DoCountTest("foo %#n bar", 4, "foo bar");
+ DoCountTest("foo % n bar", 4, "foo bar");
+ DoCountTest("foo %+n bar", 4, "foo bar");
+ DoCountTest("foo %-n bar", 4, "foo bar");
+ DoCountTest("foo %0n bar", 4, "foo bar");
+ DoShortCountTest("foo %hn bar", 4, "foo bar");
+ DoCountTest("foo %ln bar", 4, "foo bar");
+ DoCountTest("foo %Ln bar", 4, "foo bar");
+ DoCountTest("foo %I64n bar", 4, "foo bar");
+ DoCountTest("foo %20.3n bar", 4, "foo bar");
+
+ PAL_Terminate();
+
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test5/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test5/testinfo.dat
new file mode 100644
index 0000000000..31e0537bd0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test5/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sprintf
+Name = Positive Test for sprintf
+TYPE = DEFAULT
+EXE1 = test5
+Description
+= Tests sprintf with the count specifier
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test6/CMakeLists.txt
new file mode 100644
index 0000000000..7a9a5fc856
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test6.c
+)
+
+add_executable(paltest_sprintf_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sprintf_test6 coreclrpal)
+
+target_link_libraries(paltest_sprintf_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test6/test6.c b/src/pal/tests/palsuite/c_runtime/sprintf/test6/test6.c
new file mode 100644
index 0000000000..c14e075475
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test6/test6.c
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test6.c
+**
+** Purpose: Test #6 for the sprintf function. Tests the char specifier (%c).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../sprintf.h"
+
+/*
+ * Depends on memcmp and strlen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR wc = (WCHAR) 'c';
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoCharTest("foo %c", 'b', "foo b");
+ DoCharTest("foo %hc", 'b', "foo b");
+ DoWCharTest("foo %lc", wc, "foo c");
+ DoCharTest("foo %Lc", 'b', "foo b");
+ DoCharTest("foo %I64c", 'b', "foo b");
+ DoCharTest("foo %5c", 'b', "foo b");
+ DoCharTest("foo %.0c", 'b', "foo b");
+ DoCharTest("foo %-5c", 'b', "foo b ");
+ DoCharTest("foo %05c", 'b', "foo 0000b");
+ DoCharTest("foo % c", 'b', "foo b");
+ DoCharTest("foo %#c", 'b', "foo b");
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test6/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test6/testinfo.dat
new file mode 100644
index 0000000000..037e4106ff
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test6/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sprintf
+Name = Positive Test for sprintf
+TYPE = DEFAULT
+EXE1 = test6
+Description
+= Tests sprintf with characters
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test7/CMakeLists.txt
new file mode 100644
index 0000000000..a539a59ab9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test7/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test7.c
+)
+
+add_executable(paltest_sprintf_test7
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sprintf_test7 coreclrpal)
+
+target_link_libraries(paltest_sprintf_test7
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test7/test7.c b/src/pal/tests/palsuite/c_runtime/sprintf/test7/test7.c
new file mode 100644
index 0000000000..082bd20e6d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test7/test7.c
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test7.c
+**
+** Purpose: Test #7 for the sprintf function. Tests the wide char
+** specifier (%C).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../sprintf.h"
+
+/*
+ * Depends on memcmp and strlen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR wb = (WCHAR) 'b';
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoWCharTest("foo %C", wb, "foo b");
+ DoWCharTest("foo %hC", wb, "foo b");
+ DoCharTest("foo %lC", 'c', "foo c");
+ DoWCharTest("foo %LC", wb, "foo b");
+ DoWCharTest("foo %I64C", wb, "foo b");
+ DoWCharTest("foo %5C", wb, "foo b");
+ DoWCharTest("foo %.0C", wb, "foo b");
+ DoWCharTest("foo %-5C", wb, "foo b ");
+ DoWCharTest("foo %05C", wb, "foo 0000b");
+ DoWCharTest("foo % C", wb, "foo b");
+ DoWCharTest("foo %#C", wb, "foo b");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test7/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test7/testinfo.dat
new file mode 100644
index 0000000000..a2730bc97c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test7/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sprintf
+Name = Positive Test for sprintf
+TYPE = DEFAULT
+EXE1 = test7
+Description
+= Tests sprintf with wide characters
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test8/CMakeLists.txt
new file mode 100644
index 0000000000..7a92c5072a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test8/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test8.c
+)
+
+add_executable(paltest_sprintf_test8
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sprintf_test8 coreclrpal)
+
+target_link_libraries(paltest_sprintf_test8
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test8/test8.c b/src/pal/tests/palsuite/c_runtime/sprintf/test8/test8.c
new file mode 100644
index 0000000000..9587c82c94
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test8/test8.c
@@ -0,0 +1,55 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test8.c
+**
+** Purpose: Test #8 for the sprintf function. Tests the decimal
+** specifier (%d).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../sprintf.h"
+
+/*
+ * Depends on memcmp and strlen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest("foo %d", pos, "foo 42");
+ DoNumTest("foo %ld", 0xFFFF, "foo 65535");
+ DoNumTest("foo %hd", 0xFFFF, "foo -1");
+ DoNumTest("foo %Ld", pos, "foo 42");
+ DoI64Test("foo %I64d", l, "42", "foo 42");
+ DoNumTest("foo %3d", pos, "foo 42");
+ DoNumTest("foo %-3d", pos, "foo 42 ");
+ DoNumTest("foo %.1d", pos, "foo 42");
+ DoNumTest("foo %.3d", pos, "foo 042");
+ DoNumTest("foo %03d", pos, "foo 042");
+ DoNumTest("foo %#d", pos, "foo 42");
+ DoNumTest("foo %+d", pos, "foo +42");
+ DoNumTest("foo % d", pos, "foo 42");
+ DoNumTest("foo %+d", neg, "foo -42");
+ DoNumTest("foo % d", neg, "foo -42");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test8/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test8/testinfo.dat
new file mode 100644
index 0000000000..adc0b66f06
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test8/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sprintf
+Name = Positive Test for sprintf
+TYPE = DEFAULT
+EXE1 = test8
+Description
+= Tests sprintf with decimal numbers
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test9/CMakeLists.txt
new file mode 100644
index 0000000000..2a91658bd4
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test9/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test9.c
+)
+
+add_executable(paltest_sprintf_test9
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sprintf_test9 coreclrpal)
+
+target_link_libraries(paltest_sprintf_test9
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test9/test9.c b/src/pal/tests/palsuite/c_runtime/sprintf/test9/test9.c
new file mode 100644
index 0000000000..98f5db6ec1
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test9/test9.c
@@ -0,0 +1,55 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test9.c
+**
+** Purpose: Test #9 for the sprintf function. Tests the integer
+** specifier (%i).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../sprintf.h"
+
+/*
+ * Depends on memcmp and strlen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest("foo %i", pos, "foo 42");
+ DoNumTest("foo %li", 0xFFFF, "foo 65535");
+ DoNumTest("foo %hi", 0xFFFF, "foo -1");
+ DoNumTest("foo %Li", pos, "foo 42");
+ DoI64Test("foo %I64i", l, "42", "foo 42");
+ DoNumTest("foo %3i", pos, "foo 42");
+ DoNumTest("foo %-3i", pos, "foo 42 ");
+ DoNumTest("foo %.1i", pos, "foo 42");
+ DoNumTest("foo %.3i", pos, "foo 042");
+ DoNumTest("foo %03i", pos, "foo 042");
+ DoNumTest("foo %#i", pos, "foo 42");
+ DoNumTest("foo %+i", pos, "foo +42");
+ DoNumTest("foo % i", pos, "foo 42");
+ DoNumTest("foo %+i", neg, "foo -42");
+ DoNumTest("foo % i", neg, "foo -42");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test9/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test9/testinfo.dat
new file mode 100644
index 0000000000..e569e789cd
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sprintf/test9/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sprintf
+Name = Positive Test for sprintf
+TYPE = DEFAULT
+EXE1 = test9
+Description
+= Tests sprintf with integer numbers
diff --git a/src/pal/tests/palsuite/c_runtime/sqrt/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sqrt/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sqrt/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/sqrt/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sqrt/test1/CMakeLists.txt
new file mode 100644
index 0000000000..4347c44e46
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sqrt/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_sqrt_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sqrt_test1 coreclrpal)
+
+target_link_libraries(paltest_sqrt_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sqrt/test1/test1.c b/src/pal/tests/palsuite/c_runtime/sqrt/test1/test1.c
new file mode 100644
index 0000000000..62d2251d61
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sqrt/test1/test1.c
@@ -0,0 +1,123 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Call the sqrt function on a positive value, a positive value
+** with a decimal and on the maxium possible double value.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (15-17 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use
+// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx
+// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will
+// use PAL_EPSILON * 10.
+#define PAL_EPSILON 8.8817841970012523e-16
+
+#define PAL_NAN sqrt(-1.0)
+#define PAL_POSINF -log(0.0)
+#define PAL_NEGINF log(0.0)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ double value; /* value to test the function with */
+ double expected; /* expected result */
+ double variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(double value, double expected, double variance)
+{
+ double result = sqrt(value);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ double delta = fabs(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("sqrt(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(double value)
+{
+ double result = sqrt(value);
+
+ if (!_isnan(result))
+ {
+ Fail("sqrt(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, PAL_NAN);
+ }
+}
+
+int __cdecl main(int argc, char **argv)
+{
+ struct test tests[] =
+ {
+ /* value expected variance */
+ { 0.31830988618379067, 0.56418958354775629, PAL_EPSILON }, // value: 1 / pi
+ { 0.43429448190325183, 0.65901022898226081, PAL_EPSILON }, // value: log10(e)
+ { 0.63661977236758134, 0.79788456080286536, PAL_EPSILON }, // value: 2 / pi
+ { 0.69314718055994531, 0.83255461115769776, PAL_EPSILON }, // value: ln(2)
+ { 0.70710678118654752, 0.84089641525371454, PAL_EPSILON }, // value: 1 / sqrt(2)
+ { 0.78539816339744831, 0.88622692545275801, PAL_EPSILON }, // value: pi / 4
+ { 1, 1, PAL_EPSILON * 10 },
+ { 1.1283791670955126, 1.0622519320271969, PAL_EPSILON * 10 }, // value: 2 / sqrt(pi)
+ { 1.4142135623730950, 1.1892071150027211, PAL_EPSILON * 10 }, // value: sqrt(2)
+ { 1.4426950408889634, 1.2011224087864498, PAL_EPSILON * 10 }, // value: log2(e)
+ { 1.5707963267948966, 1.2533141373155003, PAL_EPSILON * 10 }, // value: pi / 2
+ { 2.3025850929940457, 1.5174271293851464, PAL_EPSILON * 10 }, // value: ln(10)
+ { 2.7182818284590452, 1.6487212707001281, PAL_EPSILON * 10 }, // value: e
+ { 3.1415926535897932, 1.7724538509055160, PAL_EPSILON * 10 }, // value: pi
+ };
+
+ /* PAL initialization */
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ validate(-0.0, -0.0, PAL_EPSILON);
+ validate( 0.0, 0.0, PAL_EPSILON);
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate(tests[i].value, tests[i].expected, tests[i].variance);
+ validate_isnan(-tests[i].value);
+ }
+
+ validate_isnan(PAL_NAN);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/sqrt/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sqrt/test1/testinfo.dat
new file mode 100644
index 0000000000..804fef088c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sqrt/test1/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sqrt
+Name = Call sqrt on positive values and zero.
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Call the sqrt function on a positive value, a positive value
+= with a decimal and on the maxium possible double value.
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/CMakeLists.txt
new file mode 100644
index 0000000000..59f39a5f58
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/CMakeLists.txt
@@ -0,0 +1,20 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test10)
+add_subdirectory(test11)
+add_subdirectory(test12)
+add_subdirectory(test13)
+add_subdirectory(test14)
+add_subdirectory(test15)
+add_subdirectory(test16)
+add_subdirectory(test17)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+add_subdirectory(test7)
+add_subdirectory(test8)
+add_subdirectory(test9)
+
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/sscanf.h b/src/pal/tests/palsuite/c_runtime/sscanf/sscanf.h
new file mode 100644
index 0000000000..675a67aed2
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/sscanf.h
@@ -0,0 +1,246 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: sscanf.h
+**
+** Purpose: Contains common testing functions for sscanf.h
+**
+**
+**==========================================================================*/
+
+#ifndef __SSCANF_H__
+#define __SSCANF_H__
+
+void DoVoidTest(char *inputstr, char *formatstr)
+{
+ char buf[256] = { 0 };
+ int i;
+ int ret;
+
+ ret = sscanf(inputstr, formatstr, buf);
+ if (ret != 0)
+ {
+ Fail("ERROR: Expected sscanf to return 0, got %d.\n"
+ "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr);
+ }
+
+ for (i=0; i<256; i++)
+ {
+ if (buf[i] != 0)
+ {
+ Fail("ERROR: Parameter unexpectedly modified scanning \"%s\" "
+ "using \"%s\".\n", inputstr, formatstr);
+ }
+ }
+
+}
+
+void DoStrTest(char *inputstr, char *formatstr, char *checkstr)
+{
+ char buf[256] = { 0 };
+ int ret;
+
+ ret = sscanf(inputstr, formatstr, buf);
+ if (ret != 1)
+ {
+ Fail("ERROR: Expected sscanf to return 1, got %d.\n"
+ "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr);
+ }
+
+ if (memcmp(checkstr, buf, strlen(checkstr) + 1) != 0)
+ {
+ Fail("ERROR: scanned string incorrectly from \"%s\" using \"%s\".\n"
+ "Expected \"%s\", got \"%s\".\n", inputstr, formatstr, checkstr,
+ buf);
+ }
+
+}
+
+void DoWStrTest(char *inputstr, char *formatstr, WCHAR *checkstr)
+{
+ WCHAR buf[256] = { 0 };
+ int ret;
+
+ ret = sscanf(inputstr, formatstr, buf);
+ if (ret != 1)
+ {
+ Fail("ERROR: Expected sscanf to return 1, got %d.\n"
+ "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr);
+ }
+
+ if (memcmp(checkstr, buf, wcslen(checkstr)*2 + 2) != 0)
+ {
+ Fail("ERROR: scanned wide string incorrectly from \"%s\" using \"%s\".\n"
+ "Expected \"%s\", got \"%s\".\n", inputstr, formatstr,
+ convertC(checkstr), convertC(buf));
+ }
+
+}
+
+void DoNumTest(char *inputstr, char *formatstr, int checknum)
+{
+ int num;
+ int ret;
+
+ ret = sscanf(inputstr, formatstr, &num);
+ if (ret != 1)
+ {
+ Fail("ERROR: Expected sscanf to return 1, got %d.\n"
+ "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr);
+ }
+
+ if (checknum != num)
+ {
+ Fail("ERROR: scanned number incorrectly from \"%s\" using \"%s\".\n"
+ "Expected %d, got %d.\n", inputstr, formatstr, checknum, num);
+ }
+}
+
+void DoShortNumTest(char *inputstr, char *formatstr, short checknum)
+{
+ short num;
+ int ret;
+
+ ret = sscanf(inputstr, formatstr, &num);
+ if (ret != 1)
+ {
+ Fail("ERROR: Expected sscanf to return 1, got %d.\n"
+ "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr);
+ }
+
+ if (checknum != num)
+ {
+ Fail("ERROR: scanned number incorrectly from \"%s\" using \"%s\".\n"
+ "Expected %hd, got %hd.\n", inputstr, formatstr, checknum, num);
+ }
+}
+
+void DoI64NumTest(char *inputstr, char *formatstr, INT64 checknum)
+{
+ char buf[256];
+ char check[256];
+ INT64 num;
+ int ret;
+
+ ret = sscanf(inputstr, formatstr, &num);
+ if (ret != 1)
+ {
+ Fail("ERROR: Expected sscanf to return 1, got %d.\n"
+ "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr);
+ }
+
+ if (checknum != num)
+ {
+ sprintf(buf, "%I64d", num);
+ sprintf(check, "%I64d", checknum);
+ Fail("ERROR: scanned I64 number incorrectly from \"%s\" using \"%s\".\n"
+ "Expected %s, got %s.\n", inputstr, formatstr, check, buf);
+ }
+}
+
+void DoCharTest(char *inputstr, char *formatstr, char* checkchars, int numchars)
+{
+ char buf[256];
+ int ret;
+ int i;
+
+ for (i=0; i<256; i++)
+ buf[i] = (char)-1;
+
+ ret = sscanf(inputstr, formatstr, buf);
+ if (ret != 1)
+ {
+ Fail("ERROR: Expected sscanf to return 1, got %d.\n"
+ "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr);
+ }
+
+ if (memcmp(buf, checkchars, numchars) != 0)
+ {
+ buf[numchars] = 0;
+
+ Fail("ERROR: scanned character(s) incorrectly from \"%s\" using \"%s\".\n"
+ "Expected %s, got %s.\n", inputstr, formatstr, checkchars,
+ buf);
+ }
+
+ if (buf[numchars] != (char)-1)
+ {
+ Fail("ERROR: overflow occurred in scanning character(s) from \"%s\" "
+ "using \"%s\".\nExpected %d character(s)\n", inputstr, formatstr,
+ numchars);
+ }
+}
+
+void DoWCharTest(char *inputstr, char *formatstr, WCHAR* checkchars, int numchars)
+{
+ WCHAR buf[256];
+ int ret;
+ int i;
+
+ for (i=0; i<256; i++)
+ buf[i] = (WCHAR)-1;
+
+ ret = sscanf(inputstr, formatstr, buf);
+ if (ret != 1)
+ {
+ Fail("ERROR: Expected sscanf to return 1, got %d.\n"
+ "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr);
+ }
+
+ if (memcmp(buf, checkchars, numchars) != 0)
+ {
+ buf[numchars] = 0;
+
+ Fail("ERROR: scanned wide character(s) incorrectly from \"%s\" using \"%s\".\n"
+ "Expected %s, got %s.\n", inputstr, formatstr, convertC(checkchars),
+ convertC(buf));
+ }
+
+ if (buf[numchars] != (WCHAR)-1)
+ {
+ Fail("ERROR: overflow occurred in scanning wide character(s) from \"%s\" "
+ "using \"%s\".\nExpected %d character(s)\n", inputstr, formatstr,
+ numchars);
+ }
+}
+
+
+void DoFloatTest(char *inputstr, char *formatstr, float checkval)
+{
+ char buf[256] = { 0 };
+ float val;
+ int ret;
+ int i;
+
+ for (i=0; i<256; i++)
+ buf[i] = (char)-1;
+
+ ret = sscanf(inputstr, formatstr, buf);
+ val = *(float*)buf;
+
+ if (ret != 1)
+ {
+ Fail("ERROR: Expected sscanf to return 1, got %d.\n"
+ "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr);
+ }
+
+ if (val != checkval)
+ {
+ Fail("ERROR: scanned float incorrectly from \"%s\" using \"%s\".\n"
+ "Expected \"%f\", got \"%f\".\n", inputstr, formatstr, checkval,
+ val);
+ }
+
+ if (buf[4] != (char)-1)
+ {
+ Fail("ERROR: overflow occurred in scanning float from \"%s\" "
+ "using \"%s\".\n", inputstr, formatstr);
+
+ }
+}
+
+
+#endif
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..dce6d1de87
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_sscanf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sscanf_test1 coreclrpal)
+
+target_link_libraries(paltest_sscanf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/sscanf/test1/test1.c
new file mode 100644
index 0000000000..c6f66a1d20
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test1/test1.c
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: General test of sscanf
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../sscanf.h"
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int num;
+ int ret;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoVoidTest("foo bar", "foo ");
+ DoVoidTest("foo bar", "baz");
+ DoVoidTest("foo bar", "foo %*s");
+
+ DoStrTest("foo % bar", "foo %% %s", "bar");
+ DoStrTest("foo bar baz", "foo %bar %s", "baz");
+
+ DoVoidTest("foo bar baz", "foo % bar %s");
+ DoVoidTest("foo baz bar", "foo% baz %s");
+
+ ret = sscanf("foo bar baz", "foo bar %n", &num);
+ if (ret != 0 || num != 8)
+ {
+ Fail("ERROR: Got incorrect values in scanning \"%s\" using \"%s\".\n"
+ "Expected to get a value of %d with return value of %d, "
+ "got %d with return %d\n", "foo bar baz", "foo bar %n", 8, 0,
+ num, ret);
+
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test1/testinfo.dat
new file mode 100644
index 0000000000..ef33ba9e13
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sscanf
+Name = Positive Test for sscanf
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= General test of sscanf
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test10/CMakeLists.txt
new file mode 100644
index 0000000000..c27e4ce33a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test10/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test10.c
+)
+
+add_executable(paltest_sscanf_test10
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sscanf_test10 coreclrpal)
+
+target_link_libraries(paltest_sscanf_test10
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test10/test10.c b/src/pal/tests/palsuite/c_runtime/sscanf/test10/test10.c
new file mode 100644
index 0000000000..aac5be43ae
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test10/test10.c
@@ -0,0 +1,37 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test10.c
+**
+** Purpose: Tests sscanf with wide charactersn
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../sscanf.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoWCharTest("1234d", "%C", convert("1"), 1);
+ DoWCharTest("1234d", "%C", convert("1"), 1);
+ DoWCharTest("abc", "%2C", convert("ab"), 2);
+ DoWCharTest(" ab", "%C", convert(" "), 1);
+ DoCharTest("ab", "%hC", "a", 1);
+ DoWCharTest("ab", "%lC", convert("a"), 1);
+ DoWCharTest("ab", "%LC", convert("a"), 1);
+ DoWCharTest("ab", "%I64C", convert("a"), 1);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test10/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test10/testinfo.dat
new file mode 100644
index 0000000000..7e854ed235
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test10/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sscanf
+Name = Positive Test for sscanf
+TYPE = DEFAULT
+EXE1 = test10
+Description
+= Tests sscanf with wide characters
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test11/CMakeLists.txt
new file mode 100644
index 0000000000..7570e990bf
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test11/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test11.c
+)
+
+add_executable(paltest_sscanf_test11
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sscanf_test11 coreclrpal)
+
+target_link_libraries(paltest_sscanf_test11
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test11/test11.c b/src/pal/tests/palsuite/c_runtime/sscanf/test11/test11.c
new file mode 100644
index 0000000000..0e3db6cca0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test11/test11.c
@@ -0,0 +1,36 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test11.c
+**
+** Purpose: Tests sscanf with strings
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../sscanf.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoStrTest("foo bar", "foo %s", "bar");
+ DoStrTest("foo bar", "foo %2s", "ba");
+ DoStrTest("foo bar", "foo %hs", "bar");
+ DoWStrTest("foo bar", "foo %ls", convert("bar"));
+ DoStrTest("foo bar", "foo %Ls", "bar");
+ DoStrTest("foo bar", "foo %I64s", "bar");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test11/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test11/testinfo.dat
new file mode 100644
index 0000000000..60f5cc46a4
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test11/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sscanf
+Name = Positive Test for sscanf
+TYPE = DEFAULT
+EXE1 = test11
+Description
+= Tests sscanf with strings
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test12/CMakeLists.txt
new file mode 100644
index 0000000000..b6509e46d4
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test12/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test12.c
+)
+
+add_executable(paltest_sscanf_test12
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sscanf_test12 coreclrpal)
+
+target_link_libraries(paltest_sscanf_test12
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test12/test12.c b/src/pal/tests/palsuite/c_runtime/sscanf/test12/test12.c
new file mode 100644
index 0000000000..f800e452c0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test12/test12.c
@@ -0,0 +1,35 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test12.c
+**
+** Purpose: Tests sscanf with wide strings
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../sscanf.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoWStrTest("foo bar", "foo %S", convert("bar"));
+ DoWStrTest("foo bar", "foo %2S", convert("ba"));
+ DoStrTest("foo bar", "foo %hS", "bar");
+ DoWStrTest("foo bar", "foo %lS", convert("bar"));
+ DoWStrTest("foo bar", "foo %LS", convert("bar"));
+ DoWStrTest("foo bar", "foo %I64S", convert("bar"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test12/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test12/testinfo.dat
new file mode 100644
index 0000000000..3c453bf53a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test12/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sscanf
+Name = Positive Test for sscanf
+TYPE = DEFAULT
+EXE1 = test12
+Description
+= Tests sscanf with wide strings
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test13/CMakeLists.txt
new file mode 100644
index 0000000000..6fb4094f00
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test13/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test13.c
+)
+
+add_executable(paltest_sscanf_test13
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sscanf_test13 coreclrpal)
+
+target_link_libraries(paltest_sscanf_test13
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test13/test13.c b/src/pal/tests/palsuite/c_runtime/sscanf/test13/test13.c
new file mode 100644
index 0000000000..314604e3ac
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test13/test13.c
@@ -0,0 +1,37 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test13.c
+**
+** Purpose: Tests sscanf with floats (decimal notation)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../sscanf.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoFloatTest("123.0", "%f", 123.0f);
+ DoFloatTest("123.0", "%2f", 12.0f);
+ DoFloatTest("10E1", "%f", 100.0f);
+ DoFloatTest("-12.01e-2", "%f", -0.1201f);
+ DoFloatTest("+12.01e-2", "%f", 0.1201f);
+ DoFloatTest("-12.01e+2", "%f", -1201.0f);
+ DoFloatTest("+12.01e+2", "%f", 1201.0f);
+ DoFloatTest("1234567890.0123456789f", "%f", 1234567936);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test13/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test13/testinfo.dat
new file mode 100644
index 0000000000..1c4c2fc26e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test13/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sscanf
+Name = Positive Test for sscanf
+TYPE = DEFAULT
+EXE1 = test13
+Description
+= Tests sscanf with floats (decimal notation)
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test14/CMakeLists.txt
new file mode 100644
index 0000000000..373a75fbda
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test14/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test14.c
+)
+
+add_executable(paltest_sscanf_test14
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sscanf_test14 coreclrpal)
+
+target_link_libraries(paltest_sscanf_test14
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test14/test14.c b/src/pal/tests/palsuite/c_runtime/sscanf/test14/test14.c
new file mode 100644
index 0000000000..d1291a3b65
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test14/test14.c
@@ -0,0 +1,36 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test14.c
+**
+** Purpose: Tests sscanf with floats (exponential notation, lowercase)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../sscanf.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoFloatTest("123.0", "%e", 123.0f);
+ DoFloatTest("123.0", "%2e", 12.0f);
+ DoFloatTest("10E1", "%e", 100.0f);
+ DoFloatTest("-12.01e-2", "%e", -0.1201f);
+ DoFloatTest("+12.01e-2", "%e", 0.1201f);
+ DoFloatTest("-12.01e+2", "%e", -1201.0f);
+ DoFloatTest("+12.01e+2", "%e", 1201.0f);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test14/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test14/testinfo.dat
new file mode 100644
index 0000000000..97db6e4ffd
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test14/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sscanf
+Name = Positive Test for sscanf
+TYPE = DEFAULT
+EXE1 = test14
+Description
+= Tests sscanf with floats (exponential notation, lowercase)
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test15/CMakeLists.txt
new file mode 100644
index 0000000000..d500901782
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test15/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test15.c
+)
+
+add_executable(paltest_sscanf_test15
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sscanf_test15 coreclrpal)
+
+target_link_libraries(paltest_sscanf_test15
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test15/test15.c b/src/pal/tests/palsuite/c_runtime/sscanf/test15/test15.c
new file mode 100644
index 0000000000..fa51467d85
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test15/test15.c
@@ -0,0 +1,36 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test15.c
+**
+** Purpose: Tests sscanf with floats (exponential notation, uppercase
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../sscanf.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoFloatTest("123.0", "%E", 123.0f);
+ DoFloatTest("123.0", "%2E", 12.0f);
+ DoFloatTest("10E1", "%E", 100.0f);
+ DoFloatTest("-12.01e-2", "%E", -0.1201f);
+ DoFloatTest("+12.01e-2", "%E", 0.1201f);
+ DoFloatTest("-12.01e+2", "%E", -1201.0f);
+ DoFloatTest("+12.01e+2", "%E", 1201.0f);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test15/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test15/testinfo.dat
new file mode 100644
index 0000000000..30c2cf4b30
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test15/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sscanf
+Name = Positive Test for sscanf
+TYPE = DEFAULT
+EXE1 = test15
+Description
+= Tests sscanf with floats (exponential notation, uppercase)
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test16/CMakeLists.txt
new file mode 100644
index 0000000000..c5e18ec061
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test16/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test16.c
+)
+
+add_executable(paltest_sscanf_test16
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sscanf_test16 coreclrpal)
+
+target_link_libraries(paltest_sscanf_test16
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test16/test16.c b/src/pal/tests/palsuite/c_runtime/sscanf/test16/test16.c
new file mode 100644
index 0000000000..787b72ed0a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test16/test16.c
@@ -0,0 +1,37 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test16.c
+**
+** Purpose:Tests sscanf with floats (compact notation, lowercase)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../sscanf.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoFloatTest("123.0", "%g", 123.0f);
+ DoFloatTest("123.0", "%2g", 12.0f);
+ DoFloatTest("10E1", "%g", 100.0f);
+ DoFloatTest("-12.01e-2", "%g", -0.1201f);
+ DoFloatTest("+12.01e-2", "%g", 0.1201f);
+ DoFloatTest("-12.01e+2", "%g", -1201.0f);
+ DoFloatTest("+12.01e+2", "%g", 1201.0f);
+ DoFloatTest("1234567890.0123456789g", "%g", 1234567936);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test16/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test16/testinfo.dat
new file mode 100644
index 0000000000..2c1dd42b70
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test16/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sscanf
+Name = Positive Test for sscanf
+TYPE = DEFAULT
+EXE1 = test16
+Description
+= Tests sscanf with floats (compact notation, lowercase)
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test17/CMakeLists.txt
new file mode 100644
index 0000000000..7d908ab832
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test17/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test17.c
+)
+
+add_executable(paltest_sscanf_test17
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sscanf_test17 coreclrpal)
+
+target_link_libraries(paltest_sscanf_test17
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test17/test17.c b/src/pal/tests/palsuite/c_runtime/sscanf/test17/test17.c
new file mode 100644
index 0000000000..c0dfd1699c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test17/test17.c
@@ -0,0 +1,37 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test17.c
+**
+** Purpose: Tests sscanf with floats (compact notation, uppercase)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../sscanf.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoFloatTest("123.0", "%G", 123.0f);
+ DoFloatTest("123.0", "%2G", 12.0f);
+ DoFloatTest("10E1", "%G", 100.0f);
+ DoFloatTest("-12.01e-2", "%G", -0.1201f);
+ DoFloatTest("+12.01e-2", "%G", 0.1201f);
+ DoFloatTest("-12.01e+2", "%G", -1201.0f);
+ DoFloatTest("+12.01e+2", "%G", 1201.0f);
+ DoFloatTest("1234567890.0123456789G", "%G", 1234567936);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test17/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test17/testinfo.dat
new file mode 100644
index 0000000000..e23be8541e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test17/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sscanf
+Name = Positive Test for sscanf
+TYPE = DEFAULT
+EXE1 = test17
+Description
+= Tests sscanf with floats (compact notation, uppercase)
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test2/CMakeLists.txt
new file mode 100644
index 0000000000..571d773a88
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_sscanf_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sscanf_test2 coreclrpal)
+
+target_link_libraries(paltest_sscanf_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test2/test2.c b/src/pal/tests/palsuite/c_runtime/sscanf/test2/test2.c
new file mode 100644
index 0000000000..1221124e3a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test2/test2.c
@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test2.c
+**
+** Purpose: Test to see if sscanf handles whitespace correctly
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../sscanf.h"
+
+
+/*
+ * Tests out how it handles whitespace. Seems to accept anything that qualifies
+ * as isspace (space, tab, vertical tab, line feed, carriage return and form
+ * feed), even if it says it only wants spaces tabs and newlines.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoStrTest("foo bar", "foo %s", "bar");
+ DoStrTest("foo\tbar", "foo %s", "bar");
+ DoStrTest("foo\nbar", "foo %s", "bar");
+ DoStrTest("foo\rbar", "foo %s", "bar");
+ DoStrTest("foo\vbar", "foo %s", "bar");
+ DoStrTest("foo\fbar", "foo %s", "bar");
+ DoStrTest("foo \t\n\r\v\fbar", "foo %s", "bar");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test2/testinfo.dat
new file mode 100644
index 0000000000..f5ee4b52d4
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test2/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sscanf
+Name = Positive Test for sscanf
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Test to see if sscanf handles whitespace correctly
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test3/CMakeLists.txt
new file mode 100644
index 0000000000..ced8d5f8da
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_sscanf_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sscanf_test3 coreclrpal)
+
+target_link_libraries(paltest_sscanf_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test3/test3.c b/src/pal/tests/palsuite/c_runtime/sscanf/test3/test3.c
new file mode 100644
index 0000000000..9d18991070
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test3/test3.c
@@ -0,0 +1,35 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test3.c
+**
+** Purpose: Tests sscanf with bracketed set strings
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../sscanf.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoStrTest("bar1", "%[a-z]", "bar");
+ DoStrTest("bar1", "%[z-a]", "bar");
+ DoStrTest("bar1", "%[ab]", "ba");
+ DoStrTest("bar1", "%[ar1b]", "bar1");
+ DoStrTest("bar1", "%[^4]", "bar1");
+ DoStrTest("bar1", "%[^4a]", "b");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test3/testinfo.dat
new file mode 100644
index 0000000000..c38a498225
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test3/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sscanf
+Name = Positive Test for sscanf
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Tests sscanf with bracketed set strings
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test4/CMakeLists.txt
new file mode 100644
index 0000000000..3e70d6dae2
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_sscanf_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sscanf_test4 coreclrpal)
+
+target_link_libraries(paltest_sscanf_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test4/test4.c b/src/pal/tests/palsuite/c_runtime/sscanf/test4/test4.c
new file mode 100644
index 0000000000..dd0538bcfe
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test4/test4.c
@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test4.c
+**
+** Purpose: Tests sscanf with decimal numbers
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../sscanf.h"
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int n65535 = 65535; /* Walkaround compiler strictness */
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoNumTest("1234d", "%d", 1234);
+ DoNumTest("1234d", "%2d", 12);
+ DoNumTest("-1", "%d", -1);
+ DoNumTest("0x1234", "%d", 0);
+ DoNumTest("012", "%d", 12);
+ DoShortNumTest("-1", "%hd", n65535);
+ DoShortNumTest("65536", "%hd", 0);
+ DoNumTest("-1", "%ld", -1);
+ DoNumTest("65536", "%ld", 65536);
+ DoNumTest("-1", "%Ld", -1);
+ DoNumTest("65536", "%Ld", 65536);
+ DoI64NumTest("4294967296", "%I64d", I64(4294967296));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test4/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test4/testinfo.dat
new file mode 100644
index 0000000000..868056a6a5
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test4/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sscanf
+Name = Positive Test for sscanf
+TYPE = DEFAULT
+EXE1 = test4
+Description
+= Tests sscanf with decimal numbers
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test5/CMakeLists.txt
new file mode 100644
index 0000000000..391e51baa2
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test5.c
+)
+
+add_executable(paltest_sscanf_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sscanf_test5 coreclrpal)
+
+target_link_libraries(paltest_sscanf_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test5/test5.c b/src/pal/tests/palsuite/c_runtime/sscanf/test5/test5.c
new file mode 100644
index 0000000000..0d45248af3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test5/test5.c
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test5.c
+**
+** Purpose: Tests sscanf with integer numbers
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../sscanf.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+ int n65535 = 65535; /* Walkaround compiler strictness */
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoNumTest("1234d", "%i", 1234);
+ DoNumTest("1234d", "%2i", 12);
+ DoNumTest("-1", "%i", -1);
+ DoNumTest("0x1234", "%i", 0x1234);
+ DoNumTest("012", "%i", 10);
+ DoShortNumTest("-1", "%hi", n65535);
+ DoShortNumTest("65536", "%hi", 0);
+ DoNumTest("-1", "%li", -1);
+ DoNumTest("65536", "%li", 65536);
+ DoNumTest("-1", "%Li", -1);
+ DoNumTest("65536", "%Li", 65536);
+ DoI64NumTest("4294967296", "%I64i", I64(4294967296));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test5/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test5/testinfo.dat
new file mode 100644
index 0000000000..8678dc8f5a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test5/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sscanf
+Name = Positive Test for sscanf
+TYPE = DEFAULT
+EXE1 = test5
+Description
+= Tests sscanf with integer numbers
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test6/CMakeLists.txt
new file mode 100644
index 0000000000..c0b21bfd0d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test6.c
+)
+
+add_executable(paltest_sscanf_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sscanf_test6 coreclrpal)
+
+target_link_libraries(paltest_sscanf_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test6/test6.c b/src/pal/tests/palsuite/c_runtime/sscanf/test6/test6.c
new file mode 100644
index 0000000000..c45ea31b04
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test6/test6.c
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test6.c
+**
+** Purpose: Tests sscanf with octal numbers
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../sscanf.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+ int n65535 = 65535; /* Walkaround compiler strictness */
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoNumTest("1234d", "%o", 668);
+ DoNumTest("1234d", "%2o", 10);
+ DoNumTest("-1", "%o", -1);
+ DoNumTest("0x1234", "%o", 0);
+ DoNumTest("012", "%o", 10);
+ DoShortNumTest("-1", "%ho", n65535);
+ DoShortNumTest("200000", "%ho", 0);
+ DoNumTest("-1", "%lo", -1);
+ DoNumTest("200000", "%lo", 65536);
+ DoNumTest("-1", "%Lo", -1);
+ DoNumTest("200000", "%Lo", 65536);
+ DoI64NumTest("40000000000", "%I64o", I64(4294967296));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test6/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test6/testinfo.dat
new file mode 100644
index 0000000000..b2547a776a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test6/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sscanf
+Name = Positive Test for sscanf
+TYPE = DEFAULT
+EXE1 = test6
+Description
+= Tests sscanf with octal numbers
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test7/CMakeLists.txt
new file mode 100644
index 0000000000..bcbd268011
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test7/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test7.c
+)
+
+add_executable(paltest_sscanf_test7
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sscanf_test7 coreclrpal)
+
+target_link_libraries(paltest_sscanf_test7
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test7/test7.c b/src/pal/tests/palsuite/c_runtime/sscanf/test7/test7.c
new file mode 100644
index 0000000000..0899671d64
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test7/test7.c
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test7.c
+**
+** Purpose: Tests sscanf with hex numbers (lowercase)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../sscanf.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+ int n65535 = 65535; /* Walkaround compiler strictness */
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoNumTest("1234i", "%x", 0x1234);
+ DoNumTest("1234i", "%2x", 0x12);
+ DoNumTest("-1", "%x", -1);
+ DoNumTest("0x1234", "%x", 0x1234);
+ DoNumTest("012", "%x", 0x12);
+ DoShortNumTest("-1", "%hx", n65535);
+ DoShortNumTest("10000", "%hx", 0);
+ DoNumTest("-1", "%lx", -1);
+ DoNumTest("10000", "%lx", 65536);
+ DoNumTest("-1", "%Lx", -1);
+ DoNumTest("10000", "%Lx", 65536);
+ DoI64NumTest("100000000", "%I64x", I64(4294967296));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test7/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test7/testinfo.dat
new file mode 100644
index 0000000000..614333e650
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test7/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sscanf
+Name = Positive Test for sscanf
+TYPE = DEFAULT
+EXE1 = test7
+Description
+= Tests sscanf with hex numbers (lowercase)
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test8/CMakeLists.txt
new file mode 100644
index 0000000000..211e9e4df6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test8/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test8.c
+)
+
+add_executable(paltest_sscanf_test8
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sscanf_test8 coreclrpal)
+
+target_link_libraries(paltest_sscanf_test8
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test8/test8.c b/src/pal/tests/palsuite/c_runtime/sscanf/test8/test8.c
new file mode 100644
index 0000000000..53252f8929
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test8/test8.c
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test8.c
+**
+** Purpose:Tests sscanf with unsigned number
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../sscanf.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+ int n65535 = 65535; /* Walkaround compiler strictness */
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoNumTest("1234d", "%u", 1234);
+ DoNumTest("1234d", "%2u", 12);
+ DoNumTest("-1", "%u", -1);
+ DoNumTest("0x1234", "%u", 0);
+ DoNumTest("012", "%u", 12);
+ DoShortNumTest("-1", "%hu", n65535);
+ DoShortNumTest("65536", "%hu", 0);
+ DoNumTest("-1", "%lu", -1);
+ DoNumTest("65536", "%lu", 65536);
+ DoNumTest("-1", "%Lu", -1);
+ DoNumTest("65536", "%Lu", 65536);
+ DoI64NumTest("4294967296", "%I64u", I64(4294967296));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test8/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test8/testinfo.dat
new file mode 100644
index 0000000000..2cbc31ad2a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test8/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = sscanf
+Name = Positive Test for sscanf
+TYPE = DEFAULT
+EXE1 = test8
+Description
+= Tests sscanf with unsigned numbers
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test9/CMakeLists.txt
new file mode 100644
index 0000000000..77c269aeaa
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test9/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test9.c
+)
+
+add_executable(paltest_sscanf_test9
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sscanf_test9 coreclrpal)
+
+target_link_libraries(paltest_sscanf_test9
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test9/test9.c b/src/pal/tests/palsuite/c_runtime/sscanf/test9/test9.c
new file mode 100644
index 0000000000..c5a2e0de5d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test9/test9.c
@@ -0,0 +1,38 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test9.c
+**
+** Purpose: Tests sscanf with characters
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../sscanf.h"
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoCharTest("1234d", "%c", "1", 1);
+ DoCharTest("1234d", "%c", "1", 1);
+ DoCharTest("abc", "%2c", "ab", 2);
+ DoCharTest(" ab", "%c", " ", 1);
+ DoCharTest("ab", "%hc", "a", 1);
+ DoWCharTest("ab", "%lc", convert("a"), 1);
+ DoCharTest("ab", "%Lc", "a", 1);
+ DoCharTest("ab", "%I64c", "a", 1);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test9/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test9/testinfo.dat
new file mode 100644
index 0000000000..c0ccc8a4c9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/sscanf/test9/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section =C Runtime
+Function = sscanf
+Name = Positive Test for sscanf
+TYPE = DEFAULT
+EXE1 = test9
+Description
+= Tests sscanf with characters
diff --git a/src/pal/tests/palsuite/c_runtime/strcat/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strcat/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strcat/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/strcat/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strcat/test1/CMakeLists.txt
new file mode 100644
index 0000000000..4a0f0be32d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strcat/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_strcat_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_strcat_test1 coreclrpal)
+
+target_link_libraries(paltest_strcat_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/strcat/test1/test1.c b/src/pal/tests/palsuite/c_runtime/strcat/test1/test1.c
new file mode 100644
index 0000000000..532d84621e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strcat/test1/test1.c
@@ -0,0 +1,66 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose:
+** Concatenate three strings into one string. Each time, check to ensure
+** the pointer returned was what we expected. When finished, compare the
+** newly formed string to what it should be to ensure no characters were
+** lost.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ char dest[80];
+ char *test = "foo bar baz";
+ char *str1 = "foo ";
+ char *str2 = "bar ";
+ char *str3 = "baz";
+ char *ptr;
+
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ dest[0] = 0;
+
+ ptr = strcat(dest, str1);
+ if (ptr != dest)
+ {
+ Fail("ERROR: Expected strcat to return ptr to %p, got %p", dest, ptr);
+ }
+
+ ptr = strcat(dest, str2);
+ if (ptr != dest)
+ {
+ Fail("ERROR: Expected strcat to return ptr to %p, got %p", dest, ptr);
+ }
+
+ ptr = strcat(dest, str3);
+ if (ptr != dest)
+ {
+ Fail("ERROR: Expected strcat to return ptr to %p, got %p", dest, ptr);
+ }
+
+ if (strcmp(dest, test) != 0)
+ {
+ Fail("ERROR: Expected strcat to give \"%s\", got \"%s\"\n",
+ test, dest);
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/strcat/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/strcat/test1/testinfo.dat
new file mode 100644
index 0000000000..6d67ffa180
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strcat/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = strcat
+Name = Test #1 for strcat
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Concatenate three strings into one string. Each time, check to ensure
+= the pointer returned was what we expected. When finished, compare the
+= newly formed string to what it should be to ensure no characters were
+= lost.
diff --git a/src/pal/tests/palsuite/c_runtime/strchr/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strchr/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strchr/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/strchr/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strchr/test1/CMakeLists.txt
new file mode 100644
index 0000000000..1d248f3f56
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strchr/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_strchr_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_strchr_test1 coreclrpal)
+
+target_link_libraries(paltest_strchr_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/strchr/test1/test1.c b/src/pal/tests/palsuite/c_runtime/strchr/test1/test1.c
new file mode 100644
index 0000000000..9190c4f7ce
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strchr/test1/test1.c
@@ -0,0 +1,86 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose:
+** Test this on a character which is in a string, and ensure the pointer
+** points to that character. Then check the string for the null character,
+** which the return pointer should point to. Then search for a character not
+** in the string and check that the return value is NULL.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+struct testCase
+{
+ int result;
+ char string[50];
+ int character;
+};
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int i = 0;
+ char *result;
+
+ /*
+ * this structure includes several strings to be tested with
+ * strchr function and the expected results
+ */
+
+ struct testCase testCases[]=
+ {
+ {22,"corn cup cat cream coast",'s'},
+ {10,"corn cup cat cream coast",'a'},
+ {2,"This is a test",'i'},
+ {10,"This is a test",'t'},
+ {'\0',"This is a test",'b'},/* zero used instead of NULL */
+ {'\0',"This is a test",121},/* zero used instead of NULL */
+ {4,"This is a test of the function",' '},
+ {25,"This is a test of the function",'c'},
+ {'\0',"This is a test of the function",'C'},
+ {24,"corn cup cat cream coast", '\0'}/* zero used instead of NULL */
+ };
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /* Loop through the structure and test each case */
+
+ for (i=0; i< sizeof(testCases)/sizeof(struct testCase); i++)
+ {
+ result = strchr(testCases[i].string,testCases[i].character);
+ if (result==NULL)
+ {
+ if (testCases[i].result != (int) NULL)
+ {
+ Fail("Expected strchr() to return \"%s\" instead of NULL!\n",
+ testCases[i].string + testCases[i].result);
+ }
+ }
+ else
+ {
+ if (result != testCases[i].string + testCases[i].result)
+ {
+ Fail("Expected strchr() to return \"%s\" instead of \"%s\"!\n",
+ testCases[i].string + testCases[i].result, result);
+ }
+ }
+
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/strchr/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/strchr/test1/testinfo.dat
new file mode 100644
index 0000000000..4985c47541
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strchr/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = strchr
+Name = Test #1 for strchr
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Test this on a character which is in a string, and ensure the pointer
+= points to that character. Then check the string for the null character,
+= which the return pointer should point to. Then search for a character not
+= in the string and check that the return value is NULL.
diff --git a/src/pal/tests/palsuite/c_runtime/strcmp/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strcmp/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strcmp/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/strcmp/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strcmp/test1/CMakeLists.txt
new file mode 100644
index 0000000000..b953dfa034
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strcmp/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_strcmp_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_strcmp_test1 coreclrpal)
+
+target_link_libraries(paltest_strcmp_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/strcmp/test1/test1.c b/src/pal/tests/palsuite/c_runtime/strcmp/test1/test1.c
new file mode 100644
index 0000000000..49428fd624
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strcmp/test1/test1.c
@@ -0,0 +1,73 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose:
+** Compare a number of different strings against each other, ensure that the
+** three return values are given at the appropriate times.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+typedef struct
+{
+ int result;
+ char string1[50];
+ char string2[50];
+} testCase;
+
+testCase testCases[]=
+{
+ {0,"Hello","Hello"},
+ {1,"hello","Hello"},
+ {-1,"Hello","hello"},
+ {0,"0Test","0Test"},
+ {0,"***???","***???"},
+ {0,"Testing the string for string comparison","Testing the string for "
+ "string comparison"},
+ {-1,"Testing the string for string comparison","Testing the string for "
+ "string comparsioa"},
+ {1,"Testing the string for string comparison","Testing the string for "
+ "comparison"},
+ {-1,"aaaabbbbb","aabcdefeccg"}
+};
+
+int __cdecl main(int argc, char *argv[])
+{
+ int i = 0;
+ int result = 0;
+
+ /*
+ * Initialize the PAL
+ */
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Loop through structure and test each case */
+ for (i=0; i < sizeof(testCases)/sizeof(testCase); i++)
+ {
+ result = strcmp(testCases[i].string1,testCases[i].string2);
+
+ /* Compare returned value */
+ if( ((result == 0) && (testCases[i].result !=0)) ||
+ ((result <0) && (testCases[i].result !=-1)) ||
+ ((result >0) && (testCases[i].result !=1)) )
+ {
+ Fail("ERROR: strcmp returned %d instead of %d\n",
+ result, testCases[i].result);
+ }
+
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/strcmp/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/strcmp/test1/testinfo.dat
new file mode 100644
index 0000000000..174cb4be85
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strcmp/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = strcmp
+Name = Test #1 for strcmp
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Compare a number of different strings against each other, ensure that the
+= three return values are given at the appropriate times.
diff --git a/src/pal/tests/palsuite/c_runtime/strcpy/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strcpy/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strcpy/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/strcpy/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strcpy/test1/CMakeLists.txt
new file mode 100644
index 0000000000..043ec57d98
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strcpy/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_strcpy_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_strcpy_test1 coreclrpal)
+
+target_link_libraries(paltest_strcpy_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/strcpy/test1/test1.c b/src/pal/tests/palsuite/c_runtime/strcpy/test1/test1.c
new file mode 100644
index 0000000000..43069e59a6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strcpy/test1/test1.c
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose:
+** Call the function to copy into an empty buffer. Check that the return value
+** is pointing at the destination buffer. Also compare the string copied to
+** the origional string, to ensure they are the same.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ char dest[80];
+ char *result = "foo";
+ char str[] = {'f','o','o',0,'b','a','r',0};
+ char *ret;
+
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ ret = strcpy(dest, str);
+
+ if (ret != dest)
+ {
+ Fail("Expected strcpy to return %p, got %p!\n", dest, ret);
+
+ }
+
+ if (strcmp(dest, result) != 0)
+ {
+ Fail("Expected strcpy to give \"%s\", got \"%s\"!\n", result, dest);
+ }
+
+
+ PAL_Terminate();
+
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/strcpy/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/strcpy/test1/testinfo.dat
new file mode 100644
index 0000000000..700b124926
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strcpy/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = strcpy
+Name = Test #1 for strcpy
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Call the function to copy into an empty buffer. Check that the return value
+= is pointing at the destination buffer. Also compare the string copied to
+= the origional string, to ensure they are the same.
diff --git a/src/pal/tests/palsuite/c_runtime/strcspn/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strcspn/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strcspn/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/strcspn/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strcspn/test1/CMakeLists.txt
new file mode 100644
index 0000000000..a38761c335
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strcspn/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_strcspn_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_strcspn_test1 coreclrpal)
+
+target_link_libraries(paltest_strcspn_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/strcspn/test1/test1.c b/src/pal/tests/palsuite/c_runtime/strcspn/test1/test1.c
new file mode 100644
index 0000000000..ddc5667570
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strcspn/test1/test1.c
@@ -0,0 +1,59 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests strcspn with a character set that should give an index into
+** the middle of the original string. Also tests with character sets
+** that are not in the string at all, and character sets that match
+** with the very first character.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+struct testCase
+{
+ long result;
+ char *string1;
+ char *string2;
+};
+
+int __cdecl main(int argc, char *argv[])
+{
+ int i=0;
+ long TheResult = 0;
+
+ struct testCase testCases[]=
+ {
+ {4,"abcdefg12345678hijklmnopqrst","t8m1sBe"},
+ {23,"This is a test, testing", "X\tylM"},
+ {0,"foobar","tzkfb"},
+ };
+
+ /*
+ * Initialize the PAL
+ */
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ for (i=0; i<sizeof(testCases)/sizeof(struct testCase); i++)
+ {
+ TheResult = strcspn(testCases[i].string1,testCases[i].string2);
+ if (TheResult != testCases[i].result)
+ {
+ Fail("Expected strcspn to return %d, got %d!\n",
+ testCases[i].result,TheResult);
+ }
+
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/strcspn/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/strcspn/test1/testinfo.dat
new file mode 100644
index 0000000000..a302eb1fb7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strcspn/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = strcspn
+Name = Test #1 for strcspn
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Tests strcspn with a character set that should give an index into
+=the middle of the original string. Also tests with character sets
+=that are not in the string at all, and character sets that match
+=with the very first character.
diff --git a/src/pal/tests/palsuite/c_runtime/strlen/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strlen/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strlen/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/strlen/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strlen/test1/CMakeLists.txt
new file mode 100644
index 0000000000..c61828a97b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strlen/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_strlen_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_strlen_test1 coreclrpal)
+
+target_link_libraries(paltest_strlen_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/strlen/test1/test1.c b/src/pal/tests/palsuite/c_runtime/strlen/test1/test1.c
new file mode 100644
index 0000000000..40f8e151c7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strlen/test1/test1.c
@@ -0,0 +1,33 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose:
+** Check the length of a string and the length of a 0 character string to
+** see that this function returns the correct values for each.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ if (strlen("foo") != 3)
+ Fail("ERROR: strlen(\"foo\") != 3\n");
+
+ if (strlen("") != 0)
+ Fail("ERROR: strlen(\"\") != 0\n");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/strlen/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/strlen/test1/testinfo.dat
new file mode 100644
index 0000000000..ac5c3aec0f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strlen/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = strlen
+Name = Positive Test for strlen
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Check the length of a string and the length of a 0 character string to
+= see that this function returns the correct values for each.
diff --git a/src/pal/tests/palsuite/c_runtime/strncat/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strncat/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strncat/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/strncat/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strncat/test1/CMakeLists.txt
new file mode 100644
index 0000000000..7595f66939
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strncat/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_strncat_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_strncat_test1 coreclrpal)
+
+target_link_libraries(paltest_strncat_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/strncat/test1/test1.c b/src/pal/tests/palsuite/c_runtime/strncat/test1/test1.c
new file mode 100644
index 0000000000..000d1685b9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strncat/test1/test1.c
@@ -0,0 +1,77 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose:
+** Concatenate a few strings together, setting different lengths to be
+** used for each one. Check to ensure the pointers which are returned are
+** correct, and that the final string is what was expected.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ char dest[80];
+ char *test = "foo barbaz";
+ char *str1 = "foo ";
+ char *str2 = "bar ";
+ char *str3 = "baz";
+ char *ptr;
+ int i;
+
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ dest[0] = 0;
+ for (i=1; i<80; i++)
+ {
+ dest[i] = 'x';
+ }
+
+ ptr = strncat(dest, str1, strlen(str1));
+ if (ptr != dest)
+ {
+ Fail("ERROR: Expected strncat to return ptr to %p, got %p", dest, ptr);
+ }
+
+ ptr = strncat(dest, str2, 3);
+ if (ptr != dest)
+ {
+ Fail("ERROR: Expected strncat to return ptr to %p, got %p", dest, ptr);
+ }
+ if (dest[7] != 0)
+ {
+ Fail("ERROR: strncat did not place a terminating NULL!");
+ }
+
+ ptr = strncat(dest, str3, 20);
+ if (ptr != dest)
+ {
+ Fail("ERROR: Expected strncat to return ptr to %p, got %p", dest, ptr);
+ }
+ if (strcmp(dest, test) != 0)
+ {
+ Fail("ERROR: Expected strncat to give \"%s\", got \"%s\"\n",
+ test, dest);
+ }
+ if (dest[strlen(test)+1] != 'x')
+ {
+ Fail("strncat went out of bounds!\n");
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/strncat/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/strncat/test1/testinfo.dat
new file mode 100644
index 0000000000..4aaedbf404
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strncat/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = strncat
+Name = Test #1 for strncat
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Concatenate a few strings together, setting different lengths to be
+= used for each one. Check to ensure the pointers which are returned are
+= correct, and that the final string is what was expected.
diff --git a/src/pal/tests/palsuite/c_runtime/strncmp/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strncmp/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strncmp/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/strncmp/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strncmp/test1/CMakeLists.txt
new file mode 100644
index 0000000000..4a0337a3dc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strncmp/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_strncmp_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_strncmp_test1 coreclrpal)
+
+target_link_libraries(paltest_strncmp_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/strncmp/test1/test1.c b/src/pal/tests/palsuite/c_runtime/strncmp/test1/test1.c
new file mode 100644
index 0000000000..7326c3b61e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strncmp/test1/test1.c
@@ -0,0 +1,80 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose:
+** Test to ensure all three possible return values are given under the
+** appropriate circumstance. Also, uses different sizes, to only compare
+** portions of strings, checking to make sure these return the correct value.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+typedef struct
+{
+ int result;
+ char string1[50];
+ char string2[50];
+ int number;
+} testCase;
+
+testCase testCases[]=
+{
+ {0,"Hello","Hello",5},
+ {1,"hello","Hello",3},
+ {-1,"Hello","hello",5},
+ {0,"heLLo","heLLo",5},
+ {1,"hello","heLlo",5},
+ {-1,"heLlo","hello",5},
+ {0,"0Test","0Test",5},
+ {0,"***???","***???",6},
+ {0,"Testing the string for string comparison","Testing the string for "
+ "string comparison",40},
+ {-1,"Testing the string for string comparison","Testing the string for "
+ "string comparsioa",40},
+ {1,"Testing the string for string comparison","Testing the string for "
+ "comparison",34},
+ {0,"aaaabbbbb","aabcdefeccg",2},
+ {0,"abcd","abcd",10}
+};
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int i=0;
+ int iresult=0;
+
+ /*
+ * Initialize the PAL
+ */
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ for (i=0; i< sizeof(testCases)/sizeof(testCase); i++)
+ {
+ iresult = strncmp(testCases[i].string1,testCases[i].string2,
+ testCases[i].number);
+
+ if( ((iresult == 0) && (testCases[i].result !=0)) ||
+ ((iresult <0) && (testCases[i].result !=-1)) ||
+ ((iresult >0) && (testCases[i].result !=1)) )
+
+ {
+ Fail("ERROR: strncmp returned %d instead of %d\n",
+ iresult, testCases[i].result);
+ }
+
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/strncmp/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/strncmp/test1/testinfo.dat
new file mode 100644
index 0000000000..8e95311f36
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strncmp/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = strncmp
+Name = Test #1 for strncmp
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Test to ensure all three possible return values are given under the
+= appropriate circumstance. Also, uses different sizes, to only compare
+= portions of strings, checking to make sure these return the correct value.
diff --git a/src/pal/tests/palsuite/c_runtime/strncpy/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strncpy/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strncpy/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/strncpy/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strncpy/test1/CMakeLists.txt
new file mode 100644
index 0000000000..6e0250bce3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strncpy/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_strncpy_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_strncpy_test1 coreclrpal)
+
+target_link_libraries(paltest_strncpy_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/strncpy/test1/test1.c b/src/pal/tests/palsuite/c_runtime/strncpy/test1/test1.c
new file mode 100644
index 0000000000..62baf61ba2
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strncpy/test1/test1.c
@@ -0,0 +1,85 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose:
+** Test to see that you can copy a portion of a string into a new buffer.
+** Also check that the strncpy function doesn't overflow when it is used.
+** Finally check that if the number of characters given is greater than the
+** amount to copy, that the destination buffer is padded with NULLs.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ char dest[80];
+ char *result = "foobar";
+ char *str = "foobar\0baz";
+ char *ret;
+ int i;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ for (i=0; i<80; i++)
+ {
+ dest[i] = 'x';
+ }
+
+ ret = strncpy(dest, str, 3);
+ if (ret != dest)
+ {
+ Fail("Expected strncpy to return %p, got %p!\n", dest, ret);
+ }
+
+ if (strncmp(dest, result, 3) != 0)
+ {
+ Fail("Expected strncpy to give \"%s\", got \"%s\"!\n", result, dest);
+ }
+
+ if (dest[3] != 'x')
+ {
+ Fail("strncpy overflowed!\n");
+ }
+
+ ret = strncpy(dest, str, 40);
+ if (ret != dest)
+ {
+ Fail("Expected strncpy to return %p, got %p!\n", dest, ret);
+ }
+
+ if (strcmp(dest, result) != 0)
+ {
+ Fail("Expected strncpy to give \"%s\", got \"%s\"!\n", result, dest);
+ }
+
+ for (i=strlen(str); i<40; i++)
+ {
+ if (dest[i] != 0)
+ {
+ Fail("strncpy failed to pad the destination with NULLs!\n");
+ }
+ }
+
+ if (dest[40] != 'x')
+ {
+ Fail("strncpy overflowed!\n");
+ }
+
+
+
+ PAL_Terminate();
+
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/strncpy/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/strncpy/test1/testinfo.dat
new file mode 100644
index 0000000000..c402adb1c1
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strncpy/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = strncpy
+Name = Test #1 for strncpy
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Test to see that you can copy a portion of a string into a new buffer.
+= Also check that the strncpy function doesn't overflow when it is used.
+= Finally check that if the number of characters given is greater than the
+= amount to copy, that the destination buffer is padded with NULLs.
diff --git a/src/pal/tests/palsuite/c_runtime/strpbrk/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strpbrk/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strpbrk/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/strpbrk/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strpbrk/test1/CMakeLists.txt
new file mode 100644
index 0000000000..eac9ac9169
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strpbrk/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_strpbrk_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_strpbrk_test1 coreclrpal)
+
+target_link_libraries(paltest_strpbrk_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/strpbrk/test1/test1.c b/src/pal/tests/palsuite/c_runtime/strpbrk/test1/test1.c
new file mode 100644
index 0000000000..a42b80f313
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strpbrk/test1/test1.c
@@ -0,0 +1,85 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose:
+** Search a string for characters in a given character set and ensure the
+** pointer returned points to the first occurance. Check to see that the
+** function returns NULL if the character is not found.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+struct testCase
+{
+ char *result;
+ char *string1;
+ char *string2;
+};
+
+int __cdecl main(int argc, char *argv[])
+{
+ char *ptr = NULL;
+ int i = 0;
+
+ /*
+ * this structure includes several strings to be tested with
+ * strpbk function and the expected results
+ */
+
+ struct testCase testCases[] =
+ {
+ {"t cream coast","corn cup cat cream coast","sit"},
+ {"eam coast","corn cup cat cream coast","like"},
+ {"is is a test","This is a test","circle"},
+ {"a test","This is a test","way"},
+ {NULL,"This is a test","boo"},
+ {NULL,"This is a test","123"},
+ {" is a test of the function","This is a test of the function",
+ "zzz xx"}
+ };
+
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* A loop to go through the testcases in the structure */
+
+ for (i=0; i< sizeof(testCases)/sizeof(struct testCase); i++)
+ {
+ ptr = strpbrk(testCases[i].string1,testCases[i].string2);
+ if (ptr==NULL)
+ {
+ if (testCases[i].result != NULL)
+ {
+ Fail("Expected strpbrk() to return %s, got NULL!\n",
+ testCases[i].result);
+ }
+ }
+ else
+ {
+ if (strcmp(ptr,testCases[i].result)!=0 )
+
+ {
+ Fail("Expected strpbrk() to return %s, got %s!\n",
+ testCases[i].result,ptr);
+ }
+
+ }
+
+ }
+
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/strpbrk/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/strpbrk/test1/testinfo.dat
new file mode 100644
index 0000000000..1bef6a7b9d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strpbrk/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = strpbrk
+Name = Test #1 for strpbrk
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Search a string for characters in a given character set and ensure the
+= pointer returned points to the first occurance. Check to see that the
+= function returns NULL if the character is not found.
diff --git a/src/pal/tests/palsuite/c_runtime/strrchr/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strrchr/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strrchr/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/strrchr/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strrchr/test1/CMakeLists.txt
new file mode 100644
index 0000000000..5c099b0cd2
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strrchr/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_strrchr_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_strrchr_test1 coreclrpal)
+
+target_link_libraries(paltest_strrchr_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/strrchr/test1/test1.c b/src/pal/tests/palsuite/c_runtime/strrchr/test1/test1.c
new file mode 100644
index 0000000000..a5c147eece
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strrchr/test1/test1.c
@@ -0,0 +1,55 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: \
+** Search a string for a given character. Search for a character contained
+** in the string, and ensure the pointer returned points to it. Then search
+** for the null character, and ensure the pointer points to that. Finally
+** search for a character which is not in the string and ensure that it
+** returns NULL.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ char *str = "foo bar baz";
+ char *ptr;
+
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ ptr = strrchr(str, 'b');
+ if (ptr != str + 8)
+ {
+ Fail("Expected strrchr() to return %p, got %p!\n", str + 8, ptr);
+ }
+
+ ptr = strrchr(str, 0);
+ if (ptr != str + 11)
+ {
+ Fail("Expected strrchr() to return %p, got %p!\n", str + 11, ptr);
+ }
+
+ ptr = strrchr(str, 'x');
+ if (ptr != NULL)
+ {
+ Fail("Expected strrchr() to return NULL, got %p!\n", ptr);
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/strrchr/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/strrchr/test1/testinfo.dat
new file mode 100644
index 0000000000..45b27aecf9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strrchr/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = strrchr
+Name = Test #1 for strrchr
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Search a string for a given character. Search for a character contained
+= in the string, and ensure the pointer returned points to it. Then search
+= for the null character, and ensure the pointer points to that. Finally
+= search for a character which is not in the string and ensure that it
+= returns NULL.
diff --git a/src/pal/tests/palsuite/c_runtime/strspn/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strspn/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strspn/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/strspn/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strspn/test1/CMakeLists.txt
new file mode 100644
index 0000000000..45caaf1bf8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strspn/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_strspn_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_strspn_test1 coreclrpal)
+
+target_link_libraries(paltest_strspn_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/strspn/test1/test1.c b/src/pal/tests/palsuite/c_runtime/strspn/test1/test1.c
new file mode 100644
index 0000000000..78d2488438
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strspn/test1/test1.c
@@ -0,0 +1,60 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose:
+** Check a character set against a string to see that the function returns
+** the length of the substring which consists of all characters in the string.
+** Also check that if the character set doesn't match the string at all, that
+** the value is 0.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+struct testCase
+{
+ long result;
+ char *string1;
+ char *string2;
+};
+
+int __cdecl main(int argc, char *argv[])
+{
+ int i=0;
+ long TheResult = 0;
+
+ struct testCase testCases[]=
+ {
+ {4,"abcdefg12345678hijklmnopqrst","a2bjk341cd"},
+ {14,"This is a test, testing", "aeioTts rh"},
+ {0,"foobar","kpzt"}
+ };
+
+ /*
+ * Initialize the PAL
+ */
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ for (i=0; i<sizeof(testCases)/sizeof(struct testCase);i++)
+ {
+ TheResult = strspn(testCases[i].string1,testCases[i].string2);
+ if (TheResult != testCases[i].result)
+ {
+ Fail("Expected strspn to return %d, got %d!\n",
+ testCases[i].result,TheResult);
+ }
+
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/strspn/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/strspn/test1/testinfo.dat
new file mode 100644
index 0000000000..b56bd1574e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strspn/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = strspn
+Name = Test #1 for strspn
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Check a character set against a string to see that the function returns
+= the length of the substring which consists of all characters in the string.
+= Also check that if the character set doesn't match the string at all, that
+= the value is 0.
diff --git a/src/pal/tests/palsuite/c_runtime/strstr/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strstr/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strstr/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/strstr/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strstr/test1/CMakeLists.txt
new file mode 100644
index 0000000000..17e6ae8457
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strstr/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_strstr_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_strstr_test1 coreclrpal)
+
+target_link_libraries(paltest_strstr_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/strstr/test1/test1.c b/src/pal/tests/palsuite/c_runtime/strstr/test1/test1.c
new file mode 100644
index 0000000000..db01e8b32a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strstr/test1/test1.c
@@ -0,0 +1,83 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose:
+** Check three cases of searching for a string within a string. First when
+** the string is contained, check that the pointer returned points to it.
+** Then when it isn't contained, ensure it returns null. And when the string
+** we're searching for is empty, it should return a pointer to the string
+** we're searching through.Test #1 for the strstr function
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+
+
+struct testCase
+{
+ char *result;
+ char *string1;
+ char *string2;
+
+};
+
+int __cdecl main(int argc, char *argv[])
+{
+ int i=0;
+ char *ptr=NULL;
+
+ struct testCase testCases[]=
+ {
+ {"is is a test", "This is a test","is"},
+ {"fghijkl","abcdefghijkl","fgh"},
+ {NULL,"aabbccddeeffgg","h"},
+ {NULL,"aabb", "eeeeeee"},
+ {"AAA", "BBddfdaaaaAAA","A"},
+ {"fdaaaaAAA", "BBddfdaaaaAAA","f"},
+ {"aadfsadfas","aadfsadfas",""},
+ {NULL,"","ccc"}
+ };
+
+ /*
+ * Initialize the PAL
+ */
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ for (i=0; i<sizeof(testCases)/sizeof(struct testCase); i++)
+ {
+ ptr = strstr(testCases[i].string1,testCases[i].string2);
+ if (ptr==NULL)
+ {
+ if (testCases[i].result != NULL)
+ {
+ Fail("ERROR: strstr returned incorrect value\n"
+ "Expected a pointer to \"%s\" , got a pointer to NULL\n",
+ testCases[i].result);
+ }
+ }
+ else
+ {
+ if (strcmp(testCases[i].result,ptr) != 0)
+ {
+ Fail("ERROR: strstr returned incorrect value\n"
+ "Expected a pointer to \"%s\" , got a pointer to \"%s\"\n",
+ testCases[i].result, ptr);
+ }
+ }
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/strstr/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/strstr/test1/testinfo.dat
new file mode 100644
index 0000000000..cf13170af5
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strstr/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = strstr
+Name = Positive Test for strstr
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Check three cases of searching for a string within a string. First when
+= the string is contained, check that the pointer returned points to it.
+= Then when it isn't contained, ensure it returns null. And when the string
+= we're searching for is empty, it should return a pointer to the string
+= we're searching through.
diff --git a/src/pal/tests/palsuite/c_runtime/strtod/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strtod/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strtod/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/c_runtime/strtod/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strtod/test1/CMakeLists.txt
new file mode 100644
index 0000000000..d3a9d61a4d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strtod/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_strtod_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_strtod_test1 coreclrpal)
+
+target_link_libraries(paltest_strtod_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/strtod/test1/test1.c b/src/pal/tests/palsuite/c_runtime/strtod/test1/test1.c
new file mode 100644
index 0000000000..e312d98f58
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strtod/test1/test1.c
@@ -0,0 +1,93 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests the PAL implementation of the strtod function.
+** Convert a number of strings to doubles. Ensure they
+** convert correctly.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+struct testCase
+{
+ double CorrectResult; /* The returned double value */
+ char ResultString[20]; /* The remainder string */
+ char string[20]; /* The test string */
+};
+
+
+int __cdecl main(int argc, char **argv)
+{
+
+ char * endptr;
+ double result;
+ int i;
+
+ struct testCase testCases[] =
+ {
+ {1234,"","1234"},
+ {-1234,"","-1234"},
+ {1234.44,"","1234.44"},
+ {1234e-5,"","1234e-5"},
+ {1234e+5,"","1234e+5"},
+ {12345E5,"","12345e5"},
+ {1234.657e-8,"","1234.657e-8"},
+ {1234567e-8,"foo","1234567e-8foo"},
+ {999,"foo","999 foo"},
+ {7,"foo"," 7foo"},
+ {0,"a7","a7"},
+ {-777777,"z zz","-777777z zz"}
+ };
+
+ /*
+ * Initialize the PAL
+ */
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* Loop through the structure to test each case */
+ for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++)
+ {
+ result = strtod(testCases[i].string,&endptr);
+
+ /* need to check the result and the endptr result */
+ if ((testCases[i].CorrectResult != result) &&
+ (strcmp(testCases[i].ResultString,endptr)!=0))
+ {
+ Fail("ERROR: strtod returned %f instead of %f and "
+ "\"%s\" instead of \"%s\" for the test of \"%s\"\n",
+ result,
+ testCases[i].CorrectResult,
+ endptr,
+ testCases[i].ResultString,
+ testCases[i].string);
+ }
+
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/strtod/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/strtod/test1/testinfo.dat
new file mode 100644
index 0000000000..2c98d2eaf6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strtod/test1/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = strtod
+Name = Positive Test for strtod
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Purpose: Tests the PAL implementation of the strtod function.
+= Convert a number of strings to doubles. Ensure they convert correctly.
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/strtod/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strtod/test2/CMakeLists.txt
new file mode 100644
index 0000000000..6f407c5914
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strtod/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_strtod_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_strtod_test2 coreclrpal)
+
+target_link_libraries(paltest_strtod_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/strtod/test2/test2.c b/src/pal/tests/palsuite/c_runtime/strtod/test2/test2.c
new file mode 100644
index 0000000000..0eaf4f53b6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strtod/test2/test2.c
@@ -0,0 +1,65 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test2.c
+**
+** Purpose: Tests strtod with overflows
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ /* Representation of positive infinty for a IEEE 64-bit double */
+ INT64 PosInifity = (INT64)(0x7ff00000) << 32;
+ double HugeVal = *(double*) &PosInifity;
+ char *PosStr = "1E+10000";
+ char *NegStr = "-1E+10000";
+ double result;
+
+
+ if (PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ result = strtod(PosStr, NULL);
+
+ if (result != HugeVal)
+ {
+ Fail("ERROR: wcstod interpreted \"%s\" as %g instead of %g\n",
+ PosStr, result, HugeVal);
+ }
+
+ result = strtod(NegStr, NULL);
+
+ if (result != -HugeVal)
+ {
+ Fail("ERROR: wcstod interpreted \"%s\" as %g instead of %g\n",
+ NegStr, result, -HugeVal);
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/strtod/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/strtod/test2/testinfo.dat
new file mode 100644
index 0000000000..a50c07b8b5
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strtod/test2/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = strtod
+Name = Negative test for strtod with overflows
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Test strtod with overflows.
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/strtok/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strtok/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strtok/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/strtok/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strtok/test1/CMakeLists.txt
new file mode 100644
index 0000000000..1d5fc04cca
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strtok/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_strtok_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_strtok_test1 coreclrpal)
+
+target_link_libraries(paltest_strtok_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/strtok/test1/test1.c b/src/pal/tests/palsuite/c_runtime/strtok/test1/test1.c
new file mode 100644
index 0000000000..f1dec70380
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strtok/test1/test1.c
@@ -0,0 +1,78 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose:
+** Search for a number of tokens within strings. Check that the return values
+** are what is expect, and also that the strings match up with our expected
+** results.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ char str[] = "foo bar baz";
+ char *result1= "foo \0ar baz";
+ char *result2= "foo \0a\0 baz";
+ int len = strlen(str) + 1;
+ char *ptr;
+
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ ptr = strtok(str, "bz");
+ if (ptr != str)
+ {
+ Fail("Expected strtok() to return %p, got %p!\n", str, ptr);
+ }
+ if (memcmp(str, result1, len) != 0)
+ {
+ Fail("strtok altered the string in an unexpeced way!\n");
+ }
+
+ ptr = strtok(NULL, "r ");
+ if (ptr != str + 5)
+ {
+ Fail("Expected strtok() to return %p, got %p!\n", str+5, ptr);
+ }
+ if (memcmp(str, result2, len) != 0)
+ {
+ Fail("strtok altered the string in an unexpeced way!\n");
+ }
+
+
+ ptr = strtok(NULL, "X");
+ if (ptr != str + 7)
+ {
+ Fail("Expected strtok() to return %p, got %p!\n", str + 7, ptr);
+ }
+ if (memcmp(str, result2, len) != 0)
+ {
+ Fail("strtok altered the string in an unexpeced way!\n");
+ }
+
+ ptr = strtok(NULL, "X");
+ if (ptr != NULL)
+ {
+ Fail("Expected strtok() to return %p, got %p!\n", NULL, ptr);
+ }
+ if (memcmp(str, result2, len) != 0)
+ {
+ Fail("strtok altered the string in an unexpeced way!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/strtok/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/strtok/test1/testinfo.dat
new file mode 100644
index 0000000000..f3773514c2
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strtok/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = strtok
+Name = Test #1 for strtok
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Search for a number of tokens within strings. Check that the return values
+= are what is expect, and also that the strings match up with our expected
+= results.
diff --git a/src/pal/tests/palsuite/c_runtime/strtoul/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strtoul/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strtoul/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/strtoul/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strtoul/test1/CMakeLists.txt
new file mode 100644
index 0000000000..61dbd4f9a3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strtoul/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_strtoul_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_strtoul_test1 coreclrpal)
+
+target_link_libraries(paltest_strtoul_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/strtoul/test1/test1.c b/src/pal/tests/palsuite/c_runtime/strtoul/test1/test1.c
new file mode 100644
index 0000000000..344671b5cc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strtoul/test1/test1.c
@@ -0,0 +1,73 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose:
+** Tests stroul with different bases and overflows, as well as valid input.
+** Makes sure that the end pointer is correct.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+char teststr1[] = "12345";
+char teststr2[] = "Z";
+char teststr3[] = "4294967295";
+char teststr4[] = "4294967296";
+
+typedef struct
+{
+ char *str;
+ char *end;
+ int base;
+ ULONG result;
+} TestCase;
+
+TestCase TestCases[] =
+{
+ { teststr1, teststr1 + 3, 4, 27},
+ { teststr1, teststr1 + 5, 10, 12345},
+ { teststr2, teststr2, 10, 0},
+ { teststr3, teststr3+10, 10, 4294967295ul},
+ { teststr4, teststr4+10, 10, 4294967295ul}
+};
+
+int NumCases = sizeof(TestCases) / sizeof(TestCases[0]);
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ char *end;
+ ULONG l;
+ int i;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ for (i=0; i<NumCases; i++)
+ {
+ l = strtoul(TestCases[i].str, &end, TestCases[i].base);
+
+ if (l != TestCases[i].result)
+ {
+ Fail("ERROR: Expected strtoul to return %u, got %u\n",
+ TestCases[i].result, l);
+ }
+
+ if (end != TestCases[i].end)
+ {
+ Fail("ERROR: Expected strtoul to give an end value of %p, got %p\n",
+ TestCases[i].end, end);
+ }
+ }
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/strtoul/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/strtoul/test1/testinfo.dat
new file mode 100644
index 0000000000..c7fc2c0c4d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/strtoul/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = strtoul
+Name = Test #1 for strtoul
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests stroul with different bases and overflows, as well as valid input.
+= Makes sure that the end pointer is correct.
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/CMakeLists.txt
new file mode 100644
index 0000000000..cafb9536b0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/CMakeLists.txt
@@ -0,0 +1,22 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test10)
+add_subdirectory(test11)
+add_subdirectory(test12)
+add_subdirectory(test13)
+add_subdirectory(test14)
+add_subdirectory(test15)
+add_subdirectory(test16)
+add_subdirectory(test17)
+add_subdirectory(test18)
+add_subdirectory(test19)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+add_subdirectory(test7)
+add_subdirectory(test8)
+add_subdirectory(test9)
+
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/swprintf.h b/src/pal/tests/palsuite/c_runtime/swprintf/swprintf.h
new file mode 100644
index 0000000000..5229506064
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/swprintf.h
@@ -0,0 +1,202 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: swprintf.h
+**
+** Purpose: Containts common testing functions for swprintf.h
+**
+**
+**==========================================================================*/
+
+#ifndef __SWPRINTF_H__
+#define __SWPRINTF_H__
+
+void DoWStrTest(WCHAR *formatstr, WCHAR *param, WCHAR *checkstr)
+{
+ WCHAR buf[256] = { 0 };
+
+ swprintf(buf, formatstr, param);
+
+ if (memcmp(buf, checkstr, wcslen(checkstr) * 2 + 2) != 0)
+ {
+ Fail("ERROR: failed to insert wide string \"%s\" into \"%s\".\n"
+ "Expected \"%s\", got \"%s\".\n",
+ convertC(param), convertC(formatstr),
+ convertC(checkstr), convertC(buf));
+ }
+}
+
+void DoStrTest(WCHAR *formatstr, char *param, WCHAR *checkstr)
+{
+ WCHAR buf[256] = { 0 };
+
+ swprintf(buf, formatstr, param);
+
+ if (memcmp(buf, checkstr, wcslen(checkstr) * 2 + 2) != 0)
+ {
+ Fail("ERROR: failed to insert wide string \"%s\" into \"%s\".\n"
+ "Expected \"%s\", got \"%s\".\n",
+ param, convertC(formatstr), convertC(checkstr),
+ convertC(buf));
+ }
+}
+
+void DoPointerTest(WCHAR *formatstr, void* param, WCHAR *checkstr1)
+{
+ WCHAR buf[256] = { 0 };
+
+ swprintf(buf, formatstr, param);
+ if (memcmp(buf, checkstr1, wcslen(checkstr1)*2 + 2) != 0)
+ {
+ Fail("ERROR: failed to insert pointer to %#p into \"%s\"\n"
+ "Expected \"%s\", got \"%s\".\n", param,
+ convertC(formatstr), convertC(checkstr1), convertC(buf));
+ }
+}
+
+void DoCountTest(WCHAR *formatstr, int param, WCHAR *checkstr)
+{
+ WCHAR buf[512] = { 0 };
+ int n = -1;
+
+ swprintf(buf, formatstr, &n);
+
+ if (n != param)
+ {
+ Fail("ERROR: Expected count parameter to resolve to %d, got %d\n",
+ param, n);
+ }
+
+ if (memcmp(buf, checkstr, wcslen(checkstr)*2 + 2) != 0)
+ {
+ Fail("ERROR: Expected \"%s\" got \"%s\".\n",
+ convertC(checkstr), convertC(buf));
+ }
+}
+
+void DoShortCountTest(WCHAR *formatstr, int param, WCHAR *checkstr)
+{
+ WCHAR buf[256] = { 0 };
+ short int n = -1;
+
+ swprintf(buf, formatstr, &n);
+
+ if (n != param)
+ {
+ Fail("ERROR: Expected count parameter to resolve to %d, got %d\n",
+ param, n);
+ }
+
+ if (memcmp(buf, checkstr, wcslen(checkstr)*2 + 2) != 0)
+ {
+ Fail("ERROR: Expected \"%s\" got \"%s\".\n",
+ convertC(checkstr), convertC(buf));
+ }
+}
+
+void DoCharTest(WCHAR *formatstr, char param, WCHAR *checkstr)
+{
+ WCHAR buf[256] = { 0 };
+
+ swprintf(buf, formatstr, param);
+ if (memcmp(buf, checkstr, wcslen(checkstr)*2 + 2) != 0)
+ {
+ Fail("ERROR: failed to insert char \'%c\' (%d) into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n", param, param,
+ convertC(formatstr), convertC(checkstr), convertC(buf));
+ }
+}
+
+void DoWCharTest(WCHAR *formatstr, WCHAR param, WCHAR *checkstr)
+{
+ WCHAR buf[256] = { 0 };
+
+ swprintf(buf, formatstr, param);
+ if (memcmp(buf, checkstr, wcslen(checkstr)*2 + 2) != 0)
+ {
+ Fail("ERROR: failed to insert wide char \'%c\' (%d) into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n", (char) param, param,
+ convertC(formatstr), convertC(checkstr), convertC(buf));
+ }
+}
+
+void DoNumTest(WCHAR *formatstr, int value, WCHAR*checkstr)
+{
+ WCHAR buf[256] = { 0 };
+
+ swprintf(buf, formatstr, value);
+ if (memcmp(buf, checkstr, wcslen(checkstr)* 2 + 2) != 0)
+ {
+ Fail("ERROR: failed to insert %#x into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n", value, convertC(formatstr),
+ convertC(checkstr), convertC(buf));
+ }
+}
+
+void DoI64Test(WCHAR *formatstr, INT64 param, char *paramdesc,
+ WCHAR *checkstr1)
+{
+ WCHAR buf[256] = { 0 };
+
+ swprintf(buf, formatstr, param);
+ if (memcmp(buf, checkstr1, wcslen(checkstr1)*2 + 2) != 0)
+ {
+ Fail("ERROR: failed to insert %s into \"%s\"\n"
+ "Expected \"%s\", got \"%s\".\n", paramdesc,
+ convertC(formatstr), convertC(checkstr1), convertC(buf));
+ }
+}
+
+void DoDoubleTest(WCHAR *formatstr, double value, WCHAR *checkstr1,
+ WCHAR *checkstr2)
+{
+ WCHAR buf[256] = { 0 };
+
+ swprintf(buf, formatstr, value);
+ if (memcmp(buf, checkstr1, wcslen(checkstr1)*2 + 2) != 0 &&
+ memcmp(buf, checkstr2, wcslen(checkstr2)*2 + 2) != 0)
+ {
+ Fail("ERROR: failed to insert %f into \"%s\"\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n",
+ value, convertC(formatstr), convertC(checkstr1),
+ convertC(checkstr2), convertC(buf));
+ }
+}
+
+void DoArgumentPrecTest(WCHAR *formatstr, int precision, void *param,
+ char *paramstr, WCHAR *checkstr1, WCHAR *checkstr2)
+{
+ WCHAR buf[256];
+
+ swprintf(buf, formatstr, precision, param);
+ if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0 &&
+ memcmp(buf, checkstr2, wcslen(checkstr2) + 2) != 0)
+ {
+ Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n", paramstr,
+ convertC(formatstr), precision,
+ convertC(checkstr1), convertC(checkstr2), convertC(buf));
+ }
+}
+
+void DoArgumentPrecDoubleTest(WCHAR *formatstr, int precision, double param,
+ WCHAR *checkstr1, WCHAR *checkstr2)
+{
+ WCHAR buf[256];
+
+ swprintf(buf, formatstr, precision, param);
+ if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0 &&
+ memcmp(buf, checkstr2, wcslen(checkstr2) + 2) != 0)
+ {
+ Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n", param,
+ convertC(formatstr), precision,
+ convertC(checkstr1), convertC(checkstr2), convertC(buf));
+ }
+}
+
+#endif
+
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..fcf816029e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_swprintf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swprintf_test1 coreclrpal)
+
+target_link_libraries(paltest_swprintf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/swprintf/test1/test1.c
new file mode 100644
index 0000000000..626040d9f7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test1/test1.c
@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: General test to see if swprintf works correctly
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swprintf.h"
+
+/*
+ * Uses memcmp & wcslen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR *checkstr;
+ WCHAR buf[256];
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ checkstr = convert("hello world");
+ swprintf(buf, convert("hello world"));
+
+ if (memcmp(checkstr, buf, wcslen(checkstr)*2+2) != 0)
+ {
+ Fail("ERROR: Expected \"%s\", got \"%s\".\n", "hello world",
+ convertC(buf));
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swprintf/test1/testinfo.dat
new file mode 100644
index 0000000000..f43d462daf
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swprintf
+Name = Positive Test for swprintf
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= General test to see if swprintf works correctly
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test10/CMakeLists.txt
new file mode 100644
index 0000000000..302c5e5923
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test10/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test10.c
+)
+
+add_executable(paltest_swprintf_test10
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swprintf_test10 coreclrpal)
+
+target_link_libraries(paltest_swprintf_test10
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test10/test10.c b/src/pal/tests/palsuite/c_runtime/swprintf/test10/test10.c
new file mode 100644
index 0000000000..61aef593a0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test10/test10.c
@@ -0,0 +1,55 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test10.c
+**
+** Purpose:Tests swprintf with octal numbers
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swprintf.h"
+
+/*
+ * Uses memcmp & wcslen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest(convert("foo %o"), pos, convert("foo 52"));
+ DoNumTest(convert("foo %lo"), 0xFFFF, convert("foo 177777"));
+ DoNumTest(convert("foo %ho"), 0xFFFF, convert("foo 177777"));
+ DoNumTest(convert("foo %Lo"), pos, convert("foo 52"));
+ DoI64Test(convert("foo %I64o"), l, "0x0000000000000042",
+ convert("foo 52"));
+ DoNumTest(convert("foo %3o"), pos, convert("foo 52"));
+ DoNumTest(convert("foo %-3o"), pos, convert("foo 52 "));
+ DoNumTest(convert("foo %.1o"), pos, convert("foo 52"));
+ DoNumTest(convert("foo %.3o"), pos, convert("foo 052"));
+ DoNumTest(convert("foo %03o"), pos, convert("foo 052"));
+ DoNumTest(convert("foo %#o"), pos, convert("foo 052"));
+ DoNumTest(convert("foo %+o"), pos, convert("foo 52"));
+ DoNumTest(convert("foo % o"), pos, convert("foo 52"));
+ DoNumTest(convert("foo %+o"), neg, convert("foo 37777777726"));
+ DoNumTest(convert("foo % o"), neg, convert("foo 37777777726"));
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test10/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swprintf/test10/testinfo.dat
new file mode 100644
index 0000000000..e860bb26e7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test10/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swprintf
+Name = Positive Test for swprintf
+TYPE = DEFAULT
+EXE1 = test10
+Description
+= Tests swprintf with octal numbers
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test11/CMakeLists.txt
new file mode 100644
index 0000000000..484d57ef58
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test11/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test11.c
+)
+
+add_executable(paltest_swprintf_test11
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swprintf_test11 coreclrpal)
+
+target_link_libraries(paltest_swprintf_test11
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test11/test11.c b/src/pal/tests/palsuite/c_runtime/swprintf/test11/test11.c
new file mode 100644
index 0000000000..216f9acdbb
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test11/test11.c
@@ -0,0 +1,55 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test11.c
+**
+** Purpose: Tests swprintf with unsigned numbers
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swprintf.h"
+
+/*
+ * Uses memcmp & wcslen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest(convert("foo %u"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %lu"), 0xFFFF, convert("foo 65535"));
+ DoNumTest(convert("foo %hu"), 0xFFFF, convert("foo 65535"));
+ DoNumTest(convert("foo %Lu"), pos, convert("foo 42"));
+ DoI64Test(convert("foo %I64u"), l, "0x0000000000000042",
+ convert("foo 42"));
+ DoNumTest(convert("foo %3u"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %-3u"), pos, convert("foo 42 "));
+ DoNumTest(convert("foo %.1u"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %.3u"), pos, convert("foo 042"));
+ DoNumTest(convert("foo %03u"), pos, convert("foo 042"));
+ DoNumTest(convert("foo %#u"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %+u"), pos, convert("foo 42"));
+ DoNumTest(convert("foo % u"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %+u"), neg, convert("foo 4294967254"));
+ DoNumTest(convert("foo % u"), neg, convert("foo 4294967254"));
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test11/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swprintf/test11/testinfo.dat
new file mode 100644
index 0000000000..430a777e7a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test11/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swprintf
+Name = Positive Test for swprintf
+TYPE = DEFAULT
+EXE1 = test11
+Description
+= Tests swprintf with unsigned numbers
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test12/CMakeLists.txt
new file mode 100644
index 0000000000..6d45ee4646
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test12/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test12.c
+)
+
+add_executable(paltest_swprintf_test12
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swprintf_test12 coreclrpal)
+
+target_link_libraries(paltest_swprintf_test12
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test12/test12.c b/src/pal/tests/palsuite/c_runtime/swprintf/test12/test12.c
new file mode 100644
index 0000000000..a41b0ddbd3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test12/test12.c
@@ -0,0 +1,56 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test12.c
+**
+** Purpose: Tests swprintf with hex numbers (lowercase)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swprintf.h"
+
+/*
+ * Uses memcmp & wcslen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 0x1234ab;
+ INT64 l = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest(convert("foo %x"), pos, convert("foo 1234ab"));
+ DoNumTest(convert("foo %lx"), pos, convert("foo 1234ab"));
+ DoNumTest(convert("foo %hx"), pos, convert("foo 34ab"));
+ DoNumTest(convert("foo %Lx"), pos, convert("foo 1234ab"));
+ DoI64Test(convert("foo %I64x"), l, "0x1234567887654321",
+ convert("foo 1234567887654321"));
+ DoNumTest(convert("foo %7x"), pos, convert("foo 1234ab"));
+ DoNumTest(convert("foo %-7x"), pos, convert("foo 1234ab "));
+ DoNumTest(convert("foo %.1x"), pos, convert("foo 1234ab"));
+ DoNumTest(convert("foo %.7x"), pos, convert("foo 01234ab"));
+ DoNumTest(convert("foo %07x"), pos, convert("foo 01234ab"));
+ DoNumTest(convert("foo %#x"), pos, convert("foo 0x1234ab"));
+ DoNumTest(convert("foo %+x"), pos, convert("foo 1234ab"));
+ DoNumTest(convert("foo % x"), pos, convert("foo 1234ab"));
+ DoNumTest(convert("foo %+x"), neg, convert("foo ffffffd6"));
+ DoNumTest(convert("foo % x"), neg, convert("foo ffffffd6"));
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test12/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swprintf/test12/testinfo.dat
new file mode 100644
index 0000000000..d53582644f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test12/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swprintf
+Name = Positive Test for swprintf
+TYPE = DEFAULT
+EXE1 = test12
+Description
+= Tests swprintf with hex numbers (lowercase)
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test13/CMakeLists.txt
new file mode 100644
index 0000000000..20f6f0df7b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test13/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test13.c
+)
+
+add_executable(paltest_swprintf_test13
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swprintf_test13 coreclrpal)
+
+target_link_libraries(paltest_swprintf_test13
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test13/test13.c b/src/pal/tests/palsuite/c_runtime/swprintf/test13/test13.c
new file mode 100644
index 0000000000..b99232f7ea
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test13/test13.c
@@ -0,0 +1,55 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test13.c
+**
+** Purpose: Tests swprintf with hex numbers (uppercase)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swprintf.h"
+
+/*
+ * Uses memcmp & wcslen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 0x1234ab;
+ INT64 l = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest(convert("foo %X"), pos, convert("foo 1234AB"));
+ DoNumTest(convert("foo %lX"), pos, convert("foo 1234AB"));
+ DoNumTest(convert("foo %hX"), pos, convert("foo 34AB"));
+ DoNumTest(convert("foo %LX"), pos, convert("foo 1234AB"));
+ DoI64Test(convert("foo %I64X"), l, "0X1234567887654321",
+ convert("foo 1234567887654321"));
+ DoNumTest(convert("foo %7X"), pos, convert("foo 1234AB"));
+ DoNumTest(convert("foo %-7X"), pos, convert("foo 1234AB "));
+ DoNumTest(convert("foo %.1X"), pos, convert("foo 1234AB"));
+ DoNumTest(convert("foo %.7X"), pos, convert("foo 01234AB"));
+ DoNumTest(convert("foo %07X"), pos, convert("foo 01234AB"));
+ DoNumTest(convert("foo %#X"), pos, convert("foo 0X1234AB"));
+ DoNumTest(convert("foo %+X"), pos, convert("foo 1234AB"));
+ DoNumTest(convert("foo % X"), pos, convert("foo 1234AB"));
+ DoNumTest(convert("foo %+X"), neg, convert("foo FFFFFFD6"));
+ DoNumTest(convert("foo % X"), neg, convert("foo FFFFFFD6"));
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test13/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swprintf/test13/testinfo.dat
new file mode 100644
index 0000000000..1ce172414c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test13/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swprintf
+Name = Positive Test for swprintf
+TYPE = DEFAULT
+EXE1 = test13
+Description
+= Tests swprintf with hex numbers (uppercase)
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test14/CMakeLists.txt
new file mode 100644
index 0000000000..a052f60116
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test14/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test14.c
+)
+
+add_executable(paltest_swprintf_test14
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swprintf_test14 coreclrpal)
+
+target_link_libraries(paltest_swprintf_test14
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test14/test14.c b/src/pal/tests/palsuite/c_runtime/swprintf/test14/test14.c
new file mode 100644
index 0000000000..bcfd6a7c24
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test14/test14.c
@@ -0,0 +1,67 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test14.c
+**
+** Purpose: Tests swprintf with exponential format doubles (lowercase)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swprintf.h"
+
+/*
+ * Uses memcmp & wcslen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 256.0;
+ double neg = -256.0;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest(convert("foo %e"), val, convert("foo 2.560000e+002"),
+ convert("foo 2.560000e+02"));
+ DoDoubleTest(convert("foo %le"), val, convert("foo 2.560000e+002"),
+ convert("foo 2.560000e+02"));
+ DoDoubleTest(convert("foo %he"), val, convert("foo 2.560000e+002"),
+ convert("foo 2.560000e+02"));
+ DoDoubleTest(convert("foo %Le"), val, convert("foo 2.560000e+002"),
+ convert("foo 2.560000e+02"));
+ DoDoubleTest(convert("foo %I64e"), val, convert("foo 2.560000e+002"),
+ convert("foo 2.560000e+02"));
+ DoDoubleTest(convert("foo %14e"), val, convert("foo 2.560000e+002"),
+ convert("foo 2.560000e+02"));
+ DoDoubleTest(convert("foo %-14e"), val, convert("foo 2.560000e+002 "),
+ convert("foo 2.560000e+02 "));
+ DoDoubleTest(convert("foo %.1e"), val, convert("foo 2.6e+002"),
+ convert("foo 2.6e+02"));
+ DoDoubleTest(convert("foo %.8e"), val, convert("foo 2.56000000e+002"),
+ convert("foo 2.56000000e+02"));
+ DoDoubleTest(convert("foo %014e"), val, convert("foo 02.560000e+002"),
+ convert("foo 002.560000e+02"));
+ DoDoubleTest(convert("foo %#e"), val, convert("foo 2.560000e+002"),
+ convert("foo 2.560000e+02"));
+ DoDoubleTest(convert("foo %+e"), val, convert("foo +2.560000e+002"),
+ convert("foo +2.560000e+02"));
+ DoDoubleTest(convert("foo % e"), val, convert("foo 2.560000e+002"),
+ convert("foo 2.560000e+02"));
+ DoDoubleTest(convert("foo %+e"), neg, convert("foo -2.560000e+002"),
+ convert("foo -2.560000e+02"));
+ DoDoubleTest(convert("foo % e"), neg, convert("foo -2.560000e+002"),
+ convert("foo -2.560000e+02"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test14/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swprintf/test14/testinfo.dat
new file mode 100644
index 0000000000..7f3451820b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test14/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swprintf
+Name = Positive Test for swprintf
+TYPE = DEFAULT
+EXE1 = test14
+Description
+= Tests swprintf with exponential format doubles (lowercase)
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test15/CMakeLists.txt
new file mode 100644
index 0000000000..7bc2da122f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test15/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test15.c
+)
+
+add_executable(paltest_swprintf_test15
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swprintf_test15 coreclrpal)
+
+target_link_libraries(paltest_swprintf_test15
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test15/test15.c b/src/pal/tests/palsuite/c_runtime/swprintf/test15/test15.c
new file mode 100644
index 0000000000..215afbe093
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test15/test15.c
@@ -0,0 +1,67 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test15.c
+**
+** Purpose:Tests swprintf with exponential format doubles (uppercase)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swprintf.h"
+
+/*
+ * Uses memcmp & wcslen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 256.0;
+ double neg = -256.0;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest(convert("foo %E"), val, convert("foo 2.560000E+002"),
+ convert("foo 2.560000E+02"));
+ DoDoubleTest(convert("foo %lE"), val, convert("foo 2.560000E+002"),
+ convert("foo 2.560000E+02"));
+ DoDoubleTest(convert("foo %hE"), val, convert("foo 2.560000E+002"),
+ convert("foo 2.560000E+02"));
+ DoDoubleTest(convert("foo %LE"), val, convert("foo 2.560000E+002"),
+ convert("foo 2.560000E+02"));
+ DoDoubleTest(convert("foo %I64E"), val, convert("foo 2.560000E+002"),
+ convert("foo 2.560000E+02"));
+ DoDoubleTest(convert("foo %14E"), val, convert("foo 2.560000E+002"),
+ convert("foo 2.560000E+02"));
+ DoDoubleTest(convert("foo %-14E"), val, convert("foo 2.560000E+002 "),
+ convert("foo 2.560000E+02 "));
+ DoDoubleTest(convert("foo %.1E"), val, convert("foo 2.6E+002"),
+ convert("foo 2.6E+02"));
+ DoDoubleTest(convert("foo %.8E"), val, convert("foo 2.56000000E+002"),
+ convert("foo 2.56000000E+02"));
+ DoDoubleTest(convert("foo %014E"), val, convert("foo 02.560000E+002"),
+ convert("foo 002.560000E+02"));
+ DoDoubleTest(convert("foo %#E"), val, convert("foo 2.560000E+002"),
+ convert("foo 2.560000E+02"));
+ DoDoubleTest(convert("foo %+E"), val, convert("foo +2.560000E+002"),
+ convert("foo +2.560000E+02"));
+ DoDoubleTest(convert("foo % E"), val, convert("foo 2.560000E+002"),
+ convert("foo 2.560000E+02"));
+ DoDoubleTest(convert("foo %+E"), neg, convert("foo -2.560000E+002"),
+ convert("foo -2.560000E+02"));
+ DoDoubleTest(convert("foo % E"), neg, convert("foo -2.560000E+002"),
+ convert("foo -2.560000E+02"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test15/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swprintf/test15/testinfo.dat
new file mode 100644
index 0000000000..a6044e7bcc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test15/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swprintf
+Name = Positive Test for swprintf
+TYPE = DEFAULT
+EXE1 = test15
+Description
+= Tests swprintf with exponential format doubles (uppercase)
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test16/CMakeLists.txt
new file mode 100644
index 0000000000..e6ad3abd3f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test16/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test16.c
+)
+
+add_executable(paltest_swprintf_test16
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swprintf_test16 coreclrpal)
+
+target_link_libraries(paltest_swprintf_test16
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test16/test16.c b/src/pal/tests/palsuite/c_runtime/swprintf/test16/test16.c
new file mode 100644
index 0000000000..859afed8dd
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test16/test16.c
@@ -0,0 +1,67 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test16.c
+**
+** Purpose:Tests swprintf with decimal point format doubles
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swprintf.h"
+
+/*
+ * Uses memcmp & wcslen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest(convert("foo %f"), val, convert("foo 2560.001000"),
+ convert("foo 2560.001000"));
+ DoDoubleTest(convert("foo %lf"), val, convert("foo 2560.001000"),
+ convert("foo 2560.001000"));
+ DoDoubleTest(convert("foo %hf"), val, convert("foo 2560.001000"),
+ convert("foo 2560.001000"));
+ DoDoubleTest(convert("foo %Lf"), val, convert("foo 2560.001000"),
+ convert("foo 2560.001000"));
+ DoDoubleTest(convert("foo %I64f"), val, convert("foo 2560.001000"),
+ convert("foo 2560.001000"));
+ DoDoubleTest(convert("foo %12f"), val, convert("foo 2560.001000"),
+ convert("foo 2560.001000"));
+ DoDoubleTest(convert("foo %-12f"), val, convert("foo 2560.001000 "),
+ convert("foo 2560.001000 "));
+ DoDoubleTest(convert("foo %.1f"), val, convert("foo 2560.0"),
+ convert("foo 2560.0"));
+ DoDoubleTest(convert("foo %.8f"), val, convert("foo 2560.00100000"),
+ convert("foo 2560.00100000"));
+ DoDoubleTest(convert("foo %012f"), val, convert("foo 02560.001000"),
+ convert("foo 02560.001000"));
+ DoDoubleTest(convert("foo %#f"), val, convert("foo 2560.001000"),
+ convert("foo 2560.001000"));
+ DoDoubleTest(convert("foo %+f"), val, convert("foo +2560.001000"),
+ convert("foo +2560.001000"));
+ DoDoubleTest(convert("foo % f"), val, convert("foo 2560.001000"),
+ convert("foo 2560.001000"));
+ DoDoubleTest(convert("foo %+f"), neg, convert("foo -2560.001000"),
+ convert("foo -2560.001000"));
+ DoDoubleTest(convert("foo % f"), neg, convert("foo -2560.001000"),
+ convert("foo -2560.001000"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test16/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swprintf/test16/testinfo.dat
new file mode 100644
index 0000000000..d2f9a125c4
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test16/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swprintf
+Name = Positive Test for swprintf
+TYPE = DEFAULT
+EXE1 = test16
+Description
+= Tests swprintf with decimal point format doubles
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test17/CMakeLists.txt
new file mode 100644
index 0000000000..401285b740
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test17/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test17.c
+)
+
+add_executable(paltest_swprintf_test17
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swprintf_test17 coreclrpal)
+
+target_link_libraries(paltest_swprintf_test17
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test17/test17.c b/src/pal/tests/palsuite/c_runtime/swprintf/test17/test17.c
new file mode 100644
index 0000000000..480f2b2fe1
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test17/test17.c
@@ -0,0 +1,69 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test17.c
+**
+** Purpose:Tests swprintf with compact format doubles (lowercase)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swprintf.h"
+
+/*
+ * Uses memcmp & wcslen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest(convert("foo %g"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %lg"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %hg"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %Lg"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %I64g"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %5g"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %-5g"), val, convert("foo 2560 "),
+ convert("foo 2560 "));
+ DoDoubleTest(convert("foo %.1g"), val, convert("foo 3e+003"),
+ convert("foo 3e+03"));
+ DoDoubleTest(convert("foo %.2g"), val, convert("foo 2.6e+003"),
+ convert("foo 2.6e+03"));
+ DoDoubleTest(convert("foo %.12g"), val, convert("foo 2560.001"),
+ convert("foo 2560.001"));
+ DoDoubleTest(convert("foo %06g"), val, convert("foo 002560"),
+ convert("foo 002560"));
+ DoDoubleTest(convert("foo %#g"), val, convert("foo 2560.00"),
+ convert("foo 2560.00"));
+ DoDoubleTest(convert("foo %+g"), val, convert("foo +2560"),
+ convert("foo +2560"));
+ DoDoubleTest(convert("foo % g"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %+g"), neg, convert("foo -2560"),
+ convert("foo -2560"));
+ DoDoubleTest(convert("foo % g"), neg, convert("foo -2560"),
+ convert("foo -2560"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test17/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swprintf/test17/testinfo.dat
new file mode 100644
index 0000000000..f26029c659
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test17/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swprintf
+Name = Positive Test for swprintf
+TYPE = DEFAULT
+EXE1 = test17
+Description
+= Tests swprintf with compact format doubles (lowercase)
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test18/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test18/CMakeLists.txt
new file mode 100644
index 0000000000..210ab2c7ec
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test18/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test18.c
+)
+
+add_executable(paltest_swprintf_test18
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swprintf_test18 coreclrpal)
+
+target_link_libraries(paltest_swprintf_test18
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test18/test18.c b/src/pal/tests/palsuite/c_runtime/swprintf/test18/test18.c
new file mode 100644
index 0000000000..1ed8cd00d8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test18/test18.c
@@ -0,0 +1,69 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test18.c
+**
+** Purpose: Tests swprintf with compact format doubles (uppercase)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swprintf.h"
+
+/*
+ * Uses memcmp & wcslen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest(convert("foo %G"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %lG"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %hG"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %LG"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %I64G"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %5G"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %-5G"), val, convert("foo 2560 "),
+ convert("foo 2560 "));
+ DoDoubleTest(convert("foo %.1G"), val, convert("foo 3E+003"),
+ convert("foo 3E+03"));
+ DoDoubleTest(convert("foo %.2G"), val, convert("foo 2.6E+003"),
+ convert("foo 2.6E+03"));
+ DoDoubleTest(convert("foo %.12G"), val, convert("foo 2560.001"),
+ convert("foo 2560.001"));
+ DoDoubleTest(convert("foo %06G"), val, convert("foo 002560"),
+ convert("foo 002560"));
+ DoDoubleTest(convert("foo %#G"), val, convert("foo 2560.00"),
+ convert("foo 2560.00"));
+ DoDoubleTest(convert("foo %+G"), val, convert("foo +2560"),
+ convert("foo +2560"));
+ DoDoubleTest(convert("foo % G"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %+G"), neg, convert("foo -2560"),
+ convert("foo -2560"));
+ DoDoubleTest(convert("foo % G"), neg, convert("foo -2560"),
+ convert("foo -2560"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test18/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swprintf/test18/testinfo.dat
new file mode 100644
index 0000000000..6a8ca702ff
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test18/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swprintf
+Name = Positive Test for swprintf
+TYPE = DEFAULT
+EXE1 = test18
+Description
+= Tests swprintf with compact format doubles (uppercase)
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test19/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test19/CMakeLists.txt
new file mode 100644
index 0000000000..b9d44a3031
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test19/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test19.c
+)
+
+add_executable(paltest_swprintf_test19
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swprintf_test19 coreclrpal)
+
+target_link_libraries(paltest_swprintf_test19
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test19/test19.c b/src/pal/tests/palsuite/c_runtime/swprintf/test19/test19.c
new file mode 100644
index 0000000000..5199cc3cd9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test19/test19.c
@@ -0,0 +1,109 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test19.c
+**
+** Purpose: Tests swprintf with argument specified precision
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swprintf.h"
+
+/*
+ * Uses memcmp & wcslen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int n = -1;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ DoArgumentPrecTest(convert("%.*s"), 2, convert("bar"), "bar",
+ convert("ba"), convert("ba"));
+ DoArgumentPrecTest(convert("%.*S"), 2, "bar", "bar", convert("ba"),
+ convert("ba"));
+ DoArgumentPrecTest(convert("%.*n"), 3, &n, "pointer to int", convert(""),
+ convert(""));
+ if (n != 0)
+ {
+ Fail("ERROR: Expected count parameter to resolve to %d, got %X\n",
+ 0, n);
+ }
+
+ DoArgumentPrecTest(convert("%.*c"), 0, (void*)'a', "a", convert("a"),
+ convert("a"));
+ DoArgumentPrecTest(convert("%.*c"), 4, (void*)'a', "a", convert("a"),
+ convert("a"));
+ DoArgumentPrecTest(convert("%.*C"), 0, (void*)'a', "a", convert("a"),
+ convert("a"));
+ DoArgumentPrecTest(convert("%.*C"), 4, (void*)'a', "a", convert("a"),
+ convert("a"));
+ DoArgumentPrecTest(convert("%.*d"), 1, (void*)42, "42", convert("42"),
+ convert("42"));
+ DoArgumentPrecTest(convert("%.*d"), 3, (void*)42, "42", convert("042"),
+ convert("042"));
+ DoArgumentPrecTest(convert("%.*i"), 1, (void*)42, "42", convert("42"),
+ convert("42"));
+ DoArgumentPrecTest(convert("%.*i"), 3, (void*)42, "42", convert("042"),
+ convert("042"));
+ DoArgumentPrecTest(convert("%.*o"), 1, (void*)42, "42", convert("52"),
+ convert("52"));
+ DoArgumentPrecTest(convert("%.*o"), 3, (void*)42, "42", convert("052"),
+ convert("052"));
+ DoArgumentPrecTest(convert("%.*u"), 1, (void*)42, "42", convert("42"),
+ convert("42"));
+ DoArgumentPrecTest(convert("%.*u"), 3, (void*)42, "42", convert("042"),
+ convert("042"));
+ DoArgumentPrecTest(convert("%.*x"), 1, (void*)0x42, "0x42", convert("42"),
+ convert("42"));
+ DoArgumentPrecTest(convert("%.*x"), 3, (void*)0x42, "0x42", convert("042"),
+ convert("042"));
+ DoArgumentPrecTest(convert("%.*X"), 1, (void*)0x42, "0x42", convert("42"),
+ convert("42"));
+ DoArgumentPrecTest(convert("%.*X"), 3, (void*)0x42, "0x42", convert("042"),
+ convert("042"));
+
+
+ DoArgumentPrecDoubleTest(convert("%.*e"), 1, 2.01, convert("2.0e+000"),
+ convert("2.0e+000"));
+ DoArgumentPrecDoubleTest(convert("%.*e"), 3, 2.01, convert("2.010e+000"),
+ convert("2.010e+000"));
+ DoArgumentPrecDoubleTest(convert("%.*E"), 1, 2.01, convert("2.0E+000"),
+ convert("2.0E+000"));
+ DoArgumentPrecDoubleTest(convert("%.*E"), 3, 2.01, convert("2.010E+000"),
+ convert("2.010E+000"));
+ DoArgumentPrecDoubleTest(convert("%.*f"), 1, 2.01, convert("2.0"),
+ convert("2.0"));
+ DoArgumentPrecDoubleTest(convert("%.*f"), 3, 2.01, convert("2.010"),
+ convert("2.010"));
+ DoArgumentPrecDoubleTest(convert("%.*g"), 1, 256.01, convert("3e+002"),
+ convert("3e+002"));
+ DoArgumentPrecDoubleTest(convert("%.*g"), 3, 256.01, convert("256"),
+ convert("256"));
+ DoArgumentPrecDoubleTest(convert("%.*g"), 4, 256.01, convert("256"),
+ convert("256"));
+ DoArgumentPrecDoubleTest(convert("%.*g"), 6, 256.01, convert("256.01"),
+ convert("256.01"));
+ DoArgumentPrecDoubleTest(convert("%.*G"), 1, 256.01, convert("3E+002"),
+ convert("3E+002"));
+ DoArgumentPrecDoubleTest(convert("%.*G"), 3, 256.01, convert("256"),
+ convert("256"));
+ DoArgumentPrecDoubleTest(convert("%.*G"), 4, 256.01, convert("256"),
+ convert("256"));
+ DoArgumentPrecDoubleTest(convert("%.*G"), 6, 256.01, convert("256.01"),
+ convert("256.01"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test19/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swprintf/test19/testinfo.dat
new file mode 100644
index 0000000000..cbd572a35c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test19/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swprintf
+Name = Positive Test for swprintf
+TYPE = DEFAULT
+EXE1 = test19
+Description
+= Tests swprintf with argument specified precision
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test2/CMakeLists.txt
new file mode 100644
index 0000000000..84446d5f6d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_swprintf_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swprintf_test2 coreclrpal)
+
+target_link_libraries(paltest_swprintf_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test2/test2.c b/src/pal/tests/palsuite/c_runtime/swprintf/test2/test2.c
new file mode 100644
index 0000000000..deffd3edd7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test2/test2.c
@@ -0,0 +1,46 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test2.c
+**
+** Purpose: Tests swprintf with strings
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swprintf.h"
+
+/*
+ * Uses memcmp & wcslen
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ DoWStrTest(convert("foo %s"), convert("bar"), convert("foo bar"));
+ DoStrTest(convert("foo %hs"), "bar", convert("foo bar"));
+ DoWStrTest(convert("foo %ws"), convert("bar"), convert("foo bar"));
+ DoWStrTest(convert("foo %ls"), convert("bar"), convert("foo bar"));
+ DoWStrTest(convert("foo %Ls"), convert("bar"), convert("foo bar"));
+ DoWStrTest(convert("foo %I64s"), convert("bar"), convert("foo bar"));
+ DoWStrTest(convert("foo %5s"), convert("bar"), convert("foo bar"));
+ DoWStrTest(convert("foo %.2s"), convert("bar"), convert("foo ba"));
+ DoWStrTest(convert("foo %5.2s"), convert("bar"), convert("foo ba"));
+ DoWStrTest(convert("foo %-5s"), convert("bar"), convert("foo bar "));
+ DoWStrTest(convert("foo %05s"), convert("bar"), convert("foo 00bar"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swprintf/test2/testinfo.dat
new file mode 100644
index 0000000000..d93fa7b400
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test2/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swprintf
+Name = Positive Test for swprintf
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Tests swprintf with strings
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test3/CMakeLists.txt
new file mode 100644
index 0000000000..6dbd8a3c36
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_swprintf_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swprintf_test3 coreclrpal)
+
+target_link_libraries(paltest_swprintf_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test3/test3.c b/src/pal/tests/palsuite/c_runtime/swprintf/test3/test3.c
new file mode 100644
index 0000000000..42875c0640
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test3/test3.c
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test3.c
+**
+** Purpose: Tests swprintf with wide strings
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swprintf.h"
+
+/*
+ * Uses memcmp & wcslen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ DoStrTest(convert("foo %S"), "bar", convert("foo bar"));
+ DoStrTest(convert("foo %hS"), "bar", convert("foo bar"));
+ DoWStrTest(convert("foo %lS"), convert("bar"), convert("foo bar"));
+ DoWStrTest(convert("foo %wS"), convert("bar"), convert("foo bar"));
+ DoStrTest(convert("foo %LS"), "bar", convert("foo bar"));
+ DoStrTest(convert("foo %I64S"), "bar", convert("foo bar"));
+ DoStrTest(convert("foo %5S"), "bar", convert("foo bar"));
+ DoStrTest(convert("foo %.2S"), "bar", convert("foo ba"));
+ DoStrTest(convert("foo %5.2S"),"bar", convert("foo ba"));
+ DoStrTest(convert("foo %-5S"), "bar", convert("foo bar "));
+ DoStrTest(convert("foo %05S"), "bar", convert("foo 00bar"));
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swprintf/test3/testinfo.dat
new file mode 100644
index 0000000000..923a8f0efd
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test3/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swprintf
+Name = Positive Test for swprintf
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Tests swprintf with wide strings
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test4/CMakeLists.txt
new file mode 100644
index 0000000000..a665948c47
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_swprintf_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swprintf_test4 coreclrpal)
+
+target_link_libraries(paltest_swprintf_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test4/test4.c b/src/pal/tests/palsuite/c_runtime/swprintf/test4/test4.c
new file mode 100644
index 0000000000..02cc3f9005
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test4/test4.c
@@ -0,0 +1,71 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test4.c
+**
+** Purpose: Tests swprintf with pointers
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swprintf.h"
+
+/*
+ * Uses memcmp & wcslen
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ void *ptr = (void*) 0x123456;
+ INT64 lptr = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+/*
+** Run only on 64 bit platforms
+*/
+#if defined(BIT64) && defined(PLATFORM_UNIX)
+ Trace("Testing for 64 Bit Platforms \n");
+ DoPointerTest(convert("%p"), NULL, convert("0000000000000000"));
+ DoPointerTest(convert("%p"), ptr, convert("0000000000123456"));
+ DoPointerTest(convert("%17p"), ptr, convert(" 0000000000123456"));
+ DoPointerTest(convert("%17p"), ptr, convert(" 0000000000123456"));
+ DoPointerTest(convert("%-17p"), ptr, convert("0000000000123456 "));
+ DoPointerTest(convert("%+p"), ptr, convert("0000000000123456"));
+ DoPointerTest(convert("% p"), ptr, convert("0000000000123456"));
+ DoPointerTest(convert("%#p"), ptr, convert("0X0000000000123456"));
+ DoPointerTest(convert("%lp"), ptr, convert("00123456"));
+ DoPointerTest(convert("%hp"), ptr, convert("00003456"));
+ DoPointerTest(convert("%Lp"), ptr, convert("00123456"));
+ DoI64Test(convert("%I64p"), lptr, "pointer to 0X1234567887654321",
+ convert("1234567887654321"));
+#else
+ Trace("Testing for Non 64 Bit Platforms \n");
+ DoPointerTest(convert("%p"), NULL, convert("00000000"));
+ DoPointerTest(convert("%p"), ptr, convert("00123456"));
+ DoPointerTest(convert("%9p"), ptr, convert(" 00123456"));
+ DoPointerTest(convert("%09p"), ptr, convert(" 00123456"));
+ DoPointerTest(convert("%-9p"), ptr, convert("00123456 "));
+ DoPointerTest(convert("%+p"), ptr, convert("00123456"));
+ DoPointerTest(convert("% p"), ptr, convert("00123456"));
+ DoPointerTest(convert("%#p"), ptr, convert("0X00123456"));
+ DoPointerTest(convert("%lp"), ptr, convert("00123456"));
+ DoPointerTest(convert("%hp"), ptr, convert("00003456"));
+ DoPointerTest(convert("%Lp"), ptr, convert("00123456"));
+ DoI64Test(convert("%I64p"), lptr, "pointer to 0X1234567887654321",
+ convert("1234567887654321"));
+#endif
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test4/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swprintf/test4/testinfo.dat
new file mode 100644
index 0000000000..dc481d32f1
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test4/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swprintf
+Name = Positive Test for swprintf
+TYPE = DEFAULT
+EXE1 = test4
+Description
+= Tests swprintf with pointers
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test5/CMakeLists.txt
new file mode 100644
index 0000000000..8268ec2963
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test5.c
+)
+
+add_executable(paltest_swprintf_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swprintf_test5 coreclrpal)
+
+target_link_libraries(paltest_swprintf_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test5/test5.c b/src/pal/tests/palsuite/c_runtime/swprintf/test5/test5.c
new file mode 100644
index 0000000000..e85adc120e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test5/test5.c
@@ -0,0 +1,67 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test5.c
+**
+** Purpose:Tests swprintf with the count specifier
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swprintf.h"
+
+/*
+ * Uses memcmp & wcslen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR *longStr;
+ WCHAR *longResult;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ longStr =
+ convert("really-long-string-that-just-keeps-going-on-and-on-and-on.."
+ "..................useless-filler.................................."
+ "..................useless-filler.................................."
+ "..................useless-filler.................................."
+ "%n bar");
+ longResult =
+ convert("really-long-string-that-just-keeps-going-on-and-on-and-on.."
+ "..................useless-filler.................................."
+ "..................useless-filler.................................."
+ "..................useless-filler.................................."
+ " bar");
+
+ DoCountTest(convert("foo %n bar"), 4, convert("foo bar"));
+ DoCountTest(longStr, 257, longResult);
+ DoCountTest(convert("fo%n bar"), 2, convert("fo bar"));
+ DoCountTest(convert("%n"), 0, convert(""));
+ DoCountTest(convert("foo %#n bar"), 4, convert("foo bar"));
+ DoCountTest(convert("foo % n bar"), 4, convert("foo bar"));
+ DoCountTest(convert("foo %+n bar"), 4, convert("foo bar"));
+ DoCountTest(convert("foo %-n bar"), 4, convert("foo bar"));
+ DoCountTest(convert("foo %0n bar"), 4, convert("foo bar"));
+ DoShortCountTest(convert("foo %hn bar"), 4, convert("foo bar"));
+ DoCountTest(convert("foo %ln bar"), 4, convert("foo bar"));
+ DoCountTest(convert("foo %Ln bar"), 4, convert("foo bar"));
+ DoCountTest(convert("foo %I64n bar"), 4, convert("foo bar"));
+ DoCountTest(convert("foo %20.3n bar"), 4, convert("foo bar"));
+
+ PAL_Terminate();
+
+ free(longStr);
+ free(longResult);
+
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test5/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swprintf/test5/testinfo.dat
new file mode 100644
index 0000000000..ef1f1ffc5a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test5/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swprintf
+Name = Positive Test for swprintf
+TYPE = DEFAULT
+EXE1 = test5
+Description
+= Tests swprintf with the count specifier
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test6/CMakeLists.txt
new file mode 100644
index 0000000000..6a90c0b88e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test6.c
+)
+
+add_executable(paltest_swprintf_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swprintf_test6 coreclrpal)
+
+target_link_libraries(paltest_swprintf_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test6/test6.c b/src/pal/tests/palsuite/c_runtime/swprintf/test6/test6.c
new file mode 100644
index 0000000000..ecd6374264
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test6/test6.c
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test6.c
+**
+** Purpose: Tests swprintf with character
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swprintf.h"
+
+/*
+ * Uses memcmp & wcslen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR wb = (WCHAR) 'b';
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoWCharTest(convert("foo %c"), wb, convert("foo b"));
+ DoCharTest(convert("foo %hc"), 'c', convert("foo c"));
+ DoWCharTest(convert("foo %lc"), wb, convert("foo b"));
+ DoWCharTest(convert("foo %Lc"), wb, convert("foo b"));
+ DoWCharTest(convert("foo %I64c"), wb, convert("foo b"));
+ DoWCharTest(convert("foo %5c"), wb, convert("foo b"));
+ DoWCharTest(convert("foo %.0c"), wb, convert("foo b"));
+ DoWCharTest(convert("foo %-5c"), wb, convert("foo b "));
+ DoWCharTest(convert("foo %05c"), wb, convert("foo 0000b"));
+ DoWCharTest(convert("foo % c"), wb, convert("foo b"));
+ DoWCharTest(convert("foo %#c"), wb, convert("foo b"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test6/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swprintf/test6/testinfo.dat
new file mode 100644
index 0000000000..4224d19519
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test6/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swprintf
+Name = Positive Test for swprintf
+TYPE = DEFAULT
+EXE1 = test6
+Description
+= Tests swprintf with characters
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test7/CMakeLists.txt
new file mode 100644
index 0000000000..2b1c30cb56
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test7/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test7.c
+)
+
+add_executable(paltest_swprintf_test7
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swprintf_test7 coreclrpal)
+
+target_link_libraries(paltest_swprintf_test7
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test7/test7.c b/src/pal/tests/palsuite/c_runtime/swprintf/test7/test7.c
new file mode 100644
index 0000000000..e231ada3d2
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test7/test7.c
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test7.c
+**
+** Purpose: Tests swprintf with wide characters
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swprintf.h"
+
+/*
+ * Uses memcmp & wcslen
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR wb = (WCHAR) 'b';
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoCharTest(convert("foo %C"), 'c', convert("foo c"));
+ DoWCharTest(convert("foo %hc"), wb, convert("foo b"));
+ DoCharTest(convert("foo %lC"), 'c', convert("foo c"));
+ DoCharTest(convert("foo %LC"), 'c', convert("foo c"));
+ DoCharTest(convert("foo %I64C"), 'c', convert("foo c"));
+ DoCharTest(convert("foo %5C"), 'c', convert("foo c"));
+ DoCharTest(convert("foo %.0C"), 'c', convert("foo c"));
+ DoCharTest(convert("foo %-5C"), 'c', convert("foo c "));
+ DoCharTest(convert("foo %05C"), 'c', convert("foo 0000c"));
+ DoCharTest(convert("foo % C"), 'c', convert("foo c"));
+ DoCharTest(convert("foo %#C"), 'c', convert("foo c"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test7/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swprintf/test7/testinfo.dat
new file mode 100644
index 0000000000..7facc90b58
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test7/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swprintf
+Name = Positive Test for swprintf
+TYPE = DEFAULT
+EXE1 = test7
+Description
+= Tests swprintf with wide characters
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test8/CMakeLists.txt
new file mode 100644
index 0000000000..281e6df097
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test8/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test8.c
+)
+
+add_executable(paltest_swprintf_test8
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swprintf_test8 coreclrpal)
+
+target_link_libraries(paltest_swprintf_test8
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test8/test8.c b/src/pal/tests/palsuite/c_runtime/swprintf/test8/test8.c
new file mode 100644
index 0000000000..b4be28e78d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test8/test8.c
@@ -0,0 +1,55 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test8.c
+**
+** Purpose: Tests swprintf with decimal numbers
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swprintf.h"
+
+/*
+ * Uses memcmp & wcslen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest(convert("foo %d"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %ld"), 0xFFFF, convert("foo 65535"));
+ DoNumTest(convert("foo %hd"), 0xFFFF, convert("foo -1"));
+ DoNumTest(convert("foo %Ld"), pos, convert("foo 42"));
+ DoI64Test(convert("foo %I64d"), l, "0x0000000000000042",
+ convert("foo 42"));
+ DoNumTest(convert("foo %3d"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %-3d"), pos, convert("foo 42 "));
+ DoNumTest(convert("foo %.1d"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %.3d"), pos, convert("foo 042"));
+ DoNumTest(convert("foo %03d"), pos, convert("foo 042"));
+ DoNumTest(convert("foo %#d"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %+d"), pos, convert("foo +42"));
+ DoNumTest(convert("foo % d"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %+d"), neg, convert("foo -42"));
+ DoNumTest(convert("foo % d"), neg, convert("foo -42"));
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test8/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swprintf/test8/testinfo.dat
new file mode 100644
index 0000000000..d5858b2cfe
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test8/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swprintf
+Name = Positive Test for swprintf
+TYPE = DEFAULT
+EXE1 = test8
+Description
+= Tests swprintf with decimal numbers
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test9/CMakeLists.txt
new file mode 100644
index 0000000000..054b40a998
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test9/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test9.c
+)
+
+add_executable(paltest_swprintf_test9
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swprintf_test9 coreclrpal)
+
+target_link_libraries(paltest_swprintf_test9
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test9/test9.c b/src/pal/tests/palsuite/c_runtime/swprintf/test9/test9.c
new file mode 100644
index 0000000000..2f5429e5fd
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test9/test9.c
@@ -0,0 +1,55 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test9.c
+**
+** Purpose: Tests swprintf with integer numbers
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swprintf.h"
+
+/*
+ * Uses memcmp & wcslen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest(convert("foo %i"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %li"), 0xFFFF, convert("foo 65535"));
+ DoNumTest(convert("foo %hi"), 0xFFFF, convert("foo -1"));
+ DoNumTest(convert("foo %Li"), pos, convert("foo 42"));
+ DoI64Test(convert("foo %I64i"), l, "0x0000000000000042",
+ convert("foo 42"));
+ DoNumTest(convert("foo %3i"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %-3i"), pos, convert("foo 42 "));
+ DoNumTest(convert("foo %.1i"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %.3i"), pos, convert("foo 042"));
+ DoNumTest(convert("foo %03i"), pos, convert("foo 042"));
+ DoNumTest(convert("foo %#i"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %+i"), pos, convert("foo +42"));
+ DoNumTest(convert("foo % i"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %+i"), neg, convert("foo -42"));
+ DoNumTest(convert("foo % i"), neg, convert("foo -42"));
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test9/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swprintf/test9/testinfo.dat
new file mode 100644
index 0000000000..7ef9eed134
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swprintf/test9/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swprintf
+Name = Positive Test for swprintf
+TYPE = DEFAULT
+EXE1 = test9
+Description
+= Tests swprintf with integer numbers
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/CMakeLists.txt
new file mode 100644
index 0000000000..59f39a5f58
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/CMakeLists.txt
@@ -0,0 +1,20 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test10)
+add_subdirectory(test11)
+add_subdirectory(test12)
+add_subdirectory(test13)
+add_subdirectory(test14)
+add_subdirectory(test15)
+add_subdirectory(test16)
+add_subdirectory(test17)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+add_subdirectory(test7)
+add_subdirectory(test8)
+add_subdirectory(test9)
+
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/swscanf.h b/src/pal/tests/palsuite/c_runtime/swscanf/swscanf.h
new file mode 100644
index 0000000000..1cac450cf4
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/swscanf.h
@@ -0,0 +1,262 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: swscanf.h
+**
+** Purpose: Contains common testing functions for swscanf.h
+**
+**
+**==========================================================================*/
+
+#ifndef __SWSCANF_H__
+#define __SWSCANF_H__
+
+void DoVoidTest(WCHAR *inputstr, WCHAR *formatstr)
+{
+ char buf[256] = { 0 };
+ int i;
+ int ret;
+
+ ret = swscanf(inputstr, formatstr, buf);
+ if (ret != 0)
+ {
+ Fail("ERROR: Expected sscanf to return 0, got %d.\n"
+ "Using \"%s\" in \"%s\".\n", ret, convertC(inputstr),
+ convertC(formatstr));
+ }
+
+ for (i=0; i<256; i++)
+ {
+ if (buf[i] != 0)
+ {
+ Fail("ERROR: Parameter unexpectedly modified scanning \"%s\" "
+ "using \"%s\".\n", convertC(inputstr),
+ convertC(formatstr));
+ }
+ }
+
+}
+
+void DoStrTest(WCHAR *inputstr, WCHAR *formatstr, char *checkstr)
+{
+ char buf[256] = { 0 };
+ int ret;
+
+ ret = swscanf(inputstr, formatstr, buf);
+ if (ret != 1)
+ {
+ Fail("ERROR: Expected swscanf to return 1, got %d.\n"
+ "Using \"%s\" in \"%s\".\n", ret, convertC(inputstr),
+ convertC(formatstr));
+ }
+
+ if (memcmp(checkstr, buf, strlen(checkstr) + 1) != 0)
+ {
+ Fail("ERROR: scanned string incorrectly from \"%s\" using \"%s\".\n"
+ "Expected \"%s\", got \"%s\".\n", convertC(inputstr),
+ convertC(formatstr), checkstr,
+ buf);
+ }
+
+}
+
+void DoWStrTest(WCHAR *inputstr, WCHAR *formatstr, WCHAR *checkstr)
+{
+ WCHAR buf[256] = { 0 };
+ int ret;
+
+ ret = swscanf(inputstr, formatstr, buf);
+ if (ret != 1)
+ {
+ Fail("ERROR: Expected swscanf to return 1, got %d.\n"
+ "Using \"%s\" in \"%s\".\n", ret, convertC(inputstr),
+ convertC(formatstr));
+ }
+
+ if (memcmp(checkstr, buf, wcslen(checkstr)*2 + 2) != 0)
+ {
+ Fail("ERROR: scanned wide string incorrectly from \"%s\" using \"%s\".\n"
+ "Expected \"%s\", got \"%s\".\n", convertC(inputstr),
+ convertC(formatstr), convertC(checkstr),
+ convertC(buf));
+ }
+
+}
+
+void DoNumTest(WCHAR *inputstr, WCHAR *formatstr, int checknum)
+{
+ int num = 0;
+ int ret;
+
+ ret = swscanf(inputstr, formatstr, &num);
+ if (ret != 1)
+ {
+ Fail("ERROR: Expected swscanf to return 1, got %d.\n"
+ "Using \"%s\" in \"%s\".\n", ret, convertC(inputstr),
+ convertC(formatstr));
+ }
+
+ if (checknum != num)
+ {
+ Fail("ERROR: scanned number incorrectly from \"%s\" using \"%s\".\n"
+ "Expected %d, got %d.\n", convertC(inputstr),
+ convertC(formatstr), checknum, num);
+ }
+}
+
+void DoShortNumTest(WCHAR *inputstr, WCHAR *formatstr, short checknum)
+{
+ short num = 0;
+ int ret;
+
+ ret = swscanf(inputstr, formatstr, &num);
+ if (ret != 1)
+ {
+ Fail("ERROR: Expected swscanf to return 1, got %d.\n"
+ "Using \"%s\" in \"%s\".\n", ret, convertC(inputstr),
+ convertC(formatstr));
+ }
+
+ if (checknum != num)
+ {
+ Fail("ERROR: scanned number incorrectly from \"%s\" using \"%s\".\n"
+ "Expected %hd, got %hd.\n", convertC(inputstr),
+ convertC(formatstr), checknum, num);
+ }
+}
+
+void DoI64NumTest(WCHAR *inputstr, WCHAR *formatstr, INT64 checknum)
+{
+ char buf[256];
+ char check[256];
+ INT64 num;
+ int ret;
+
+ ret = swscanf(inputstr, formatstr, &num);
+ if (ret != 1)
+ {
+ Fail("ERROR: Expected swscanf to return 1, got %d.\n"
+ "Using \"%s\" in \"%s\".\n", ret, convertC(inputstr),
+ convertC(formatstr));
+ }
+
+ if (checknum != num)
+ {
+ sprintf(buf, "%I64d", num);
+ sprintf(check, "%I64d", checknum);
+ Fail("ERROR: scanned I64 number incorrectly from \"%s\" using \"%s\".\n"
+ "Expected %s, got %s.\n", convertC(inputstr),
+ convertC(formatstr), check, buf);
+ }
+}
+
+void DoCharTest(WCHAR *inputstr, WCHAR*formatstr, char* checkchars, int numchars)
+{
+ char buf[256];
+ int ret;
+ int i;
+
+ for (i=0; i<256; i++)
+ buf[i] = (char)-1;
+
+ ret = swscanf(inputstr, formatstr, buf);
+ if (ret != 1)
+ {
+ Fail("ERROR: Expected swscanf to return 1, got %d.\n"
+ "Using \"%s\" in \"%s\".\n", ret, convertC(inputstr),
+ convertC(formatstr));
+ }
+
+ if (memcmp(buf, checkchars, numchars) != 0)
+ {
+ buf[numchars] = 0;
+
+ Fail("ERROR: scanned character(s) incorrectly from \"%s\" using \"%s\".\n"
+ "Expected %s, got %s.\n", convertC(inputstr),
+ convertC(formatstr), checkchars, buf);
+ }
+
+ if (buf[numchars] != (char)-1)
+ {
+ Fail("ERROR: overflow occurred in scanning character(s) from \"%s\" "
+ "using \"%s\".\nExpected %d character(s)\n",
+ convertC(inputstr), convertC(formatstr), numchars);
+ }
+}
+
+void DoWCharTest(WCHAR *inputstr, WCHAR *formatstr, WCHAR *checkchars, int numchars)
+{
+ WCHAR buf[256];
+ int ret;
+ int i;
+
+ for (i=0; i<256; i++)
+ buf[i] = (WCHAR)-1;
+
+ ret = swscanf(inputstr, formatstr, buf);
+ if (ret != 1)
+ {
+ Fail("ERROR: Expected swscanf to return 1, got %d.\n"
+ "Using \"%s\" in \"%s\".\n", ret, convertC(inputstr),
+ convertC(formatstr));
+ }
+
+ if (memcmp(buf, checkchars, numchars*2) != 0)
+ {
+ buf[numchars] = 0;
+
+ Fail("ERROR: scanned wide character(s) incorrectly from \"%s\" using \"%s\".\n"
+ "Expected %s, got %s.\n", convertC(inputstr),
+ convertC(formatstr), convertC(checkchars),
+ convertC(buf));
+ }
+
+ if (buf[numchars] != (WCHAR)-1)
+ {
+ Fail("ERROR: overflow occurred in scanning wide character(s) from \"%s\" "
+ "using \"%s\".\nExpected %d character(s)\n",
+ convertC(inputstr), convertC(formatstr), numchars);
+ }
+}
+
+
+void DoFloatTest(WCHAR *inputstr, WCHAR *formatstr, float checkval)
+{
+ char buf[256] = { 0 };
+ float val;
+ int ret;
+ int i;
+
+ for (i=0; i<256; i++)
+ buf[i] = (char)-1;
+
+ ret = swscanf(inputstr, formatstr, buf);
+ val = *(float*)buf;
+
+ if (ret != 1)
+ {
+ Fail("ERROR: Expected swscanf to return 1, got %d.\n"
+ "Using \"%s\" in \"%s\".\n", ret, convertC(inputstr),
+ convertC(formatstr));
+ }
+
+ if (val != checkval)
+ {
+ Fail("ERROR: scanned float incorrectly from \"%s\" using \"%s\".\n"
+ "Expected \"%f\", got \"%f\".\n", convertC(inputstr),
+ convertC(formatstr), checkval, val);
+ }
+
+ if (buf[4] != (char)-1)
+ {
+ Fail("ERROR: overflow occurred in scanning float from \"%s\" "
+ "using \"%s\".\n", convertC(inputstr), convertC(formatstr));
+
+ }
+}
+
+
+#endif
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..030aaaf709
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_swscanf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swscanf_test1 coreclrpal)
+
+target_link_libraries(paltest_swscanf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/swscanf/test1/test1.c
new file mode 100644
index 0000000000..66136e57c5
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test1/test1.c
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: General test of swscanf
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swscanf.h"
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int num;
+ int ret;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoVoidTest(convert("foo bar"), convert("foo"));
+ DoVoidTest(convert("foo bar"), convert("baz"));
+ DoVoidTest(convert("foo bar"), convert("foo %*s"));
+
+ DoStrTest(convert("foo % bar"), convert("foo %% %S"), "bar");
+ DoStrTest(convert("foo bar baz"), convert("foo %bar %S"), "baz");
+
+ DoVoidTest(convert("foo bar baz"), convert("foo % bar %S"));
+ DoVoidTest(convert("foo bar baz"), convert("foo% bar %S"));
+
+
+ ret = swscanf(convert("foo bar baz"), convert("foo bar %n"), &num);
+ if (ret != 0 || num != 8)
+ {
+ Fail("ERROR: Got incorrect values in scanning \"%s\" using \"%s\".\n"
+ "Expected to get a value of %d with return value of %d, "
+ "got %d with return %d\n", "foo bar baz", "foo bar %n", 8, 0,
+ num, ret);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swscanf/test1/testinfo.dat
new file mode 100644
index 0000000000..b6366a73d0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swscanf
+Name = Positive Test for swscanf
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= General test of swscanf
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test10/CMakeLists.txt
new file mode 100644
index 0000000000..f7c8b284ff
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test10/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test10.c
+)
+
+add_executable(paltest_swscanf_test10
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swscanf_test10 coreclrpal)
+
+target_link_libraries(paltest_swscanf_test10
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test10/test10.c b/src/pal/tests/palsuite/c_runtime/swscanf/test10/test10.c
new file mode 100644
index 0000000000..a8628e0de1
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test10/test10.c
@@ -0,0 +1,36 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test10.c
+**
+** Purpose:Tests swscanf with wide characters
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swscanf.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoCharTest(convert("1234"), convert("%C"), "1", 1);
+ DoCharTest(convert("abc"), convert("%2C"), "ab", 2);
+ DoCharTest(convert(" ab"), convert("%C"), " ", 1);
+ DoCharTest(convert("ab"), convert("%hC"), "a", 1);
+ DoWCharTest(convert("ab"), convert("%lC"), convert("a"), 1);
+ DoCharTest(convert("ab"), convert("%LC"), "a", 1);
+ DoCharTest(convert("ab"), convert("%I64C"), "a", 1);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test10/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swscanf/test10/testinfo.dat
new file mode 100644
index 0000000000..2f8890db20
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test10/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swscanf
+Name = Positive Test for swscanf
+TYPE = DEFAULT
+EXE1 = test10
+Description
+= Tests swscanf with wide characters
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test11/CMakeLists.txt
new file mode 100644
index 0000000000..17066f31b8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test11/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test11.c
+)
+
+add_executable(paltest_swscanf_test11
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swscanf_test11 coreclrpal)
+
+target_link_libraries(paltest_swscanf_test11
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test11/test11.c b/src/pal/tests/palsuite/c_runtime/swscanf/test11/test11.c
new file mode 100644
index 0000000000..f7eb4af46f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test11/test11.c
@@ -0,0 +1,35 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test11.c
+**
+** Purpose: Tests swscanf with strings
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swscanf.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoWStrTest(convert("foo bar"), convert("foo %s"), convert("bar"));
+ DoWStrTest(convert("foo bar"), convert("foo %2s"), convert("ba"));
+ DoStrTest(convert("foo bar"), convert("foo %hs"), "bar");
+ DoWStrTest(convert("foo bar"), convert("foo %ls"), convert("bar"));
+ DoWStrTest(convert("foo bar"), convert("foo %Ls"), convert("bar"));
+ DoWStrTest(convert("foo bar"), convert("foo %I64s"), convert("bar"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test11/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swscanf/test11/testinfo.dat
new file mode 100644
index 0000000000..5bbc2e433b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test11/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swscanf
+Name = Positive Test for swscanf
+TYPE = DEFAULT
+EXE1 = test11
+Description
+= Tests swscanf with strings
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test12/CMakeLists.txt
new file mode 100644
index 0000000000..95f5174ecb
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test12/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test12.c
+)
+
+add_executable(paltest_swscanf_test12
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swscanf_test12 coreclrpal)
+
+target_link_libraries(paltest_swscanf_test12
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test12/test12.c b/src/pal/tests/palsuite/c_runtime/swscanf/test12/test12.c
new file mode 100644
index 0000000000..f5f8bbdf8a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test12/test12.c
@@ -0,0 +1,35 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test12.c
+**
+** Purpose: Tests swscanf with wide strings
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swscanf.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoStrTest(convert("foo bar"), convert("foo %S"), "bar");
+ DoStrTest(convert("foo bar"), convert("foo %2S"), "ba");
+ DoStrTest(convert("foo bar"), convert("foo %hS"), "bar");
+ DoWStrTest(convert("foo bar"), convert("foo %lS"), convert("bar"));
+ DoStrTest(convert("foo bar"), convert("foo %LS"), "bar");
+ DoStrTest(convert("foo bar"), convert("foo %I64S"), "bar");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test12/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swscanf/test12/testinfo.dat
new file mode 100644
index 0000000000..06bf26af9b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test12/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swscanf
+Name = Positive Test for swscanf
+TYPE = DEFAULT
+EXE1 = test12
+Description
+= Tests swscanf with wide strings
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test13/CMakeLists.txt
new file mode 100644
index 0000000000..47abc50313
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test13/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test13.c
+)
+
+add_executable(paltest_swscanf_test13
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swscanf_test13 coreclrpal)
+
+target_link_libraries(paltest_swscanf_test13
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test13/test13.c b/src/pal/tests/palsuite/c_runtime/swscanf/test13/test13.c
new file mode 100644
index 0000000000..1bb0b7b21c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test13/test13.c
@@ -0,0 +1,37 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test13.c
+**
+** Purpose: Tests swscanf with floats (decimal notation)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swscanf.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoFloatTest(convert("123.0"), convert("%f"), 123.0f);
+ DoFloatTest(convert("123.0"), convert("%2f"), 12.0f);
+ DoFloatTest(convert("10E1"), convert("%f"), 100.0f);
+ DoFloatTest(convert("-12.01e-2"), convert("%f"), -0.1201f);
+ DoFloatTest(convert("+12.01e-2"), convert("%f"), 0.1201f);
+ DoFloatTest(convert("-12.01e+2"), convert("%f"), -1201.0f);
+ DoFloatTest(convert("+12.01e+2"), convert("%f"), 1201.0f);
+ DoFloatTest(convert("1234567890.0123456789f"), convert("%f"), 1234567936);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test13/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swscanf/test13/testinfo.dat
new file mode 100644
index 0000000000..a3c01c5d76
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test13/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swscanf
+Name = Positive Test for swscanf
+TYPE = DEFAULT
+EXE1 = test13
+Description
+= Tests swscanf with floats (decimal notation)
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test14/CMakeLists.txt
new file mode 100644
index 0000000000..a470436ce7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test14/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test14.c
+)
+
+add_executable(paltest_swscanf_test14
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swscanf_test14 coreclrpal)
+
+target_link_libraries(paltest_swscanf_test14
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test14/test14.c b/src/pal/tests/palsuite/c_runtime/swscanf/test14/test14.c
new file mode 100644
index 0000000000..80581b726f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test14/test14.c
@@ -0,0 +1,38 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test14.c
+**
+** Purpose: Tests swscanf with floats (exponential notation, lowercase)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swscanf.h"
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoFloatTest(convert("123.0"), convert("%e"), 123.0f);
+ DoFloatTest(convert("123.0"), convert("%2e"), 12.0f);
+ DoFloatTest(convert("10E1"), convert("%e"), 100.0f);
+ DoFloatTest(convert("-12.01e-2"), convert("%e"), -0.1201f);
+ DoFloatTest(convert("+12.01e-2"), convert("%e"), 0.1201f);
+ DoFloatTest(convert("-12.01e+2"), convert("%e"), -1201.0f);
+ DoFloatTest(convert("+12.01e+2"), convert("%e"), 1201.0f);
+ DoFloatTest(convert("1234567890.0123456789f"), convert("%e"), 1234567936);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test14/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swscanf/test14/testinfo.dat
new file mode 100644
index 0000000000..184a3e7fb8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test14/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swscanf
+Name = Positive Test for swscanf
+TYPE = DEFAULT
+EXE1 = test14
+Description
+= Tests swscanf with floats (exponential notation, lowercase)
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test15/CMakeLists.txt
new file mode 100644
index 0000000000..d89650b12c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test15/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test15.c
+)
+
+add_executable(paltest_swscanf_test15
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swscanf_test15 coreclrpal)
+
+target_link_libraries(paltest_swscanf_test15
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test15/test15.c b/src/pal/tests/palsuite/c_runtime/swscanf/test15/test15.c
new file mode 100644
index 0000000000..9b7d277e17
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test15/test15.c
@@ -0,0 +1,37 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test15.c
+**
+** Purpose: Tests swscanf with floats (exponential notation, uppercase)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swscanf.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoFloatTest(convert("123.0"), convert("%E"), 123.0f);
+ DoFloatTest(convert("123.0"), convert("%2E"), 12.0f);
+ DoFloatTest(convert("10E1"), convert("%E"), 100.0f);
+ DoFloatTest(convert("-12.01e-2"), convert("%E"), -0.1201f);
+ DoFloatTest(convert("+12.01e-2"), convert("%E"), 0.1201f);
+ DoFloatTest(convert("-12.01e+2"), convert("%E"), -1201.0f);
+ DoFloatTest(convert("+12.01e+2"), convert("%E"), 1201.0f);
+ DoFloatTest(convert("1234567890.0123456789f"), convert("%E"), 1234567936);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test15/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swscanf/test15/testinfo.dat
new file mode 100644
index 0000000000..ab20463ecd
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test15/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swscanf
+Name = Positive Test for swscanf
+TYPE = DEFAULT
+EXE1 = test15
+Description
+= Tests swscanf with floats (exponential notation, uppercase)
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test16/CMakeLists.txt
new file mode 100644
index 0000000000..a2a00f11b6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test16/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test16.c
+)
+
+add_executable(paltest_swscanf_test16
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swscanf_test16 coreclrpal)
+
+target_link_libraries(paltest_swscanf_test16
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test16/test16.c b/src/pal/tests/palsuite/c_runtime/swscanf/test16/test16.c
new file mode 100644
index 0000000000..c83b64468b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test16/test16.c
@@ -0,0 +1,37 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test16.c
+**
+** Purpose: Tests swscanf with floats (compact notation, lowercase)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swscanf.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoFloatTest(convert("123.0"), convert("%g"), 123.0f);
+ DoFloatTest(convert("123.0"), convert("%2g"), 12.0f);
+ DoFloatTest(convert("10E1"), convert("%g"), 100.0f);
+ DoFloatTest(convert("-12.01e-2"), convert("%g"), -0.1201f);
+ DoFloatTest(convert("+12.01e-2"), convert("%g"), 0.1201f);
+ DoFloatTest(convert("-12.01e+2"), convert("%g"), -1201.0f);
+ DoFloatTest(convert("+12.01e+2"), convert("%g"), 1201.0f);
+ DoFloatTest(convert("1234567890.0123456789f"), convert("%g"), 1234567936);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test16/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swscanf/test16/testinfo.dat
new file mode 100644
index 0000000000..0cfa37d63b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test16/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swscanf
+Name = Positive Test for swscanf
+TYPE = DEFAULT
+EXE1 = test16
+Description
+= Tests swscanf with floats (compact notation, lowercase)
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test17/CMakeLists.txt
new file mode 100644
index 0000000000..c224f5d9a6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test17/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test17.c
+)
+
+add_executable(paltest_swscanf_test17
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swscanf_test17 coreclrpal)
+
+target_link_libraries(paltest_swscanf_test17
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test17/test17.c b/src/pal/tests/palsuite/c_runtime/swscanf/test17/test17.c
new file mode 100644
index 0000000000..9023f7020a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test17/test17.c
@@ -0,0 +1,37 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test17.c
+**
+** Purpose: Tests swscanf with floats (compact notation, uppercase)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swscanf.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoFloatTest(convert("123.0"), convert("%G"), 123.0f);
+ DoFloatTest(convert("123.0"), convert("%2G"), 12.0f);
+ DoFloatTest(convert("10E1"), convert("%G"), 100.0f);
+ DoFloatTest(convert("-12.01e-2"), convert("%G"), -0.1201f);
+ DoFloatTest(convert("+12.01e-2"), convert("%G"), 0.1201f);
+ DoFloatTest(convert("-12.01e+2"), convert("%G"), -1201.0f);
+ DoFloatTest(convert("+12.01e+2"), convert("%G"), 1201.0f);
+ DoFloatTest(convert("1234567890.0123456789f"), convert("%G"), 1234567936);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test17/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swscanf/test17/testinfo.dat
new file mode 100644
index 0000000000..f0489dfa41
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test17/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swscanf
+Name = Positive Test for swscanf
+TYPE = DEFAULT
+EXE1 = test17
+Description
+= Tests swscanf with floats (compact notation, uppercase)
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test2/CMakeLists.txt
new file mode 100644
index 0000000000..a5335ddb48
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_swscanf_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swscanf_test2 coreclrpal)
+
+target_link_libraries(paltest_swscanf_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test2/test2.c b/src/pal/tests/palsuite/c_runtime/swscanf/test2/test2.c
new file mode 100644
index 0000000000..8fbd3f86ba
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test2/test2.c
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test2.c
+**
+** Purpose: Test to see if swscanf handles whitespace correctly
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swscanf.h"
+
+/*
+ * Tests out how it handles whitespace. Seems to accept anything that qualifies
+ * as isspace (space, tab, vertical tab, line feed, carriage return and form
+ * feed), even if it says it only wants spaces tabs and newlines.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoStrTest(convert("foo bar"), convert("foo %S"), "bar");
+ DoStrTest(convert("foo\tbar"), convert("foo %S"), "bar");
+ DoStrTest(convert("foo\nbar"), convert("foo %S"), "bar");
+ DoStrTest(convert("foo\rbar"), convert("foo %S"), "bar");
+ DoStrTest(convert("foo\vbar"), convert("foo %S"), "bar");
+ DoStrTest(convert("foo\fbar"), convert("foo %S"), "bar");
+ DoStrTest(convert("foo \t\n\r\v\fbar"), convert("foo %S"), "bar");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swscanf/test2/testinfo.dat
new file mode 100644
index 0000000000..88768ca465
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test2/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swscanf
+Name = Positive Test for swscanf
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Test to see if swscanf handles whitespace correctly
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test3/CMakeLists.txt
new file mode 100644
index 0000000000..5c229c26d3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_swscanf_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swscanf_test3 coreclrpal)
+
+target_link_libraries(paltest_swscanf_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test3/test3.c b/src/pal/tests/palsuite/c_runtime/swscanf/test3/test3.c
new file mode 100644
index 0000000000..8b05df20f2
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test3/test3.c
@@ -0,0 +1,36 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test3.c
+**
+** Purpose: Tests swscanf with bracketed set strings
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swscanf.h"
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoWStrTest(convert("bar1"), convert("%[a-z]"), convert("bar"));
+ DoWStrTest(convert("bar1"), convert("%[z-a]"), convert("bar"));
+ DoWStrTest(convert("bar1"), convert("%[ab]"), convert("ba"));
+ DoWStrTest(convert("bar1"), convert("%[ar1b]"), convert("bar1"));
+ DoWStrTest(convert("bar1"), convert("%[^4]"), convert("bar1"));
+ DoWStrTest(convert("bar1"), convert("%[^4a]"), convert("b"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swscanf/test3/testinfo.dat
new file mode 100644
index 0000000000..998cba8b6b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test3/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swscanf
+Name = Positive Test for swscanf
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Tests swscanf with bracketed set strings
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test4/CMakeLists.txt
new file mode 100644
index 0000000000..5e281aaf34
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_swscanf_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swscanf_test4 coreclrpal)
+
+target_link_libraries(paltest_swscanf_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test4/test4.c b/src/pal/tests/palsuite/c_runtime/swscanf/test4/test4.c
new file mode 100644
index 0000000000..d63d25b7d0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test4/test4.c
@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test4.c
+**
+** Purpose:Tests swscanf with decimal numbers
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swscanf.h"
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int n65535 = 65535; /* Walkaround compiler strictness */
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoNumTest(convert("1234d"), convert("%d"), 1234);
+ DoNumTest(convert("1234d"), convert("%2d"), 12);
+ DoNumTest(convert("-1"), convert("%d"), -1);
+ DoNumTest(convert("0x1234"), convert("%d"), 0);
+ DoNumTest(convert("012"), convert("%d"), 12);
+ DoShortNumTest(convert("-1"), convert("%hd"), n65535);
+ DoShortNumTest(convert("65536"), convert("%hd"), 0);
+ DoNumTest(convert("-1"), convert("%ld"), -1);
+ DoNumTest(convert("65536"), convert("%ld"), 65536);
+ DoNumTest(convert("-1"), convert("%Ld"), -1);
+ DoNumTest(convert("65536"), convert("%Ld"), 65536);
+ DoI64NumTest(convert("4294967296"), convert("%I64d"), I64(4294967296));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test4/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swscanf/test4/testinfo.dat
new file mode 100644
index 0000000000..e6102872d7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test4/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swscanf
+Name = Positive Test for swscanf
+TYPE = DEFAULT
+EXE1 = test4
+Description
+= Tests swscanf with decimal numbers
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test5/CMakeLists.txt
new file mode 100644
index 0000000000..8b259aa78d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test5.c
+)
+
+add_executable(paltest_swscanf_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swscanf_test5 coreclrpal)
+
+target_link_libraries(paltest_swscanf_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test5/test5.c b/src/pal/tests/palsuite/c_runtime/swscanf/test5/test5.c
new file mode 100644
index 0000000000..8ae2d81da6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test5/test5.c
@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test5.c
+**
+** Purpose: Tests swscanf with integer numbers
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swscanf.h"
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int n65535 = 65535; /* Walkaround compiler strictness */
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoNumTest(convert("1234d"), convert("%i"), 1234);
+ DoNumTest(convert("1234d"), convert("%2i"), 12);
+ DoNumTest(convert("-1"), convert("%i"), -1);
+ DoNumTest(convert("0x1234"), convert("%i"), 0x1234);
+ DoNumTest(convert("012"), convert("%i"), 10);
+ DoShortNumTest(convert("-1"), convert("%hi"), n65535);
+ DoShortNumTest(convert("65536"), convert("%hi"), 0);
+ DoNumTest(convert("-1"), convert("%li"), -1);
+ DoNumTest(convert("65536"), convert("%li"), 65536);
+ DoNumTest(convert("-1"), convert("%Li"), -1);
+ DoNumTest(convert("65536"), convert("%Li"), 65536);
+ DoI64NumTest(convert("4294967296"), convert("%I64i"), I64(4294967296));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test5/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swscanf/test5/testinfo.dat
new file mode 100644
index 0000000000..9991286402
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test5/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swscanf
+Name = Positive Test for swscanf
+TYPE = DEFAULT
+EXE1 = test5
+Description
+= Tests swscanf with integer numbers
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test6/CMakeLists.txt
new file mode 100644
index 0000000000..c3fd8696ab
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test6.c
+)
+
+add_executable(paltest_swscanf_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swscanf_test6 coreclrpal)
+
+target_link_libraries(paltest_swscanf_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test6/test6.c b/src/pal/tests/palsuite/c_runtime/swscanf/test6/test6.c
new file mode 100644
index 0000000000..982f799cfc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test6/test6.c
@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test6.c
+**
+** Purpose:Tests swscanf with octal numbers
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swscanf.h"
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int n65535 = 65535; /* Walkaround compiler strictness */
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoNumTest(convert("1234d"), convert("%o"), 668);
+ DoNumTest(convert("1234d"), convert("%2o"), 10);
+ DoNumTest(convert("-1"), convert("%o"), -1);
+ DoNumTest(convert("0x1234"), convert("%o"), 0);
+ DoNumTest(convert("012"), convert("%o"), 10);
+ DoShortNumTest(convert("-1"), convert("%ho"), n65535);
+ DoShortNumTest(convert("200000"), convert("%ho"), 0);
+ DoNumTest(convert("-1"), convert("%lo"), -1);
+ DoNumTest(convert("200000"), convert("%lo"), 65536);
+ DoNumTest(convert("-1"), convert("%Lo"), -1);
+ DoNumTest(convert("200000"), convert("%Lo"), 65536);
+ DoI64NumTest(convert("40000000000"), convert("%I64o"), I64(4294967296));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test6/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swscanf/test6/testinfo.dat
new file mode 100644
index 0000000000..ca7870e962
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test6/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swscanf
+Name = Positive Test for swscanf
+TYPE = DEFAULT
+EXE1 = test6
+Description
+= Tests swscanf with octal numbers
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test7/CMakeLists.txt
new file mode 100644
index 0000000000..00541306df
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test7/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test7.c
+)
+
+add_executable(paltest_swscanf_test7
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swscanf_test7 coreclrpal)
+
+target_link_libraries(paltest_swscanf_test7
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test7/test7.c b/src/pal/tests/palsuite/c_runtime/swscanf/test7/test7.c
new file mode 100644
index 0000000000..45e9400549
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test7/test7.c
@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test7.c
+**
+** Purpose: Test #6 for the swscanf function
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swscanf.h"
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int n65535 = 65535; /* Walkaround compiler strictness */
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoNumTest(convert("1234d"), convert("%x"), 0x1234d);
+ DoNumTest(convert("1234d"), convert("%2x"), 0x12);
+ DoNumTest(convert("-1"), convert("%x"), -1);
+ DoNumTest(convert("0x1234"), convert("%x"), 0x1234);
+ DoNumTest(convert("012"), convert("%x"), 0x12);
+ DoShortNumTest(convert("-1"), convert("%hx"), n65535);
+ DoShortNumTest(convert("10000"), convert("%hx"), 0);
+ DoNumTest(convert("-1"), convert("%lx"), -1);
+ DoNumTest(convert("10000"), convert("%lx"), 65536);
+ DoNumTest(convert("-1"), convert("%Lx"), -1);
+ DoNumTest(convert("10000"), convert("%Lx"), 65536);
+ DoI64NumTest(convert("100000000"), convert("%I64x"), I64(4294967296));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test7/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swscanf/test7/testinfo.dat
new file mode 100644
index 0000000000..43ff8108df
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test7/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swscanf
+Name = Positive Test for swscanf
+TYPE = DEFAULT
+EXE1 = test7
+Description
+= Tests swscanf with hex numbers (lowercase)
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test8/CMakeLists.txt
new file mode 100644
index 0000000000..d6aa631ab9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test8/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test8.c
+)
+
+add_executable(paltest_swscanf_test8
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swscanf_test8 coreclrpal)
+
+target_link_libraries(paltest_swscanf_test8
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test8/test8.c b/src/pal/tests/palsuite/c_runtime/swscanf/test8/test8.c
new file mode 100644
index 0000000000..a244de748f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test8/test8.c
@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test8.c
+**
+** Purpose: Tests swscanf with unsigned numbers
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swscanf.h"
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int n65535 = 65535; /* Walkaround compiler strictness */
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoNumTest(convert("1234d"), convert("%u"), 1234);
+ DoNumTest(convert("1234d"), convert("%2u"), 12);
+ DoNumTest(convert("-1"), convert("%u"), -1);
+ DoNumTest(convert("0x1234"), convert("%u"), 0);
+ DoNumTest(convert("012"), convert("%u"), 12);
+ DoShortNumTest(convert("-1"), convert("%hu"), n65535);
+ DoShortNumTest(convert("65536"), convert("%hu"), 0);
+ DoNumTest(convert("-1"), convert("%lu"), -1);
+ DoNumTest(convert("65536"), convert("%lu"), 65536);
+ DoNumTest(convert("-1"), convert("%Lu"), -1);
+ DoNumTest(convert("65536"), convert("%Lu"), 65536);
+ DoI64NumTest(convert("4294967296"), convert("%I64u"), I64(4294967296));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test8/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swscanf/test8/testinfo.dat
new file mode 100644
index 0000000000..0edefb0756
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test8/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swscanf
+Name = Positive Test for swscanf
+TYPE = DEFAULT
+EXE1 = test8
+Description
+= Tests swscanf with unsigned numbers
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test9/CMakeLists.txt
new file mode 100644
index 0000000000..4f7595a205
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test9/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test9.c
+)
+
+add_executable(paltest_swscanf_test9
+ ${SOURCES}
+)
+
+add_dependencies(paltest_swscanf_test9 coreclrpal)
+
+target_link_libraries(paltest_swscanf_test9
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test9/test9.c b/src/pal/tests/palsuite/c_runtime/swscanf/test9/test9.c
new file mode 100644
index 0000000000..e289d26f58
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test9/test9.c
@@ -0,0 +1,37 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test9.c
+**
+** Purpose: Tests swscanf with characters
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../swscanf.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoWCharTest(convert("1234"), convert("%c"), convert("1"), 1);
+ DoWCharTest(convert("1234"), convert("%c"), convert("1"), 1);
+ DoWCharTest(convert("abc"), convert("%2c"), convert("ab"), 2);
+ DoWCharTest(convert(" ab"), convert("%c"), convert(" "), 1);
+ DoCharTest(convert("ab"), convert("%hc"), "a", 1);
+ DoWCharTest(convert("ab"), convert("%lc"), convert("a"), 1);
+ DoWCharTest(convert("ab"), convert("%Lc"), convert("a"), 1);
+ DoWCharTest(convert("ab"), convert("%I64c"), convert("a"), 1);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test9/testinfo.dat b/src/pal/tests/palsuite/c_runtime/swscanf/test9/testinfo.dat
new file mode 100644
index 0000000000..955b62b12f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/swscanf/test9/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = swscanf
+Name = Positive Test for swscanf
+TYPE = DEFAULT
+EXE1 = test9
+Description
+= Tests swscanf with characters
diff --git a/src/pal/tests/palsuite/c_runtime/tan/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/tan/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/tan/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/tan/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/tan/test1/CMakeLists.txt
new file mode 100644
index 0000000000..665fc22d5e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/tan/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_tan_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_tan_test1 coreclrpal)
+
+target_link_libraries(paltest_tan_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/tan/test1/test1.c b/src/pal/tests/palsuite/c_runtime/tan/test1/test1.c
new file mode 100644
index 0000000000..443e5da6d6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/tan/test1/test1.c
@@ -0,0 +1,137 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test to ensure that tan return the correct values
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** fabs
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (15-17 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use
+// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx
+// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will
+// use PAL_EPSILON * 10.
+#define PAL_EPSILON 8.8817841970012523e-16
+
+#define PAL_NAN sqrt(-1.0)
+#define PAL_POSINF -log(0.0)
+#define PAL_NEGINF log(0.0)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ double value; /* value to test the function with */
+ double expected; /* expected result */
+ double variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(double value, double expected, double variance)
+{
+ double result = tan(value);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ double delta = fabs(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("tan(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(double value)
+{
+ double result = tan(value);
+
+ if (!_isnan(result))
+ {
+ Fail("tan(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char **argv)
+{
+ struct test tests[] =
+ {
+ /* value expected variance */
+ { 0, 0, PAL_EPSILON },
+ { 0.31830988618379067, 0.32951473309607836, PAL_EPSILON }, // value: 1 / pi
+ { 0.43429448190325183, 0.46382906716062964, PAL_EPSILON }, // value: log10(e)
+ { 0.63661977236758134, 0.73930295048660405, PAL_EPSILON }, // value: 2 / pi
+ { 0.69314718055994531, 0.83064087786078395, PAL_EPSILON }, // value: ln(2)
+ { 0.70710678118654752, 0.85451043200960189, PAL_EPSILON }, // value: 1 / sqrt(2)
+ { 0.78539816339744831, 1, PAL_EPSILON * 10 }, // value: pi / 4
+ { 1, 1.5574077246549022, PAL_EPSILON * 10 },
+ { 1.1283791670955126, 2.1108768356626451, PAL_EPSILON * 10 }, // value: 2 / sqrt(pi)
+ { 1.4142135623730950, 6.3341191670421916, PAL_EPSILON * 10 }, // value: sqrt(2)
+ { 1.4426950408889634, 7.7635756709721848, PAL_EPSILON * 10 }, // value: log2(e)
+ // SEE BELOW -- { 1.5707963267948966, PAL_POSINF, 0 }, // value: pi / 2
+ { 2.3025850929940457, -1.1134071468135374, PAL_EPSILON * 10 }, // value: ln(10)
+ { 2.7182818284590452, -0.45054953406980750, PAL_EPSILON }, // value: e
+ { 3.1415926535897932, 0, PAL_EPSILON }, // value: pi
+ };
+
+ /* PAL initialization */
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate( tests[i].value, tests[i].expected, tests[i].variance);
+ validate(-tests[i].value, -tests[i].expected, tests[i].variance);
+ }
+
+ // -- SPECIAL CASE --
+ // Normally, tan(pi / 2) would return PAL_POSINF (atan2(PAL_POSINF) does return (pi / 2)).
+ // However, it seems instead (on all supported systems), we get a different number entirely.
+ validate( 1.5707963267948966, 16331239353195370.0, 0);
+ validate(-1.5707963267948966, -16331239353195370.0, 0);
+
+ validate_isnan(PAL_NEGINF);
+ validate_isnan(PAL_NAN);
+ validate_isnan(PAL_POSINF);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/tan/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/tan/test1/testinfo.dat
new file mode 100644
index 0000000000..05d6cfeb74
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/tan/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = tan
+Name = Positive Test for tan
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes to tan() a series of angle value, checking that
+= each one return to correct value.
diff --git a/src/pal/tests/palsuite/c_runtime/tanh/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/tanh/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/tanh/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/c_runtime/tanh/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/tanh/test1/CMakeLists.txt
new file mode 100644
index 0000000000..f8e439dd95
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/tanh/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_tanh_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_tanh_test1 coreclrpal)
+
+target_link_libraries(paltest_tanh_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/tanh/test1/test1.c b/src/pal/tests/palsuite/c_runtime/tanh/test1/test1.c
new file mode 100644
index 0000000000..3b8f87964a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/tanh/test1/test1.c
@@ -0,0 +1,130 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test to ensure that tanh return the correct values
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** fabs
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+// binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this
+// is slightly too accurate when writing tests meant to run against libm implementations
+// for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get.
+//
+// The tests themselves will take PAL_EPSILON and adjust it according to the expected result
+// so that the delta used for comparison will compare the most significant digits and ignore
+// any digits that are outside the double precision range (15-17 digits).
+
+// For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use
+// PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx
+// will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will
+// use PAL_EPSILON * 10.
+#define PAL_EPSILON 8.8817841970012523e-16
+
+#define PAL_NAN sqrt(-1.0)
+#define PAL_POSINF -log(0.0)
+#define PAL_NEGINF log(0.0)
+
+/**
+ * Helper test structure
+ */
+struct test
+{
+ double value; /* value to test the function with */
+ double expected; /* expected result */
+ double variance; /* maximum delta between the expected and actual result */
+};
+
+/**
+ * validate
+ *
+ * test validation function
+ */
+void __cdecl validate(double value, double expected, double variance)
+{
+ double result = tanh(value);
+
+ /*
+ * The test is valid when the difference between result
+ * and expected is less than or equal to variance
+ */
+ double delta = fabs(result - expected);
+
+ if (delta > variance)
+ {
+ Fail("tanh(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, expected);
+ }
+}
+
+/**
+ * validate
+ *
+ * test validation function for values returning NaN
+ */
+void __cdecl validate_isnan(double value)
+{
+ double result = tanh(value);
+
+ if (!_isnan(result))
+ {
+ Fail("tanh(%g) returned %20.17g when it should have returned %20.17g",
+ value, result, PAL_NAN);
+ }
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+int __cdecl main(int argc, char **argv)
+{
+ struct test tests[] =
+ {
+ /* value expected variance */
+ { 0, 0, PAL_EPSILON },
+ { 0.31830988618379067, 0.30797791269089433, PAL_EPSILON }, // value: 1 / pi
+ { 0.43429448190325183, 0.40890401183401433, PAL_EPSILON }, // value: log10(e)
+ { 0.63661977236758134, 0.56259360033158334, PAL_EPSILON }, // value: 2 / pi
+ { 0.69314718055994531, 0.6, PAL_EPSILON }, // value: ln(2)
+ { 0.70710678118654752, 0.60885936501391381, PAL_EPSILON }, // value: 1 / sqrt(2)
+ { 0.78539816339744831, 0.65579420263267244, PAL_EPSILON }, // value: pi / 4
+ { 1, 0.76159415595576489, PAL_EPSILON },
+ { 1.1283791670955126, 0.81046380599898809, PAL_EPSILON }, // value: 2 / sqrt(pi)
+ { 1.4142135623730950, 0.88838556158566054, PAL_EPSILON }, // value: sqrt(2)
+ { 1.4426950408889634, 0.89423894585503855, PAL_EPSILON }, // value: log2(e)
+ { 1.5707963267948966, 0.91715233566727435, PAL_EPSILON }, // value: pi / 2
+ { 2.3025850929940457, 0.98019801980198020, PAL_EPSILON }, // value: ln(10)
+ { 2.7182818284590452, 0.99132891580059984, PAL_EPSILON }, // value: e
+ { 3.1415926535897932, 0.99627207622074994, PAL_EPSILON }, // value: pi
+ { PAL_POSINF, 1, PAL_EPSILON * 10 }
+ };
+
+ /* PAL initialization */
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++)
+ {
+ validate( tests[i].value, tests[i].expected, tests[i].variance);
+ validate(-tests[i].value, -tests[i].expected, tests[i].variance);
+ }
+
+ validate_isnan(PAL_NAN);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/tanh/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/tanh/test1/testinfo.dat
new file mode 100644
index 0000000000..1b2bc91b2b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/tanh/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = tanh
+Name = Positive Test for tanh
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Passes to tanh() a series of angle value, checking that
+= each one return to correct value.
diff --git a/src/pal/tests/palsuite/c_runtime/time/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/time/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/time/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/time/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/time/test1/CMakeLists.txt
new file mode 100644
index 0000000000..d495266cef
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/time/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_time_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_time_test1 coreclrpal)
+
+target_link_libraries(paltest_time_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/time/test1/test1.c b/src/pal/tests/palsuite/c_runtime/time/test1/test1.c
new file mode 100644
index 0000000000..c668bf38e7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/time/test1/test1.c
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Calls the time function and verifies that the time returned
+** is at least a positive value.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ time_t t = 0;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ time(&t);
+ /*I was going to test that the time returned didn't exceed some
+ reasonable value, but decided not to, for fear of creating my own
+ little Y2K-style disaster.*/
+
+ if (t <= 0)
+ {
+ Fail("time() function doesn't return a time.\n");
+ }
+ t = 0;
+ t = time(NULL);
+ if (t <= 0)
+ {
+ Fail("time() function doesn't return a time.\n");
+ }
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/time/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/time/test1/testinfo.dat
new file mode 100644
index 0000000000..40134c7623
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/time/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = time
+Name = Positive Test for time
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Calls the time function and verifies that the time returned is at
+= least a positive value.
+
diff --git a/src/pal/tests/palsuite/c_runtime/tolower/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/tolower/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/tolower/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/tolower/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/tolower/test1/CMakeLists.txt
new file mode 100644
index 0000000000..537f239cf8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/tolower/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_tolower_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_tolower_test1 coreclrpal)
+
+target_link_libraries(paltest_tolower_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/tolower/test1/test1.c b/src/pal/tests/palsuite/c_runtime/tolower/test1/test1.c
new file mode 100644
index 0000000000..cab623d3f9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/tolower/test1/test1.c
@@ -0,0 +1,79 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests the PAL implementation of the tolower function.
+** Check that the tolower function makes capital character
+** lower case. Also check that it has no effect on lower
+** case letters and special characters.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+struct testCase
+{
+ int lower;
+ int start;
+};
+
+int __cdecl main(int argc, char **argv)
+{
+
+ int result;
+ int i;
+
+ struct testCase testCases[] =
+ {
+ {'a', 'A'}, /* Basic cases */
+ {'z', 'Z'},
+ {'b', 'b'}, /* Lower case */
+ {'?', '?'}, /* Characters without case */
+ {230, 230}
+ };
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /* Loop through each case. Convert each character to lower case
+ and then compare to ensure that it is the correct value.
+ */
+
+ for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++)
+ {
+ /*Convert to lower case*/
+ result = tolower(testCases[i].start);
+
+ if (testCases[i].lower != result)
+ {
+ Fail("ERROR: tolower lowered \"%i\" to %i instead of %i.\n",
+ testCases[i].start, result, testCases[i].lower);
+ }
+
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/tolower/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/tolower/test1/testinfo.dat
new file mode 100644
index 0000000000..90f1c729cd
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/tolower/test1/testinfo.dat
@@ -0,0 +1,19 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = tolower
+Name = Positive Test for tolower
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests the PAL implementation of the tolower function.
+= Check that the tolower function makes capital character lower case.
+= Also check that it has no effect on lower case letters and special
+= characters.
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/toupper/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/toupper/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/toupper/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/toupper/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/toupper/test1/CMakeLists.txt
new file mode 100644
index 0000000000..e5aa375a9b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/toupper/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_toupper_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_toupper_test1 coreclrpal)
+
+target_link_libraries(paltest_toupper_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/toupper/test1/test1.c b/src/pal/tests/palsuite/c_runtime/toupper/test1/test1.c
new file mode 100644
index 0000000000..c580699e3b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/toupper/test1/test1.c
@@ -0,0 +1,64 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c (toupper)
+**
+**
+** Purpose: Tests the PAL implementation of the toupper function.
+** Check that the toupper function makes lower case
+** character a capital. Also check that it has no effect
+** on upper case letters and special characters.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+struct testCase
+{
+ int upper;
+ int start;
+};
+
+int __cdecl main(int argc, char **argv)
+{
+
+ int result;
+ int i;
+
+ struct testCase testCases[] =
+ {
+ {'A', 'a'}, /* Basic cases */
+ {'Z', 'z'},
+ {'B', 'B'}, /* Upper case */
+ {'%', '%'}, /* Characters without case */
+ {157, 157}
+ };
+
+ if ((PAL_Initialize(argc, argv)) != 0)
+ {
+ return FAIL;
+ }
+
+
+ /* Loop through each case. Convert each character to upper case
+ and then compare to ensure that it is the correct value.
+ */
+ for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++)
+ {
+ /*Convert to upper case*/
+ result = toupper(testCases[i].start);
+
+ if (testCases[i].upper != result)
+ {
+ Fail("ERROR: toupper capitalized \"%c\" to %c instead of %c.\n",
+ testCases[i].start, result, testCases[i].upper);
+ }
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/toupper/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/toupper/test1/testinfo.dat
new file mode 100644
index 0000000000..bde7affa4e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/toupper/test1/testinfo.dat
@@ -0,0 +1,19 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = toupper
+Name = Positive Test for toupper
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests the PAL implementation of the toupper function.
+= Check that the toupper function makes lower case character a capital.
+= Also check that it has no effect on upper case letters and special
+= characters.
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/towlower/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/towlower/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/towlower/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/towlower/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/towlower/test1/CMakeLists.txt
new file mode 100644
index 0000000000..2a3e6a07ef
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/towlower/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_towlower_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_towlower_test1 coreclrpal)
+
+target_link_libraries(paltest_towlower_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/towlower/test1/test1.c b/src/pal/tests/palsuite/c_runtime/towlower/test1/test1.c
new file mode 100644
index 0000000000..5f2457a5fe
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/towlower/test1/test1.c
@@ -0,0 +1,79 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests the PAL implementation of the towlower function.
+** Check that the tolower function makes capital character
+** lower case. Also check that it has no effect on lower
+** case letters and special characters.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+struct testCase
+{
+ WCHAR lower;
+ WCHAR start;
+};
+
+int __cdecl main(int argc, char **argv)
+{
+
+ int result;
+ int i;
+
+ struct testCase testCases[] =
+ {
+ {'a', 'A'}, /* Basic cases */
+ {'z', 'Z'},
+ {'b', 'b'}, /* Lower case */
+ {'?', '?'}, /* Characters without case */
+ {230, 230}
+ };
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /* Loop through each case. Convert each character to lower case
+ and then compare to ensure that it is the correct value.
+ */
+
+ for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++)
+ {
+ /*Convert to lower case*/
+ result = towlower(testCases[i].start);
+
+ if (testCases[i].lower != result)
+ {
+ Fail("ERROR: towlower lowered \"%c\" to %c instead of %c.\n",
+ testCases[i].start, result, testCases[i].lower);
+ }
+
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/towlower/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/towlower/test1/testinfo.dat
new file mode 100644
index 0000000000..2df179a8b6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/towlower/test1/testinfo.dat
@@ -0,0 +1,19 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = towlower
+Name = Positive Test for towlower
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests the PAL implementation of the towlower function.
+= Check that the tolower function makes capital character lower case.
+= Also check that it has no effect on lower case letters and special
+= characters.
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/towupper/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/towupper/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/towupper/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/towupper/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/towupper/test1/CMakeLists.txt
new file mode 100644
index 0000000000..537efbe0fa
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/towupper/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_towupper_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_towupper_test1 coreclrpal)
+
+target_link_libraries(paltest_towupper_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/towupper/test1/test1.c b/src/pal/tests/palsuite/c_runtime/towupper/test1/test1.c
new file mode 100644
index 0000000000..63f051fa66
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/towupper/test1/test1.c
@@ -0,0 +1,65 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c(towupper)
+**
+**
+** Purpose: Tests the PAL implementation of the towupper function.
+** Check that the towupper function makes lower case
+** character a capital. Also check that it has no effect
+** on upper case letters and special characters.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+struct testCase
+{
+ WCHAR upper;
+ WCHAR start;
+};
+
+int __cdecl main(int argc, char **argv)
+{
+
+ int result;
+ int i;
+
+ struct testCase testCases[] =
+ {
+ {'A', 'a'}, /* Basic cases */
+ {'Z', 'z'},
+ {'B', 'B'}, /* Upper case */
+ {'%', '%'}, /* Characters without case */
+ {157, 157}
+ };
+
+ if ((PAL_Initialize(argc, argv)) != 0)
+ {
+ return FAIL;
+ }
+
+
+ /* Loop through each case. Convert each character to upper case
+ and then compare to ensure that it is the correct value.
+ */
+
+ for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++)
+ {
+ /*Convert to upper case*/
+ result = towupper(testCases[i].start);
+
+ if (testCases[i].upper != result)
+ {
+ Fail("ERROR: towupper capitalized \"%c\" to %c instead of %c.\n",
+ testCases[i].start, result, testCases[i].upper);
+ }
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/towupper/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/towupper/test1/testinfo.dat
new file mode 100644
index 0000000000..40b6fadd5a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/towupper/test1/testinfo.dat
@@ -0,0 +1,19 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = towupper
+Name = Positive Test for towupper
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests the PAL implementation of the towupper function.
+= Check that the towupper function makes lower case character a capital.
+= Also check that it has no effect on upper case letters and special
+= characters.
+
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/ungetc/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/ungetc/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ungetc/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/c_runtime/ungetc/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/ungetc/test1/CMakeLists.txt
new file mode 100644
index 0000000000..da19397e2c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ungetc/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ ungetc.c
+)
+
+add_executable(paltest_ungetc_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_ungetc_test1 coreclrpal)
+
+target_link_libraries(paltest_ungetc_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/ungetc/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/ungetc/test1/testinfo.dat
new file mode 100644
index 0000000000..08d5b0699a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ungetc/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = c_runtime
+Function = ungetc
+Name = test for ungetc (test 1)
+Type = DEFAULT
+EXE1 = ungetc
+Description
+= Test how ungetc handles a write-only file (should fail)
diff --git a/src/pal/tests/palsuite/c_runtime/ungetc/test1/ungetc.c b/src/pal/tests/palsuite/c_runtime/ungetc/test1/ungetc.c
new file mode 100644
index 0000000000..397e42ac64
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ungetc/test1/ungetc.c
@@ -0,0 +1,130 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: ungetc.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the ungetc function by calling
+** the function on a write-only file.
+**
+** Dependencies:
+** fopen
+** fclose
+** fseek
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ char szFileName[] = {"test1.tmp"};
+ const char text[] =
+ {"The quick brown fox jumped over the lazy dog's back."};
+ FILE* pFile = NULL;
+ int nChar = 65; /* 'A' */
+ int nRc = 0;
+ int itemsExpected;
+ int itemsWritten;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* create the file */
+ pFile = fopen(szFileName, "w");
+ if (pFile == NULL)
+ {
+ Fail("ungetc: ERROR -> fopen failed to create the file \"%s\""
+ " as write-only.\n",
+ szFileName);
+ }
+
+ /* write to the file */
+ itemsExpected = sizeof(text);
+ itemsWritten = fwrite(text, sizeof(text[0]), sizeof(text), pFile);
+ if (itemsWritten == 0)
+ {
+ Trace("ungetc: ERROR -> fwrite failed to write to the file \"%s\"\n",
+ szFileName);
+
+ if (fclose(pFile) != 0)
+ {
+ Fail("ungetc: ERROR -> fclose failed to close the file.\n");
+ }
+ Fail("");
+
+ }
+ else if (itemsWritten != itemsExpected)
+ {
+ Trace("ungetc: ERROR -> fwrite failed to write the correct number "
+ "of characters to the file \"%s\"\n",
+ szFileName);
+
+ if (fclose(pFile) != 0)
+ {
+ Fail("ungetc: ERROR -> fclose failed to close the file.\n");
+ }
+ Fail("");
+ }
+
+ /* Close the file */
+ if (fclose(pFile) != 0)
+ {
+ Fail("ungetc: ERROR -> fclose failed to close the file.\n");
+ }
+
+ /*
+ ** open the file in write only mode and
+ ** attempt to push an unread character back on the stream
+ */
+
+
+ /* open the file write-only */
+ pFile = fopen(szFileName, "a");
+ if (pFile == NULL)
+ {
+ Fail("ungetc: ERROR -> fopen failed to open the file \"%s\""
+ " as write-only.\n",
+ szFileName);
+ }
+
+ /* move the file pointer back to the beginning of the file */
+ if (fseek(pFile, 1, SEEK_SET) != 0)
+ {
+
+ Trace("ungetc: ERROR -> fseek failed to move the file pointer to the "
+ "beginning of the file.\n");
+ if (fclose(pFile) != 0)
+ {
+ Trace("ungetc: ERROR -> fclose failed to close the file.\n");
+ }
+ Fail("");
+ }
+
+ /* call ungetc on a write-only file which should fail */
+ if ((nRc = ungetc(nChar, pFile)) != EOF)
+ {
+ Trace("ungetc: ERROR -> ungetc returned \"%c\" when run on "
+ "an write-only file.\n", nChar);
+ if (fclose(pFile) != 0)
+ {
+ Trace("ungetc: ERROR -> fclose failed to close the file.\n");
+ }
+ Fail("");
+ }
+
+ if (fclose(pFile) != 0)
+ {
+ Fail("ungetc: ERROR -> fclose failed to close the file.\n");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/ungetc/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/ungetc/test2/CMakeLists.txt
new file mode 100644
index 0000000000..7b63423628
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ungetc/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ ungetc.c
+)
+
+add_executable(paltest_ungetc_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_ungetc_test2 coreclrpal)
+
+target_link_libraries(paltest_ungetc_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/ungetc/test2/test2.txt b/src/pal/tests/palsuite/c_runtime/ungetc/test2/test2.txt
new file mode 100644
index 0000000000..96c906756d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ungetc/test2/test2.txt
@@ -0,0 +1 @@
+foo bar \ No newline at end of file
diff --git a/src/pal/tests/palsuite/c_runtime/ungetc/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/ungetc/test2/testinfo.dat
new file mode 100644
index 0000000000..b942c931f5
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ungetc/test2/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = c_runtime
+Function = ungetc
+Name = test for ungetc (test 2)
+Type = DEFAULT
+EXE1 = ungetc
+Description
+= Push characters back onto the stream and verify
diff --git a/src/pal/tests/palsuite/c_runtime/ungetc/test2/ungetc.c b/src/pal/tests/palsuite/c_runtime/ungetc/test2/ungetc.c
new file mode 100644
index 0000000000..cbc8102eec
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/ungetc/test2/ungetc.c
@@ -0,0 +1,188 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: ungetc.c (test 2)
+**
+** Purpose: Tests the PAL implementation of the ungetc function
+**
+** Dependencies:
+** fopen
+** fread
+** fclose
+** fseek
+** getc
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ const char szFileName[] = {"test2.txt"};
+ const char szNewString[] = {"bar bar"};
+ char szBuffer[MAX_PATH];
+ FILE* pFile = NULL;
+ int nChar = 32; /* space */
+ int i = 0;
+ int nRc = 0;
+ size_t nCount = 0;
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+
+ memset(szBuffer, 0, MAX_PATH);
+
+ /*
+ ** open the file in write only mode, populate it and
+ ** attempt to push an unread character back on the stream
+ */
+
+
+ /* open the file for read */
+ pFile = fopen(szFileName, "r");
+ if (pFile == NULL)
+ {
+ Fail("ungetc: ERROR -> fopen failed to open the file \"%s\""
+ " as read-only.n",
+ szFileName);
+ }
+
+
+ /*
+ ** Call getc to get the first char and ungetc to put
+ ** it back. getc should read it again.
+ */
+
+ /* read a character */
+ if ((nChar = getc(pFile)) == EOF)
+ {
+ Trace("ungetc: ERROR -> getc encountered an error reading.\n");
+ if (fclose(pFile) != 0)
+ {
+ Trace("ungetc: ERROR -> fclose failed to close the file.\n");
+ }
+ Fail("");
+ }
+
+ /* put it back */
+ if ((nRc = ungetc(nChar, pFile)) == EOF)
+ {
+ Trace("ungetc: ERROR -> ungetc failed to push '%c' back onto the"
+ " stream.\n");
+ if (fclose(pFile) != 0)
+ {
+ Trace("ungetc: ERROR -> fclose failed to close the file.\n");
+ }
+ Fail("");
+ }
+
+ /* read it again... hopefully */
+ if (((nChar = getc(pFile)) == EOF) || (nChar != nRc))
+ {
+ Trace("ungetc: ERROR -> getc encountered an error reading.\n");
+ if (fclose(pFile) != 0)
+ {
+ Trace("ungetc: ERROR -> fclose failed to close the file.\n");
+ }
+ Fail("");
+ }
+
+ /*
+ ** test multiple ungetcs by replacing "foo" in the stream with "bar"
+ */
+
+ /* move the file pointer back to the beginning of the file */
+ if (fseek(pFile, 0, SEEK_SET) != 0)
+ {
+ Trace("ungetc: ERROR -> fseek failed to move the file pointer to the "
+ "beginning of the file. GetLastError returned %ld\n",
+ GetLastError());
+ if (fclose(pFile) != 0)
+ {
+ Trace("ungetc: ERROR -> fclose failed to close the file.\n");
+ }
+ Fail("");
+ }
+
+ /* read a few characters */
+ for (i = 0; i < 3; i++)
+ {
+ if (getc(pFile) == EOF)
+ {
+ Trace("ungetc: ERROR -> getc encountered an error reading. "
+ "GetLastError returned %ld\n",
+ GetLastError());
+ if (fclose(pFile) != 0)
+ {
+ Trace("ungetc: ERROR -> fclose failed to close the file.\n");
+ }
+ Fail("");
+ }
+ }
+
+ /* we just read "foo" so push "bar" back on the stream */
+ for (i = 2; i >= 0; i--)
+ {
+ if ((nRc = ungetc(szNewString[i], pFile)) == EOF)
+ {
+ Trace("ungetc: ERROR -> ungetc failed to push '%c' back onto the"
+ " stream.\n");
+ if (fclose(pFile) != 0)
+ {
+ Trace("ungetc: ERROR -> fclose failed to close the file.\n");
+ }
+ Fail("");
+ }
+ }
+
+
+ /* read the new and improved stream - I use szNewString because it
+ is correct length */
+ nCount = fread(szBuffer, sizeof(char), strlen(szNewString), pFile);
+
+ /* did we get the right number of characters?*/
+ if (nCount != strlen(szNewString))
+ {
+ Trace("ungetc: ERROR -> fread read %d characters from the stream but"
+ " %d characters were expected\n",
+ nRc,
+ strlen(szNewString));
+ if (fclose(pFile) != 0)
+ {
+ Trace("ungetc: ERROR -> fclose failed to close the file.\n");
+ }
+ Fail("");
+ }
+
+ /* did we get the right string? */
+ if (strcmp(szBuffer, szNewString) != 0)
+ {
+ Trace("ungetc: ERROR -> fread returned \"%s\" but \"%s\" was "
+ "expected\n",
+ szBuffer,
+ szNewString);
+ if (fclose(pFile) != 0)
+ {
+ Trace("ungetc: ERROR -> fclose failed to close the file.\n");
+ }
+ Fail("");
+ }
+
+ if (fclose(pFile) != 0)
+ {
+ Fail("ungetc: ERROR -> fclose failed to close the file.\n");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/CMakeLists.txt
new file mode 100644
index 0000000000..cafb9536b0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/CMakeLists.txt
@@ -0,0 +1,22 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test10)
+add_subdirectory(test11)
+add_subdirectory(test12)
+add_subdirectory(test13)
+add_subdirectory(test14)
+add_subdirectory(test15)
+add_subdirectory(test16)
+add_subdirectory(test17)
+add_subdirectory(test18)
+add_subdirectory(test19)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+add_subdirectory(test7)
+add_subdirectory(test8)
+add_subdirectory(test9)
+
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..4c967fbc5b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_vfprintf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vfprintf_test1 coreclrpal)
+
+target_link_libraries(paltest_vfprintf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test1/test1.c
new file mode 100644
index 0000000000..302c914e3a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test1/test1.c
@@ -0,0 +1,68 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test #1 for the vfprintf function. A single, basic, test
+** case with no formatting.
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../vfprintf.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+ FILE *fp;
+ char testfile[] = "testfile.txt";
+ char buf[256];
+ char checkstr[] = "hello world";
+ int ret;
+
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ if ((fp = fopen(testfile, "w+")) == NULL)
+ {
+ Fail("ERROR: fopen failed to create \"%s\"\n", testfile);
+ }
+
+ ret = DoVfprintf(fp, "hello world");
+
+ if (ret != strlen(checkstr))
+ {
+ Fail("Expected vfprintf to return %d, got %d.\n",
+ strlen(checkstr), ret);
+
+ }
+
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ {
+ Fail("ERROR: Fseek failed to set pointer to beginning of file\n" );
+ }
+
+ if ((fgets(buf, 100, fp)) == NULL)
+ {
+ Fail("ERROR: fgets failed\n");
+ }
+ if (memcmp(checkstr, buf, strlen(checkstr)+1) != 0)
+ {
+ Fail("ERROR: expected %s, got %s\n", checkstr, buf);
+ }
+ if ((fclose(fp)) != 0)
+ {
+ Fail("ERROR: fclose failed to close \"%s\"\n", testfile);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vfprintf/test1/testinfo.dat
new file mode 100644
index 0000000000..8359de8e3d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vfprintf
+Name = Positive Test for vfprintf
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= General test to see if vfprintf works correctly
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test10/CMakeLists.txt
new file mode 100644
index 0000000000..e154107e36
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test10/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test10.c
+)
+
+add_executable(paltest_vfprintf_test10
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vfprintf_test10 coreclrpal)
+
+target_link_libraries(paltest_vfprintf_test10
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test10/test10.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test10/test10.c
new file mode 100644
index 0000000000..ecb4b0314a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test10/test10.c
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test10.c
+**
+** Purpose: Test #10 for the vfprintf function. Tests the octal specifier
+** (%o).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../vfprintf.h"
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest("foo %o", pos, "foo 52");
+ DoNumTest("foo %lo", 0xFFFF, "foo 177777");
+ DoNumTest("foo %ho", 0xFFFF, "foo 177777");
+ DoNumTest("foo %Lo", pos, "foo 52");
+ DoI64Test("foo %I64o", l, "42", "foo 52");
+ DoNumTest("foo %3o", pos, "foo 52");
+ DoNumTest("foo %-3o", pos, "foo 52 ");
+ DoNumTest("foo %.1o", pos, "foo 52");
+ DoNumTest("foo %.3o", pos, "foo 052");
+ DoNumTest("foo %03o", pos, "foo 052");
+ DoNumTest("foo %#o", pos, "foo 052");
+ DoNumTest("foo %+o", pos, "foo 52");
+ DoNumTest("foo % o", pos, "foo 52");
+ DoNumTest("foo %+o", neg, "foo 37777777726");
+ DoNumTest("foo % o", neg, "foo 37777777726");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test10/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vfprintf/test10/testinfo.dat
new file mode 100644
index 0000000000..034610a7dc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test10/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vfprintf
+Name = Positive Test for vfprintf
+TYPE = DEFAULT
+EXE1 = test10
+Description
+= Tests vfprintf with octal numbers
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test11/CMakeLists.txt
new file mode 100644
index 0000000000..f51f379bcd
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test11/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test11.c
+)
+
+add_executable(paltest_vfprintf_test11
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vfprintf_test11 coreclrpal)
+
+target_link_libraries(paltest_vfprintf_test11
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test11/test11.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test11/test11.c
new file mode 100644
index 0000000000..5f7bc118cc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test11/test11.c
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test11.c
+**
+** Purpose: Test #11 for the vfprintf function. Test the unsigned int
+** specifier (%u).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../vfprintf.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest("foo %u", pos, "foo 42");
+ DoNumTest("foo %lu", 0xFFFF, "foo 65535");
+ DoNumTest("foo %hu", 0xFFFF, "foo 65535");
+ DoNumTest("foo %Lu", pos, "foo 42");
+ DoI64Test("foo %I64u", l, "42", "foo 42");
+ DoNumTest("foo %3u", pos, "foo 42");
+ DoNumTest("foo %-3u", pos, "foo 42 ");
+ DoNumTest("foo %.1u", pos, "foo 42");
+ DoNumTest("foo %.3u", pos, "foo 042");
+ DoNumTest("foo %03u", pos, "foo 042");
+ DoNumTest("foo %#u", pos, "foo 42");
+ DoNumTest("foo %+u", pos, "foo 42");
+ DoNumTest("foo % u", pos, "foo 42");
+ DoNumTest("foo %+u", neg, "foo 4294967254");
+ DoNumTest("foo % u", neg, "foo 4294967254");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test11/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vfprintf/test11/testinfo.dat
new file mode 100644
index 0000000000..4050bd610e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test11/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vfprintf
+Name = Positive Test for vfprintf
+TYPE = DEFAULT
+EXE1 = test11
+Description
+= Tests vfprintf with unsigned numbers
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test12/CMakeLists.txt
new file mode 100644
index 0000000000..3ef68cff70
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test12/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test12.c
+)
+
+add_executable(paltest_vfprintf_test12
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vfprintf_test12 coreclrpal)
+
+target_link_libraries(paltest_vfprintf_test12
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test12/test12.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test12/test12.c
new file mode 100644
index 0000000000..0bf61d3ecc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test12/test12.c
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test12.c
+**
+** Purpose: Test #12 for the vfprintf function. Tests the (lowercase)
+** hexadecimal specifier (%x)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../vfprintf.h"
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 0x1234ab;
+ INT64 l = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest("foo %x", pos, "foo 1234ab");
+ DoNumTest("foo %lx", pos, "foo 1234ab");
+ DoNumTest("foo %hx", pos, "foo 34ab");
+ DoNumTest("foo %Lx", pos, "foo 1234ab");
+ DoI64Test("foo %I64x", l, "0x1234567887654321",
+ "foo 1234567887654321");
+ DoNumTest("foo %7x", pos, "foo 1234ab");
+ DoNumTest("foo %-7x", pos, "foo 1234ab ");
+ DoNumTest("foo %.1x", pos, "foo 1234ab");
+ DoNumTest("foo %.7x", pos, "foo 01234ab");
+ DoNumTest("foo %07x", pos, "foo 01234ab");
+ DoNumTest("foo %#x", pos, "foo 0x1234ab");
+ DoNumTest("foo %+x", pos, "foo 1234ab");
+ DoNumTest("foo % x", pos, "foo 1234ab");
+ DoNumTest("foo %+x", neg, "foo ffffffd6");
+ DoNumTest("foo % x", neg, "foo ffffffd6");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test12/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vfprintf/test12/testinfo.dat
new file mode 100644
index 0000000000..640af62aff
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test12/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vfprintf
+Name = Positive Test for vfprintf
+TYPE = DEFAULT
+EXE1 = test12
+Description
+= Tests vfprintf with hex numbers (lowercase)
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test13/CMakeLists.txt
new file mode 100644
index 0000000000..cd34f6649c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test13/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test13.c
+)
+
+add_executable(paltest_vfprintf_test13
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vfprintf_test13 coreclrpal)
+
+target_link_libraries(paltest_vfprintf_test13
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test13/test13.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test13/test13.c
new file mode 100644
index 0000000000..1e42ce9e8d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test13/test13.c
@@ -0,0 +1,54 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test13.c
+**
+** Purpose: Test #13 for the vfprintf function. Tests the (uppercase)
+** hexadecimal specifier (%X)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../vfprintf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 0x1234AB;
+ INT64 l = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest("foo %X", pos, "foo 1234AB");
+ DoNumTest("foo %lX", pos, "foo 1234AB");
+ DoNumTest("foo %hX", pos, "foo 34AB");
+ DoNumTest("foo %LX", pos, "foo 1234AB");
+ DoI64Test("foo %I64X", l, "0x1234567887654321",
+ "foo 1234567887654321");
+ DoNumTest("foo %7X", pos, "foo 1234AB");
+ DoNumTest("foo %-7X", pos, "foo 1234AB ");
+ DoNumTest("foo %.1X", pos, "foo 1234AB");
+ DoNumTest("foo %.7X", pos, "foo 01234AB");
+ DoNumTest("foo %07X", pos, "foo 01234AB");
+ DoNumTest("foo %#X", pos, "foo 0X1234AB");
+ DoNumTest("foo %+X", pos, "foo 1234AB");
+ DoNumTest("foo % X", pos, "foo 1234AB");
+ DoNumTest("foo %+X", neg, "foo FFFFFFD6");
+ DoNumTest("foo % X", neg, "foo FFFFFFD6");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test13/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vfprintf/test13/testinfo.dat
new file mode 100644
index 0000000000..26c7db0523
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test13/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vfprintf
+Name = Positive Test for vfprintf
+TYPE = DEFAULT
+EXE1 = test13
+Description
+= Tests vfprintf with hex numbers (uppercase)
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test14/CMakeLists.txt
new file mode 100644
index 0000000000..396a4631c5
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test14/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test14.c
+)
+
+add_executable(paltest_vfprintf_test14
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vfprintf_test14 coreclrpal)
+
+target_link_libraries(paltest_vfprintf_test14
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test14/test14.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test14/test14.c
new file mode 100644
index 0000000000..82f247430f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test14/test14.c
@@ -0,0 +1,54 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test14.c
+**
+** Purpose: Test #14 for the vfprintf function. Tests the lowercase
+** exponential notation double specifier (%e)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../vfprintf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 256.0;
+ double neg = -256.0;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest("foo %e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %le", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %he", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %Le", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %I64e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %14e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %-14e", val, "foo 2.560000e+002 ",
+ "foo 2.560000e+02 ");
+ DoDoubleTest("foo %.1e", val, "foo 2.6e+002", "foo 2.6e+02");
+ DoDoubleTest("foo %.8e", val, "foo 2.56000000e+002",
+ "foo 2.56000000e+02");
+ DoDoubleTest("foo %014e", val, "foo 02.560000e+002",
+ "foo 002.560000e+02");
+ DoDoubleTest("foo %#e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %+e", val, "foo +2.560000e+002", "foo +2.560000e+02");
+ DoDoubleTest("foo % e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %+e", neg, "foo -2.560000e+002", "foo -2.560000e+02");
+ DoDoubleTest("foo % e", neg, "foo -2.560000e+002", "foo -2.560000e+02");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test14/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vfprintf/test14/testinfo.dat
new file mode 100644
index 0000000000..fa36319311
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test14/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vfprintf
+Name = Positive Test for vfprintf
+TYPE = DEFAULT
+EXE1 = test14
+Description
+= Tests vfprintf with exponential format doubles (lowercase)
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test15/CMakeLists.txt
new file mode 100644
index 0000000000..b9ddbe3b4a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test15/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test15.c
+)
+
+add_executable(paltest_vfprintf_test15
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vfprintf_test15 coreclrpal)
+
+target_link_libraries(paltest_vfprintf_test15
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test15/test15.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test15/test15.c
new file mode 100644
index 0000000000..53cc2ceb87
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test15/test15.c
@@ -0,0 +1,54 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test15.c
+**
+** Purpose: Test #15 for the vfprintf function. Tests the uppercase
+** exponential notation double specifier (%E)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../vfprintf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 256.0;
+ double neg = -256.0;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest("foo %E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %lE", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %hE", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %LE", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %I64E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %14E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %-14E", val, "foo 2.560000E+002 ",
+ "foo 2.560000E+02 ");
+ DoDoubleTest("foo %.1E", val, "foo 2.6E+002", "foo 2.6E+02");
+ DoDoubleTest("foo %.8E", val, "foo 2.56000000E+002",
+ "foo 2.56000000E+02");
+ DoDoubleTest("foo %014E", val, "foo 02.560000E+002",
+ "foo 002.560000E+02");
+ DoDoubleTest("foo %#E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %+E", val, "foo +2.560000E+002", "foo +2.560000E+02");
+ DoDoubleTest("foo % E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %+E", neg, "foo -2.560000E+002", "foo -2.560000E+02");
+ DoDoubleTest("foo % E", neg, "foo -2.560000E+002", "foo -2.560000E+02");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test15/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vfprintf/test15/testinfo.dat
new file mode 100644
index 0000000000..f51f72c122
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test15/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vfprintf
+Name = Positive Test for vfprintf
+TYPE = DEFAULT
+EXE1 = test15
+Description
+= Tests vfprintf with exponential format doubles (uppercase)
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test16/CMakeLists.txt
new file mode 100644
index 0000000000..0fd4177ed8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test16/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test16.c
+)
+
+add_executable(paltest_vfprintf_test16
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vfprintf_test16 coreclrpal)
+
+target_link_libraries(paltest_vfprintf_test16
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test16/test16.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test16/test16.c
new file mode 100644
index 0000000000..2b7674bb94
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test16/test16.c
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test16.c
+**
+** Purpose: Test #16 for the vfprintf function. Tests the decimal notation
+** double specifier (%f)
+**
+**
+**==========================================================================*/
+
+
+#include <palsuite.h>
+#include "../vfprintf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest("foo %f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %lf", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %hf", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %Lf", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %I64f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %12f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %-12f", val, "foo 2560.001000 ", "foo 2560.001000 ");
+ DoDoubleTest("foo %.1f", val, "foo 2560.0", "foo 2560.0");
+ DoDoubleTest("foo %.8f", val, "foo 2560.00100000", "foo 2560.00100000");
+ DoDoubleTest("foo %012f", val, "foo 02560.001000", "foo 02560.001000");
+ DoDoubleTest("foo %#f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %+f", val, "foo +2560.001000", "foo +2560.001000");
+ DoDoubleTest("foo % f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %+f", neg, "foo -2560.001000", "foo -2560.001000");
+ DoDoubleTest("foo % f", neg, "foo -2560.001000", "foo -2560.001000");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test16/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vfprintf/test16/testinfo.dat
new file mode 100644
index 0000000000..f91d9f429c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test16/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vfprintf
+Name = Positive Test for vfprintf
+TYPE = DEFAULT
+EXE1 = test16
+Description
+= Tests vfprintf with decimal point format doubles
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test17/CMakeLists.txt
new file mode 100644
index 0000000000..afc0b3828d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test17/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test17.c
+)
+
+add_executable(paltest_vfprintf_test17
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vfprintf_test17 coreclrpal)
+
+target_link_libraries(paltest_vfprintf_test17
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test17/test17.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test17/test17.c
new file mode 100644
index 0000000000..956be15f6f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test17/test17.c
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test17.c
+**
+** Purpose: Test #17 for the vfprintf function. Tests the lowercase
+** shorthand notation double specifier (%g)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../vfprintf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest("foo %g", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %lg", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %hg", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %Lg", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %I64g", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %5g", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %-5g", val, "foo 2560 ", "foo 2560 ");
+ DoDoubleTest("foo %.1g", val, "foo 3e+003", "foo 3e+03");
+ DoDoubleTest("foo %.2g", val, "foo 2.6e+003", "foo 2.6e+03");
+ DoDoubleTest("foo %.12g", val, "foo 2560.001", "foo 2560.001");
+ DoDoubleTest("foo %06g", val, "foo 002560", "foo 002560");
+ DoDoubleTest("foo %#g", val, "foo 2560.00", "foo 2560.00");
+ DoDoubleTest("foo %+g", val, "foo +2560", "foo +2560");
+ DoDoubleTest("foo % g", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %+g", neg, "foo -2560", "foo -2560");
+ DoDoubleTest("foo % g", neg, "foo -2560", "foo -2560");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test17/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vfprintf/test17/testinfo.dat
new file mode 100644
index 0000000000..623846465f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test17/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vfprintf
+Name = Positive Test for vfprintf
+TYPE = DEFAULT
+EXE1 = test17
+Description
+= Tests vfprintf with compact format doubles (lowercase)
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test18/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test18/CMakeLists.txt
new file mode 100644
index 0000000000..9e373b999e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test18/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test18.c
+)
+
+add_executable(paltest_vfprintf_test18
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vfprintf_test18 coreclrpal)
+
+target_link_libraries(paltest_vfprintf_test18
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test18/test18.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test18/test18.c
new file mode 100644
index 0000000000..c61c8cbdab
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test18/test18.c
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test18.c
+**
+** Purpose: Test #18 for the vfprintf function. Tests the uppercase
+** shorthand notation double specifier (%G)
+**
+**
+**==========================================================================*/
+
+
+#include <palsuite.h>
+#include "../vfprintf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest("foo %G", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %lG", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %hG", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %LG", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %I64G", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %5G", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %-5G", val, "foo 2560 ", "foo 2560 ");
+ DoDoubleTest("foo %.1G", val, "foo 3E+003", "foo 3E+03");
+ DoDoubleTest("foo %.2G", val, "foo 2.6E+003", "foo 2.6E+03");
+ DoDoubleTest("foo %.12G", val, "foo 2560.001", "foo 2560.001");
+ DoDoubleTest("foo %06G", val, "foo 002560", "foo 002560");
+ DoDoubleTest("foo %#G", val, "foo 2560.00", "foo 2560.00");
+ DoDoubleTest("foo %+G", val, "foo +2560", "foo +2560");
+ DoDoubleTest("foo % G", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %+G", neg, "foo -2560", "foo -2560");
+ DoDoubleTest("foo % G", neg, "foo -2560", "foo -2560");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test18/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vfprintf/test18/testinfo.dat
new file mode 100644
index 0000000000..44ddab30bc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test18/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vfprintf
+Name = Positive Test for vfprintf
+TYPE = DEFAULT
+EXE1 = test18
+Description
+= Tests vfprintf with compact format doubles (uppercase)
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test19/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test19/CMakeLists.txt
new file mode 100644
index 0000000000..3120c9117f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test19/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test19.c
+)
+
+add_executable(paltest_vfprintf_test19
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vfprintf_test19 coreclrpal)
+
+target_link_libraries(paltest_vfprintf_test19
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test19/test19.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test19/test19.c
new file mode 100644
index 0000000000..e88ce23663
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test19/test19.c
@@ -0,0 +1,76 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test19.c
+**
+** Purpose: Test #19 for the vfprintf function. Tests the variable length
+** precision argument.
+**
+**
+**==========================================================================*/
+
+
+#include <palsuite.h>
+#include "../vfprintf.h"
+
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int n = -1;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoArgumentPrecTest("%.*s", 2, "bar", "bar", "ba", "ba");
+ DoArgumentPrecTest("%.*S", 2, convert("bar"), "bar", "ba", "ba");
+
+ DoArgumentPrecTest("%.*n ", 3, &n, "pointer to int", " ", " ");
+ if (n != 0)
+ {
+ Fail("ERROR: Expected count parameter to resolve to %d, got %X\n",
+ 0, n);
+ }
+
+ DoArgumentPrecTest("%.*c", 0, (void*)'a', "a", "a", "a");
+ DoArgumentPrecTest("%.*c", 4, (void*)'a', "a", "a", "a");
+ DoArgumentPrecTest("%.*C", 0, (void*)'a', "a", "a", "a");
+ DoArgumentPrecTest("%.*C", 4, (void*)'a', "a", "a", "a");
+ DoArgumentPrecTest("%.*d", 1, (void*)42, "42", "42", "42");
+ DoArgumentPrecTest("%.*d", 3, (void*)42, "42", "042", "042");
+ DoArgumentPrecTest("%.*i", 1, (void*)42, "42", "42", "42");
+ DoArgumentPrecTest("%.*i", 3, (void*)42, "42", "042", "042");
+ DoArgumentPrecTest("%.*o", 1, (void*)42, "42", "52", "52");
+ DoArgumentPrecTest("%.*o", 3, (void*)42, "42", "052", "052");
+ DoArgumentPrecTest("%.*u", 1, (void*)42, "42", "42", "42");
+ DoArgumentPrecTest("%.*u", 3, (void*)42, "42", "042", "042");
+ DoArgumentPrecTest("%.*x", 1, (void*)0x42, "0x42", "42", "42");
+ DoArgumentPrecTest("%.*x", 3, (void*)0x42, "0x42", "042", "042");
+ DoArgumentPrecTest("%.*X", 1, (void*)0x42, "0x42", "42", "42");
+ DoArgumentPrecTest("%.*X", 3, (void*)0x42, "0x42", "042", "042");
+
+
+ DoArgumentPrecDoubleTest("%.*e", 1, 2.01, "2.0e+000", "2.0e+00");
+ DoArgumentPrecDoubleTest("%.*e", 3, 2.01, "2.010e+000", "2.010e+00");
+ DoArgumentPrecDoubleTest("%.*E", 1, 2.01, "2.0E+000", "2.0E+00");
+ DoArgumentPrecDoubleTest("%.*E", 3, 2.01, "2.010E+000", "2.010E+00");
+ DoArgumentPrecDoubleTest("%.*f", 1, 2.01, "2.0", "2.0");
+ DoArgumentPrecDoubleTest("%.*f", 3, 2.01, "2.010", "2.010");
+ DoArgumentPrecDoubleTest("%.*g", 1, 256.01, "3e+002", "3e+02");
+ DoArgumentPrecDoubleTest("%.*g", 3, 256.01, "256", "256");
+ DoArgumentPrecDoubleTest("%.*g", 4, 256.01, "256", "256");
+ DoArgumentPrecDoubleTest("%.*g", 6, 256.01, "256.01", "256.01");
+ DoArgumentPrecDoubleTest("%.*G", 1, 256.01, "3E+002", "3E+02");
+ DoArgumentPrecDoubleTest("%.*G", 3, 256.01, "256", "256");
+ DoArgumentPrecDoubleTest("%.*G", 4, 256.01, "256", "256");
+ DoArgumentPrecDoubleTest("%.*G", 6, 256.01, "256.01", "256.01");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test19/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vfprintf/test19/testinfo.dat
new file mode 100644
index 0000000000..729c279608
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test19/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vfprintf
+Name = Positive Test for vfprintf
+TYPE = DEFAULT
+EXE1 = test19
+Description
+= Tests vfprintf with argument specified precision
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test2/CMakeLists.txt
new file mode 100644
index 0000000000..6e700090d6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_vfprintf_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vfprintf_test2 coreclrpal)
+
+target_link_libraries(paltest_vfprintf_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test2/test2.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test2/test2.c
new file mode 100644
index 0000000000..d01117f047
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test2/test2.c
@@ -0,0 +1,45 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test2.c
+**
+** Purpose: Test #2 for the vfprintf function. Tests the string specifier
+** (%s).
+**
+**
+**==========================================================================*/
+
+
+#include <palsuite.h>
+#include "../vfprintf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoStrTest("foo %s", "bar", "foo bar");
+ DoStrTest("foo %hs", "bar", "foo bar");
+ DoWStrTest("foo %ls", convert("bar"), "foo bar");
+ DoWStrTest("foo %ws", convert("bar"), "foo bar");
+ DoStrTest("foo %Ls", "bar", "foo bar");
+ DoStrTest("foo %I64s", "bar", "foo bar");
+ DoStrTest("foo %5s", "bar", "foo bar");
+ DoStrTest("foo %.2s", "bar", "foo ba");
+ DoStrTest("foo %5.2s", "bar", "foo ba");
+ DoStrTest("foo %-5s", "bar", "foo bar ");
+ DoStrTest("foo %05s", "bar", "foo 00bar");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vfprintf/test2/testinfo.dat
new file mode 100644
index 0000000000..6d2f231566
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test2/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vfprintf
+Name = Positive Test for vfprintf
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Tests vfprintf with strings
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test3/CMakeLists.txt
new file mode 100644
index 0000000000..1a14d85603
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_vfprintf_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vfprintf_test3 coreclrpal)
+
+target_link_libraries(paltest_vfprintf_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test3/test3.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test3/test3.c
new file mode 100644
index 0000000000..0081daa426
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test3/test3.c
@@ -0,0 +1,45 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test3.c
+**
+** Purpose: Test #3 for the vfprintf function. Tests the wide string
+** specifier (%S).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../vfprintf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoWStrTest("foo %S", convert("bar"), "foo bar");
+ DoStrTest("foo %hS", "bar", "foo bar");
+ DoWStrTest("foo %lS", convert("bar"), "foo bar");
+ DoWStrTest("foo %wS", convert("bar"), "foo bar");
+ DoWStrTest("foo %LS", convert("bar"), "foo bar");
+ DoWStrTest("foo %I64S", convert("bar"), "foo bar");
+ DoWStrTest("foo %5S", convert("bar"), "foo bar");
+ DoWStrTest("foo %.2S", convert("bar"), "foo ba");
+ DoWStrTest("foo %5.2S", convert("bar"), "foo ba");
+ DoWStrTest("foo %-5S", convert("bar"), "foo bar ");
+ DoWStrTest("foo %05S", convert("bar"), "foo 00bar");
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vfprintf/test3/testinfo.dat
new file mode 100644
index 0000000000..b5aa1e2f07
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test3/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vfprintf
+Name = Positive Test for vfprintf
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Tests vfprintf with wide strings
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test4/CMakeLists.txt
new file mode 100644
index 0000000000..c1285942bc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_vfprintf_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vfprintf_test4 coreclrpal)
+
+target_link_libraries(paltest_vfprintf_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test4/test4.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test4/test4.c
new file mode 100644
index 0000000000..d24f08d6e0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test4/test4.c
@@ -0,0 +1,70 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test4.c
+**
+** Purpose: Test #4 for the vfprintf function. Tests the pointer
+** specifier (%p).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../vfprintf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ void *ptr = (void*) 0x123456;
+ INT64 lptr = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+/*
+** Run only on 64 bit platforms
+*/
+#if defined(BIT64) && defined(PLATFORM_UNIX)
+ Trace("Testing for 64 Bit Platforms \n");
+ DoPointerTest("%p", NULL, "NULL", "0000000000000000");
+ DoPointerTest("%p", ptr, "pointer to 0x123456", "0000000000123456");
+ DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456");
+ DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456");
+ DoPointerTest("%-17p", ptr, "pointer to 0x123456", "0000000000123456 ");
+ DoPointerTest("%+p", ptr, "pointer to 0x123456", "0000000000123456");
+ DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X0000000000123456");
+ DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456");
+ DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456");
+ DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456");
+ DoI64Test("%I64p", lptr, "pointer to 0x1234567887654321",
+ "1234567887654321");
+
+#else
+ Trace("Testing for Non 64 Bit Platforms \n");
+ DoPointerTest("%p", NULL, "NULL", "00000000");
+ DoPointerTest("%p", ptr, "pointer to 0x123456", "00123456");
+ DoPointerTest("%9p", ptr, "pointer to 0x123456", " 00123456");
+ DoPointerTest("%09p", ptr, "pointer to 0x123456", " 00123456");
+ DoPointerTest("%-9p", ptr, "pointer to 0x123456", "00123456 ");
+ DoPointerTest("%+p", ptr, "pointer to 0x123456", "00123456");
+ DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X00123456");
+ DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456");
+ DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456");
+ DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456");
+ DoI64Test("%I64p", lptr, "pointer to 0x1234567887654321",
+ "1234567887654321");
+
+#endif
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test4/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vfprintf/test4/testinfo.dat
new file mode 100644
index 0000000000..d08928a8b6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test4/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vfprintf
+Name = Positive Test for vfprintf
+TYPE = DEFAULT
+EXE1 = test4
+Description
+= Tests vfprintf with pointers
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test5/CMakeLists.txt
new file mode 100644
index 0000000000..0cccdfd630
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test5.c
+)
+
+add_executable(paltest_vfprintf_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vfprintf_test5 coreclrpal)
+
+target_link_libraries(paltest_vfprintf_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test5/test5.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test5/test5.c
new file mode 100644
index 0000000000..44f21b61db
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test5/test5.c
@@ -0,0 +1,60 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test5.c
+**
+** Purpose: Test #5 for the vfprintf function. Tests the count specifier (%n).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../vfprintf.h"
+
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ char *longStr =
+ "really-long-string-that-just-keeps-going-on-and-on-and-on.."
+ "..................useless-filler.................................."
+ "..................useless-filler.................................."
+ "..................useless-filler.................................."
+ "%n bar";
+ char *longResult =
+ "really-long-string-that-just-keeps-going-on-and-on-and-on.."
+ "..................useless-filler.................................."
+ "..................useless-filler.................................."
+ "..................useless-filler.................................."
+ " bar";
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoCountTest("foo %n bar", 4, "foo bar");
+ DoCountTest(longStr, 257, longResult);
+ DoCountTest("fo%n bar", 2, "fo bar");
+ DoCountTest("%n ", 0, " ");
+ DoCountTest("foo %#n bar", 4, "foo bar");
+ DoCountTest("foo % n bar", 4, "foo bar");
+ DoCountTest("foo %+n bar", 4, "foo bar");
+ DoCountTest("foo %-n bar", 4, "foo bar");
+ DoCountTest("foo %0n bar", 4, "foo bar");
+ DoShortCountTest("foo %hn bar", 4, "foo bar");
+ DoCountTest("foo %ln bar", 4, "foo bar");
+ DoCountTest("foo %Ln bar", 4, "foo bar");
+ DoCountTest("foo %I64n bar", 4, "foo bar");
+ DoCountTest("foo %20.3n bar", 4, "foo bar");
+
+ PAL_Terminate();
+
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test5/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vfprintf/test5/testinfo.dat
new file mode 100644
index 0000000000..73feaa0202
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test5/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vfprintf
+Name = Positive Test for vfprintf
+TYPE = DEFAULT
+EXE1 = test5
+Description
+= Tests vfprintf with the count specifier
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test6/CMakeLists.txt
new file mode 100644
index 0000000000..2c036a45ae
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test6.c
+)
+
+add_executable(paltest_vfprintf_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vfprintf_test6 coreclrpal)
+
+target_link_libraries(paltest_vfprintf_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test6/test6.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test6/test6.c
new file mode 100644
index 0000000000..36c6fe51ca
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test6/test6.c
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test6.c
+**
+** Purpose: Test #6 for the vfprintf function. Tests the char specifier (%c).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../vfprintf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR wc = (WCHAR) 'c';
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoCharTest("foo %c", 'b', "foo b");
+ DoCharTest("foo %hc", 'b', "foo b");
+ DoWCharTest("foo %lc", wc, "foo c");
+ DoCharTest("foo %Lc", 'b', "foo b");
+ DoCharTest("foo %I64c", 'b', "foo b");
+ DoCharTest("foo %5c", 'b', "foo b");
+ DoCharTest("foo %.0c", 'b', "foo b");
+ DoCharTest("foo %-5c", 'b', "foo b ");
+ DoCharTest("foo %05c", 'b', "foo 0000b");
+ DoCharTest("foo % c", 'b', "foo b");
+ DoCharTest("foo %#c", 'b', "foo b");
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test6/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vfprintf/test6/testinfo.dat
new file mode 100644
index 0000000000..cb1337dfd7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test6/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vfprintf
+Name = Positive Test for vfprintf
+TYPE = DEFAULT
+EXE1 = test6
+Description
+= Tests vfprintf with characters
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test7/CMakeLists.txt
new file mode 100644
index 0000000000..ca483af773
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test7/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test7.c
+)
+
+add_executable(paltest_vfprintf_test7
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vfprintf_test7 coreclrpal)
+
+target_link_libraries(paltest_vfprintf_test7
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test7/test7.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test7/test7.c
new file mode 100644
index 0000000000..a9cfe319bd
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test7/test7.c
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test7.c
+**
+** Purpose: Test #7 for the vfprintf function. Tests the wide char
+** specifier (%C).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../vfprintf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR wb = (WCHAR) 'b';
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoWCharTest("foo %C", wb, "foo b");
+ DoWCharTest("foo %hC", wb, "foo b");
+ DoCharTest("foo %lC", 'c', "foo c");
+ DoWCharTest("foo %LC", wb, "foo b");
+ DoWCharTest("foo %I64C", wb, "foo b");
+ DoWCharTest("foo %5C", wb, "foo b");
+ DoWCharTest("foo %.0C", wb, "foo b");
+ DoWCharTest("foo %-5C", wb, "foo b ");
+ DoWCharTest("foo %05C", wb, "foo 0000b");
+ DoWCharTest("foo % C", wb, "foo b");
+ DoWCharTest("foo %#C", wb, "foo b");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test7/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vfprintf/test7/testinfo.dat
new file mode 100644
index 0000000000..c861344845
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test7/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vfprintf
+Name = Positive Test for vfprintf
+TYPE = DEFAULT
+EXE1 = test7
+Description
+= Tests vfprintf with wide characters
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test8/CMakeLists.txt
new file mode 100644
index 0000000000..89459b4e93
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test8/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test8.c
+)
+
+add_executable(paltest_vfprintf_test8
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vfprintf_test8 coreclrpal)
+
+target_link_libraries(paltest_vfprintf_test8
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test8/test8.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test8/test8.c
new file mode 100644
index 0000000000..5cef99741a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test8/test8.c
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test8.c
+**
+** Purpose: Test #8 for the vfprintf function. Tests the decimal
+** specifier (%d).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../vfprintf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest("foo %d", pos, "foo 42");
+ DoNumTest("foo %ld", 0xFFFF, "foo 65535");
+ DoNumTest("foo %hd", 0xFFFF, "foo -1");
+ DoNumTest("foo %Ld", pos, "foo 42");
+ DoI64Test("foo %I64d", l, "42", "foo 42");
+ DoNumTest("foo %3d", pos, "foo 42");
+ DoNumTest("foo %-3d", pos, "foo 42 ");
+ DoNumTest("foo %.1d", pos, "foo 42");
+ DoNumTest("foo %.3d", pos, "foo 042");
+ DoNumTest("foo %03d", pos, "foo 042");
+ DoNumTest("foo %#d", pos, "foo 42");
+ DoNumTest("foo %+d", pos, "foo +42");
+ DoNumTest("foo % d", pos, "foo 42");
+ DoNumTest("foo %+d", neg, "foo -42");
+ DoNumTest("foo % d", neg, "foo -42");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test8/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vfprintf/test8/testinfo.dat
new file mode 100644
index 0000000000..e96723378d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test8/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vfprintf
+Name = Positive Test for vfprintf
+TYPE = DEFAULT
+EXE1 = test8
+Description
+= Tests vfprintf with decimal numbers
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test9/CMakeLists.txt
new file mode 100644
index 0000000000..3e3b5b99ed
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test9/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test9.c
+)
+
+add_executable(paltest_vfprintf_test9
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vfprintf_test9 coreclrpal)
+
+target_link_libraries(paltest_vfprintf_test9
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test9/test9.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test9/test9.c
new file mode 100644
index 0000000000..45d0dc7a9e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test9/test9.c
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test9.c
+**
+** Purpose: Test #9 for the vfprintf function. Tests the integer
+** specifier (%i).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../vfprintf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest("foo %i", pos, "foo 42");
+ DoNumTest("foo %li", 0xFFFF, "foo 65535");
+ DoNumTest("foo %hi", 0xFFFF, "foo -1");
+ DoNumTest("foo %Li", pos, "foo 42");
+ DoI64Test("foo %I64i", l, "42", "foo 42");
+ DoNumTest("foo %3i", pos, "foo 42");
+ DoNumTest("foo %-3i", pos, "foo 42 ");
+ DoNumTest("foo %.1i", pos, "foo 42");
+ DoNumTest("foo %.3i", pos, "foo 042");
+ DoNumTest("foo %03i", pos, "foo 042");
+ DoNumTest("foo %#i", pos, "foo 42");
+ DoNumTest("foo %+i", pos, "foo +42");
+ DoNumTest("foo % i", pos, "foo 42");
+ DoNumTest("foo %+i", neg, "foo -42");
+ DoNumTest("foo % i", neg, "foo -42");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test9/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vfprintf/test9/testinfo.dat
new file mode 100644
index 0000000000..48621773cc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test9/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vfprintf
+Name = Positive Test for vfprintf
+TYPE = DEFAULT
+EXE1 = test9
+Description
+= Tests vfprintf with integer numbers
diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/vfprintf.h b/src/pal/tests/palsuite/c_runtime/vfprintf/vfprintf.h
new file mode 100644
index 0000000000..f4ae7a53fa
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vfprintf/vfprintf.h
@@ -0,0 +1,463 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: vfprintf.h
+**
+** Purpose: Contains common testing functions for vfprintf
+**
+**
+**==========================================================================*/
+
+#ifndef __vfprintf_H__
+#define __vfprintf_H__
+
+int DoVfprintf(FILE *fp, char *format, ...)
+{
+ int retVal;
+ va_list arglist;
+
+ va_start(arglist, format);
+ retVal = vfprintf(fp, format, arglist);
+ va_end(arglist);
+
+ return (retVal);
+}
+
+void DoStrTest(char *formatstr, char* param, char *checkstr)
+{
+ FILE *fp;
+ char buf[256] = { 0 };
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ {
+ Fail("ERROR: fopen failed to create testfile\n");
+ }
+ if ((DoVfprintf(fp, formatstr, param)) < 0)
+ {
+ Fail("ERROR: vfprintf failed\n");
+ }
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+ if ((fgets(buf, 100, fp)) == NULL)
+ {
+ Fail("ERROR: fgets failed\n");
+ }
+
+ if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert string \"%s\" into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ param, formatstr, checkstr, buf);
+ }
+ fclose(fp);
+}
+
+void DoWStrTest(char *formatstr, WCHAR* param, char *checkstr)
+{
+ FILE *fp;
+ char buf[256] = { 0 };
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ {
+ Fail("ERROR: fopen failed to create testfile\n");
+ }
+ if ((DoVfprintf(fp, formatstr, param)) < 0)
+ {
+ Fail("ERROR: vfprintf failed\n");
+ }
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+ if ((fgets(buf, 100, fp)) == NULL)
+ {
+ Fail("ERROR: fgets failed\n");
+ }
+
+ if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert wide string \"%S\" into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ param, formatstr, checkstr, buf);
+ }
+ fclose(fp);
+}
+
+
+void DoPointerTest(char *formatstr, void* param, char* paramstr,
+ char *checkstr1)
+{
+ FILE *fp;
+ char buf[256] = { 0 };
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ {
+ Fail("ERROR: fopen failed to create testfile\n");
+ }
+
+ if ((DoVfprintf(fp, formatstr, param)) < 0)
+ {
+ Fail("ERROR: vfprintf failed\n");
+ }
+
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+
+ if ((fgets(buf, 100, fp)) == NULL)
+ {
+ Fail("ERROR: fgets failed\n");
+ }
+
+ if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %s into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ paramstr, formatstr, checkstr1, buf);
+ }
+
+ if ((fclose( fp )) != 0)
+ {
+ Fail("ERROR: fclose failed to close \"testfile.txt\"\n");
+ }
+}
+
+
+
+void DoCountTest(char *formatstr, int param, char *checkstr)
+{
+ FILE *fp;
+ char buf[512] = { 0 };
+ int n = -1;
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ {
+ Fail("ERROR: fopen failed to create testfile\n");
+ }
+
+ if ((DoVfprintf(fp, formatstr, &n)) < 0)
+ {
+ Fail("ERROR: vfprintf failed\n");
+ }
+
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+
+ if ((fgets(buf, sizeof(buf), fp)) == NULL)
+ {
+ Fail("ERROR: fgets failed\n");
+ }
+
+ if (n != param)
+ {
+ Fail("ERROR: Expected count parameter to resolve to %d, got %X\n",
+ param, n);
+ }
+
+ if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0)
+ {
+ Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf);
+ }
+
+ if ((fclose( fp )) != 0)
+ {
+ Fail("ERROR: fclose failed to close \"testfile.txt\"\n");
+ }
+}
+
+void DoShortCountTest(char *formatstr, int param, char *checkstr)
+{
+ FILE *fp;
+ char buf[512] = { 0 };
+ short int n = -1;
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ {
+ Fail("ERROR: fopen failed to create testfile\n");
+ }
+
+ if ((DoVfprintf(fp, formatstr, &n)) < 0)
+ {
+ Fail("ERROR: vfprintf failed\n");
+ }
+
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+
+ if ((fgets(buf, 100, fp)) == NULL)
+ {
+ Fail("ERROR: fgets failed\n");
+ }
+
+ if (n != param)
+ {
+ Fail("ERROR: Expected count parameter to resolve to %d, got %X\n",
+ param, n);
+ }
+
+ if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0)
+ {
+ Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf);
+ }
+
+ if ((fclose( fp )) != 0)
+ {
+ Fail("ERROR: fclose failed to close \"testfile.txt\"\n");
+ }
+}
+
+
+void DoCharTest(char *formatstr, char param, char *checkstr)
+{
+ FILE *fp;
+ char buf[256] = { 0 };
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ {
+ Fail("ERROR: fopen failed to create testfile\n");
+ }
+ if ((DoVfprintf(fp, formatstr, param)) < 0)
+ {
+ Fail("ERROR: vfprintf failed\n");
+ }
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+ if ((fgets(buf, 100, fp)) == NULL)
+ {
+ Fail("ERROR: fgets failed\n");
+ }
+
+ if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert char \'%c\' (%d) into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ param, param, formatstr, checkstr, buf);
+ }
+ fclose(fp);
+}
+
+void DoWCharTest(char *formatstr, WCHAR param, char *checkstr)
+{
+ FILE *fp;
+ char buf[256] = { 0 };
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ {
+ Fail("ERROR: fopen failed to create testfile\n");
+ }
+ if ((DoVfprintf(fp, formatstr, param)) < 0)
+ {
+ Fail("ERROR: vfprintf failed\n");
+ }
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+ if ((fgets(buf, 100, fp)) == NULL)
+ {
+ Fail("ERROR: fgets failed\n");
+ }
+
+ if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert wide char \'%c\' (%d) into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ (char)param, param, formatstr, checkstr, buf);
+ }
+ fclose(fp);
+}
+
+void DoNumTest(char *formatstr, int value, char *checkstr)
+{
+ FILE *fp;
+ char buf[256] = { 0 };
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ {
+ Fail("ERROR: fopen failed to create testfile\n");
+ }
+ if ((DoVfprintf(fp, formatstr, value)) < 0)
+ {
+ Fail("ERROR: vfprintf failed\n");
+ }
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+ if ((fgets(buf, 100, fp)) == NULL)
+ {
+ Fail("ERROR: fgets failed\n");
+ }
+
+ if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %#x into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ value, formatstr, checkstr, buf);
+ }
+ fclose(fp);
+}
+
+void DoI64Test(char *formatstr, INT64 value, char *valuestr, char *checkstr1)
+{
+ FILE *fp;
+ char buf[256] = { 0 };
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ {
+ Fail("ERROR: fopen failed to create testfile\n");
+ }
+ if ((DoVfprintf(fp, formatstr, value)) < 0)
+ {
+ Fail("ERROR: vfprintf failed\n");
+ }
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+ if ((fgets(buf, 100, fp)) == NULL)
+ {
+ Fail("ERROR: fgets failed\n");
+ }
+
+ if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %s into \"%s\"\n"
+ "Expected \"%s\", got \"%s\".\n",
+ valuestr, formatstr, checkstr1, buf);
+ }
+ fclose(fp);
+}
+
+void DoDoubleTest(char *formatstr, double value, char *checkstr1,
+ char *checkstr2)
+{
+ FILE *fp;
+ char buf[256] = { 0 };
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ {
+ Fail("ERROR: fopen failed to create testfile\n");
+ }
+
+ if ((DoVfprintf(fp, formatstr, value)) < 0)
+ {
+ Fail("ERROR: vfprintf failed\n");
+ }
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+ if ((fgets(buf, 100, fp)) == NULL)
+ {
+ Fail("ERROR: fgets failed\n");
+ }
+
+ if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 &&
+ memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %f into \"%s\"\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n",
+ value, formatstr, checkstr1, checkstr2, buf);
+ }
+ fclose(fp);
+}
+
+
+void DoArgumentPrecTest(char *formatstr, int precision, void *param,
+ char *paramstr, char *checkstr1, char *checkstr2)
+{
+ FILE *fp;
+ char buf[256];
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ {
+ Fail("ERROR: fopen failed to create testfile\n");
+ }
+
+ if ((DoVfprintf(fp, formatstr, precision, param)) < 0)
+ {
+ Fail("ERROR: vfprintf failed\n");
+ }
+
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+
+ if ((fgets(buf, 100, fp)) == NULL)
+ {
+ Fail("ERROR: fgets failed\n");
+ }
+
+ if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 &&
+ memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n", paramstr, formatstr,
+ precision, checkstr1, checkstr2, buf);
+ }
+
+
+ if ((fclose( fp )) != 0)
+ {
+ Fail("ERROR: fclose failed to close \"testfile.txt\"\n");
+ }
+
+}
+
+void DoArgumentPrecDoubleTest(char *formatstr, int precision, double param,
+ char *checkstr1, char *checkstr2)
+{
+ FILE *fp;
+ char buf[256];
+
+ if ((fp = fopen("testfile.txt", "w+")) == NULL )
+ {
+ Fail("ERROR: fopen failed to create testfile\n");
+ }
+
+ if ((DoVfprintf(fp, formatstr, precision, param)) < 0)
+ {
+ Fail("ERROR: vfprintf failed\n");
+ }
+
+ if ((fseek(fp, 0, SEEK_SET)) != 0)
+ {
+ Fail("ERROR: fseek failed\n");
+ }
+
+ if ((fgets(buf, 100, fp)) == NULL)
+ {
+ Fail("ERROR: fgets failed\n");
+ }
+
+ if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 &&
+ memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n", param, formatstr,
+ precision, checkstr1, checkstr2, buf);
+ }
+
+ if ((fclose( fp )) != 0)
+ {
+ Fail("ERROR: fclose failed to close \"testfile.txt\"\n");
+ }
+
+}
+
+#endif
+
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/CMakeLists.txt
new file mode 100644
index 0000000000..c7e7647ea9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/CMakeLists.txt
@@ -0,0 +1,23 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+# This test fails to build on ARM
+#add_subdirectory(test1)
+add_subdirectory(test10)
+add_subdirectory(test11)
+add_subdirectory(test12)
+add_subdirectory(test13)
+add_subdirectory(test14)
+add_subdirectory(test15)
+add_subdirectory(test16)
+add_subdirectory(test17)
+add_subdirectory(test18)
+add_subdirectory(test19)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+add_subdirectory(test7)
+add_subdirectory(test8)
+add_subdirectory(test9)
+
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..eabdf87393
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_vprintf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vprintf_test1 coreclrpal)
+
+target_link_libraries(paltest_vprintf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/vprintf/test1/test1.c
new file mode 100644
index 0000000000..404d7a0dc9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test1/test1.c
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test #1 for the vprintf function. A single, basic, test
+** case with no formatting.
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../vprintf.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+ char checkstr[] = "hello world";
+ int ret;
+
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ ret = vprintf("hello world", NULL);
+
+ if (ret != strlen(checkstr))
+ {
+ Fail("Expected vprintf to return %d, got %d.\n",
+ strlen(checkstr), ret);
+
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vprintf/test1/testinfo.dat
new file mode 100644
index 0000000000..ac5de86341
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vprintf
+Name = Positive Test for vprintf
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= General test to see if vprintf works correctly
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test10/CMakeLists.txt
new file mode 100644
index 0000000000..47a21d909a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test10/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test10.c
+)
+
+add_executable(paltest_vprintf_test10
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vprintf_test10 coreclrpal)
+
+target_link_libraries(paltest_vprintf_test10
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test10/test10.c b/src/pal/tests/palsuite/c_runtime/vprintf/test10/test10.c
new file mode 100644
index 0000000000..b363d7c02c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test10/test10.c
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test10.c
+**
+** Purpose: Test #10 for the vprintf function. Tests the octal specifier
+** (%o).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../vprintf.h"
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest("foo %o", pos, "foo 52");
+ DoNumTest("foo %lo", 0xFFFF, "foo 177777");
+ DoNumTest("foo %ho", 0xFFFF, "foo 177777");
+ DoNumTest("foo %Lo", pos, "foo 52");
+ DoI64Test("foo %I64o", l, "42", "foo 52");
+ DoNumTest("foo %3o", pos, "foo 52");
+ DoNumTest("foo %-3o", pos, "foo 52 ");
+ DoNumTest("foo %.1o", pos, "foo 52");
+ DoNumTest("foo %.3o", pos, "foo 052");
+ DoNumTest("foo %03o", pos, "foo 052");
+ DoNumTest("foo %#o", pos, "foo 052");
+ DoNumTest("foo %+o", pos, "foo 52");
+ DoNumTest("foo % o", pos, "foo 52");
+ DoNumTest("foo %+o", neg, "foo 37777777726");
+ DoNumTest("foo % o", neg, "foo 37777777726");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test10/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vprintf/test10/testinfo.dat
new file mode 100644
index 0000000000..4494024300
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test10/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vprintf
+Name = Positive Test for vprintf
+TYPE = DEFAULT
+EXE1 = test10
+Description
+= Tests vprintf with octal numbers
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test11/CMakeLists.txt
new file mode 100644
index 0000000000..4c750b72ac
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test11/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test11.c
+)
+
+add_executable(paltest_vprintf_test11
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vprintf_test11 coreclrpal)
+
+target_link_libraries(paltest_vprintf_test11
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test11/test11.c b/src/pal/tests/palsuite/c_runtime/vprintf/test11/test11.c
new file mode 100644
index 0000000000..f5157ac99f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test11/test11.c
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test11.c
+**
+** Purpose: Test #11 for the vprintf function. Test the unsigned int
+** specifier (%u).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../vprintf.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest("foo %u", pos, "foo 42");
+ DoNumTest("foo %lu", 0xFFFF, "foo 65535");
+ DoNumTest("foo %hu", 0xFFFF, "foo 65535");
+ DoNumTest("foo %Lu", pos, "foo 42");
+ DoI64Test("foo %I64u", l, "42", "foo 42");
+ DoNumTest("foo %3u", pos, "foo 42");
+ DoNumTest("foo %-3u", pos, "foo 42 ");
+ DoNumTest("foo %.1u", pos, "foo 42");
+ DoNumTest("foo %.3u", pos, "foo 042");
+ DoNumTest("foo %03u", pos, "foo 042");
+ DoNumTest("foo %#u", pos, "foo 42");
+ DoNumTest("foo %+u", pos, "foo 42");
+ DoNumTest("foo % u", pos, "foo 42");
+ DoNumTest("foo %+u", neg, "foo 4294967254");
+ DoNumTest("foo % u", neg, "foo 4294967254");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test11/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vprintf/test11/testinfo.dat
new file mode 100644
index 0000000000..c504c70e88
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test11/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vprintf
+Name = Positive Test for vprintf
+TYPE = DEFAULT
+EXE1 = test11
+Description
+= Tests vprintf with unsigned numbers
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test12/CMakeLists.txt
new file mode 100644
index 0000000000..1feb886fc1
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test12/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test12.c
+)
+
+add_executable(paltest_vprintf_test12
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vprintf_test12 coreclrpal)
+
+target_link_libraries(paltest_vprintf_test12
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test12/test12.c b/src/pal/tests/palsuite/c_runtime/vprintf/test12/test12.c
new file mode 100644
index 0000000000..703a8c4fdc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test12/test12.c
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test12.c
+**
+** Purpose: Test #12 for the vprintf function. Tests the (lowercase)
+** hexadecimal specifier (%x)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../vprintf.h"
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 0x1234ab;
+ INT64 l = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest("foo %x", pos, "foo 1234ab");
+ DoNumTest("foo %lx", pos, "foo 1234ab");
+ DoNumTest("foo %hx", pos, "foo 34ab");
+ DoNumTest("foo %Lx", pos, "foo 1234ab");
+ DoI64Test("foo %I64x", l, "0x1234567887654321",
+ "foo 1234567887654321");
+ DoNumTest("foo %7x", pos, "foo 1234ab");
+ DoNumTest("foo %-7x", pos, "foo 1234ab ");
+ DoNumTest("foo %.1x", pos, "foo 1234ab");
+ DoNumTest("foo %.7x", pos, "foo 01234ab");
+ DoNumTest("foo %07x", pos, "foo 01234ab");
+ DoNumTest("foo %#x", pos, "foo 0x1234ab");
+ DoNumTest("foo %+x", pos, "foo 1234ab");
+ DoNumTest("foo % x", pos, "foo 1234ab");
+ DoNumTest("foo %+x", neg, "foo ffffffd6");
+ DoNumTest("foo % x", neg, "foo ffffffd6");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test12/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vprintf/test12/testinfo.dat
new file mode 100644
index 0000000000..558ce37c8b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test12/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vprintf
+Name = Positive Test for vprintf
+TYPE = DEFAULT
+EXE1 = test12
+Description
+= Tests vprintf with hex numbers (lowercase)
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test13/CMakeLists.txt
new file mode 100644
index 0000000000..cd7535a1ad
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test13/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test13.c
+)
+
+add_executable(paltest_vprintf_test13
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vprintf_test13 coreclrpal)
+
+target_link_libraries(paltest_vprintf_test13
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test13/test13.c b/src/pal/tests/palsuite/c_runtime/vprintf/test13/test13.c
new file mode 100644
index 0000000000..ecb83ba38d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test13/test13.c
@@ -0,0 +1,54 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test13.c
+**
+** Purpose: Test #13 for the vprintf function. Tests the (uppercase)
+** hexadecimal specifier (%X)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../vprintf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 0x1234AB;
+ INT64 l = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest("foo %X", pos, "foo 1234AB");
+ DoNumTest("foo %lX", pos, "foo 1234AB");
+ DoNumTest("foo %hX", pos, "foo 34AB");
+ DoNumTest("foo %LX", pos, "foo 1234AB");
+ DoI64Test("foo %I64X", l, "0x1234567887654321",
+ "foo 1234567887654321");
+ DoNumTest("foo %7X", pos, "foo 1234AB");
+ DoNumTest("foo %-7X", pos, "foo 1234AB ");
+ DoNumTest("foo %.1X", pos, "foo 1234AB");
+ DoNumTest("foo %.7X", pos, "foo 01234AB");
+ DoNumTest("foo %07X", pos, "foo 01234AB");
+ DoNumTest("foo %#X", pos, "foo 0X1234AB");
+ DoNumTest("foo %+X", pos, "foo 1234AB");
+ DoNumTest("foo % X", pos, "foo 1234AB");
+ DoNumTest("foo %+X", neg, "foo FFFFFFD6");
+ DoNumTest("foo % X", neg, "foo FFFFFFD6");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test13/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vprintf/test13/testinfo.dat
new file mode 100644
index 0000000000..33822958dd
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test13/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vprintf
+Name = Positive Test for vprintf
+TYPE = DEFAULT
+EXE1 = test13
+Description
+= Tests vprintf with hex numbers (uppercase)
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test14/CMakeLists.txt
new file mode 100644
index 0000000000..82cfd68ecf
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test14/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test14.c
+)
+
+add_executable(paltest_vprintf_test14
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vprintf_test14 coreclrpal)
+
+target_link_libraries(paltest_vprintf_test14
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test14/test14.c b/src/pal/tests/palsuite/c_runtime/vprintf/test14/test14.c
new file mode 100644
index 0000000000..536c1950e3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test14/test14.c
@@ -0,0 +1,54 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test14.c
+**
+** Purpose: Test #14 for the vprintf function. Tests the lowercase
+** exponential notation double specifier (%e)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../vprintf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 256.0;
+ double neg = -256.0;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest("foo %e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %le", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %he", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %Le", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %I64e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %14e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %-14e", val, "foo 2.560000e+002 ",
+ "foo 2.560000e+02 ");
+ DoDoubleTest("foo %.1e", val, "foo 2.6e+002", "foo 2.6e+02");
+ DoDoubleTest("foo %.8e", val, "foo 2.56000000e+002",
+ "foo 2.56000000e+02");
+ DoDoubleTest("foo %014e", val, "foo 02.560000e+002",
+ "foo 002.560000e+02");
+ DoDoubleTest("foo %#e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %+e", val, "foo +2.560000e+002", "foo +2.560000e+02");
+ DoDoubleTest("foo % e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %+e", neg, "foo -2.560000e+002", "foo -2.560000e+02");
+ DoDoubleTest("foo % e", neg, "foo -2.560000e+002", "foo -2.560000e+02");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test14/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vprintf/test14/testinfo.dat
new file mode 100644
index 0000000000..d2633fca43
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test14/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vprintf
+Name = Positive Test for vprintf
+TYPE = DEFAULT
+EXE1 = test14
+Description
+= Tests vprintf with exponential format doubles (lowercase)
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test15/CMakeLists.txt
new file mode 100644
index 0000000000..29a134d48c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test15/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test15.c
+)
+
+add_executable(paltest_vprintf_test15
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vprintf_test15 coreclrpal)
+
+target_link_libraries(paltest_vprintf_test15
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test15/test15.c b/src/pal/tests/palsuite/c_runtime/vprintf/test15/test15.c
new file mode 100644
index 0000000000..9aff6e457d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test15/test15.c
@@ -0,0 +1,54 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test15.c
+**
+** Purpose: Test #15 for the vprintf function. Tests the uppercase
+** exponential notation double specifier (%E)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../vprintf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 256.0;
+ double neg = -256.0;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest("foo %E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %lE", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %hE", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %LE", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %I64E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %14E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %-14E", val, "foo 2.560000E+002 ",
+ "foo 2.560000E+02 ");
+ DoDoubleTest("foo %.1E", val, "foo 2.6E+002", "foo 2.6E+02");
+ DoDoubleTest("foo %.8E", val, "foo 2.56000000E+002",
+ "foo 2.56000000E+02");
+ DoDoubleTest("foo %014E", val, "foo 02.560000E+002",
+ "foo 002.560000E+02");
+ DoDoubleTest("foo %#E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %+E", val, "foo +2.560000E+002", "foo +2.560000E+02");
+ DoDoubleTest("foo % E", val, "foo 2.560000E+002", "foo 2.560000E+02");
+ DoDoubleTest("foo %+E", neg, "foo -2.560000E+002", "foo -2.560000E+02");
+ DoDoubleTest("foo % E", neg, "foo -2.560000E+002", "foo -2.560000E+02");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test15/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vprintf/test15/testinfo.dat
new file mode 100644
index 0000000000..c1e00520a7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test15/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vprintf
+Name = Positive Test for vprintf
+TYPE = DEFAULT
+EXE1 = test15
+Description
+= Tests vprintf with exponential format doubles (uppercase)
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test16/CMakeLists.txt
new file mode 100644
index 0000000000..7fbf43ac84
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test16/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test16.c
+)
+
+add_executable(paltest_vprintf_test16
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vprintf_test16 coreclrpal)
+
+target_link_libraries(paltest_vprintf_test16
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test16/test16.c b/src/pal/tests/palsuite/c_runtime/vprintf/test16/test16.c
new file mode 100644
index 0000000000..66e9afe2d7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test16/test16.c
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test16.c
+**
+** Purpose: Test #16 for the vprintf function. Tests the decimal notation
+** double specifier (%f)
+**
+**
+**==========================================================================*/
+
+
+#include <palsuite.h>
+#include "../vprintf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest("foo %f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %lf", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %hf", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %Lf", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %I64f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %12f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %-12f", val, "foo 2560.001000 ", "foo 2560.001000 ");
+ DoDoubleTest("foo %.1f", val, "foo 2560.0", "foo 2560.0");
+ DoDoubleTest("foo %.8f", val, "foo 2560.00100000", "foo 2560.00100000");
+ DoDoubleTest("foo %012f", val, "foo 02560.001000", "foo 02560.001000");
+ DoDoubleTest("foo %#f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %+f", val, "foo +2560.001000", "foo +2560.001000");
+ DoDoubleTest("foo % f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %+f", neg, "foo -2560.001000", "foo -2560.001000");
+ DoDoubleTest("foo % f", neg, "foo -2560.001000", "foo -2560.001000");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test16/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vprintf/test16/testinfo.dat
new file mode 100644
index 0000000000..8b17d2f71a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test16/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vprintf
+Name = Positive Test for vprintf
+TYPE = DEFAULT
+EXE1 = test16
+Description
+= Tests vprintf with decimal point format doubles
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test17/CMakeLists.txt
new file mode 100644
index 0000000000..25970cba15
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test17/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test17.c
+)
+
+add_executable(paltest_vprintf_test17
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vprintf_test17 coreclrpal)
+
+target_link_libraries(paltest_vprintf_test17
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test17/test17.c b/src/pal/tests/palsuite/c_runtime/vprintf/test17/test17.c
new file mode 100644
index 0000000000..d36a084903
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test17/test17.c
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test17.c
+**
+** Purpose: Test #17 for the vprintf function. Tests the lowercase
+** shorthand notation double specifier (%g)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../vprintf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest("foo %g", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %lg", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %hg", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %Lg", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %I64g", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %5g", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %-5g", val, "foo 2560 ", "foo 2560 ");
+ DoDoubleTest("foo %.1g", val, "foo 3e+003", "foo 3e+03");
+ DoDoubleTest("foo %.2g", val, "foo 2.6e+003", "foo 2.6e+03");
+ DoDoubleTest("foo %.12g", val, "foo 2560.001", "foo 2560.001");
+ DoDoubleTest("foo %06g", val, "foo 002560", "foo 002560");
+ DoDoubleTest("foo %#g", val, "foo 2560.00", "foo 2560.00");
+ DoDoubleTest("foo %+g", val, "foo +2560", "foo +2560");
+ DoDoubleTest("foo % g", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %+g", neg, "foo -2560", "foo -2560");
+ DoDoubleTest("foo % g", neg, "foo -2560", "foo -2560");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test17/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vprintf/test17/testinfo.dat
new file mode 100644
index 0000000000..9f40fb03a0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test17/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vprintf
+Name = Positive Test for vprintf
+TYPE = DEFAULT
+EXE1 = test17
+Description
+= Tests vprintf with compact format doubles (lowercase)
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test18/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test18/CMakeLists.txt
new file mode 100644
index 0000000000..45676b93dd
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test18/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test18.c
+)
+
+add_executable(paltest_vprintf_test18
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vprintf_test18 coreclrpal)
+
+target_link_libraries(paltest_vprintf_test18
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test18/test18.c b/src/pal/tests/palsuite/c_runtime/vprintf/test18/test18.c
new file mode 100644
index 0000000000..6fde79b5fb
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test18/test18.c
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test18.c
+**
+** Purpose: Test #18 for the vprintf function. Tests the uppercase
+** shorthand notation double specifier (%G)
+**
+**
+**==========================================================================*/
+
+
+#include <palsuite.h>
+#include "../vprintf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoDoubleTest("foo %G", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %lG", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %hG", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %LG", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %I64G", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %5G", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %-5G", val, "foo 2560 ", "foo 2560 ");
+ DoDoubleTest("foo %.1G", val, "foo 3E+003", "foo 3E+03");
+ DoDoubleTest("foo %.2G", val, "foo 2.6E+003", "foo 2.6E+03");
+ DoDoubleTest("foo %.12G", val, "foo 2560.001", "foo 2560.001");
+ DoDoubleTest("foo %06G", val, "foo 002560", "foo 002560");
+ DoDoubleTest("foo %#G", val, "foo 2560.00", "foo 2560.00");
+ DoDoubleTest("foo %+G", val, "foo +2560", "foo +2560");
+ DoDoubleTest("foo % G", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %+G", neg, "foo -2560", "foo -2560");
+ DoDoubleTest("foo % G", neg, "foo -2560", "foo -2560");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test18/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vprintf/test18/testinfo.dat
new file mode 100644
index 0000000000..b41f8c63e0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test18/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vprintf
+Name = Positive Test for vprintf
+TYPE = DEFAULT
+EXE1 = test18
+Description
+= Tests vprintf with compact format doubles (uppercase)
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test19/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test19/CMakeLists.txt
new file mode 100644
index 0000000000..25bc2fccd1
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test19/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test19.c
+)
+
+add_executable(paltest_vprintf_test19
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vprintf_test19 coreclrpal)
+
+target_link_libraries(paltest_vprintf_test19
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test19/test19.c b/src/pal/tests/palsuite/c_runtime/vprintf/test19/test19.c
new file mode 100644
index 0000000000..d79f2e2591
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test19/test19.c
@@ -0,0 +1,76 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test19.c
+**
+** Purpose: Test #19 for the vprintf function. Tests the variable length
+** precision argument.
+**
+**
+**==========================================================================*/
+
+
+#include <palsuite.h>
+#include "../vprintf.h"
+
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int n = -1;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoArgumentPrecTest("%.*s", 2, "bar", "bar", "ba", "ba");
+ DoArgumentPrecTest("%.*S", 2, convert("bar"), "bar", "ba", "ba");
+
+ DoArgumentPrecTest("%.*n", 3, &n, "pointer to int", "", "");
+ if (n != 0)
+ {
+ Fail("ERROR: Expected count parameter to resolve to %d, got %X\n",
+ 0, n);
+ }
+
+ DoArgumentPrecTest("%.*c", 0, (void*)'a', "a", "a", "a");
+ DoArgumentPrecTest("%.*c", 4, (void*)'a', "a", "a", "a");
+ DoArgumentPrecTest("%.*C", 0, (void*)'a', "a", "a", "a");
+ DoArgumentPrecTest("%.*C", 4, (void*)'a', "a", "a", "a");
+ DoArgumentPrecTest("%.*d", 1, (void*)42, "42", "42", "42");
+ DoArgumentPrecTest("%.*d", 3, (void*)42, "42", "042", "042");
+ DoArgumentPrecTest("%.*i", 1, (void*)42, "42", "42", "42");
+ DoArgumentPrecTest("%.*i", 3, (void*)42, "42", "042", "042");
+ DoArgumentPrecTest("%.*o", 1, (void*)42, "42", "52", "52");
+ DoArgumentPrecTest("%.*o", 3, (void*)42, "42", "052", "052");
+ DoArgumentPrecTest("%.*u", 1, (void*)42, "42", "42", "42");
+ DoArgumentPrecTest("%.*u", 3, (void*)42, "42", "042", "042");
+ DoArgumentPrecTest("%.*x", 1, (void*)0x42, "0x42", "42", "42");
+ DoArgumentPrecTest("%.*x", 3, (void*)0x42, "0x42", "042", "042");
+ DoArgumentPrecTest("%.*X", 1, (void*)0x42, "0x42", "42", "42");
+ DoArgumentPrecTest("%.*X", 3, (void*)0x42, "0x42", "042", "042");
+
+
+ DoArgumentPrecDoubleTest("%.*e", 1, 2.01, "2.0e+000", "2.0e+00");
+ DoArgumentPrecDoubleTest("%.*e", 3, 2.01, "2.010e+000", "2.010e+00");
+ DoArgumentPrecDoubleTest("%.*E", 1, 2.01, "2.0E+000", "2.0E+00");
+ DoArgumentPrecDoubleTest("%.*E", 3, 2.01, "2.010E+000", "2.010E+00");
+ DoArgumentPrecDoubleTest("%.*f", 1, 2.01, "2.0", "2.0");
+ DoArgumentPrecDoubleTest("%.*f", 3, 2.01, "2.010", "2.010");
+ DoArgumentPrecDoubleTest("%.*g", 1, 256.01, "3e+002", "3e+02");
+ DoArgumentPrecDoubleTest("%.*g", 3, 256.01, "256", "256");
+ DoArgumentPrecDoubleTest("%.*g", 4, 256.01, "256", "256");
+ DoArgumentPrecDoubleTest("%.*g", 6, 256.01, "256.01", "256.01");
+ DoArgumentPrecDoubleTest("%.*G", 1, 256.01, "3E+002", "3E+02");
+ DoArgumentPrecDoubleTest("%.*G", 3, 256.01, "256", "256");
+ DoArgumentPrecDoubleTest("%.*G", 4, 256.01, "256", "256");
+ DoArgumentPrecDoubleTest("%.*G", 6, 256.01, "256.01", "256.01");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test19/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vprintf/test19/testinfo.dat
new file mode 100644
index 0000000000..03c3afa693
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test19/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vprintf
+Name = Positive Test for vprintf
+TYPE = DEFAULT
+EXE1 = test19
+Description
+= Tests vprintf with argument specified precision
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test2/CMakeLists.txt
new file mode 100644
index 0000000000..6820069cb9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_vprintf_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vprintf_test2 coreclrpal)
+
+target_link_libraries(paltest_vprintf_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test2/test2.c b/src/pal/tests/palsuite/c_runtime/vprintf/test2/test2.c
new file mode 100644
index 0000000000..4d9c9bc6f5
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test2/test2.c
@@ -0,0 +1,45 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test2.c
+**
+** Purpose: Test #2 for the vprintf function. Tests the string specifier
+** (%s).
+**
+**
+**==========================================================================*/
+
+
+#include <palsuite.h>
+#include "../vprintf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoStrTest("foo %s", "bar", "foo bar");
+ DoStrTest("foo %hs", "bar", "foo bar");
+ DoWStrTest("foo %ls", convert("bar"), "foo bar");
+ DoWStrTest("foo %ws", convert("bar"), "foo bar");
+ DoStrTest("foo %Ls", "bar", "foo bar");
+ DoStrTest("foo %I64s", "bar", "foo bar");
+ DoStrTest("foo %5s", "bar", "foo bar");
+ DoStrTest("foo %.2s", "bar", "foo ba");
+ DoStrTest("foo %5.2s", "bar", "foo ba");
+ DoStrTest("foo %-5s", "bar", "foo bar ");
+ DoStrTest("foo %05s", "bar", "foo 00bar");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vprintf/test2/testinfo.dat
new file mode 100644
index 0000000000..32c1d70d9e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test2/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vprintf
+Name = Positive Test for vprintf
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Tests vprintf with strings
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test3/CMakeLists.txt
new file mode 100644
index 0000000000..676d19bf7a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_vprintf_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vprintf_test3 coreclrpal)
+
+target_link_libraries(paltest_vprintf_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test3/test3.c b/src/pal/tests/palsuite/c_runtime/vprintf/test3/test3.c
new file mode 100644
index 0000000000..5376c56b76
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test3/test3.c
@@ -0,0 +1,45 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test3.c
+**
+** Purpose: Test #3 for the vprintf function. Tests the wide string
+** specifier (%S).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../vprintf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoWStrTest("foo %S", convert("bar"), "foo bar");
+ DoStrTest("foo %hS", "bar", "foo bar");
+ DoWStrTest("foo %lS", convert("bar"), "foo bar");
+ DoWStrTest("foo %wS", convert("bar"), "foo bar");
+ DoWStrTest("foo %LS", convert("bar"), "foo bar");
+ DoWStrTest("foo %I64S", convert("bar"), "foo bar");
+ DoWStrTest("foo %5S", convert("bar"), "foo bar");
+ DoWStrTest("foo %.2S", convert("bar"), "foo ba");
+ DoWStrTest("foo %5.2S", convert("bar"), "foo ba");
+ DoWStrTest("foo %-5S", convert("bar"), "foo bar ");
+ DoWStrTest("foo %05S", convert("bar"), "foo 00bar");
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vprintf/test3/testinfo.dat
new file mode 100644
index 0000000000..c3b385e8f1
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test3/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vprintf
+Name = Positive Test for vprintf
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Tests vprintf with wide strings
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test4/CMakeLists.txt
new file mode 100644
index 0000000000..9ddb087e83
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_vprintf_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vprintf_test4 coreclrpal)
+
+target_link_libraries(paltest_vprintf_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test4/test4.c b/src/pal/tests/palsuite/c_runtime/vprintf/test4/test4.c
new file mode 100644
index 0000000000..3b66cde22e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test4/test4.c
@@ -0,0 +1,70 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test4.c
+**
+** Purpose: Test #4 for the vprintf function. Tests the pointer
+** specifier (%p).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../vprintf.h"
+
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ void *ptr = (void*) 0x123456;
+ INT64 lptr = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+/*
+** Run only on 64 bit platforms
+*/
+#if defined(BIT64) && defined(PLATFORM_UNIX)
+ Trace("Testing for 64 Bit Platforms \n");
+ DoPointerTest("%p", NULL, "NULL", "0000000000000000");
+ DoPointerTest("%p", ptr, "pointer to 0x123456", "0000000000123456");
+ DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456");
+ DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456");
+ DoPointerTest("%-17p", ptr, "pointer to 0x123456", "0000000000123456 ");
+ DoPointerTest("%+p", ptr, "pointer to 0x123456", "0000000000123456");
+ DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X0000000000123456");
+ DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456");
+ DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456");
+ DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456");
+ DoI64Test("%I64p", lptr, "pointer to 0x1234567887654321",
+ "1234567887654321");
+
+#else
+ Trace("Testing for Non 64 Bit Platforms \n");
+ DoPointerTest("%p", NULL, "NULL", "00000000");
+ DoPointerTest("%p", ptr, "pointer to 0x123456", "00123456");
+ DoPointerTest("%9p", ptr, "pointer to 0x123456", " 00123456");
+ DoPointerTest("%09p", ptr, "pointer to 0x123456", " 00123456");
+ DoPointerTest("%-9p", ptr, "pointer to 0x123456", "00123456 ");
+ DoPointerTest("%+p", ptr, "pointer to 0x123456", "00123456");
+ DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X00123456");
+ DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456");
+ DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456");
+ DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456");
+ DoI64Test("%I64p", lptr, "pointer to 0x1234567887654321",
+ "1234567887654321");
+
+#endif
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test4/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vprintf/test4/testinfo.dat
new file mode 100644
index 0000000000..74c4ce932e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test4/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vprintf
+Name = Positive Test for vprintf
+TYPE = DEFAULT
+EXE1 = test4
+Description
+= Tests vprintf with pointers
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test5/CMakeLists.txt
new file mode 100644
index 0000000000..f453bb66ee
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test5.c
+)
+
+add_executable(paltest_vprintf_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vprintf_test5 coreclrpal)
+
+target_link_libraries(paltest_vprintf_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test5/test5.c b/src/pal/tests/palsuite/c_runtime/vprintf/test5/test5.c
new file mode 100644
index 0000000000..c9e2901230
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test5/test5.c
@@ -0,0 +1,60 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test5.c
+**
+** Purpose: Test #5 for the vprintf function. Tests the count specifier (%n).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../vprintf.h"
+
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ char *longStr =
+ "really-long-string-that-just-keeps-going-on-and-on-and-on.."
+ "..................useless-filler.................................."
+ "..................useless-filler.................................."
+ "..................useless-filler.................................."
+ "%n bar";
+ char *longResult =
+ "really-long-string-that-just-keeps-going-on-and-on-and-on.."
+ "..................useless-filler.................................."
+ "..................useless-filler.................................."
+ "..................useless-filler.................................."
+ " bar";
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoCountTest("foo %n bar", 4, "foo bar");
+ DoCountTest(longStr, 257, longResult);
+ DoCountTest("fo%n bar", 2, "fo bar");
+ DoCountTest("%n", 0, "");
+ DoCountTest("foo %#n bar", 4, "foo bar");
+ DoCountTest("foo % n bar", 4, "foo bar");
+ DoCountTest("foo %+n bar", 4, "foo bar");
+ DoCountTest("foo %-n bar", 4, "foo bar");
+ DoCountTest("foo %0n bar", 4, "foo bar");
+ DoShortCountTest("foo %hn bar", 4, "foo bar");
+ DoCountTest("foo %ln bar", 4, "foo bar");
+ DoCountTest("foo %Ln bar", 4, "foo bar");
+ DoCountTest("foo %I64n bar", 4, "foo bar");
+ DoCountTest("foo %20.3n bar", 4, "foo bar");
+
+ PAL_Terminate();
+
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test5/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vprintf/test5/testinfo.dat
new file mode 100644
index 0000000000..01ff864208
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test5/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vprintf
+Name = Positive Test for vprintf
+TYPE = DEFAULT
+EXE1 = test5
+Description
+= Tests vprintf with the count specifier
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test6/CMakeLists.txt
new file mode 100644
index 0000000000..1ce8d5aa4c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test6.c
+)
+
+add_executable(paltest_vprintf_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vprintf_test6 coreclrpal)
+
+target_link_libraries(paltest_vprintf_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test6/test6.c b/src/pal/tests/palsuite/c_runtime/vprintf/test6/test6.c
new file mode 100644
index 0000000000..6a83cccea6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test6/test6.c
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test6.c
+**
+** Purpose: Test #6 for the vprintf function. Tests the char specifier (%c).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../vprintf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR wc = (WCHAR) 'c';
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoCharTest("foo %c", 'b', "foo b");
+ DoCharTest("foo %hc", 'b', "foo b");
+ DoWCharTest("foo %lc", wc, "foo c");
+ DoCharTest("foo %Lc", 'b', "foo b");
+ DoCharTest("foo %I64c", 'b', "foo b");
+ DoCharTest("foo %5c", 'b', "foo b");
+ DoCharTest("foo %.0c", 'b', "foo b");
+ DoCharTest("foo %-5c", 'b', "foo b ");
+ DoCharTest("foo %05c", 'b', "foo 0000b");
+ DoCharTest("foo % c", 'b', "foo b");
+ DoCharTest("foo %#c", 'b', "foo b");
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test6/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vprintf/test6/testinfo.dat
new file mode 100644
index 0000000000..ce450183f6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test6/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vprintf
+Name = Positive Test for vprintf
+TYPE = DEFAULT
+EXE1 = test6
+Description
+= Tests vprintf with characters
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test7/CMakeLists.txt
new file mode 100644
index 0000000000..5627fe4c1e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test7/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test7.c
+)
+
+add_executable(paltest_vprintf_test7
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vprintf_test7 coreclrpal)
+
+target_link_libraries(paltest_vprintf_test7
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test7/test7.c b/src/pal/tests/palsuite/c_runtime/vprintf/test7/test7.c
new file mode 100644
index 0000000000..5096ace42c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test7/test7.c
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test7.c
+**
+** Purpose: Test #7 for the vprintf function. Tests the wide char
+** specifier (%C).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../vprintf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR wb = (WCHAR) 'b';
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoWCharTest("foo %C", wb, "foo b");
+ DoWCharTest("foo %hC", wb, "foo b");
+ DoCharTest("foo %lC", 'c', "foo c");
+ DoWCharTest("foo %LC", wb, "foo b");
+ DoWCharTest("foo %I64C", wb, "foo b");
+ DoWCharTest("foo %5C", wb, "foo b");
+ DoWCharTest("foo %.0C", wb, "foo b");
+ DoWCharTest("foo %-5C", wb, "foo b ");
+ DoWCharTest("foo %05C", wb, "foo 0000b");
+ DoWCharTest("foo % C", wb, "foo b");
+ DoWCharTest("foo %#C", wb, "foo b");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test7/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vprintf/test7/testinfo.dat
new file mode 100644
index 0000000000..254e31e5f8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test7/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vprintf
+Name = Positive Test for vprintf
+TYPE = DEFAULT
+EXE1 = test7
+Description
+= Tests vprintf with wide characters
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test8/CMakeLists.txt
new file mode 100644
index 0000000000..0131e4943e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test8/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test8.c
+)
+
+add_executable(paltest_vprintf_test8
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vprintf_test8 coreclrpal)
+
+target_link_libraries(paltest_vprintf_test8
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test8/test8.c b/src/pal/tests/palsuite/c_runtime/vprintf/test8/test8.c
new file mode 100644
index 0000000000..2683339ece
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test8/test8.c
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test8.c
+**
+** Purpose: Test #8 for the vprintf function. Tests the decimal
+** specifier (%d).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../vprintf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest("foo %d", pos, "foo 42");
+ DoNumTest("foo %ld", 0xFFFF, "foo 65535");
+ DoNumTest("foo %hd", 0xFFFF, "foo -1");
+ DoNumTest("foo %Ld", pos, "foo 42");
+ DoI64Test("foo %I64d", l, "42", "foo 42");
+ DoNumTest("foo %3d", pos, "foo 42");
+ DoNumTest("foo %-3d", pos, "foo 42 ");
+ DoNumTest("foo %.1d", pos, "foo 42");
+ DoNumTest("foo %.3d", pos, "foo 042");
+ DoNumTest("foo %03d", pos, "foo 042");
+ DoNumTest("foo %#d", pos, "foo 42");
+ DoNumTest("foo %+d", pos, "foo +42");
+ DoNumTest("foo % d", pos, "foo 42");
+ DoNumTest("foo %+d", neg, "foo -42");
+ DoNumTest("foo % d", neg, "foo -42");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test8/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vprintf/test8/testinfo.dat
new file mode 100644
index 0000000000..73f287b9fe
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test8/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vprintf
+Name = Positive Test for vprintf
+TYPE = DEFAULT
+EXE1 = test8
+Description
+= Tests vprintf with decimal numbers
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test9/CMakeLists.txt
new file mode 100644
index 0000000000..c70631f9dc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test9/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test9.c
+)
+
+add_executable(paltest_vprintf_test9
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vprintf_test9 coreclrpal)
+
+target_link_libraries(paltest_vprintf_test9
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test9/test9.c b/src/pal/tests/palsuite/c_runtime/vprintf/test9/test9.c
new file mode 100644
index 0000000000..8545bc760e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test9/test9.c
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test9.c
+**
+** Purpose: Test #9 for the vprintf function. Tests the integer
+** specifier (%i).
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../vprintf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoNumTest("foo %i", pos, "foo 42");
+ DoNumTest("foo %li", 0xFFFF, "foo 65535");
+ DoNumTest("foo %hi", 0xFFFF, "foo -1");
+ DoNumTest("foo %Li", pos, "foo 42");
+ DoI64Test("foo %I64i", l, "42", "foo 42");
+ DoNumTest("foo %3i", pos, "foo 42");
+ DoNumTest("foo %-3i", pos, "foo 42 ");
+ DoNumTest("foo %.1i", pos, "foo 42");
+ DoNumTest("foo %.3i", pos, "foo 042");
+ DoNumTest("foo %03i", pos, "foo 042");
+ DoNumTest("foo %#i", pos, "foo 42");
+ DoNumTest("foo %+i", pos, "foo +42");
+ DoNumTest("foo % i", pos, "foo 42");
+ DoNumTest("foo %+i", neg, "foo -42");
+ DoNumTest("foo % i", neg, "foo -42");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test9/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vprintf/test9/testinfo.dat
new file mode 100644
index 0000000000..c4c77b9d11
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/test9/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vprintf
+Name = Positive Test for vprintf
+TYPE = DEFAULT
+EXE1 = test9
+Description
+= Tests vprintf with integer numbers
diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/vprintf.h b/src/pal/tests/palsuite/c_runtime/vprintf/vprintf.h
new file mode 100644
index 0000000000..477db32f4d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vprintf/vprintf.h
@@ -0,0 +1,193 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: vprintf.h
+**
+** Purpose: Containts common testing functions for vprintf
+**
+**
+**==========================================================================*/
+
+#ifndef __vprintf_H__
+#define __vprintf_H__
+
+int DoVprintf(char *format, ...)
+{
+ int retVal;
+ va_list arglist;
+
+ va_start(arglist, format);
+ retVal = vprintf(format, arglist);
+ va_end(arglist);
+
+ return (retVal);
+}
+
+void DoStrTest(char *formatstr, char* param, char *checkstr)
+{
+ int ret;
+
+ ret = DoVprintf(formatstr, param);
+ if (ret != strlen(checkstr))
+ {
+ Fail("Expected vprintf to return %d, got %d.\n",
+ strlen(checkstr), ret);
+ }
+}
+
+void DoWStrTest(char *formatstr, WCHAR* param, char *checkstr)
+{
+ int ret;
+
+ ret = DoVprintf(formatstr, param);
+ if (ret != strlen(checkstr))
+ {
+ Fail("Expected vprintf to return %d, got %d.\n",
+ strlen(checkstr), ret);
+ }
+}
+
+void DoPointerTest(char *formatstr, void* param, char* paramstr,
+ char *checkstr1)
+{
+ int ret;
+
+ ret = DoVprintf(formatstr, param);
+ if (ret != strlen(checkstr1))
+ {
+ Fail("Expected vprintf to return %d, got %d.\n",
+ strlen(checkstr1), ret);
+ }
+}
+
+void DoCountTest(char *formatstr, int param, char *checkstr)
+{
+ int ret;
+ int n = -1;
+
+ ret = DoVprintf(formatstr, &n);
+
+ if (n != param)
+ {
+ Fail("Expected count parameter to resolve to %d, got %d\n", param, n);
+ }
+
+ if (ret != strlen(checkstr))
+ {
+ Fail("Expected vprintf to return %d, got %d.\n",
+ strlen(checkstr), ret);
+ }
+}
+
+void DoShortCountTest(char *formatstr, int param, char *checkstr)
+{
+ int ret;
+ short int n = -1;
+
+ ret = DoVprintf(formatstr, &n);
+
+ if (n != param)
+ {
+ Fail("Expected count parameter to resolve to %d, got %d\n", param, n);
+ }
+
+ if (ret != strlen(checkstr))
+ {
+ Fail("Expected vprintf to return %d, got %d.\n",
+ strlen(checkstr), ret);
+ }
+}
+
+
+void DoCharTest(char *formatstr, char param, char *checkstr)
+{
+ int ret;
+
+ ret = DoVprintf(formatstr, param);
+ if (ret != strlen(checkstr))
+ {
+ Fail("Expected vprintf to return %d, got %d.\n",
+ strlen(checkstr), ret);
+ }
+}
+
+void DoWCharTest(char *formatstr, WCHAR param, char *checkstr)
+{
+ int ret;
+
+ ret = DoVprintf(formatstr, param);
+ if (ret != strlen(checkstr))
+ {
+ Fail("Expected vprintf to return %d, got %d.\n",
+ strlen(checkstr), ret);
+ }
+}
+
+void DoNumTest(char *formatstr, int param, char *checkstr)
+{
+ int ret;
+
+ ret = DoVprintf(formatstr, param);
+ if (ret != strlen(checkstr))
+ {
+ Fail("Expected vprintf to return %d, got %d.\n",
+ strlen(checkstr), ret);
+ }
+}
+
+void DoI64Test(char *formatstr, INT64 param, char *valuestr, char *checkstr1)
+{
+ int ret;
+
+ ret = DoVprintf(formatstr, param);
+ if (ret != strlen(checkstr1))
+ {
+ Fail("Expected vprintf to return %d, got %d.\n",
+ strlen(checkstr1), ret);
+ }
+}
+
+void DoDoubleTest(char *formatstr, double param, char *checkstr1,
+ char *checkstr2)
+{
+ int ret;
+
+ ret = DoVprintf(formatstr, param);
+ if (ret != strlen(checkstr1) && ret != strlen(checkstr2))
+ {
+ Fail("Expected vprintf to return %d or %d, got %d.\n",
+ strlen(checkstr1), strlen(checkstr2), ret);
+ }
+}
+
+void DoArgumentPrecTest(char *formatstr, int precision, void *param,
+ char *paramstr, char *checkstr1, char *checkstr2)
+{
+ int ret;
+
+ ret = DoVprintf(formatstr, precision, param);
+ if (ret != strlen(checkstr1) && ret != strlen(checkstr2))
+ {
+ Fail("Expected vprintf to return %d or %d, got %d.\n",
+ strlen(checkstr1), strlen(checkstr2), ret);
+ }
+}
+
+void DoArgumentPrecDoubleTest(char *formatstr, int precision, double param,
+ char *checkstr1, char *checkstr2)
+{
+ int ret;
+
+ ret = DoVprintf(formatstr, precision, param);
+ if (ret != strlen(checkstr1) && ret != strlen(checkstr2))
+ {
+ Fail("Expected vprintf to return %d or %d, got %d.\n",
+ strlen(checkstr1), strlen(checkstr2), ret);
+ }
+}
+
+#endif
+
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/CMakeLists.txt
new file mode 100644
index 0000000000..cafb9536b0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/CMakeLists.txt
@@ -0,0 +1,22 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test10)
+add_subdirectory(test11)
+add_subdirectory(test12)
+add_subdirectory(test13)
+add_subdirectory(test14)
+add_subdirectory(test15)
+add_subdirectory(test16)
+add_subdirectory(test17)
+add_subdirectory(test18)
+add_subdirectory(test19)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+add_subdirectory(test7)
+add_subdirectory(test8)
+add_subdirectory(test9)
+
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..4f0872eccc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_vsprintf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsprintf_test1 coreclrpal)
+
+target_link_libraries(paltest_vsprintf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test1/test1.c
new file mode 100644
index 0000000000..2007fefc5b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test1/test1.c
@@ -0,0 +1,55 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test #1 for the vsprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vsprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ char checkstr[] = "hello world";
+ char buf[256] = { 0 };
+ int ret;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ testvsp(buf, "hello world");
+
+ if (memcmp(checkstr, buf, strlen(checkstr)+1) != 0)
+ {
+ Fail("ERROR: expected \"%s\" (up to %d chars), got \"%s\"\n",
+ checkstr, 256, buf);
+ }
+
+ testvsp(buf, "xxxxxxxxxxxxxxxxx");
+ ret = testvsp(buf, "hello world");
+
+ if (ret != strlen(checkstr))
+ {
+ Fail("ERROR: expected negative return value, got %d", ret);
+ }
+
+ if (memcmp(checkstr, buf, ret) != 0)
+ {
+ Fail("ERROR: expected %s, got %s\n", checkstr, buf);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vsprintf/test1/testinfo.dat
new file mode 100644
index 0000000000..996364f366
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vsprintf
+Name = Positive Test for vsprintf
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests the PAL implementation of the vsprintf function.
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test10/CMakeLists.txt
new file mode 100644
index 0000000000..d32de01ba1
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test10/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test10.c
+)
+
+add_executable(paltest_vsprintf_test10
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsprintf_test10 coreclrpal)
+
+target_link_libraries(paltest_vsprintf_test10
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test10/test10.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test10/test10.c
new file mode 100644
index 0000000000..791213fccc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test10/test10.c
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test10.c
+**
+** Purpose: Test #10 for the vsprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vsprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoNumTest("foo %o", pos, "foo 52");
+ DoNumTest("foo %lo", 0xFFFF, "foo 177777");
+ DoNumTest("foo %ho", 0xFFFF, "foo 177777");
+ DoNumTest("foo %Lo", pos, "foo 52");
+ DoI64Test("foo %I64o", l, "42", "foo 52");
+ DoNumTest("foo %3o", pos, "foo 52");
+ DoNumTest("foo %-3o", pos, "foo 52 ");
+ DoNumTest("foo %.1o", pos, "foo 52");
+ DoNumTest("foo %.3o", pos, "foo 052");
+ DoNumTest("foo %03o", pos, "foo 052");
+ DoNumTest("foo %#o", pos, "foo 052");
+ DoNumTest("foo %+o", pos, "foo 52");
+ DoNumTest("foo % o", pos, "foo 52");
+ DoNumTest("foo %+o", neg, "foo 37777777726");
+ DoNumTest("foo % o", neg, "foo 37777777726");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test10/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vsprintf/test10/testinfo.dat
new file mode 100644
index 0000000000..1a1f4ef217
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test10/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vsprintf
+Name = Positive Test for vsprintf
+TYPE = DEFAULT
+EXE1 = test10
+Description
+= Tests the PAL implementation of the vsprintf function.
+= Tests vsprintf with octal numbers.
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test11/CMakeLists.txt
new file mode 100644
index 0000000000..ce67444c39
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test11/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test11.c
+)
+
+add_executable(paltest_vsprintf_test11
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsprintf_test11 coreclrpal)
+
+target_link_libraries(paltest_vsprintf_test11
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test11/test11.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test11/test11.c
new file mode 100644
index 0000000000..e0af94981b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test11/test11.c
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test11.c
+**
+** Purpose: Test #11 for the vsprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vsprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoNumTest("foo %u", pos, "foo 42");
+ DoNumTest("foo %lu", 0xFFFF, "foo 65535");
+ DoNumTest("foo %hu", 0xFFFF, "foo 65535");
+ DoNumTest("foo %Lu", pos, "foo 42");
+ DoI64Test("foo %I64u", l, "42", "foo 42");
+ DoNumTest("foo %3u", pos, "foo 42");
+ DoNumTest("foo %-3u", pos, "foo 42 ");
+ DoNumTest("foo %.1u", pos, "foo 42");
+ DoNumTest("foo %.3u", pos, "foo 042");
+ DoNumTest("foo %03u", pos, "foo 042");
+ DoNumTest("foo %#u", pos, "foo 42");
+ DoNumTest("foo %+u", pos, "foo 42");
+ DoNumTest("foo % u", pos, "foo 42");
+ DoNumTest("foo %+u", neg, "foo 4294967254");
+ DoNumTest("foo % u", neg, "foo 4294967254");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test11/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vsprintf/test11/testinfo.dat
new file mode 100644
index 0000000000..d44167e255
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test11/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vsprintf
+Name = Positive Test for vsprintf
+TYPE = DEFAULT
+EXE1 = test11
+Description
+= Tests the PAL implementation of the vsprintf function.
+= Tests vsprintf with unsigned numbers.
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test12/CMakeLists.txt
new file mode 100644
index 0000000000..fe6ccb8399
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test12/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test12.c
+)
+
+add_executable(paltest_vsprintf_test12
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsprintf_test12 coreclrpal)
+
+target_link_libraries(paltest_vsprintf_test12
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test12/test12.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test12/test12.c
new file mode 100644
index 0000000000..f86ddcade8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test12/test12.c
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test12.c
+**
+** Purpose: Test #12 for the vsprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vsprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 0x1234ab;
+ INT64 l = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return (FAIL);
+ }
+
+ DoNumTest("foo %x", pos, "foo 1234ab");
+ DoNumTest("foo %lx", pos, "foo 1234ab");
+ DoNumTest("foo %hx", pos, "foo 34ab");
+ DoNumTest("foo %Lx", pos, "foo 1234ab");
+ DoI64Test("foo %I64x", l, "0x1234567887654321",
+ "foo 1234567887654321");
+ DoNumTest("foo %7x", pos, "foo 1234ab");
+ DoNumTest("foo %-7x", pos, "foo 1234ab ");
+ DoNumTest("foo %.1x", pos, "foo 1234ab");
+ DoNumTest("foo %.7x", pos, "foo 01234ab");
+ DoNumTest("foo %07x", pos, "foo 01234ab");
+ DoNumTest("foo %#x", pos, "foo 0x1234ab");
+ DoNumTest("foo %+x", pos, "foo 1234ab");
+ DoNumTest("foo % x", pos, "foo 1234ab");
+ DoNumTest("foo %+x", neg, "foo ffffffd6");
+ DoNumTest("foo % x", neg, "foo ffffffd6");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test12/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vsprintf/test12/testinfo.dat
new file mode 100644
index 0000000000..781fb9cae8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test12/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vsprintf
+Name = Positive Test for vsprintf
+TYPE = DEFAULT
+EXE1 = test12
+Description
+= Tests the PAL implementation of the vsprintf function.
+= Tests vsprintf with hex numbers (lowercase).
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test13/CMakeLists.txt
new file mode 100644
index 0000000000..97fdf8cdd0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test13/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test13.c
+)
+
+add_executable(paltest_vsprintf_test13
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsprintf_test13 coreclrpal)
+
+target_link_libraries(paltest_vsprintf_test13
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test13/test13.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test13/test13.c
new file mode 100644
index 0000000000..36e7825531
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test13/test13.c
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test13.c
+**
+** Purpose: Test #13 for the vsprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vsprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 0x1234AB;
+ INT64 l = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoNumTest("foo %X", pos, "foo 1234AB");
+ DoNumTest("foo %lX", pos, "foo 1234AB");
+ DoNumTest("foo %hX", pos, "foo 34AB");
+ DoNumTest("foo %LX", pos, "foo 1234AB");
+ DoI64Test("foo %I64X", l, "0x1234567887654321",
+ "foo 1234567887654321");
+ DoNumTest("foo %7X", pos, "foo 1234AB");
+ DoNumTest("foo %-7X", pos, "foo 1234AB ");
+ DoNumTest("foo %.1X", pos, "foo 1234AB");
+ DoNumTest("foo %.7X", pos, "foo 01234AB");
+ DoNumTest("foo %07X", pos, "foo 01234AB");
+ DoNumTest("foo %#X", pos, "foo 0X1234AB");
+ DoNumTest("foo %+X", pos, "foo 1234AB");
+ DoNumTest("foo % X", pos, "foo 1234AB");
+ DoNumTest("foo %+X", neg, "foo FFFFFFD6");
+ DoNumTest("foo % X", neg, "foo FFFFFFD6");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test13/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vsprintf/test13/testinfo.dat
new file mode 100644
index 0000000000..7b28a91e65
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test13/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vsprintf
+Name = Positive Test for vsprintf
+TYPE = DEFAULT
+EXE1 = test13
+Description
+= Tests the PAL implementation of the vsprintf function.
+= Tests vsprintf with hex numbers (uppercase).
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test14/CMakeLists.txt
new file mode 100644
index 0000000000..2851a8893e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test14/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test14.c
+)
+
+add_executable(paltest_vsprintf_test14
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsprintf_test14 coreclrpal)
+
+target_link_libraries(paltest_vsprintf_test14
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test14/test14.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test14/test14.c
new file mode 100644
index 0000000000..360fafc37f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test14/test14.c
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test14.c
+**
+** Purpose: Test #14 for the vsprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vsprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 256.0;
+ double neg = -256.0;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoDoubleTest("foo %e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %le", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %he", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %Le", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %I64e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %14e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %-14e", val, "foo 2.560000e+002 ", "foo 2.560000e+02 ");
+ DoDoubleTest("foo %.1e", val, "foo 2.6e+002", "foo 2.6e+02");
+ DoDoubleTest("foo %.8e", val, "foo 2.56000000e+002", "foo 2.56000000e+02");
+ DoDoubleTest("foo %014e", val, "foo 02.560000e+002", "foo 002.560000e+02");
+ DoDoubleTest("foo %#e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %+e", val, "foo +2.560000e+002", "foo +2.560000e+02");
+ DoDoubleTest("foo % e", val, "foo 2.560000e+002", "foo 2.560000e+02");
+ DoDoubleTest("foo %+e", neg, "foo -2.560000e+002", "foo -2.560000e+02");
+ DoDoubleTest("foo % e", neg, "foo -2.560000e+002", "foo -2.560000e+02");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test14/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vsprintf/test14/testinfo.dat
new file mode 100644
index 0000000000..a0934096cc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test14/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vsprintf
+Name = Positive Test for vsprintf
+TYPE = DEFAULT
+EXE1 = test14
+Description
+= Tests the PAL implementation of the vsprintf function.
+= Tests vsprintf with exponential format doubles (lowercase).
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test15/CMakeLists.txt
new file mode 100644
index 0000000000..6fb1d321b8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test15/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test15.c
+)
+
+add_executable(paltest_vsprintf_test15
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsprintf_test15 coreclrpal)
+
+target_link_libraries(paltest_vsprintf_test15
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test15/test15.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test15/test15.c
new file mode 100644
index 0000000000..a5b4c94226
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test15/test15.c
@@ -0,0 +1,64 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test15.c
+**
+** Purpose: Test #15 for the vsprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vsprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 256.0;
+ double neg = -256.0;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoDoubleTest("foo %E", val, "foo 2.560000E+002",
+ "foo 2.560000E+02");
+ DoDoubleTest("foo %lE", val, "foo 2.560000E+002",
+ "foo 2.560000E+02");
+ DoDoubleTest("foo %hE", val, "foo 2.560000E+002",
+ "foo 2.560000E+02");
+ DoDoubleTest("foo %LE", val, "foo 2.560000E+002",
+ "foo 2.560000E+02");
+ DoDoubleTest("foo %I64E", val, "foo 2.560000E+002",
+ "foo 2.560000E+02");
+ DoDoubleTest("foo %14E", val, "foo 2.560000E+002",
+ "foo 2.560000E+02");
+ DoDoubleTest("foo %-14E", val, "foo 2.560000E+002 ",
+ "foo 2.560000E+02 ");
+ DoDoubleTest("foo %.1E", val, "foo 2.6E+002",
+ "foo 2.6E+02");
+ DoDoubleTest("foo %.8E", val, "foo 2.56000000E+002",
+ "foo 2.56000000E+02");
+ DoDoubleTest("foo %014E", val, "foo 02.560000E+002",
+ "foo 002.560000E+02");
+ DoDoubleTest("foo %#E", val, "foo 2.560000E+002",
+ "foo 2.560000E+02");
+ DoDoubleTest("foo %+E", val, "foo +2.560000E+002",
+ "foo +2.560000E+02");
+ DoDoubleTest("foo % E", val, "foo 2.560000E+002",
+ "foo 2.560000E+02");
+ DoDoubleTest("foo %+E", neg, "foo -2.560000E+002",
+ "foo -2.560000E+02");
+ DoDoubleTest("foo % E", neg, "foo -2.560000E+002",
+ "foo -2.560000E+02");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test15/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vsprintf/test15/testinfo.dat
new file mode 100644
index 0000000000..c3b8ebd292
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test15/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vsprintf
+Name = Positive Test for vsprintf
+TYPE = DEFAULT
+EXE1 = test15
+Description
+= Tests the PAL implementation of the vsprintf function.
+= Tests vsprintf with exponential format doubles (uppercase).
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test16/CMakeLists.txt
new file mode 100644
index 0000000000..ccc21378fc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test16/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test16.c
+)
+
+add_executable(paltest_vsprintf_test16
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsprintf_test16 coreclrpal)
+
+target_link_libraries(paltest_vsprintf_test16
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test16/test16.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test16/test16.c
new file mode 100644
index 0000000000..a7258db9d6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test16/test16.c
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test16.c
+**
+** Purpose: Test #16 for the vsprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vsprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoDoubleTest("foo %f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %lf", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %hf", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %Lf", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %I64f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %12f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %-12f", val, "foo 2560.001000 ", "foo 2560.001000 ");
+ DoDoubleTest("foo %.1f", val, "foo 2560.0", "foo 2560.0");
+ DoDoubleTest("foo %.8f", val, "foo 2560.00100000", "foo 2560.00100000");
+ DoDoubleTest("foo %012f", val, "foo 02560.001000", "foo 02560.001000");
+ DoDoubleTest("foo %#f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %+f", val, "foo +2560.001000", "foo +2560.001000");
+ DoDoubleTest("foo % f", val, "foo 2560.001000", "foo 2560.001000");
+ DoDoubleTest("foo %+f", neg, "foo -2560.001000", "foo -2560.001000");
+ DoDoubleTest("foo % f", neg, "foo -2560.001000", "foo -2560.001000");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test16/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vsprintf/test16/testinfo.dat
new file mode 100644
index 0000000000..d29634e3ed
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test16/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vsprintf
+Name = Positive Test for vsprintf
+TYPE = DEFAULT
+EXE1 = test16
+Description
+= Tests the PAL implementation of the vsprintf function.
+= Tests vsprintf with decimal point format doubles.
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test17/CMakeLists.txt
new file mode 100644
index 0000000000..4c9dcd986f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test17/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test17.c
+)
+
+add_executable(paltest_vsprintf_test17
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsprintf_test17 coreclrpal)
+
+target_link_libraries(paltest_vsprintf_test17
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test17/test17.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test17/test17.c
new file mode 100644
index 0000000000..0ad246a1ae
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test17/test17.c
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test17.c
+**
+** Purpose: Test #17 for the vsprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vsprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoDoubleTest("foo %g", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %lg", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %hg", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %Lg", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %I64g", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %5g", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %-5g", val, "foo 2560 ", "foo 2560 ");
+ DoDoubleTest("foo %.1g", val, "foo 3e+003", "foo 3e+03");
+ DoDoubleTest("foo %.2g", val, "foo 2.6e+003", "foo 2.6e+03");
+ DoDoubleTest("foo %.12g", val, "foo 2560.001", "foo 2560.001");
+ DoDoubleTest("foo %06g", val, "foo 002560", "foo 002560");
+ DoDoubleTest("foo %#g", val, "foo 2560.00", "foo 2560.00");
+ DoDoubleTest("foo %+g", val, "foo +2560", "foo +2560");
+ DoDoubleTest("foo % g", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %+g", neg, "foo -2560", "foo -2560");
+ DoDoubleTest("foo % g", neg, "foo -2560", "foo -2560");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test17/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vsprintf/test17/testinfo.dat
new file mode 100644
index 0000000000..0dcd3c869e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test17/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vsprintf
+Name = Positive Test for vsprintf
+TYPE = DEFAULT
+EXE1 = test17
+Description
+= Tests the PAL implementation of the vsprintf function.
+= Tests vsprintf with compact format doubles (lowercase).
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test18/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test18/CMakeLists.txt
new file mode 100644
index 0000000000..2e8610d4a5
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test18/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test18.c
+)
+
+add_executable(paltest_vsprintf_test18
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsprintf_test18 coreclrpal)
+
+target_link_libraries(paltest_vsprintf_test18
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test18/test18.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test18/test18.c
new file mode 100644
index 0000000000..9a45305562
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test18/test18.c
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test18.c
+**
+** Purpose: Test #18 for the vsprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vsprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoDoubleTest("foo %G", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %lG", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %hG", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %LG", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %I64G", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %5G", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %-5G", val, "foo 2560 ", "foo 2560 ");
+ DoDoubleTest("foo %.1G", val, "foo 3E+003", "foo 3E+03");
+ DoDoubleTest("foo %.2G", val, "foo 2.6E+003", "foo 2.6E+03");
+ DoDoubleTest("foo %.12G", val, "foo 2560.001", "foo 2560.001");
+ DoDoubleTest("foo %06G", val, "foo 002560", "foo 002560");
+ DoDoubleTest("foo %#G", val, "foo 2560.00", "foo 2560.00");
+ DoDoubleTest("foo %+G", val, "foo +2560", "foo +2560");
+ DoDoubleTest("foo % G", val, "foo 2560", "foo 2560");
+ DoDoubleTest("foo %+G", neg, "foo -2560", "foo -2560");
+ DoDoubleTest("foo % G", neg, "foo -2560", "foo -2560");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test18/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vsprintf/test18/testinfo.dat
new file mode 100644
index 0000000000..43299968c3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test18/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vsprintf
+Name = Positive Test for vsprintf
+TYPE = DEFAULT
+EXE1 = test18
+Description
+= Tests the PAL implementation of the vsprintf function.
+= Tests vsprintf with compact format doubles (uppercase).
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test19/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test19/CMakeLists.txt
new file mode 100644
index 0000000000..92e39ab597
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test19/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test19.c
+)
+
+add_executable(paltest_vsprintf_test19
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsprintf_test19 coreclrpal)
+
+target_link_libraries(paltest_vsprintf_test19
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test19/test19.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test19/test19.c
new file mode 100644
index 0000000000..18590ed51b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test19/test19.c
@@ -0,0 +1,67 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test19.c
+**
+** Purpose: Test #19 for the vsprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vsprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+
+ DoArgumentPrecTest("%.*s", 2, "bar", "bar", "ba", "ba");
+ DoArgumentPrecTest("%.*S", 2, convert("bar"), "bar", "ba", "ba");
+ DoArgumentPrecTest("%.*c", 0, (void*)'a', "a", "a", "a");
+ DoArgumentPrecTest("%.*c", 4, (void*)'a', "a", "a", "a");
+ DoArgumentPrecTest("%.*C", 0, (void*)'a', "a", "a", "a");
+ DoArgumentPrecTest("%.*C", 4, (void*)'a', "a", "a", "a");
+ DoArgumentPrecTest("%.*d", 1, (void*)42, "42", "42", "42");
+ DoArgumentPrecTest("%.*d", 3, (void*)42, "42", "042", "042");
+ DoArgumentPrecTest("%.*i", 1, (void*)42, "42", "42", "42");
+ DoArgumentPrecTest("%.*i", 3, (void*)42, "42", "042", "042");
+ DoArgumentPrecTest("%.*o", 1, (void*)42, "42", "52", "52");
+ DoArgumentPrecTest("%.*o", 3, (void*)42, "42", "052", "052");
+ DoArgumentPrecTest("%.*u", 1, (void*)42, "42", "42", "42");
+ DoArgumentPrecTest("%.*u", 3, (void*)42, "42", "042", "042");
+ DoArgumentPrecTest("%.*x", 1, (void*)0x42, "0x42", "42", "42");
+ DoArgumentPrecTest("%.*x", 3, (void*)0x42, "0x42", "042", "042");
+ DoArgumentPrecTest("%.*X", 1, (void*)0x42, "0x42", "42", "42");
+ DoArgumentPrecTest("%.*X", 3, (void*)0x42, "0x42", "042", "042");
+
+
+ DoArgumentPrecDoubleTest("%.*e", 1, 2.01, "2.0e+000", "2.0e+00");
+ DoArgumentPrecDoubleTest("%.*e", 3, 2.01, "2.010e+000", "2.010e+00");
+ DoArgumentPrecDoubleTest("%.*E", 1, 2.01, "2.0E+000", "2.0E+00");
+ DoArgumentPrecDoubleTest("%.*E", 3, 2.01, "2.010E+000", "2.010E+00");
+ DoArgumentPrecDoubleTest("%.*f", 1, 2.01, "2.0", "2.0");
+ DoArgumentPrecDoubleTest("%.*f", 3, 2.01, "2.010", "2.010");
+ DoArgumentPrecDoubleTest("%.*g", 1, 256.01, "3e+002", "3e+02");
+ DoArgumentPrecDoubleTest("%.*g", 3, 256.01, "256", "256");
+ DoArgumentPrecDoubleTest("%.*g", 4, 256.01, "256", "256");
+ DoArgumentPrecDoubleTest("%.*g", 6, 256.01, "256.01", "256.01");
+ DoArgumentPrecDoubleTest("%.*G", 1, 256.01, "3E+002", "3E+02");
+ DoArgumentPrecDoubleTest("%.*G", 3, 256.01, "256", "256");
+ DoArgumentPrecDoubleTest("%.*G", 4, 256.01, "256", "256");
+ DoArgumentPrecDoubleTest("%.*G", 6, 256.01, "256.01", "256.01");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test19/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vsprintf/test19/testinfo.dat
new file mode 100644
index 0000000000..1e7bc7615e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test19/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vsprintf
+Name = Positive Test for vsprintf
+TYPE = DEFAULT
+EXE1 = test19
+Description
+= Tests the PAL implementation of the vsprintf function.
+= Tests vsprintf with argument specified precision.
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test2/CMakeLists.txt
new file mode 100644
index 0000000000..2308bc2573
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_vsprintf_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsprintf_test2 coreclrpal)
+
+target_link_libraries(paltest_vsprintf_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test2/test2.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test2/test2.c
new file mode 100644
index 0000000000..fbd4b41068
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test2/test2.c
@@ -0,0 +1,42 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test2.c
+**
+** Purpose: Test #2 for the vsprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vsprintf.h"
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoStrTest("foo %s", "bar", "foo bar");
+ DoStrTest("foo %hs", "bar", "foo bar");
+ DoWStrTest("foo %ls", convert("bar"), "foo bar");
+ DoWStrTest("foo %ws", convert("bar"), "foo bar");
+ DoStrTest("foo %Ls", "bar", "foo bar");
+ DoStrTest("foo %I64s", "bar", "foo bar");
+ DoStrTest("foo %5s", "bar", "foo bar");
+ DoStrTest("foo %.2s", "bar", "foo ba");
+ DoStrTest("foo %5.2s", "bar", "foo ba");
+ DoStrTest("foo %-5s", "bar", "foo bar ");
+ DoStrTest("foo %05s", "bar", "foo 00bar");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vsprintf/test2/testinfo.dat
new file mode 100644
index 0000000000..7958c1ad97
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test2/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vsprintf
+Name = Positive Test for vsprintf
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Tests the PAL implementation of the vsprintf function.
+= Tests vsprintf with strings.
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test3/CMakeLists.txt
new file mode 100644
index 0000000000..aef24171fc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_vsprintf_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsprintf_test3 coreclrpal)
+
+target_link_libraries(paltest_vsprintf_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test3/test3.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test3/test3.c
new file mode 100644
index 0000000000..742370ebe9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test3/test3.c
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test3.c
+**
+** Purpose: Test #3 for the vsprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vsprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoWStrTest("foo %S", convert("bar"), "foo bar");
+ DoStrTest("foo %hS", "bar", "foo bar");
+ DoWStrTest("foo %lS", convert("bar"), "foo bar");
+ DoWStrTest("foo %wS", convert("bar"), "foo bar");
+ DoWStrTest("foo %LS", convert("bar"), "foo bar");
+ DoWStrTest("foo %I64S", convert("bar"), "foo bar");
+ DoWStrTest("foo %5S", convert("bar"), "foo bar");
+ DoWStrTest("foo %.2S", convert("bar"), "foo ba");
+ DoWStrTest("foo %5.2S", convert("bar"), "foo ba");
+ DoWStrTest("foo %-5S", convert("bar"), "foo bar ");
+ DoWStrTest("foo %05S", convert("bar"), "foo 00bar");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vsprintf/test3/testinfo.dat
new file mode 100644
index 0000000000..afeb7da953
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test3/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vsprintf
+Name = Positive Test for vsprintf
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Tests the PAL implementation of the vsprintf function.
+= Tests vsprintf with wide strings.
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test4/CMakeLists.txt
new file mode 100644
index 0000000000..9570255475
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_vsprintf_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsprintf_test4 coreclrpal)
+
+target_link_libraries(paltest_vsprintf_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test4/test4.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test4/test4.c
new file mode 100644
index 0000000000..dc43a9e2c7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test4/test4.c
@@ -0,0 +1,72 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test4.c
+**
+** Purpose: Test #4 for the vsprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vsprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ void *ptr = (void*) 0x123456;
+ INT64 lptr = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+/*
+** Run only on 64 bit platforms
+*/
+#if defined(BIT64) && defined(PLATFORM_UNIX)
+ Trace("Testing for 64 Bit Platforms \n");
+ DoPointerTest("%p", NULL, "NULL", "0000000000000000");
+ DoPointerTest("%p", ptr, "pointer to 0x123456", "0000000000123456");
+ DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456");
+ DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456");
+ DoPointerTest("%-17p", ptr, "pointer to 0x123456", "0000000000123456 ");
+ DoPointerTest("%+p", ptr, "pointer to 0x123456", "0000000000123456");
+ DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X0000000000123456");
+ DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456");
+ DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456");
+ DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456");
+ DoI64DoubleTest("%I64p", lptr, "pointer to 0x1234567887654321",
+ "1234567887654321");
+#else
+ Trace("Testing for Non 64 Bit Platforms \n");
+ DoPointerTest("%p", NULL, "NULL", "00000000");
+ DoPointerTest("%p", ptr, "pointer to 0x123456", "00123456");
+ DoPointerTest("%9p", ptr, "pointer to 0x123456", " 00123456");
+ DoPointerTest("%09p", ptr, "pointer to 0x123456", " 00123456");
+ DoPointerTest("%-9p", ptr, "pointer to 0x123456", "00123456 ");
+ DoPointerTest("%+p", ptr, "pointer to 0x123456", "00123456");
+ DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X00123456");
+ DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456");
+ DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456");
+ DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456");
+ DoI64DoubleTest("%I64p", lptr, "pointer to 0x1234567887654321",
+ "1234567887654321");
+#endif
+
+
+
+
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test4/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vsprintf/test4/testinfo.dat
new file mode 100644
index 0000000000..7331c20375
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test4/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vsprintf
+Name = Positive Test for vsprintf
+TYPE = DEFAULT
+EXE1 = test4
+Description
+= Tests the PAL implementation of the vsprintf function.
+= Tests vsprintf with pointers.
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test5/CMakeLists.txt
new file mode 100644
index 0000000000..34a3e6243f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test5.c
+)
+
+add_executable(paltest_vsprintf_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsprintf_test5 coreclrpal)
+
+target_link_libraries(paltest_vsprintf_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test5/test5.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test5/test5.c
new file mode 100644
index 0000000000..e630d8863b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test5/test5.c
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test5.c
+**
+** Purpose: Test #5 for the vsprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vsprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoTest("foo %n bar", 4, "foo bar");
+ DoTest("foo %#n bar", 4, "foo bar");
+ DoTest("foo % n bar", 4, "foo bar");
+ DoTest("foo %+n bar", 4, "foo bar");
+ DoTest("foo %-n bar", 4, "foo bar");
+ DoTest("foo %0n bar", 4, "foo bar");
+ DoShortTest("foo %hn bar", 4, "foo bar");
+ DoTest("foo %ln bar", 4, "foo bar");
+ DoTest("foo %Ln bar", 4, "foo bar");
+ DoTest("foo %I64n bar", 4, "foo bar");
+ DoTest("foo %20.3n bar", 4, "foo bar");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test5/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vsprintf/test5/testinfo.dat
new file mode 100644
index 0000000000..81748f88b9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test5/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vsprintf
+Name = Positive Test for vsprintf
+TYPE = DEFAULT
+EXE1 = test5
+Description
+= Tests the PAL implementation of the vsprintf function.
+= Tests vsprintf with the count specifier.
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test6/CMakeLists.txt
new file mode 100644
index 0000000000..dccca0b2b7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test6.c
+)
+
+add_executable(paltest_vsprintf_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsprintf_test6 coreclrpal)
+
+target_link_libraries(paltest_vsprintf_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test6/test6.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test6/test6.c
new file mode 100644
index 0000000000..0d38a3a114
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test6/test6.c
@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test6.c
+**
+** Purpose: Test #6 for the vsprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vsprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR wc = (WCHAR) 'c';
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoCharTest("foo %c", 'b', "foo b");
+ DoCharTest("foo %hc", 'b', "foo b");
+ DoWCharTest("foo %lc", wc, "foo c");
+ DoCharTest("foo %Lc", 'b', "foo b");
+ DoCharTest("foo %I64c", 'b', "foo b");
+ DoCharTest("foo %5c", 'b', "foo b");
+ DoCharTest("foo %.0c", 'b', "foo b");
+ DoCharTest("foo %-5c", 'b', "foo b ");
+ DoCharTest("foo %05c", 'b', "foo 0000b");
+ DoCharTest("foo % c", 'b', "foo b");
+ DoCharTest("foo %#c", 'b', "foo b");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test6/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vsprintf/test6/testinfo.dat
new file mode 100644
index 0000000000..d76c5bf1a8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test6/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vsprintf
+Name = Positive Test for vsprintf
+TYPE = DEFAULT
+EXE1 = test6
+Description
+= Tests the PAL implementation of the vsprintf function.
+= Tests vsprintf with characters.
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test7/CMakeLists.txt
new file mode 100644
index 0000000000..7f18de056e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test7/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test7.c
+)
+
+add_executable(paltest_vsprintf_test7
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsprintf_test7 coreclrpal)
+
+target_link_libraries(paltest_vsprintf_test7
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test7/test7.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test7/test7.c
new file mode 100644
index 0000000000..c9f87d4343
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test7/test7.c
@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test7.c
+**
+** Purpose: Test #7 for the vsprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vsprintf.h"
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR wb = (WCHAR) 'b';
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoWCharTest("foo %c", wb, "foo b");
+ DoWCharTest("foo %hc", wb, "foo b");
+ DoCharTest("foo %lc", 'c', "foo c");
+ DoWCharTest("foo %Lc", wb, "foo b");
+ DoWCharTest("foo %I64c", wb, "foo b");
+ DoWCharTest("foo %5c", wb, "foo b");
+ DoWCharTest("foo %.0c", wb, "foo b");
+ DoWCharTest("foo %-5c", wb, "foo b ");
+ DoWCharTest("foo %05c", wb, "foo 0000b");
+ DoWCharTest("foo % c", wb, "foo b");
+ DoWCharTest("foo %#c", wb, "foo b");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test7/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vsprintf/test7/testinfo.dat
new file mode 100644
index 0000000000..facf60d6aa
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test7/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vsprintf
+Name = Positive Test for vsprintf
+TYPE = DEFAULT
+EXE1 = test7
+Description
+= Tests the PAL implementation of the vsprintf function.
+= Tests vsprintf with wide characters.
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test8/CMakeLists.txt
new file mode 100644
index 0000000000..34c92e1045
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test8/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test8.c
+)
+
+add_executable(paltest_vsprintf_test8
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsprintf_test8 coreclrpal)
+
+target_link_libraries(paltest_vsprintf_test8
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test8/test8.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test8/test8.c
new file mode 100644
index 0000000000..e741d1da8b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test8/test8.c
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test8.c
+**
+** Purpose: Test #8 for the vsprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vsprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoNumTest("foo %d", pos, "foo 42");
+ DoNumTest("foo %ld", 0xFFFF, "foo 65535");
+ DoNumTest("foo %hd", 0xFFFF, "foo -1");
+ DoNumTest("foo %Ld", pos, "foo 42");
+ DoI64Test("foo %I64d", l, "42", "foo 42");
+ DoNumTest("foo %3d", pos, "foo 42");
+ DoNumTest("foo %-3d", pos, "foo 42 ");
+ DoNumTest("foo %.1d", pos, "foo 42");
+ DoNumTest("foo %.3d", pos, "foo 042");
+ DoNumTest("foo %03d", pos, "foo 042");
+ DoNumTest("foo %#d", pos, "foo 42");
+ DoNumTest("foo %+d", pos, "foo +42");
+ DoNumTest("foo % d", pos, "foo 42");
+ DoNumTest("foo %+d", neg, "foo -42");
+ DoNumTest("foo % d", neg, "foo -42");
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test8/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vsprintf/test8/testinfo.dat
new file mode 100644
index 0000000000..05f84f4999
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test8/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vsprintf
+Name = Positive Test for vsprintf
+TYPE = DEFAULT
+EXE1 = test8
+Description
+= Tests the PAL implementation of the vsprintf function.
+= Tests vsprintf with decimal numbers.
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test9/CMakeLists.txt
new file mode 100644
index 0000000000..1fe177de95
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test9/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test9.c
+)
+
+add_executable(paltest_vsprintf_test9
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vsprintf_test9 coreclrpal)
+
+target_link_libraries(paltest_vsprintf_test9
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test9/test9.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test9/test9.c
new file mode 100644
index 0000000000..e1f7c84195
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test9/test9.c
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test9.c
+**
+** Purpose: Test #9 for the vsprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vsprintf.h"
+
+/*
+ * Notes: memcmp is used, as is strlen.
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return(FAIL);
+ }
+
+ DoNumTest("foo %i", pos, "foo 42");
+ DoNumTest("foo %li", 0xFFFF, "foo 65535");
+ DoNumTest("foo %hi", 0xFFFF, "foo -1");
+ DoNumTest("foo %Li", pos, "foo 42");
+ DoI64Test("foo %I64i", l, "42", "foo 42");
+ DoNumTest("foo %3i", pos, "foo 42");
+ DoNumTest("foo %-3i", pos, "foo 42 ");
+ DoNumTest("foo %.1i", pos, "foo 42");
+ DoNumTest("foo %.3i", pos, "foo 042");
+ DoNumTest("foo %03i", pos, "foo 042");
+ DoNumTest("foo %#i", pos, "foo 42");
+ DoNumTest("foo %+i", pos, "foo +42");
+ DoNumTest("foo % i", pos, "foo 42");
+ DoNumTest("foo %+i", neg, "foo -42");
+ DoNumTest("foo % i", neg, "foo -42");
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test9/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vsprintf/test9/testinfo.dat
new file mode 100644
index 0000000000..3bc0057c96
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test9/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vsprintf
+Name = Positive Test for vsprintf
+TYPE = DEFAULT
+EXE1 = test9
+Description
+= Tests the PAL implementation of the vsprintf function.
+= Tests vsprintf with integer numbers.
+= This test is modeled after _snprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/vsprintf.h b/src/pal/tests/palsuite/c_runtime/vsprintf/vsprintf.h
new file mode 100644
index 0000000000..10648d896f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vsprintf/vsprintf.h
@@ -0,0 +1,218 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: vsprintf.h
+**
+** Purpose: Helper functions for the vsprintf tests.
+**
+**
+**===================================================================*/
+#ifndef __VSPRINTF_H__
+#define __VSPRINTF_H__
+
+/* These functions leaks memory like crazy. C'est la vie. */
+int testvsp(char* buf, const char* format, ...)
+{
+ int retVal;
+ va_list arglist;
+
+ va_start(arglist, format);
+ retVal = vsprintf(buf, format, arglist);
+ va_end(arglist);
+
+ return (retVal);
+}
+
+void DoStrTest(char *formatstr, char* param, char *checkstr)
+{
+ char buf[256] = { 0 };
+
+ testvsp(buf, formatstr, param);
+ if (memcmp(buf, checkstr, strlen(buf) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert string \"%s\" into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ param, formatstr, checkstr, buf);
+ }
+}
+
+void DoWStrTest(char *formatstr, WCHAR* param, char *checkstr)
+{
+ char buf[256] = { 0 };
+
+ testvsp(buf, formatstr, param);
+ if (memcmp(buf, checkstr, strlen(buf) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert wide string \"%s\" into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ convertC(param), formatstr, checkstr, buf);
+ }
+}
+
+
+void DoCharTest(char *formatstr, char param, char *checkstr)
+{
+ char buf[256] = { 0 };
+
+ testvsp(buf, formatstr, param);
+ if (memcmp(buf, checkstr, strlen(buf) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert char \'%c\' (%d) into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ param, param, formatstr, checkstr, buf);
+ }
+}
+
+void DoWCharTest(char *formatstr, WCHAR param, char *checkstr)
+{
+ char buf[256] = { 0 };
+
+ testvsp(buf, formatstr, param);
+ if (memcmp(buf, checkstr, strlen(buf) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert wide char \'%c\' (%d) into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ (char)param, param, formatstr, checkstr, buf);
+ }
+}
+
+void DoNumTest(char *formatstr, int value, char *checkstr)
+{
+ char buf[256] = { 0 };
+
+ testvsp(buf, formatstr, value);
+ if (memcmp(buf, checkstr, strlen(buf) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %#x into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ value, formatstr, checkstr, buf);
+ }
+}
+
+void DoI64Test(char *formatstr, INT64 value, char *valuestr, char *checkstr)
+{
+ char buf[256] = { 0 };
+
+ testvsp(buf, formatstr, value);
+ if (memcmp(buf, checkstr, strlen(buf) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %s into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ valuestr, formatstr, checkstr, buf);
+ }
+}
+void DoDoubleTest(char *formatstr, double value, char *checkstr1, char
+*checkstr2)
+{
+ char buf[256] = { 0 };
+
+ testvsp(buf, formatstr, value);
+ if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 &&
+ memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %f into \"%s\"\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n",
+ value, formatstr, checkstr1, checkstr2, buf);
+ }
+}
+/*FROM TEST 9*/
+void DoArgumentPrecTest(char *formatstr, int precision, void *param,
+ char *paramstr, char *checkstr1, char *checkstr2)
+{
+ char buf[256];
+
+ testvsp(buf, formatstr, precision, param);
+ if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 &&
+ memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n", paramstr, formatstr,
+ precision, checkstr1, checkstr2, buf);
+ }
+
+}
+
+void DoArgumentPrecDoubleTest(char *formatstr, int precision, double param,
+ char *checkstr1, char *checkstr2)
+{
+ char buf[256];
+
+ testvsp(buf, formatstr, precision, param);
+ if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 &&
+ memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n", param, formatstr,
+ precision, checkstr1, checkstr2, buf);
+ }
+}
+/*FROM TEST4*/
+void DoPointerTest(char *formatstr, void* param, char* paramstr,
+ char *checkstr1)
+{
+ char buf[256] = { 0 };
+
+ testvsp(buf, formatstr, param);
+ if (memcmp(buf, checkstr1, strlen(checkstr1) + 1))
+ {
+ Fail("ERROR: failed to insert %s into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ paramstr, formatstr, checkstr1, buf);
+ }
+}
+
+void DoI64DoubleTest(char *formatstr, INT64 value, char *valuestr,
+ char *checkstr1)
+{
+ char buf[256] = { 0 };
+
+ testvsp(buf, formatstr, value);
+ if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0)
+ {
+ Fail("ERROR: failed to insert %s into \"%s\"\n"
+ "Expected \"%s\", got \"%s\".\n",
+ valuestr, formatstr, checkstr1, buf);
+ }
+}
+
+void DoTest(char *formatstr, int param, char *checkstr)
+{
+ char buf[256] = { 0 };
+ int n = -1;
+
+ testvsp(buf, formatstr, &n);
+
+ if (n != param)
+ {
+ Fail("ERROR: Expected count parameter to resolve to %d, got %X\n",
+ param, n);
+ }
+ if (memcmp(buf, checkstr, strlen(buf) + 1) != 0)
+ {
+ Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf);
+ }
+}
+
+void DoShortTest(char *formatstr, int param, char *checkstr)
+{
+ char buf[256] = { 0 };
+ short int n = -1;
+
+ testvsp(buf, formatstr, &n);
+
+ if (n != param)
+ {
+ Fail("ERROR: Expected count parameter to resolve to %d, got %X\n",
+ param, n);
+ }
+ if (memcmp(buf, checkstr, strlen(buf) + 1) != 0)
+ {
+ Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf);
+ }
+}
+
+#endif
+
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/CMakeLists.txt
new file mode 100644
index 0000000000..cafb9536b0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/CMakeLists.txt
@@ -0,0 +1,22 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test10)
+add_subdirectory(test11)
+add_subdirectory(test12)
+add_subdirectory(test13)
+add_subdirectory(test14)
+add_subdirectory(test15)
+add_subdirectory(test16)
+add_subdirectory(test17)
+add_subdirectory(test18)
+add_subdirectory(test19)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+add_subdirectory(test7)
+add_subdirectory(test8)
+add_subdirectory(test9)
+
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..97fbeb4e28
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_vswprintf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vswprintf_test1 coreclrpal)
+
+target_link_libraries(paltest_vswprintf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test1/test1.c
new file mode 100644
index 0000000000..d386ce104f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test1/test1.c
@@ -0,0 +1,41 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test #1 for the vswprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vswprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR *checkstr = NULL;
+ WCHAR buf[256] = { 0 };
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ checkstr = convert("hello world");
+ testvswp(buf, checkstr);
+
+ if (memcmp(checkstr, buf, wcslen(checkstr)*2+2) != 0)
+ {
+ Fail("ERROR: Expected \"%s\", got \"%s\"\n",
+ convertC(checkstr), convertC(buf));
+ }
+
+ free(checkstr);
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vswprintf/test1/testinfo.dat
new file mode 100644
index 0000000000..6161190d4c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vswprintf
+Name = Positive Test for vswprintf
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests the PAL implementation of the vswprintf function.
+= General test to see if vswprintf works correctly.
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test10/CMakeLists.txt
new file mode 100644
index 0000000000..06c11f68ca
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test10/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test10.c
+)
+
+add_executable(paltest_vswprintf_test10
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vswprintf_test10 coreclrpal)
+
+target_link_libraries(paltest_vswprintf_test10
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test10/test10.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test10/test10.c
new file mode 100644
index 0000000000..7f316e28f6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test10/test10.c
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test10.c
+**
+** Purpose: Test #10 for the vswprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vswprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoNumTest(convert("foo %o"), pos, convert("foo 52"));
+ DoNumTest(convert("foo %lo"), 0xFFFF, convert("foo 177777"));
+ DoNumTest(convert("foo %ho"), 0xFFFF, convert("foo 177777"));
+ DoNumTest(convert("foo %Lo"), pos, convert("foo 52"));
+ DoI64NumTest(convert("foo %I64o"), l, "42", convert("foo 52"));
+ DoNumTest(convert("foo %3o"), pos, convert("foo 52"));
+ DoNumTest(convert("foo %-3o"), pos, convert("foo 52 "));
+ DoNumTest(convert("foo %.1o"), pos, convert("foo 52"));
+ DoNumTest(convert("foo %.3o"), pos, convert("foo 052"));
+ DoNumTest(convert("foo %03o"), pos, convert("foo 052"));
+ DoNumTest(convert("foo %#o"), pos, convert("foo 052"));
+ DoNumTest(convert("foo %+o"), pos, convert("foo 52"));
+ DoNumTest(convert("foo % o"), pos, convert("foo 52"));
+ DoNumTest(convert("foo %+o"), neg, convert("foo 37777777726"));
+ DoNumTest(convert("foo % o"), neg, convert("foo 37777777726"));
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test10/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vswprintf/test10/testinfo.dat
new file mode 100644
index 0000000000..81fbce5e4d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test10/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vswprintf
+Name = Positive Test for vswprintf
+TYPE = DEFAULT
+EXE1 = test10
+Description
+= Tests the PAL implementation of the vswprintf function.
+= Tests vswprintf with octal numbers.
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test11/CMakeLists.txt
new file mode 100644
index 0000000000..5237ba4e1d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test11/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test11.c
+)
+
+add_executable(paltest_vswprintf_test11
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vswprintf_test11 coreclrpal)
+
+target_link_libraries(paltest_vswprintf_test11
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test11/test11.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test11/test11.c
new file mode 100644
index 0000000000..608069f829
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test11/test11.c
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test11.c
+**
+** Purpose: Test #11 for the vswprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vswprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoNumTest(convert("foo %u"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %lu"), 0xFFFF, convert("foo 65535"));
+ DoNumTest(convert("foo %hu"), 0xFFFF, convert("foo 65535"));
+ DoNumTest(convert("foo %Lu"), pos, convert("foo 42"));
+ DoI64NumTest(convert("foo %I64u"), l, "42", convert("foo 42"));
+ DoNumTest(convert("foo %3u"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %-3u"), pos, convert("foo 42 "));
+ DoNumTest(convert("foo %.1u"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %.3u"), pos, convert("foo 042"));
+ DoNumTest(convert("foo %03u"), pos, convert("foo 042"));
+ DoNumTest(convert("foo %#u"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %+u"), pos, convert("foo 42"));
+ DoNumTest(convert("foo % u"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %+u"), neg, convert("foo 4294967254"));
+ DoNumTest(convert("foo % u"), neg, convert("foo 4294967254"));
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test11/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vswprintf/test11/testinfo.dat
new file mode 100644
index 0000000000..13585cc94e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test11/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vswprintf
+Name = Positive Test for vswprintf
+TYPE = DEFAULT
+EXE1 = test11
+Description
+= Tests the PAL implementation of the vswprintf function.
+= Tests vswprintf with unsigned numbers.
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test12/CMakeLists.txt
new file mode 100644
index 0000000000..26199c3dcc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test12/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test12.c
+)
+
+add_executable(paltest_vswprintf_test12
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vswprintf_test12 coreclrpal)
+
+target_link_libraries(paltest_vswprintf_test12
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test12/test12.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test12/test12.c
new file mode 100644
index 0000000000..36b203853a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test12/test12.c
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test12.c
+**
+** Purpose: Test #12 for the vswprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vswprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 0x1234ab;
+ INT64 l = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoNumTest(convert("foo %x"), pos, convert("foo 1234ab"));
+ DoNumTest(convert("foo %lx"), pos, convert("foo 1234ab"));
+ DoNumTest(convert("foo %hx"), pos, convert("foo 34ab"));
+ DoNumTest(convert("foo %Lx"), pos, convert("foo 1234ab"));
+ DoI64NumTest(convert("foo %I64x"), l, "0x1234567887654321",
+ convert("foo 1234567887654321"));
+ DoNumTest(convert("foo %7x"), pos, convert("foo 1234ab"));
+ DoNumTest(convert("foo %-7x"), pos, convert("foo 1234ab "));
+ DoNumTest(convert("foo %.1x"), pos, convert("foo 1234ab"));
+ DoNumTest(convert("foo %.7x"), pos, convert("foo 01234ab"));
+ DoNumTest(convert("foo %07x"), pos, convert("foo 01234ab"));
+ DoNumTest(convert("foo %#x"), pos, convert("foo 0x1234ab"));
+ DoNumTest(convert("foo %+x"), pos, convert("foo 1234ab"));
+ DoNumTest(convert("foo % x"), pos, convert("foo 1234ab"));
+ DoNumTest(convert("foo %+x"), neg, convert("foo ffffffd6"));
+ DoNumTest(convert("foo % x"), neg, convert("foo ffffffd6"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test12/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vswprintf/test12/testinfo.dat
new file mode 100644
index 0000000000..d42e9a1801
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test12/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vswprintf
+Name = Positive Test for vswprintf
+TYPE = DEFAULT
+EXE1 = test12
+Description
+= Tests the PAL implementation of the vswprintf function.
+= Tests vswprintf with hex numbers (lowercase).
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test13/CMakeLists.txt
new file mode 100644
index 0000000000..d0acd98d64
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test13/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test13.c
+)
+
+add_executable(paltest_vswprintf_test13
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vswprintf_test13 coreclrpal)
+
+target_link_libraries(paltest_vswprintf_test13
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test13/test13.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test13/test13.c
new file mode 100644
index 0000000000..63dc36a960
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test13/test13.c
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test13.c
+**
+** Purpose: Test #13 for the vswprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vswprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 0x1234ab;
+ INT64 l = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoNumTest(convert("foo %X"), pos, convert("foo 1234AB"));
+ DoNumTest(convert("foo %lX"), pos, convert("foo 1234AB"));
+ DoNumTest(convert("foo %hX"), pos, convert("foo 34AB"));
+ DoNumTest(convert("foo %LX"), pos, convert("foo 1234AB"));
+ DoI64NumTest(convert("foo %I64X"), l, "0x1234567887654321",
+ convert("foo 1234567887654321"));
+ DoNumTest(convert("foo %7X"), pos, convert("foo 1234AB"));
+ DoNumTest(convert("foo %-7X"), pos, convert("foo 1234AB "));
+ DoNumTest(convert("foo %.1X"), pos, convert("foo 1234AB"));
+ DoNumTest(convert("foo %.7X"), pos, convert("foo 01234AB"));
+ DoNumTest(convert("foo %07X"), pos, convert("foo 01234AB"));
+ DoNumTest(convert("foo %#X"), pos, convert("foo 0X1234AB"));
+ DoNumTest(convert("foo %+X"), pos, convert("foo 1234AB"));
+ DoNumTest(convert("foo % X"), pos, convert("foo 1234AB"));
+ DoNumTest(convert("foo %+X"), neg, convert("foo FFFFFFD6"));
+ DoNumTest(convert("foo % X"), neg, convert("foo FFFFFFD6"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test13/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vswprintf/test13/testinfo.dat
new file mode 100644
index 0000000000..f7c6756e30
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test13/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vswprintf
+Name = Positive Test for vswprintf
+TYPE = DEFAULT
+EXE1 = test13
+Description
+= Tests the PAL implementation of the vswprintf function.
+= Tests vswprintf with hex numbers (uppercase).
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test14/CMakeLists.txt
new file mode 100644
index 0000000000..06c12674a4
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test14/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test14.c
+)
+
+add_executable(paltest_vswprintf_test14
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vswprintf_test14 coreclrpal)
+
+target_link_libraries(paltest_vswprintf_test14
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test14/test14.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test14/test14.c
new file mode 100644
index 0000000000..bb4ab16a54
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test14/test14.c
@@ -0,0 +1,61 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test14.c
+**
+** Purpose: Test #14 for the vswprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vswprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 256.0;
+ double neg = -256.0;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoDoubleTest(convert("foo %e"), val, convert("foo 2.560000e+002"),
+ convert("foo 2.560000e+02"));
+ DoDoubleTest(convert("foo %le"), val, convert("foo 2.560000e+002"),
+ convert("foo 2.560000e+02"));
+ DoDoubleTest(convert("foo %he"), val, convert("foo 2.560000e+002"),
+ convert("foo 2.560000e+02"));
+ DoDoubleTest(convert("foo %Le"), val, convert("foo 2.560000e+002"),
+ convert("foo 2.560000e+02"));
+ DoDoubleTest(convert("foo %I64e"), val, convert("foo 2.560000e+002"),
+ convert("foo 2.560000e+02"));
+ DoDoubleTest(convert("foo %14e"), val, convert("foo 2.560000e+002"),
+ convert("foo 2.560000e+02"));
+ DoDoubleTest(convert("foo %-14e"), val, convert("foo 2.560000e+002 "),
+ convert("foo 2.560000e+02 "));
+ DoDoubleTest(convert("foo %.1e"), val, convert("foo 2.6e+002"),
+ convert("foo 2.6e+02"));
+ DoDoubleTest(convert("foo %.8e"), val, convert("foo 2.56000000e+002"),
+ convert("foo 2.56000000e+02"));
+ DoDoubleTest(convert("foo %014e"), val, convert("foo 02.560000e+002"),
+ convert("foo 002.560000e+02"));
+ DoDoubleTest(convert("foo %#e"), val, convert("foo 2.560000e+002"),
+ convert("foo 2.560000e+02"));
+ DoDoubleTest(convert("foo %+e"), val, convert("foo +2.560000e+002"),
+ convert("foo +2.560000e+02"));
+ DoDoubleTest(convert("foo % e"), val, convert("foo 2.560000e+002"),
+ convert("foo 2.560000e+02"));
+ DoDoubleTest(convert("foo %+e"), neg, convert("foo -2.560000e+002"),
+ convert("foo -2.560000e+02"));
+ DoDoubleTest(convert("foo % e"), neg, convert("foo -2.560000e+002"),
+ convert("foo -2.560000e+02"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test14/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vswprintf/test14/testinfo.dat
new file mode 100644
index 0000000000..e9615f906a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test14/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vswprintf
+Name = Positive Test for vswprintf
+TYPE = DEFAULT
+EXE1 = test14
+Description
+= Tests the PAL implementation of the vswprintf function.
+= Tests vswprintf with exponential format doubles (lowercase).
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test15/CMakeLists.txt
new file mode 100644
index 0000000000..05dc41b0d8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test15/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test15.c
+)
+
+add_executable(paltest_vswprintf_test15
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vswprintf_test15 coreclrpal)
+
+target_link_libraries(paltest_vswprintf_test15
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test15/test15.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test15/test15.c
new file mode 100644
index 0000000000..6296220c4e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test15/test15.c
@@ -0,0 +1,62 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test15.c
+**
+** Purpose: Test #15 for the vswprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vswprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 256.0;
+ double neg = -256.0;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoDoubleTest(convert("foo %E"), val, convert("foo 2.560000E+002"),
+ convert("foo 2.560000E+02"));
+ DoDoubleTest(convert("foo %lE"), val, convert("foo 2.560000E+002"),
+ convert("foo 2.560000E+02"));
+ DoDoubleTest(convert("foo %hE"), val, convert("foo 2.560000E+002"),
+ convert("foo 2.560000E+02"));
+ DoDoubleTest(convert("foo %LE"), val, convert("foo 2.560000E+002"),
+ convert("foo 2.560000E+02"));
+ DoDoubleTest(convert("foo %I64E"), val, convert("foo 2.560000E+002"),
+ convert("foo 2.560000E+02"));
+ DoDoubleTest(convert("foo %14E"), val, convert("foo 2.560000E+002"),
+ convert("foo 2.560000E+02"));
+ DoDoubleTest(convert("foo %-14E"), val, convert("foo 2.560000E+002 "),
+ convert("foo 2.560000E+02 "));
+ DoDoubleTest(convert("foo %.1E"), val, convert("foo 2.6E+002"),
+ convert("foo 2.6E+02"));
+ DoDoubleTest(convert("foo %.8E"), val, convert("foo 2.56000000E+002"),
+ convert("foo 2.56000000E+02"));
+ DoDoubleTest(convert("foo %014E"), val, convert("foo 02.560000E+002"),
+ convert("foo 002.560000E+02"));
+ DoDoubleTest(convert("foo %#E"), val, convert("foo 2.560000E+002"),
+ convert("foo 2.560000E+02"));
+ DoDoubleTest(convert("foo %+E"), val, convert("foo +2.560000E+002"),
+ convert("foo +2.560000E+02"));
+ DoDoubleTest(convert("foo % E"), val, convert("foo 2.560000E+002"),
+ convert("foo 2.560000E+02"));
+ DoDoubleTest(convert("foo %+E"), neg, convert("foo -2.560000E+002"),
+ convert("foo -2.560000E+02"));
+ DoDoubleTest(convert("foo % E"), neg, convert("foo -2.560000E+002"),
+ convert("foo -2.560000E+002"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test15/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vswprintf/test15/testinfo.dat
new file mode 100644
index 0000000000..24ff03b11a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test15/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vswprintf
+Name = Positive Test for vswprintf
+TYPE = DEFAULT
+EXE1 = test15
+Description
+= Tests the PAL implementation of the vswprintf function.
+= Tests vswprintf with exponential format doubles (uppercase).
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test16/CMakeLists.txt
new file mode 100644
index 0000000000..3c42755043
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test16/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test16.c
+)
+
+add_executable(paltest_vswprintf_test16
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vswprintf_test16 coreclrpal)
+
+target_link_libraries(paltest_vswprintf_test16
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test16/test16.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test16/test16.c
new file mode 100644
index 0000000000..3a2059a491
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test16/test16.c
@@ -0,0 +1,61 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test16.c
+**
+** Purpose: Test #16 for the vswprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vswprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoDoubleTest(convert("foo %f"), val, convert("foo 2560.001000"),
+ convert("foo 2560.001000"));
+ DoDoubleTest(convert("foo %lf"), val, convert("foo 2560.001000"),
+ convert("foo 2560.001000"));
+ DoDoubleTest(convert("foo %hf"), val, convert("foo 2560.001000"),
+ convert("foo 2560.001000"));
+ DoDoubleTest(convert("foo %Lf"), val, convert("foo 2560.001000"),
+ convert("foo 2560.001000"));
+ DoDoubleTest(convert("foo %I64f"), val, convert("foo 2560.001000"),
+ convert("foo 2560.001000"));
+ DoDoubleTest(convert("foo %12f"), val, convert("foo 2560.001000"),
+ convert("foo 2560.001000"));
+ DoDoubleTest(convert("foo %-12f"), val, convert("foo 2560.001000 "),
+ convert("foo 2560.001000 "));
+ DoDoubleTest(convert("foo %.1f"), val, convert("foo 2560.0"),
+ convert("foo 2560.0"));
+ DoDoubleTest(convert("foo %.8f"), val, convert("foo 2560.00100000"),
+ convert("foo 2560.00100000"));
+ DoDoubleTest(convert("foo %012f"), val, convert("foo 02560.001000"),
+ convert("foo 02560.001000"));
+ DoDoubleTest(convert("foo %#f"), val, convert("foo 2560.001000"),
+ convert("foo 2560.001000"));
+ DoDoubleTest(convert("foo %+f"), val, convert("foo +2560.001000"),
+ convert("foo +2560.001000"));
+ DoDoubleTest(convert("foo % f"), val, convert("foo 2560.001000"),
+ convert("foo 2560.001000"));
+ DoDoubleTest(convert("foo %+f"), neg, convert("foo -2560.001000"),
+ convert("foo -2560.001000"));
+ DoDoubleTest(convert("foo % f"), neg, convert("foo -2560.001000"),
+ convert("foo -2560.001000"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test16/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vswprintf/test16/testinfo.dat
new file mode 100644
index 0000000000..6dc45f4c78
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test16/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vswprintf
+Name = Positive Test for vswprintf
+TYPE = DEFAULT
+EXE1 = test16
+Description
+= Tests the PAL implementation of the vswprintf function.
+= Tests vswprintf with decimal point format doubles.
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test17/CMakeLists.txt
new file mode 100644
index 0000000000..b94c466d5f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test17/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test17.c
+)
+
+add_executable(paltest_vswprintf_test17
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vswprintf_test17 coreclrpal)
+
+target_link_libraries(paltest_vswprintf_test17
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test17/test17.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test17/test17.c
new file mode 100644
index 0000000000..95e3bd9995
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test17/test17.c
@@ -0,0 +1,63 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test17.c
+**
+** Purpose: Test #17 for the vswprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vswprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoDoubleTest(convert("foo %g"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %lg"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %hg"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %Lg"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %I64g"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %5g"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %-5g"), val, convert("foo 2560 "),
+ convert("foo 2560 "));
+ DoDoubleTest(convert("foo %.1g"), val, convert("foo 3e+003"),
+ convert("foo 3e+03"));
+ DoDoubleTest(convert("foo %.2g"), val, convert("foo 2.6e+003"),
+ convert("foo 2.6e+03"));
+ DoDoubleTest(convert("foo %.12g"), val, convert("foo 2560.001"),
+ convert("foo 2560.001"));
+ DoDoubleTest(convert("foo %06g"), val, convert("foo 002560"),
+ convert("foo 002560"));
+ DoDoubleTest(convert("foo %#g"), val, convert("foo 2560.00"),
+ convert("foo 2560.00"));
+ DoDoubleTest(convert("foo %+g"), val, convert("foo +2560"),
+ convert("foo +2560"));
+ DoDoubleTest(convert("foo % g"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %+g"), neg, convert("foo -2560"),
+ convert("foo -2560"));
+ DoDoubleTest(convert("foo % g"), neg, convert("foo -2560"),
+ convert("foo -2560"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test17/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vswprintf/test17/testinfo.dat
new file mode 100644
index 0000000000..815e57ddf5
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test17/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vswprintf
+Name = Positive Test for vswprintf
+TYPE = DEFAULT
+EXE1 = test17
+Description
+= Tests the PAL implementation of the vswprintf function.
+= Tests vswprintf with compact format doubles (lowercase).
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test18/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test18/CMakeLists.txt
new file mode 100644
index 0000000000..57cc8ccb03
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test18/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test18.c
+)
+
+add_executable(paltest_vswprintf_test18
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vswprintf_test18 coreclrpal)
+
+target_link_libraries(paltest_vswprintf_test18
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test18/test18.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test18/test18.c
new file mode 100644
index 0000000000..ae7ae4c44b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test18/test18.c
@@ -0,0 +1,63 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test18.c
+**
+** Purpose: Test #18 for the vswprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vswprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ double val = 2560.001;
+ double neg = -2560.001;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoDoubleTest(convert("foo %G"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %lG"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %hG"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %LG"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %I64G"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %5G"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %-5G"), val, convert("foo 2560 "),
+ convert("foo 2560 "));
+ DoDoubleTest(convert("foo %.1G"), val, convert("foo 3E+003"),
+ convert("foo 3E+03"));
+ DoDoubleTest(convert("foo %.2G"), val, convert("foo 2.6E+003"),
+ convert("foo 2.6E+03"));
+ DoDoubleTest(convert("foo %.12G"), val, convert("foo 2560.001"),
+ convert("foo 2560.001"));
+ DoDoubleTest(convert("foo %06G"), val, convert("foo 002560"),
+ convert("foo 002560"));
+ DoDoubleTest(convert("foo %#G"), val, convert("foo 2560.00"),
+ convert("foo 2560.00"));
+ DoDoubleTest(convert("foo %+G"), val, convert("foo +2560"),
+ convert("foo +2560"));
+ DoDoubleTest(convert("foo % G"), val, convert("foo 2560"),
+ convert("foo 2560"));
+ DoDoubleTest(convert("foo %+G"), neg, convert("foo -2560"),
+ convert("foo -2560"));
+ DoDoubleTest(convert("foo % G"), neg, convert("foo -2560"),
+ convert("foo -2560"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test18/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vswprintf/test18/testinfo.dat
new file mode 100644
index 0000000000..b5165999a6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test18/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vswprintf
+Name = Positive Test for vswprintf
+TYPE = DEFAULT
+EXE1 = test18
+Description
+= Tests the PAL implementation of the vswprintf function.
+= Tests vswprintf with compact format doubles (uppercase).
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test19/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test19/CMakeLists.txt
new file mode 100644
index 0000000000..2187b58727
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test19/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test19.c
+)
+
+add_executable(paltest_vswprintf_test19
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vswprintf_test19 coreclrpal)
+
+target_link_libraries(paltest_vswprintf_test19
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test19/test19.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test19/test19.c
new file mode 100644
index 0000000000..c00185be6d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test19/test19.c
@@ -0,0 +1,137 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test18.c
+**
+** Purpose: Test #18 for the vswprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vswprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+#define DOTEST(a,b,c,d,e) DoTest(a,b,(void*)c,d,e)
+
+void DoArgumentPrecTest(WCHAR *formatstr, int precision, void *param,
+ WCHAR *paramstr, WCHAR *checkstr1, WCHAR *checkstr2)
+{
+ WCHAR buf[256];
+
+ testvswp(buf, formatstr, precision, param);
+ if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0 &&
+ memcmp(buf, checkstr2, wcslen(checkstr2) + 2) != 0)
+ {
+ Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n",
+ paramstr,
+ convertC(formatstr),
+ precision,
+ convertC(checkstr1),
+ convertC(checkstr2),
+ convertC(buf));
+ }
+}
+void DoArgumentPrecDoubleTest(WCHAR *formatstr, int precision, double param,
+ WCHAR *checkstr1, WCHAR *checkstr2)
+{
+ WCHAR buf[256];
+
+ testvswp(buf, formatstr, precision, param);
+ if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0 &&
+ memcmp(buf, checkstr2, wcslen(checkstr2) + 2) != 0)
+ {
+ Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n",
+ param, convertC(formatstr),
+ precision,
+ convertC(checkstr1),
+ convertC(checkstr2),
+ convertC(buf));
+ }
+}
+
+/*
+ * Uses memcmp & wcslen
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoArgumentPrecTest(convert("%.*s"), 2, convert("bar"), convert("bar"),
+ convert("ba"), convert("ba"));
+ DoArgumentPrecTest(convert("%.*c"), 0, (void*)'a', convert("a"),
+ convert("a"), convert("a"));
+ DoArgumentPrecTest(convert("%.*c"), 4, (void*)'a', convert("a"),
+ convert("a"), convert("a"));
+ DoArgumentPrecTest(convert("%.*C"), 0, (void*)'a', convert("a"),
+ convert("a"), convert("a"));
+ DoArgumentPrecTest(convert("%.*C"), 4, (void*)'a', convert("a"),
+ convert("a"), convert("a"));
+ DoArgumentPrecTest(convert("%.*d"), 1, (void*)42, convert("42"),
+ convert("42"), convert("42"));
+ DoArgumentPrecTest(convert("%.*d"), 3, (void*)42, convert("42"),
+ convert("042"), convert("042"));
+ DoArgumentPrecTest(convert("%.*i"), 1, (void*)42, convert("42"),
+ convert("42"), convert("42"));
+ DoArgumentPrecTest(convert("%.*i"), 3, (void*)42, convert("42"),
+ convert("042"), convert("042"));
+ DoArgumentPrecTest(convert("%.*o"), 1, (void*)42, convert("42"),
+ convert("52"), convert("52"));
+ DoArgumentPrecTest(convert("%.*o"), 3, (void*)42, convert("42"),
+ convert("052"), convert("052"));
+ DoArgumentPrecTest(convert("%.*u"), 1, (void*)42, convert("42"),
+ convert("42"), convert("42"));
+ DoArgumentPrecTest(convert("%.*u"), 3, (void*)42, convert("42"),
+ convert("042"), convert("042"));
+ DoArgumentPrecTest(convert("%.*x"), 1, (void*)0x42, convert("0x42"),
+ convert("42"), convert("42"));
+ DoArgumentPrecTest(convert("%.*x"), 3, (void*)0x42, convert("0x42"),
+ convert("042"), convert("042"));
+ DoArgumentPrecTest(convert("%.*X"), 1, (void*)0x42, convert("0x42"),
+ convert("42"), convert("42"));
+ DoArgumentPrecTest(convert("%.*X"), 3, (void*)0x42, convert("0x42"),
+ convert("042"), convert("042"));
+
+
+ DoArgumentPrecDoubleTest(convert("%.*e"), 1, 2.01, convert("2.0e+000"),
+ convert("2.0e+00"));
+ DoArgumentPrecDoubleTest(convert("%.*e"), 3, 2.01, convert("2.010e+000"),
+ convert("2.010e+00"));
+ DoArgumentPrecDoubleTest(convert("%.*E"), 1, 2.01, convert("2.0E+000"),
+ convert("2.0E+00"));
+ DoArgumentPrecDoubleTest(convert("%.*E"), 3, 2.01, convert("2.010E+000"),
+ convert("2.010E+00"));
+ DoArgumentPrecDoubleTest(convert("%.*f"), 1, 2.01, convert("2.0"),
+ convert("2.0"));
+ DoArgumentPrecDoubleTest(convert("%.*f"), 3, 2.01, convert("2.010"),
+ convert("2.010"));
+ DoArgumentPrecDoubleTest(convert("%.*g"), 1, 256.01, convert("3e+002"),
+ convert("3e+02"));
+ DoArgumentPrecDoubleTest(convert("%.*g"), 3, 256.01, convert("256"),
+ convert("256"));
+ DoArgumentPrecDoubleTest(convert("%.*g"), 4, 256.01, convert("256"),
+ convert("256"));
+ DoArgumentPrecDoubleTest(convert("%.*g"), 6, 256.01, convert("256.01"),
+ convert("256.01"));
+ DoArgumentPrecDoubleTest(convert("%.*G"), 1, 256.01, convert("3E+002"),
+ convert("3E+02"));
+ DoArgumentPrecDoubleTest(convert("%.*G"), 3, 256.01, convert("256"),
+ convert("256"));
+ DoArgumentPrecDoubleTest(convert("%.*G"), 4, 256.01, convert("256"),
+ convert("256"));
+ DoArgumentPrecDoubleTest(convert("%.*G"), 6, 256.01, convert("256.01"),
+ convert("256.01"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test19/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vswprintf/test19/testinfo.dat
new file mode 100644
index 0000000000..ccc08cd7ba
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test19/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vswprintf
+Name = Positive Test for vswprintf
+TYPE = DEFAULT
+EXE1 = test19
+Description
+= Tests the PAL implementation of the vswprintf function.
+= Tests vswprintf with argument specified precision.
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test2/CMakeLists.txt
new file mode 100644
index 0000000000..295448cb0c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_vswprintf_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vswprintf_test2 coreclrpal)
+
+target_link_libraries(paltest_vswprintf_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test2/test2.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test2/test2.c
new file mode 100644
index 0000000000..491d99f0cf
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test2/test2.c
@@ -0,0 +1,40 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test2.c
+**
+** Purpose: Test #2 for the vswprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vswprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoWStrTest(convert("foo %s"), convert("bar"), convert("foo bar"));
+ DoStrTest(convert("foo %hs"), "bar", convert("foo bar"));
+ DoWStrTest(convert("foo %ls"), convert("bar"), convert("foo bar"));
+ DoWStrTest(convert("foo %ws"), convert("bar"), convert("foo bar"));
+ DoWStrTest(convert("foo %Ls"), convert("bar"), convert("foo bar"));
+ DoWStrTest(convert("foo %I64s"), convert("bar"), convert("foo bar"));
+ DoWStrTest(convert("foo %5s"), convert("bar"), convert("foo bar"));
+ DoWStrTest(convert("foo %.2s"), convert("bar"), convert("foo ba"));
+ DoWStrTest(convert("foo %5.2s"), convert("bar"), convert("foo ba"));
+ DoWStrTest(convert("foo %-5s"), convert("bar"), convert("foo bar "));
+ DoWStrTest(convert("foo %05s"), convert("bar"), convert("foo 00bar"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vswprintf/test2/testinfo.dat
new file mode 100644
index 0000000000..d6d7c3e8bd
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test2/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vswprintf
+Name = Positive Test for vswprintf
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Tests the PAL implementation of the vswprintf function.
+= Tests vswprintf with strings.
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test3/CMakeLists.txt
new file mode 100644
index 0000000000..1fb6272ae7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_vswprintf_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vswprintf_test3 coreclrpal)
+
+target_link_libraries(paltest_vswprintf_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test3/test3.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test3/test3.c
new file mode 100644
index 0000000000..1eb0b65ebe
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test3/test3.c
@@ -0,0 +1,40 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test3.c
+**
+** Purpose: Test #3 for the vswprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vswprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoStrTest(convert("foo %S"), "bar", convert("foo bar"));
+ DoStrTest(convert("foo %hS"), "bar", convert("foo bar"));
+ DoWStrTest(convert("foo %lS"), convert("bar"), convert("foo bar"));
+ DoWStrTest(convert("foo %wS"), convert("bar"), convert("foo bar"));
+ DoStrTest(convert("foo %LS"), "bar", convert("foo bar"));
+ DoStrTest(convert("foo %I64S"), "bar", convert("foo bar"));
+ DoStrTest(convert("foo %5S"), "bar", convert("foo bar"));
+ DoStrTest(convert("foo %.2S"), "bar", convert("foo ba"));
+ DoStrTest(convert("foo %5.2S"), "bar", convert("foo ba"));
+ DoStrTest(convert("foo %-5S"), "bar", convert("foo bar "));
+ DoStrTest(convert("foo %05S"), "bar", convert("foo 00bar"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vswprintf/test3/testinfo.dat
new file mode 100644
index 0000000000..8fb9dc8060
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test3/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vswprintf
+Name = Positive Test for vswprintf
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Tests the PAL implementation of the vswprintf function.
+= Tests vswprintf with wide strings.
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test4/CMakeLists.txt
new file mode 100644
index 0000000000..cae0806e03
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_vswprintf_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vswprintf_test4 coreclrpal)
+
+target_link_libraries(paltest_vswprintf_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test4/test4.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test4/test4.c
new file mode 100644
index 0000000000..5c9047b5a7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test4/test4.c
@@ -0,0 +1,118 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test4.c
+**
+** Purpose: Test #4 for the vswprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vswprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+static void DoPointerTest(WCHAR *formatstr, void* param, WCHAR* paramstr,
+ WCHAR *checkstr1)
+{
+ WCHAR buf[256] = { 0 };
+
+ testvswp(buf, formatstr, param);
+ if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0)
+
+ {
+ Fail("ERROR: failed to insert pointer to %#p into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ paramstr,
+ convertC(formatstr),
+ convertC(checkstr1),
+ convertC(buf));
+ }
+}
+
+static void DoI64DoubleTest(WCHAR *formatstr, INT64 value, WCHAR *valuestr,
+ WCHAR *checkstr1)
+{
+ WCHAR buf[256] = { 0 };
+
+ testvswp(buf, formatstr, value);
+ if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0)
+ {
+ Fail("ERROR: failed to insert %s into \"%s\"\n"
+ "Expected \"%s\", got \"%s\".\n",
+ value,
+ convertC(formatstr),
+ convertC(checkstr1),
+ convertC(buf));
+ }
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ void *ptr = (void*) 0x123456;
+ INT64 lptr = I64(0x1234567887654321);
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+/*
+** Run only on 64 bit platforms
+*/
+#if defined(BIT64) && defined(PLATFORM_UNIX)
+ Trace("Testing for 64 Bit Platforms \n");
+ DoPointerTest(convert("%p"), NULL, convert("NULL"), convert("0000000000000000"));
+ DoPointerTest(convert("%p"), ptr, convert("pointer to 0x123456"),
+ convert("0000000000123456"));
+ DoPointerTest(convert("%17p"), ptr, convert("pointer to 0x123456"),
+ convert(" 0000000000123456"));
+ DoPointerTest(convert("%17p"), ptr, convert("pointer to 0x123456"),
+ convert(" 0000000000123456"));
+ DoPointerTest(convert("%-17p"), ptr, convert("pointer to 0x123456"),
+ convert("0000000000123456 "));
+ DoPointerTest(convert("%+p"), ptr, convert("pointer to 0x123456"),
+ convert("0000000000123456"));
+ DoPointerTest(convert("%#p"), ptr, convert("pointer to 0x123456"),
+ convert("0X0000000000123456"));
+ DoPointerTest(convert("%lp"), ptr, convert("pointer to 0x123456"),
+ convert("00123456"));
+ DoPointerTest(convert("%hp"), ptr, convert("pointer to 0x123456"),
+ convert("00003456"));
+ DoPointerTest(convert("%Lp"), ptr, convert("pointer to 0x123456"),
+ convert("00123456"));
+ DoI64DoubleTest(convert("%I64p"), lptr,
+ convert("pointer to 0x1234567887654321"), convert("1234567887654321"));
+
+#else
+ Trace("Testing for Non 64 Bit Platforms \n");
+ DoPointerTest(convert("%p"), NULL, convert("NULL"), convert("00000000"));
+ DoPointerTest(convert("%p"), ptr, convert("pointer to 0x123456"),
+ convert("00123456"));
+ DoPointerTest(convert("%9p"), ptr, convert("pointer to 0x123456"),
+ convert(" 00123456"));
+ DoPointerTest(convert("%09p"), ptr, convert("pointer to 0x123456"),
+ convert(" 00123456"));
+ DoPointerTest(convert("%-9p"), ptr, convert("pointer to 0x123456"),
+ convert("00123456 "));
+ DoPointerTest(convert("%+p"), ptr, convert("pointer to 0x123456"),
+ convert("00123456"));
+ DoPointerTest(convert("%#p"), ptr, convert("pointer to 0x123456"),
+ convert("0X00123456"));
+ DoPointerTest(convert("%lp"), ptr, convert("pointer to 0x123456"),
+ convert("00123456"));
+ DoPointerTest(convert("%hp"), ptr, convert("pointer to 0x123456"),
+ convert("00003456"));
+ DoPointerTest(convert("%Lp"), ptr, convert("pointer to 0x123456"),
+ convert("00123456"));
+ DoI64DoubleTest(convert("%I64p"), lptr,
+ convert("pointer to 0x1234567887654321"), convert("1234567887654321"));
+
+#endif
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test4/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vswprintf/test4/testinfo.dat
new file mode 100644
index 0000000000..435f9703cd
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test4/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vswprintf
+Name = Positive Test for vswprintf
+TYPE = DEFAULT
+EXE1 = test4
+Description
+= Tests the PAL implementation of the vswprintf function.
+= Tests vswprintf with pointers.
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test5/CMakeLists.txt
new file mode 100644
index 0000000000..7c480455ed
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test5.c
+)
+
+add_executable(paltest_vswprintf_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vswprintf_test5 coreclrpal)
+
+target_link_libraries(paltest_vswprintf_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test5/test5.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test5/test5.c
new file mode 100644
index 0000000000..42146c8be7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test5/test5.c
@@ -0,0 +1,79 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test5.c
+**
+** Purpose: Test #5 for the vswprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vswprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+static void DoTest(WCHAR *formatstr, int param, WCHAR *checkstr)
+{
+ WCHAR buf[256] = { 0 };
+ int n = -1;
+
+ testvswp(buf, formatstr, &n);
+
+ if (n != param)
+ {
+ Fail("ERROR: Expected count parameter to resolve to %d, got %d\n",
+ param, n);
+ }
+
+ if (memcmp(buf, checkstr, wcslen(buf)*2 + 2) != 0)
+ {
+ Fail("ERROR: Expected \"%s\" got \"%s\".\n",
+ convertC(checkstr), convertC(buf));
+ }
+}
+
+static void DoShortTest(WCHAR *formatstr, int param, WCHAR *checkstr)
+{
+ WCHAR buf[256] = { 0 };
+ short int n = -1;
+
+ testvswp(buf, formatstr, &n);
+
+ if (n != param)
+ {
+ Fail("ERROR: Expected count parameter to resolve to %d, got %d\n",
+ param, n);
+ }
+
+ if (memcmp(buf, checkstr, wcslen(buf)*2 + 2) != 0)
+ {
+ Fail("ERROR: Expected \"%s\" got \"%s\".\n",
+ convertC(checkstr), convertC(buf));
+ }
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoTest(convert("foo %n bar"), 4, convert("foo bar"));
+ DoTest(convert("foo %#n bar"), 4, convert("foo bar"));
+ DoTest(convert("foo % n bar"), 4, convert("foo bar"));
+ DoTest(convert("foo %+n bar"), 4, convert("foo bar"));
+ DoTest(convert("foo %-n bar"), 4, convert("foo bar"));
+ DoTest(convert("foo %0n bar"), 4, convert("foo bar"));
+ DoShortTest(convert("foo %hn bar"), 4, convert("foo bar"));
+ DoTest(convert("foo %ln bar"), 4, convert("foo bar"));
+ DoTest(convert("foo %Ln bar"), 4, convert("foo bar"));
+ DoTest(convert("foo %I64n bar"), 4, convert("foo bar"));
+ DoTest(convert("foo %20.3n bar"), 4, convert("foo bar"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test5/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vswprintf/test5/testinfo.dat
new file mode 100644
index 0000000000..17ca0fd33b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test5/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vswprintf
+Name = Positive Test for vswprintf
+TYPE = DEFAULT
+EXE1 = test5
+Description
+= Tests the PAL implementation of the vswprintf function.
+= Tests vswprintf with the count specifier.
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test6/CMakeLists.txt
new file mode 100644
index 0000000000..d7de580853
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test6.c
+)
+
+add_executable(paltest_vswprintf_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vswprintf_test6 coreclrpal)
+
+target_link_libraries(paltest_vswprintf_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test6/test6.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test6/test6.c
new file mode 100644
index 0000000000..51e99267a1
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test6/test6.c
@@ -0,0 +1,41 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test6.c
+**
+** Purpose: Test #6 for the vswprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vswprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR wc = (WCHAR) 'c';
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoWCharTest(convert("foo %c"), wc, convert("foo c"));
+ DoCharTest(convert("foo %hc"), 'b', convert("foo b"));
+ DoWCharTest(convert("foo %lc"), wc, convert("foo c"));
+ DoWCharTest(convert("foo %Lc"), wc, convert("foo c"));
+ DoWCharTest(convert("foo %I64c"), wc, convert("foo c"));
+ DoWCharTest(convert("foo %5c"), wc, convert("foo c"));
+ DoWCharTest(convert("foo %.0c"), wc, convert("foo c"));
+ DoWCharTest(convert("foo %-5c"), wc, convert("foo c "));
+ DoWCharTest(convert("foo %05c"), wc, convert("foo 0000c"));
+ DoWCharTest(convert("foo % c"), wc, convert("foo c"));
+ DoWCharTest(convert("foo %#c"), wc, convert("foo c"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test6/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vswprintf/test6/testinfo.dat
new file mode 100644
index 0000000000..f4ad2e954e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test6/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vswprintf
+Name = Positive Test for vswprintf
+TYPE = DEFAULT
+EXE1 = test6
+Description
+= Tests the PAL implementation of the vswprintf function.
+= Tests vswprintf with characters.
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test7/CMakeLists.txt
new file mode 100644
index 0000000000..eb07ee2cae
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test7/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test7.c
+)
+
+add_executable(paltest_vswprintf_test7
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vswprintf_test7 coreclrpal)
+
+target_link_libraries(paltest_vswprintf_test7
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test7/test7.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test7/test7.c
new file mode 100644
index 0000000000..6037cb0fe7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test7/test7.c
@@ -0,0 +1,41 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test7.c
+**
+** Purpose: Test #7 for the vswprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vswprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR wc = (WCHAR) 'c';
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoCharTest(convert("foo %C"), 'b', convert("foo b"));
+ DoWCharTest(convert("foo %hC"), wc, convert("foo c"));
+ DoCharTest(convert("foo %lC"), 'b', convert("foo b"));
+ DoCharTest(convert("foo %LC"), 'b', convert("foo b"));
+ DoCharTest(convert("foo %I64C"), 'b', convert("foo b"));
+ DoCharTest(convert("foo %5C"), 'b', convert("foo b"));
+ DoCharTest(convert("foo %.0C"), 'b', convert("foo b"));
+ DoCharTest(convert("foo %-5C"), 'b', convert("foo b "));
+ DoCharTest(convert("foo %05C"), 'b', convert("foo 0000b"));
+ DoCharTest(convert("foo % C"), 'b', convert("foo b"));
+ DoCharTest(convert("foo %#C"), 'b', convert("foo b"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test7/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vswprintf/test7/testinfo.dat
new file mode 100644
index 0000000000..ed0a474f7e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test7/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vswprintf
+Name = Positive Test for vswprintf
+TYPE = DEFAULT
+EXE1 = test7
+Description
+= Tests the PAL implementation of the vswprintf function.
+= Tests vswprintf with wide characters.
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test8/CMakeLists.txt
new file mode 100644
index 0000000000..ed35ea8dd0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test8/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test8.c
+)
+
+add_executable(paltest_vswprintf_test8
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vswprintf_test8 coreclrpal)
+
+target_link_libraries(paltest_vswprintf_test8
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test8/test8.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test8/test8.c
new file mode 100644
index 0000000000..baba524650
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test8/test8.c
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test8.c
+**
+** Purpose: Test #8 for the vswprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vswprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoNumTest(convert("foo %d"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %ld"), 0xFFFF, convert("foo 65535"));
+ DoNumTest(convert("foo %hd"), 0xFFFF, convert("foo -1"));
+ DoNumTest(convert("foo %Ld"), pos, convert("foo 42"));
+ DoI64NumTest(convert("foo %I64d"), l, "42", convert("foo 42"));
+ DoNumTest(convert("foo %3d"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %-3d"), pos, convert("foo 42 "));
+ DoNumTest(convert("foo %.1d"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %.3d"), pos, convert("foo 042"));
+ DoNumTest(convert("foo %03d"), pos, convert("foo 042"));
+ DoNumTest(convert("foo %#d"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %+d"), pos, convert("foo +42"));
+ DoNumTest(convert("foo % d"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %+d"), neg, convert("foo -42"));
+ DoNumTest(convert("foo % d"), neg, convert("foo -42"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test8/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vswprintf/test8/testinfo.dat
new file mode 100644
index 0000000000..4c5114bd27
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test8/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vswprintf
+Name = Positive Test for vswprintf
+TYPE = DEFAULT
+EXE1 = test8
+Description
+= Tests the PAL implementation of the vswprintf function.
+= Tests vswprintf with decimal numbers.
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test9/CMakeLists.txt
new file mode 100644
index 0000000000..7098da31d0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test9/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test9.c
+)
+
+add_executable(paltest_vswprintf_test9
+ ${SOURCES}
+)
+
+add_dependencies(paltest_vswprintf_test9 coreclrpal)
+
+target_link_libraries(paltest_vswprintf_test9
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test9/test9.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test9/test9.c
new file mode 100644
index 0000000000..5de004f5ed
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test9/test9.c
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test9.c
+**
+** Purpose: Test #9 for the vswprintf function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+#include "../vswprintf.h"
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with wcslen */
+
+int __cdecl main(int argc, char *argv[])
+{
+ int neg = -42;
+ int pos = 42;
+ INT64 l = 42;
+
+ if (PAL_Initialize(argc, argv) != 0)
+ return(FAIL);
+
+ DoNumTest(convert("foo %i"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %li"), 0xFFFF, convert("foo 65535"));
+ DoNumTest(convert("foo %hi"), 0xFFFF, convert("foo -1"));
+ DoNumTest(convert("foo %Li"), pos, convert("foo 42"));
+ DoI64NumTest(convert("foo %I64i"), l, "42", convert("foo 42"));
+ DoNumTest(convert("foo %3i"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %-3i"), pos, convert("foo 42 "));
+ DoNumTest(convert("foo %.1i"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %.3i"), pos, convert("foo 042"));
+ DoNumTest(convert("foo %03i"), pos, convert("foo 042"));
+ DoNumTest(convert("foo %#i"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %+i"), pos, convert("foo +42"));
+ DoNumTest(convert("foo % i"), pos, convert("foo 42"));
+ DoNumTest(convert("foo %+i"), neg, convert("foo -42"));
+ DoNumTest(convert("foo % i"), neg, convert("foo -42"));
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test9/testinfo.dat b/src/pal/tests/palsuite/c_runtime/vswprintf/test9/testinfo.dat
new file mode 100644
index 0000000000..3c2bcdf3e5
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test9/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = vswprintf
+Name = Positive Test for vswprintf
+TYPE = DEFAULT
+EXE1 = test9
+Description
+= Tests the PAL implementation of the vswprintf function.
+= Tests vswprintf with integer numbers
+= This test is modeled after _snwprintf.
diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/vswprintf.h b/src/pal/tests/palsuite/c_runtime/vswprintf/vswprintf.h
new file mode 100644
index 0000000000..a79c9bb7a9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/vswprintf/vswprintf.h
@@ -0,0 +1,132 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: vswprintf.h
+**
+** Purpose: Containts common testing functions for vswprintf
+**
+**
+**==========================================================================*/
+
+#ifndef __vswprintf_H__
+#define __vswprintf_H__
+
+/* These functions leaks memory like crazy. C'est la vie. */
+int testvswp(wchar_t* buf, const wchar_t* format, ...)
+{
+ int retVal = 0;
+ va_list arglist;
+
+ va_start(arglist, format);
+ retVal = vswprintf(buf, format, arglist);
+ va_end(arglist);
+
+ return( retVal);
+}
+
+void DoWStrTest(WCHAR *formatstr, WCHAR *param, WCHAR *checkstr)
+{
+ WCHAR buf[256] = { 0 };
+
+ testvswp(buf, formatstr, param);
+
+ if (memcmp(buf, checkstr, wcslen(buf) * 2 + 2) != 0)
+ {
+ Fail("ERROR: failed to insert wide string \"%s\" into \"%s\".\n"
+ "Expected \"%s\", got \"%s\".\n",
+ convertC(param), convertC(formatstr),
+ convertC(checkstr), convertC(buf));
+ }
+}
+
+void DoStrTest(WCHAR *formatstr, char *param, WCHAR *checkstr)
+{
+ WCHAR buf[256] = { 0 };
+
+ testvswp(buf, formatstr, param);
+
+ if (memcmp(buf, checkstr, wcslen(buf) * 2 + 2) != 0)
+ {
+ Fail("ERROR: failed to insert wide string \"%s\" into \"%s\".\n"
+ "Expected \"%s\", got \"%s\".\n",
+ param, convertC(formatstr), convertC(checkstr),
+ convertC(buf));
+ }
+}
+
+void DoCharTest(WCHAR *formatstr, char param, WCHAR *checkstr)
+{
+ WCHAR buf[256] = { 0 };
+
+ testvswp(buf, formatstr, param);
+ if (memcmp(buf, checkstr, wcslen(buf)*2 + 2) != 0)
+ {
+ Fail("ERROR: failed to insert char \'%c\' (%d) into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ param, param, convertC(formatstr), convertC(checkstr),
+ convertC(buf));
+ }
+}
+
+void DoWCharTest(WCHAR *formatstr, WCHAR param, WCHAR *checkstr)
+{
+ WCHAR buf[256] = { 0 };
+
+ testvswp(buf, formatstr, param);
+ if (memcmp(buf, checkstr, wcslen(buf)*2 + 2) != 0)
+ {
+ Fail("ERROR: failed to insert wide char \'%c\' (%d) into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n",
+ (char) param, param, convertC(formatstr), convertC(checkstr),
+ convertC(buf));
+ }
+}
+
+void DoNumTest(WCHAR *formatstr, int value, WCHAR*checkstr)
+{
+ WCHAR buf[256] = { 0 };
+
+ testvswp(buf, formatstr, value);
+ if (memcmp(buf, checkstr, wcslen(buf)* 2 + 2) != 0)
+ {
+ Fail("ERROR: failed to insert %#x into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n", value, convertC(formatstr),
+ convertC(checkstr), convertC(buf));
+ }
+}
+
+void DoI64NumTest(WCHAR *formatstr, INT64 value, char *valuestr, WCHAR*checkstr)
+{
+ WCHAR buf[256] = { 0 };
+
+ testvswp(buf, formatstr, value);
+ if (memcmp(buf, checkstr, wcslen(buf)* 2 + 2) != 0)
+ {
+ Fail("ERROR: failed to insert %s into \"%s\"\n"
+ "Expected \"%s\" got \"%s\".\n", valuestr, convertC(formatstr),
+ convertC(checkstr), convertC(buf));
+ }
+}
+void DoDoubleTest(WCHAR *formatstr, double value, WCHAR *checkstr1, WCHAR
+ *checkstr2)
+{
+ WCHAR buf[256] = { 0 };
+
+ testvswp(buf, formatstr, value);
+ if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0 &&
+ memcmp(buf, checkstr2, wcslen(checkstr2) + 2) != 0)
+ {
+ Fail("ERROR: failed to insert %f into \"%s\"\n"
+ "Expected \"%s\" or \"%s\", got \"%s\".\n",
+ value,
+ convertC(formatstr),
+ convertC(checkstr1),
+ convertC(checkstr2),
+ convertC(buf));
+ }
+}
+
+#endif
diff --git a/src/pal/tests/palsuite/c_runtime/wcscat/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcscat/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcscat/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/wcscat/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcscat/test1/CMakeLists.txt
new file mode 100644
index 0000000000..34dfee01bd
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcscat/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_wcscat_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wcscat_test1 coreclrpal)
+
+target_link_libraries(paltest_wcscat_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/wcscat/test1/test1.c b/src/pal/tests/palsuite/c_runtime/wcscat/test1/test1.c
new file mode 100644
index 0000000000..789eebf5a3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcscat/test1/test1.c
@@ -0,0 +1,71 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose:
+** Test to that wcscat correctly concatanates wide strings, including placing
+** null pointers.
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+
+/*
+ * Notes: uses memcmp and the (pal) sprintf
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR dest[80];
+ WCHAR test[] = {'f','o','o',' ','b','a','r',' ','b','a','z',0};
+ WCHAR str1[] = {'f','o','o',' ',0};
+ WCHAR str2[] = {'b','a','r',' ',0};
+ WCHAR str3[] = {'b','a','z',0};
+ WCHAR *ptr;
+ char buffer[256];
+
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ dest[0] = 0;
+
+ ptr = wcscat(dest, str1);
+ if (ptr != dest)
+ {
+ Fail("ERROR: Expected wcscat to return ptr to %p, got %p", dest, ptr);
+ }
+
+ ptr = wcscat(dest, str2);
+ if (ptr != dest)
+ {
+ Fail("ERROR: Expected wcscat to return ptr to %p, got %p", dest, ptr);
+ }
+
+ ptr = wcscat(dest, str3);
+ if (ptr != dest)
+ {
+ Fail("ERROR: Expected wcscat to return ptr to %p, got %p", dest, ptr);
+ }
+
+ if (memcmp(dest, test, sizeof(test)) != 0)
+ {
+ sprintf(buffer, "%S", dest);
+ Fail("ERROR: Expected wcscat to give \"%s\", got \"%s\"\n",
+ "foo bar baz", buffer);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/wcscat/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/wcscat/test1/testinfo.dat
new file mode 100644
index 0000000000..878c446251
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcscat/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = wcscat
+Name = Positive Test for wcscat
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Test to that wcscat correctly concatanates wide strings, including placing
+= null pointers
diff --git a/src/pal/tests/palsuite/c_runtime/wcschr/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcschr/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcschr/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/wcschr/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcschr/test1/CMakeLists.txt
new file mode 100644
index 0000000000..542d70b7e6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcschr/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_wcschr_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wcschr_test1 coreclrpal)
+
+target_link_libraries(paltest_wcschr_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/wcschr/test1/test1.c b/src/pal/tests/palsuite/c_runtime/wcschr/test1/test1.c
new file mode 100644
index 0000000000..a4963672f8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcschr/test1/test1.c
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose:
+** Tests that wcschr correctly finds the first occurrence of a character in a
+** string
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR str[] = {'f','o','o',' ','b','a','r',' ',0};
+ WCHAR c = (WCHAR)' ';
+ WCHAR c2 = (WCHAR)'$';
+ WCHAR *ptr;
+
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ ptr = wcschr(str, c);
+ if (ptr != str + 3)
+ {
+ Fail("ERROR: expected wcschr to return pointer to %p, got %p\n",
+ str + 3, ptr);
+ }
+
+ ptr = wcschr(str, c2);
+ if (ptr != NULL)
+ {
+ Fail("ERROR: expected wcschr to return pointer to %p, got %p\n",
+ NULL, ptr);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/wcschr/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/wcschr/test1/testinfo.dat
new file mode 100644
index 0000000000..40a166d615
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcschr/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = wcschr
+Name = Positive Test for wcschr
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests that wcschr correctly finds the first occurrence of a character in a
+= string.
diff --git a/src/pal/tests/palsuite/c_runtime/wcscmp/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcscmp/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcscmp/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/wcscmp/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcscmp/test1/CMakeLists.txt
new file mode 100644
index 0000000000..009e48e1ba
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcscmp/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_wcscmp_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wcscmp_test1 coreclrpal)
+
+target_link_libraries(paltest_wcscmp_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/wcscmp/test1/test1.c b/src/pal/tests/palsuite/c_runtime/wcscmp/test1/test1.c
new file mode 100644
index 0000000000..1c38dd6d58
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcscmp/test1/test1.c
@@ -0,0 +1,57 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests that wcscmp correctly compares two strings with
+** case sensitivity.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR str1[] = {'f','o','o',0};
+ WCHAR str2[] = {'f','o','o','x',0};
+ WCHAR str3[] = {'f','O','o',0};
+ char cstr1[] = "foo";
+ char cstr2[] = "foox";
+ char cstr3[] = "fOo";
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+
+ if (wcscmp(str1, str2) >= 0)
+ {
+ Fail("ERROR: wcscmp(\"%s\", \"%s\") returned >= 0\n", cstr1, cstr2);
+ }
+
+ if (wcscmp(str2, str1) <= 0)
+ {
+ Fail("ERROR: wcscmp(\"%s\", \"%s\") returned <= 0\n", cstr2, cstr1);
+ }
+
+ if (wcscmp(str1, str3) <= 0)
+ {
+ Fail("ERROR: wcscmp(\"%s\", \"%s\") returned >= 0\n", cstr1, cstr3);
+ }
+
+ if (wcscmp(str3, str1) >= 0)
+ {
+ Fail("ERROR: wcscmp(\"%s\", \"%s\") returned >= 0\n", cstr3, cstr1);
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/wcscmp/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/wcscmp/test1/testinfo.dat
new file mode 100644
index 0000000000..0fe696fbe7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcscmp/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = wcscmp
+Name = Test #1 for wcscmp
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests that wcscmp correctly compares two strings with case sensitivity.
diff --git a/src/pal/tests/palsuite/c_runtime/wcscpy/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcscpy/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcscpy/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/wcscpy/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcscpy/test1/CMakeLists.txt
new file mode 100644
index 0000000000..5f21b829ee
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcscpy/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_wcscpy_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wcscpy_test1 coreclrpal)
+
+target_link_libraries(paltest_wcscpy_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/wcscpy/test1/test1.c b/src/pal/tests/palsuite/c_runtime/wcscpy/test1/test1.c
new file mode 100644
index 0000000000..4e45c86516
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcscpy/test1/test1.c
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests that wcscpy correctly copies a null-terminated wide string.
+**
+**
+**==========================================================================*/
+
+
+#include <palsuite.h>
+
+/*
+ * Notes: uses memcmp and sprintf.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR str[] = {'f','o','o',0,'b','a','r',0};
+ WCHAR dest[80];
+ WCHAR result[] = {'f','o','o',0};
+ WCHAR *ret;
+ char buffer[256];
+
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ ret = wcscpy(dest, str);
+
+ if (ret != dest || memcmp(dest, result, sizeof(result)) != 0)
+ {
+ sprintf(buffer, "%S", dest);
+ Fail("Expected wcscpy to give \"%s\" with a return value of %p, got \"%s\" "
+ "with a return value of %p.\n", "foo", dest, buffer, ret);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/wcscpy/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/wcscpy/test1/testinfo.dat
new file mode 100644
index 0000000000..ef9c58ecc9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcscpy/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = wcscpy
+Name = Positive Test for wcscpy
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests that wcscpy correctly copies a null-terminated wide string.
diff --git a/src/pal/tests/palsuite/c_runtime/wcslen/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcslen/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcslen/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/wcslen/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcslen/test1/CMakeLists.txt
new file mode 100644
index 0000000000..de0f1c22d3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcslen/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_wcslen_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wcslen_test1 coreclrpal)
+
+target_link_libraries(paltest_wcslen_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/wcslen/test1/test1.c b/src/pal/tests/palsuite/c_runtime/wcslen/test1/test1.c
new file mode 100644
index 0000000000..17d0327628
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcslen/test1/test1.c
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose:
+** Tests that wcslen correctly returns the length (in wide characters,
+** not byte) of a wide string
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR str1[] = {'f','o','o',' ',0};
+ WCHAR str2[] = {0};
+ int ret;
+
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ ret = wcslen(str1);
+ if (ret != 4)
+ {
+ Fail("ERROR: Expected wcslen of \"foo \" to be 4, got %d\n", ret);
+ }
+
+ ret = wcslen(str2);
+ if (ret != 0)
+ {
+ Fail("ERROR: Expected wcslen of \"\" to be 0, got %d\n", ret);
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/wcslen/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/wcslen/test1/testinfo.dat
new file mode 100644
index 0000000000..cfdef4819d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcslen/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = wcslen
+Name = Positive Test for wcslen
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests that wcslen correctly returns the length (in wide characters, not byte)
+= of a wide string
diff --git a/src/pal/tests/palsuite/c_runtime/wcsncat/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcsncat/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcsncat/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/wcsncat/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcsncat/test1/CMakeLists.txt
new file mode 100644
index 0000000000..12c286a43a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcsncat/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_wcsncat_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wcsncat_test1 coreclrpal)
+
+target_link_libraries(paltest_wcsncat_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/wcsncat/test1/test1.c b/src/pal/tests/palsuite/c_runtime/wcsncat/test1/test1.c
new file mode 100644
index 0000000000..0cd5c3e15a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcsncat/test1/test1.c
@@ -0,0 +1,77 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose:
+** Tests that wcsncat correctly appends wide strings, making sure it handles
+** count argument correctly (appending no more than count characters, always
+** placing a null, and padding the string if necessary).
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR dest[80];
+ WCHAR test[] = {'f','o','o',' ','b','a','r','b','a','z',0};
+ WCHAR str1[] = {'f','o','o',' ',0};
+ WCHAR str2[] = {'b','a','r',' ',0};
+ WCHAR str3[] = {'b','a','z',0};
+ WCHAR *ptr;
+ int i;
+
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ dest[0] = 0;
+ for (i=1; i<80; i++)
+ {
+ dest[i] = (WCHAR)'x';
+ }
+
+ ptr = wcsncat(dest, str1, wcslen(str1));
+ if (ptr != dest)
+ {
+ Fail("ERROR: Expected wcsncat to return ptr to %p, got %p", dest, ptr);
+ }
+
+ ptr = wcsncat(dest, str2, 3);
+ if (ptr != dest)
+ {
+ Fail("ERROR: Expected wcsncat to return ptr to %p, got %p", dest, ptr);
+ }
+ if (dest[7] != 0)
+ {
+ Fail("ERROR: wcsncat did not place a terminating NULL!");
+ }
+
+ ptr = wcsncat(dest, str3, 20);
+ if (ptr != dest)
+ {
+ Fail("ERROR: Expected wcsncat to return ptr to %p, got %p", dest, ptr);
+ }
+ if (wcscmp(dest, test) != 0)
+ {
+ Fail("ERROR: Expected wcsncat to give \"%S\", got \"%S\"\n",
+ test, dest);
+ }
+ if (dest[wcslen(test)+1] != (WCHAR)'x')
+ {
+ Fail("wcsncat went out of bounds!\n");
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/wcsncat/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/wcsncat/test1/testinfo.dat
new file mode 100644
index 0000000000..39077a237d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcsncat/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = wcsncat
+Name = Test #1 for wcsncat
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests that wcsncat correctly appends wide strings, making sure it handles
+= count argument correctly (appending no more than count characters, always
+= placing a null, and padding the string if necessary).
diff --git a/src/pal/tests/palsuite/c_runtime/wcsncmp/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcsncmp/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcsncmp/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/wcsncmp/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcsncmp/test1/CMakeLists.txt
new file mode 100644
index 0000000000..56c9b25806
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcsncmp/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_wcsncmp_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wcsncmp_test1 coreclrpal)
+
+target_link_libraries(paltest_wcsncmp_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/wcsncmp/test1/test1.c b/src/pal/tests/palsuite/c_runtime/wcsncmp/test1/test1.c
new file mode 100644
index 0000000000..4e4488f5a1
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcsncmp/test1/test1.c
@@ -0,0 +1,73 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose:
+** Tests that wcsncmp case-sensitively compares wide strings, making sure that
+** the count argument is handled correctly.
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+
+/*
+ * Notes: uses wcslen.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR str1[] = {'f','o','o',0};
+ WCHAR str2[] = {'f','o','o','x',0};
+ WCHAR str3[] = {'f','O','o',0};
+ char cstr1[] = "foo";
+ char cstr2[] = "foox";
+ char cstr3[] = "fOo";
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+
+ if (wcsncmp(str1, str2, wcslen(str2)) >= 0)
+ {
+ Fail("ERROR: wcsncmp(\"%s\", \"%s\", %d) returned >= 0\n", cstr1,
+ cstr2, wcslen(str2));
+ }
+
+ if (wcsncmp(str2, str1, wcslen(str2)) <= 0)
+ {
+ Fail("ERROR: wcsncmp(\"%s\", \"%s\", %d) returned <= 0\n", cstr2,
+ cstr1, wcslen(str2));
+ }
+
+ if (wcsncmp(str1, str2, wcslen(str1)) != 0)
+ {
+ Fail("ERROR: wcsncmp(\"%s\", \"%s\", %d) returned != 0\n", cstr1,
+ cstr2, wcslen(str1));
+ }
+
+ if (wcsncmp(str1, str3, wcslen(str1)) <= 0)
+ {
+ Fail("ERROR: wcsncmp(\"%s\", \"%s\", %d) returned >= 0\n", cstr1,
+ cstr3, wcslen(str1));
+ }
+
+ if (wcsncmp(str3, str1, wcslen(str1)) >= 0)
+ {
+ Fail("ERROR: wcsncmp(\"%s\", \"%s\", %d) returned >= 0\n", cstr3,
+ cstr1, wcslen(str1));
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/wcsncmp/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/wcsncmp/test1/testinfo.dat
new file mode 100644
index 0000000000..1f8b508748
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcsncmp/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = wcsncmp
+Name = Positive Test for wcsncmp
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests that wcsncmp case-sensitively compares wide strings, making sure that
+= the count argument is handled correctly.
diff --git a/src/pal/tests/palsuite/c_runtime/wcsncpy/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcsncpy/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcsncpy/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/wcsncpy/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcsncpy/test1/CMakeLists.txt
new file mode 100644
index 0000000000..1c1d70ba04
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcsncpy/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_wcsncpy_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wcsncpy_test1 coreclrpal)
+
+target_link_libraries(paltest_wcsncpy_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/wcsncpy/test1/test1.c b/src/pal/tests/palsuite/c_runtime/wcsncpy/test1/test1.c
new file mode 100644
index 0000000000..50d97b0e9c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcsncpy/test1/test1.c
@@ -0,0 +1,84 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose:
+** Tests to see that wcsncpy correctly copies wide strings, including handling
+** the count argument correctly (copying no more that count characters, not
+** automatically adding a null, and padding if necessary).
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR dest[80];
+ WCHAR result[] = {'f','o','o','b','a','r',0};
+ WCHAR str[] = {'f','o','o','b','a','r',0,'b','a','z',0};
+ WCHAR *ret;
+ int i;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ for (i=0; i<80; i++)
+ {
+ dest[i] = 'x';
+ }
+
+ ret = wcsncpy(dest, str, 3);
+ if (ret != dest)
+ {
+ Fail("Expected wcsncpy to return %p, got %p!\n", dest, ret);
+ }
+
+ if (wcsncmp(dest, result, 3) != 0)
+ {
+ Fail("Expected wcsncpy to give \"%S\", got \"%S\"!\n", result, dest);
+ }
+
+ if (dest[3] != (WCHAR)'x')
+ {
+ Fail("wcsncpy overflowed!\n");
+ }
+
+ ret = wcsncpy(dest, str, 40);
+ if (ret != dest)
+ {
+ Fail("Expected wcsncpy to return %p, got %p!\n", dest, ret);
+ }
+
+ if (wcscmp(dest, result) != 0)
+ {
+ Fail("Expected wcsncpy to give \"%S\", got \"%S\"!\n", result, dest);
+ }
+
+ for (i=wcslen(str); i<40; i++)
+ {
+ if (dest[i] != 0)
+ {
+ Fail("wcsncpy failed to pad the destination with NULLs!\n");
+ }
+ }
+
+ if (dest[40] != (WCHAR)'x')
+ {
+ Fail("wcsncpy overflowed!\n");
+ }
+
+
+
+ PAL_Terminate();
+
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/wcsncpy/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/wcsncpy/test1/testinfo.dat
new file mode 100644
index 0000000000..b8b0ddb3f7
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcsncpy/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = wcsncpy
+Name = Test #1 for wcsncpy
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests to see that wcsncpy correctly copies wide strings, including handling
+= the count argument correctly (copying no more that count characters, not
+= automatically adding a null, and padding if necessary).
+
diff --git a/src/pal/tests/palsuite/c_runtime/wcspbrk/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcspbrk/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcspbrk/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/wcspbrk/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcspbrk/test1/CMakeLists.txt
new file mode 100644
index 0000000000..c6a3f87d75
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcspbrk/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_wcspbrk_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wcspbrk_test1 coreclrpal)
+
+target_link_libraries(paltest_wcspbrk_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/wcspbrk/test1/test1.c b/src/pal/tests/palsuite/c_runtime/wcspbrk/test1/test1.c
new file mode 100644
index 0000000000..b0432f7819
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcspbrk/test1/test1.c
@@ -0,0 +1,61 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose:
+** Tests that wcspbrk returns a pointer to the first element in the first
+** string that matches a character in the second (or NULL).
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR *string;
+ WCHAR *key1;
+ WCHAR *key2;
+ WCHAR key3[] = {0};
+ WCHAR *result;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ string = convert("foo bar baz bar");
+ key1 = convert("z ");
+ key2 = convert("Q");
+
+ result = wcspbrk(string, key1);
+ if (result != string + 3)
+ {
+ Fail("ERROR: Got incorrect result in scanning \"%s\" with the set \"%s\".\n"
+ "Expected to get pointer to %#p, got %#p\n", convertC(string),
+ convertC(key1), string + 3, result);
+ }
+
+ result = wcspbrk(string, key2);
+ if (result != NULL)
+ {
+ Fail("ERROR: Got incorrect result in scanning \"%s\" with the set \"%s\".\n"
+ "Expected to get pointer to %#p, got %#p\n", convertC(string),
+ convertC(key2), NULL, result);
+ }
+
+ result = wcspbrk(string, key3);
+ if (result != NULL)
+ {
+ Fail("ERROR: Got incorrect result in scanning \"%s\" with the set \"%s\".\n"
+ "Expected to get pointer to %#p, got %#p\n", convertC(string),
+ convertC(key3), NULL, result);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/wcspbrk/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/wcspbrk/test1/testinfo.dat
new file mode 100644
index 0000000000..7044197b77
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcspbrk/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = wcspbrk
+Name = Positive Test for wcspbrk
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests that wcspbrk returns a pointer to the first element in the first
+= string that matches a character in the second (or NULL).
diff --git a/src/pal/tests/palsuite/c_runtime/wcsrchr/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcsrchr/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcsrchr/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/wcsrchr/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcsrchr/test1/CMakeLists.txt
new file mode 100644
index 0000000000..80513af1af
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcsrchr/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_wcsrchr_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wcsrchr_test1 coreclrpal)
+
+target_link_libraries(paltest_wcsrchr_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/wcsrchr/test1/test1.c b/src/pal/tests/palsuite/c_runtime/wcsrchr/test1/test1.c
new file mode 100644
index 0000000000..ae8765776e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcsrchr/test1/test1.c
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose:
+** Tests to see that wcsrchr correctly returns a pointer to the last occurence
+** of a character in a a string.
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR str[] = {'f','o','o',' ','b','a','r',' ','b','a','z',0};
+ WCHAR c = (WCHAR)' ';
+ WCHAR c2 = (WCHAR)'$';
+ WCHAR *ptr;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ ptr = wcsrchr(str, c);
+ if (ptr != str + 7)
+ {
+ Fail("ERROR: expected wcsrchr to return pointer to %p, got %p\n",
+ str + 7, ptr);
+ }
+
+ ptr = wcsrchr(str, c2);
+ if (ptr != NULL)
+ {
+ Fail("ERROR: expected wcsrchr to return pointer to %p, got %p\n",
+ NULL, ptr);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/wcsrchr/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/wcsrchr/test1/testinfo.dat
new file mode 100644
index 0000000000..984df9a3f3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcsrchr/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = wcsrchr
+Name = Positive Test for wcsrchr
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests to see that wcsrchr correctly returns a pointer to the last occurence
+= of a character in a a string.
diff --git a/src/pal/tests/palsuite/c_runtime/wcsstr/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcsstr/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcsstr/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/wcsstr/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcsstr/test1/CMakeLists.txt
new file mode 100644
index 0000000000..e42619344d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcsstr/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_wcsstr_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wcsstr_test1 coreclrpal)
+
+target_link_libraries(paltest_wcsstr_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/wcsstr/test1/test1.c b/src/pal/tests/palsuite/c_runtime/wcsstr/test1/test1.c
new file mode 100644
index 0000000000..8296a74983
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcsstr/test1/test1.c
@@ -0,0 +1,62 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose:
+** Tests that wcsstr correctly find substrings in wide stings, including
+** returning NULL when the substring can't be found.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR *string;
+ WCHAR *key1;
+ WCHAR *key2;
+ WCHAR key3[] = { 0 };
+ WCHAR *result;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ string = convert("foo bar baz bar");
+ key1 = convert("bar");
+ key2 = convert("Bar");
+
+ result = wcsstr(string, key1);
+ if (result != string + 4)
+ {
+ Fail("ERROR: Got incorrect result in scanning \"%s\" for \"%s\".\n"
+ "Expected to get pointer to %#p, got %#p\n", convertC(string),
+ convertC(key1), string + 4, result);
+ }
+
+
+ result = wcsstr(string, key2);
+ if (result != NULL)
+ {
+ Fail("ERROR: Got incorrect result in scanning \"%s\" for \"%s\".\n"
+ "Expected to get pointer to %#p, got %#p\n", convertC(string),
+ convertC(key2), NULL, result);
+ }
+
+ result = wcsstr(string, key3);
+ if (result != string)
+ {
+ Fail("ERROR: Got incorrect result in scanning \"%s\" for \"%s\".\n"
+ "Expected to get pointer to %#p, got %#p\n", convertC(string),
+ convertC(key3), string, result);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/wcsstr/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/wcsstr/test1/testinfo.dat
new file mode 100644
index 0000000000..e42fd8c9eb
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcsstr/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = wcsstr
+Name = Positive Test for wcsstr
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests that wcsstr correctly find substrings in wide stings, including
+= returning NULL when the substring can't be found.
diff --git a/src/pal/tests/palsuite/c_runtime/wcstod/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstod/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstod/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/c_runtime/wcstod/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstod/test1/CMakeLists.txt
new file mode 100644
index 0000000000..cf585d051a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstod/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_wcstod_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wcstod_test1 coreclrpal)
+
+target_link_libraries(paltest_wcstod_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/wcstod/test1/test1.c b/src/pal/tests/palsuite/c_runtime/wcstod/test1/test1.c
new file mode 100644
index 0000000000..e41e92e961
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstod/test1/test1.c
@@ -0,0 +1,79 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests wcstod with a number of sample strings.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+struct testCase
+{
+ double CorrectResult;
+ char string[20];
+ int stopChar;
+};
+
+struct testCase testCases[] =
+{
+ {1234,"1234", 4},
+ {-1234,"-1234", 5},
+ {1234.44,"1234.44", 7},
+ {1234e-5,"1234e-5", 7},
+ {1234e+5,"1234e+5", 7},
+ {1234E5,"1234E5", 6},
+ {1234.657e-8, "1234.657e-8", 11},
+ {0, "1e-800", 6},
+ {0, "-1e-800", 7},
+ {1234567e-8, " 1234567e-8 foo", 13},
+ {0, " foo 32 bar", 0},
+};
+
+int __cdecl main(int argc, char **argv)
+{
+ WCHAR *wideStr;
+ WCHAR *endptr;
+ double result;
+ int i;
+
+ if (PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++)
+ {
+ wideStr = convert(testCases[i].string);
+ result = wcstod(wideStr, &endptr);
+
+ if (testCases[i].CorrectResult != result)
+ {
+ free(wideStr);
+ Fail("ERROR: wcstod misinterpreted \"%s\" as %g instead of "
+ "%g.\n",
+ testCases[i].string,
+ result,
+ testCases[i].CorrectResult);
+ }
+
+ if (endptr != wideStr + testCases[i].stopChar)
+ {
+ free(wideStr);
+ Fail("ERROR: wcstod stopped scanning \"%s\" at %p, "
+ "instead of %p!\n", testCases[i].string, endptr,
+ wideStr + testCases[i].stopChar);
+ }
+
+ free(wideStr);
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/wcstod/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/wcstod/test1/testinfo.dat
new file mode 100644
index 0000000000..19da0b5a42
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstod/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = wcstod
+Name = Positive Test for wcstod
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests wcstod with a number of sample strings.
+
diff --git a/src/pal/tests/palsuite/c_runtime/wcstod/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstod/test2/CMakeLists.txt
new file mode 100644
index 0000000000..43d5bf8a40
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstod/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_wcstod_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wcstod_test2 coreclrpal)
+
+target_link_libraries(paltest_wcstod_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/wcstod/test2/test2.c b/src/pal/tests/palsuite/c_runtime/wcstod/test2/test2.c
new file mode 100644
index 0000000000..8f9b5cbf58
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstod/test2/test2.c
@@ -0,0 +1,59 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test2.c
+**
+** Purpose: Tests wcstod with overflows
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ /* Representation of positive infinty for a IEEE 64-bit double */
+ INT64 PosInifity = (INT64)(0x7ff00000) << 32;
+ double HugeVal = *(double*) &PosInifity;
+ char *PosStr = "1E+10000";
+ char *NegStr = "-1E+10000";
+ WCHAR *wideStr;
+ double result;
+
+
+ if (PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ wideStr = convert(PosStr);
+ result = wcstod(wideStr, NULL);
+ free(wideStr);
+
+ if (result != HugeVal)
+ {
+ Fail("ERROR: wcstod interpreted \"%s\" as %g instead of %g\n",
+ PosStr, result, HugeVal);
+ }
+
+
+
+ wideStr = convert(NegStr);
+ result = wcstod(wideStr, NULL);
+ free(wideStr);
+
+ if (result != -HugeVal)
+ {
+ Fail("ERROR: wcstod interpreted \"%s\" as %g instead of %g\n",
+ NegStr, result, -HugeVal);
+ }
+
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/wcstod/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/wcstod/test2/testinfo.dat
new file mode 100644
index 0000000000..bf41e97075
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstod/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = wcstod
+Name = Positive Test for wcstod
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Tests wcstod with overflows
+
diff --git a/src/pal/tests/palsuite/c_runtime/wcstok/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstok/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstok/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/c_runtime/wcstok/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstok/test1/CMakeLists.txt
new file mode 100644
index 0000000000..863f5d8c29
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstok/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_wcstok_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wcstok_test1 coreclrpal)
+
+target_link_libraries(paltest_wcstok_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/wcstok/test1/test1.c b/src/pal/tests/palsuite/c_runtime/wcstok/test1/test1.c
new file mode 100644
index 0000000000..76d7dc02b3
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstok/test1/test1.c
@@ -0,0 +1,114 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose:
+** Search for a number of tokens within strings. Check that the return values
+** are what is expected, and also that the strings match up with our expected
+** results.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ /* foo bar baz */
+ WCHAR str[] = {'f','o','o',' ','b','a','r',' ','b','a','z','\0'};
+
+ /* foo \0ar baz */
+ WCHAR result1[] = {'f','o','o',' ','\0','a','r',' ','b','a','z','\0'};
+
+ /* foo \0a\0 baz */
+ WCHAR result2[] = {'f','o','o',' ','\0','a','\0',' ','b','a','z','\0'};
+
+ WCHAR* tempString;
+ int len = 0;
+ WCHAR *ptr;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ len = (wcslen(str)*sizeof(WCHAR)) + 2;
+
+ /* Tokenize 'str'. It will hit the 'b' delimiter first. Check to see
+ that the ptr is pointing to the start of the string and do a compare
+ to ensure the tokenized string is what we expected.
+ */
+
+ tempString = convert("bz");
+ ptr = wcstok(str, tempString);
+ free(tempString);
+
+ if (ptr != str)
+ {
+ Fail("ERROR: Expected wcstok() to return %p, got %p!\n", str, ptr);
+ }
+
+ if (memcmp(str, result1, len) != 0)
+ {
+ Fail("ERROR: wcstok altered the string in an unexpected fashion.");
+ }
+
+ /* If NULL is passed as the first parameter, wcstok will continue
+ tokenizing the same string. Test that this works properly.
+ */
+ tempString = convert("r ");
+ ptr = wcstok(NULL, tempString);
+ free(tempString);
+
+ if (ptr != str + 5)
+ {
+ Fail("ERROR: Expected wcstok() to return %p, got %p!\n", str+5, ptr);
+ }
+
+ if (memcmp(str, result2, len) != 0)
+ {
+ Fail("ERROR: wcstok altered the string in an unexpected fashion.");
+ }
+
+ /* Continue onward, and search for 'X' now, which won't be found. The
+ pointer should point just after the last NULL in the string. And
+ the string itself shouldn't have changed.
+ */
+ tempString = convert("X");
+ ptr = wcstok(NULL, tempString);
+ free(tempString);
+
+ if (ptr != str + 7)
+ {
+ Fail("ERROR: Expected wcstok() to return %p, got %p!\n", str + 7, ptr);
+ }
+
+ if (memcmp(str, result2, len) != 0)
+ {
+ Fail("ERROR: wcstok altered the string in an unexpeced fashion.\n");
+ }
+
+ /* Call wcstok again. Now the ptr should point to the end of the
+ string at NULL. And the string itself shouldn't have changed.
+ */
+ tempString = convert("X");
+ ptr = wcstok(NULL, tempString);
+ free(tempString);
+
+ if (ptr != NULL)
+ {
+ Fail("ERROR: Expected wcstok() to return %p, got %p!\n", NULL, ptr);
+ }
+
+ if (memcmp(str, result2, len) != 0)
+ {
+ Fail("ERROR: wcstok altered the string in an unexpeced fashion.\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/wcstok/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/wcstok/test1/testinfo.dat
new file mode 100644
index 0000000000..cc00844c6a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstok/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = wcstok
+Name = wcstok test- tokenize a string and ensure the string takes correct form.
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Search for a number of tokens within strings. Check that the return values
+= are what is expect, and also that the strings match up with our expected
+= results.
diff --git a/src/pal/tests/palsuite/c_runtime/wcstol/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstol/CMakeLists.txt
new file mode 100644
index 0000000000..7c20179353
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstol/CMakeLists.txt
@@ -0,0 +1,9 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+
diff --git a/src/pal/tests/palsuite/c_runtime/wcstol/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstol/test1/CMakeLists.txt
new file mode 100644
index 0000000000..25e96e7de0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstol/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_wcstol_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wcstol_test1 coreclrpal)
+
+target_link_libraries(paltest_wcstol_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/wcstol/test1/test1.c b/src/pal/tests/palsuite/c_runtime/wcstol/test1/test1.c
new file mode 100644
index 0000000000..d84ba66adc
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstol/test1/test1.c
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test #1 for the wcstol function. Does a simple test with radix 4.
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+
+
+/*
+ * Notes: wcstol should depend on the current locale's LC_NUMERIC category,
+ * this is not currently tested.
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR *end;
+ WCHAR teststr[] = {'1','2','3','4','5',0};
+ LONG result = 27;
+ LONG l;
+
+ if ( 0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ l = wcstol(teststr, &end, 4);
+
+ if (l != result)
+ {
+ Fail("ERROR: Expected wcstol to return %d, got %d\n", result, l);
+ }
+
+ if (end != teststr + 3)
+ {
+ Fail("ERROR: Expected wcstol to give an end value of %p, got %p\n",
+ teststr + 3, end);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/wcstol/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/wcstol/test1/testinfo.dat
new file mode 100644
index 0000000000..48108f22bf
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstol/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = wcstol
+Name = Positive Test for wcstol
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests wcstol with base 4 and a string that includes some invalid characters.
diff --git a/src/pal/tests/palsuite/c_runtime/wcstol/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstol/test2/CMakeLists.txt
new file mode 100644
index 0000000000..ea33ec8c7e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstol/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_wcstol_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wcstol_test2 coreclrpal)
+
+target_link_libraries(paltest_wcstol_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/wcstol/test2/test2.c b/src/pal/tests/palsuite/c_runtime/wcstol/test2/test2.c
new file mode 100644
index 0000000000..58309be6b4
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstol/test2/test2.c
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test2.c
+**
+** Purpose: Test #2 for the wcstol function. Does a simple test with radix
+** 10.
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+
+
+/*
+ * Notes: wcstol should depend on the current locale's LC_NUMERIC category,
+ * this is not currently tested.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR *end;
+ WCHAR teststr[] = {'1','2','3','4','5',0};
+ LONG result = 12345;
+ LONG l;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ l = wcstol(teststr, &end, 10);
+
+ if (l != result)
+ {
+ Fail("ERROR: Expected wcstol to return %d, got %d\n", result, l);
+ }
+
+ if (end != teststr + 5)
+ {
+ Fail("ERROR: Expected wcstol to give an end value of %p, got %p\n",
+ teststr + 5, end);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/wcstol/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/wcstol/test2/testinfo.dat
new file mode 100644
index 0000000000..8dd1460010
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstol/test2/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = wcstol
+Name = Positive Test for wcstol
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Tests wcstol with base 10 and a completely valid string.
diff --git a/src/pal/tests/palsuite/c_runtime/wcstol/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstol/test3/CMakeLists.txt
new file mode 100644
index 0000000000..509feca08c
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstol/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_wcstol_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wcstol_test3 coreclrpal)
+
+target_link_libraries(paltest_wcstol_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/wcstol/test3/test3.c b/src/pal/tests/palsuite/c_runtime/wcstol/test3/test3.c
new file mode 100644
index 0000000000..8b5ce6943d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstol/test3/test3.c
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test3.c
+**
+** Purpose: Test #3 for the wcstol function. Tests an invalid string
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+
+
+/*
+ * Notes: wcstol should depend on the current locale's LC_NUMERIC category,
+ * this is not currently tested.
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR str[] = {'Z',0};
+ WCHAR *end;
+ LONG l;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ l = wcstol(str, &end, 10);
+
+ if (l != 0)
+ {
+ Fail("ERROR: Expected wcstol to return %d, got %d\n", 0, l);
+ }
+
+ if (end != str)
+ {
+ Fail("ERROR: Expected wcstol to give an end value of %p, got %p\n",
+ str + 3, end);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/wcstol/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/wcstol/test3/testinfo.dat
new file mode 100644
index 0000000000..0e851d8657
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstol/test3/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = wcstol
+Name = Positive Test for wcstol
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Tests wcstol with a completely invalid string (base 10).
diff --git a/src/pal/tests/palsuite/c_runtime/wcstol/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstol/test4/CMakeLists.txt
new file mode 100644
index 0000000000..043c562102
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstol/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_wcstol_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wcstol_test4 coreclrpal)
+
+target_link_libraries(paltest_wcstol_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/wcstol/test4/test4.c b/src/pal/tests/palsuite/c_runtime/wcstol/test4/test4.c
new file mode 100644
index 0000000000..a5e65946e9
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstol/test4/test4.c
@@ -0,0 +1,77 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test4.c
+**
+** Purpose: Test #4 for the wcstol function. Tests the limits of the
+** conversions.
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+
+
+/*
+ * Notes: wcstol should depend on the current locale's LC_NUMERIC category,
+ * this is not currently tested.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR maxstr[] = {'2','1','4','7','4','8','3','6','4','7',0};
+ LONG max = 2147483647;
+ WCHAR minstr[] = {'-','2','1','4','7','4','8','3','6','4','8',0};
+ LONG min = 0x80000000; /* putting -2147483648 gives a warning */
+ WCHAR *end;
+ LONG l;
+
+ if ( 0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ errno = 0;
+
+ l = wcstol(maxstr, &end, 10);
+
+ if (l != max)
+ {
+ Fail("ERROR: Expected wcstol to return %d, got %d\n", max, l);
+ }
+ if (end != maxstr + 10)
+ {
+ Fail("ERROR: Expected wcstol to give an end value of %p, got %p\n",
+ maxstr + 10, end);
+ }
+ if (errno != 0)
+ {
+ Fail("ERROR: wcstol set errno to non-zero (%d)\n", errno);
+ }
+
+
+ l = wcstol(minstr, &end, 10);
+
+ if (l != min)
+ {
+ Fail("ERROR: Expected wcstol to return %d, got %d\n", min, l);
+ }
+ if (end != minstr + 11)
+ {
+ Fail("ERROR: Expected wcstol to give an end value of %p, got %p\n",
+ minstr + 11, end);
+ }
+ if (errno != 0)
+ {
+ Fail("ERROR: wcstol set errno to non-zero (%d)\n", errno);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/wcstol/test4/testinfo.dat b/src/pal/tests/palsuite/c_runtime/wcstol/test4/testinfo.dat
new file mode 100644
index 0000000000..d2c5652e6e
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstol/test4/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = wcstol
+Name = Positive Test for wcstol
+TYPE = DEFAULT
+EXE1 = test4
+Description
+= Tests wcstol with base 10 and the highest and lowest possible values.
diff --git a/src/pal/tests/palsuite/c_runtime/wcstol/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstol/test5/CMakeLists.txt
new file mode 100644
index 0000000000..c887369880
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstol/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test5.c
+)
+
+add_executable(paltest_wcstol_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wcstol_test5 coreclrpal)
+
+target_link_libraries(paltest_wcstol_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/wcstol/test5/test5.c b/src/pal/tests/palsuite/c_runtime/wcstol/test5/test5.c
new file mode 100644
index 0000000000..62f0a895a6
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstol/test5/test5.c
@@ -0,0 +1,76 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test5.c
+**
+** Purpose: Test #5 for the wcstol function. Tests over and under flowing.
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+
+
+/*
+ * Notes: wcstol should depend on the current locale's LC_NUMERIC category,
+ * this is not currently tested.
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR overstr[] = {'2','1','4','7','4','8','3','6','4','8',0};
+ WCHAR understr[] = {'-','2','1','4','7','4','8','3','6','4','9',0};
+ WCHAR *end;
+ LONG l;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ errno = 0;
+
+ l = wcstol(overstr, &end, 10);
+
+ if (l != LONG_MAX)
+ {
+ Fail("ERROR: Expected wcstol to return %u, got %u\n", LONG_MAX, l);
+ }
+ if (end != overstr + 10)
+ {
+ Fail("ERROR: Expected wcstol to give an end value of %p, got %p\n",
+ overstr + 10, end);
+ }
+ if (errno != ERANGE)
+ {
+ Fail("ERROR: wcstol did not set errno to ERANGE (%d)\n", errno);
+ }
+
+
+ errno = 0;
+ l = wcstol(understr, &end, 10);
+
+ if (l != LONG_MIN)
+ {
+ Fail("ERROR: Expected wcstol to return %u, got %u\n", LONG_MIN, l);
+ }
+ if (end != understr + 11)
+ {
+ Fail("ERROR: Expected wcstol to give an end value of %p, got %p\n",
+ understr + 11, end);
+ }
+ if (errno != ERANGE)
+ {
+ Fail("ERROR: wcstol did not set errno to ERANGE (%d)\n", errno);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/wcstol/test5/testinfo.dat b/src/pal/tests/palsuite/c_runtime/wcstol/test5/testinfo.dat
new file mode 100644
index 0000000000..18b4478e3a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstol/test5/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = wcstol
+Name = Positive Test for wcstol
+TYPE = DEFAULT
+EXE1 = test5
+Description
+= Tests wcstol (base 10) with underflowing and overflowing.
+= Chesks that errno gets set to ERANGE.
diff --git a/src/pal/tests/palsuite/c_runtime/wcstol/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstol/test6/CMakeLists.txt
new file mode 100644
index 0000000000..d328161f39
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstol/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test6.c
+)
+
+add_executable(paltest_wcstol_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wcstol_test6 coreclrpal)
+
+target_link_libraries(paltest_wcstol_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/wcstol/test6/test6.c b/src/pal/tests/palsuite/c_runtime/wcstol/test6/test6.c
new file mode 100644
index 0000000000..14f6208231
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstol/test6/test6.c
@@ -0,0 +1,86 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test6.c
+**
+** Purpose: Test #6 for the wcstol function. Tests strings with octal/hex
+** number specifers
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+
+
+/*
+ * Notes: wcstol should depend on the current locale's LC_NUMERIC category,
+ * this is not currently tested.
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR test1[] = {'0','x','1','2', 0};
+ WCHAR test2[] = {'0','1','2',0};
+ WCHAR *end;
+ LONG l;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ l = wcstol(test1, &end, 16);
+ if (l != 0x12)
+ {
+ Fail("ERROR: Expected wcstol to return %d, got %d\n", 0x12, l);
+ }
+ if (end != test1 + 4)
+ {
+ Fail("ERROR: Expected wcstol to give an end value of %p, got %p\n",
+ test1 + 4, end);
+ }
+
+ l = wcstol(test1, &end, 10);
+ if (l != 0)
+ {
+ Fail("ERROR: Expected wcstol to return %d, got %d\n", 0, l);
+ }
+ if (end != test1+1)
+ {
+ Fail("ERROR: Expected wcstol to give an end value of %p, got %p\n",
+ test1+1, end);
+ }
+
+ l = wcstol(test2, &end, 8);
+ if (l != 10)
+ {
+ Fail("ERROR: Expected wcstol to return %d, got %d\n", 10, l);
+ }
+ if (end != test2 + 3)
+ {
+ Fail("ERROR: Expected wcstol to give an end value of %p, got %p\n",
+ test2 + 3, end);
+ }
+
+ l = wcstol(test2, &end, 10);
+ if (l != 12)
+ {
+ Fail("ERROR: Expected wcstol to return %d, got %d\n", 12, l);
+ }
+
+ if (end != test2 + 3)
+ {
+ Fail("ERROR: Expected wcstol to give an end value of %p, got %p\n",
+ test2 + 3, end);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/wcstol/test6/testinfo.dat b/src/pal/tests/palsuite/c_runtime/wcstol/test6/testinfo.dat
new file mode 100644
index 0000000000..0e10761e4d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstol/test6/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = wcstol
+Name = Positive Test for wcstol
+TYPE = DEFAULT
+EXE1 = test6
+Description
+= Tests wcstol with hex and octal strings, with different bases.
diff --git a/src/pal/tests/palsuite/c_runtime/wcstoul/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstoul/CMakeLists.txt
new file mode 100644
index 0000000000..7c20179353
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstoul/CMakeLists.txt
@@ -0,0 +1,9 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+
diff --git a/src/pal/tests/palsuite/c_runtime/wcstoul/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstoul/test1/CMakeLists.txt
new file mode 100644
index 0000000000..b24523e93b
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstoul/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_wcstoul_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wcstoul_test1 coreclrpal)
+
+target_link_libraries(paltest_wcstoul_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/wcstoul/test1/test1.c b/src/pal/tests/palsuite/c_runtime/wcstoul/test1/test1.c
new file mode 100644
index 0000000000..5274905e30
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstoul/test1/test1.c
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test #1 for the wcstoul function
+**
+**
+**==========================================================================*/
+#include <palsuite.h>
+
+/*
+ * Notes: wcstoul should depend on the current locale's LC_NUMERIC category,
+ * this is not currently tested.
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR teststr[] = {'1','2','3','4','5',0};
+ WCHAR *end;
+ ULONG result = 27;
+ ULONG l;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ l = wcstoul(teststr, &end, 4);
+
+ if (l != result)
+ {
+ Fail("ERROR: Expected wcstoul to return %u, got %u\n", result, l);
+ }
+
+ if (end != teststr + 3)
+ {
+ Fail("ERROR: Expected wcstoul to give an end value of %p, got %p\n",
+ teststr + 3, end);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/wcstoul/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/wcstoul/test1/testinfo.dat
new file mode 100644
index 0000000000..af4fb7e55d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstoul/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = wcstoul
+Name = Positive Test for wcstoul
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests wcstoul with base 4 and a string that includes some invalid characters.
diff --git a/src/pal/tests/palsuite/c_runtime/wcstoul/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstoul/test2/CMakeLists.txt
new file mode 100644
index 0000000000..e262078e34
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstoul/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_wcstoul_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wcstoul_test2 coreclrpal)
+
+target_link_libraries(paltest_wcstoul_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/wcstoul/test2/test2.c b/src/pal/tests/palsuite/c_runtime/wcstoul/test2/test2.c
new file mode 100644
index 0000000000..2ab2dbf5d1
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstoul/test2/test2.c
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test2.c
+**
+** Purpose: Test #2 for the wcstoul function
+**
+**
+**==========================================================================*/
+#include <palsuite.h>
+
+/*
+ * Notes: wcstoul should depend on the current locale's LC_NUMERIC category,
+ * this is not currently tested.
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR teststr[] = {'1','2','3','4','5',0};
+ WCHAR *end;
+ ULONG result = 12345;
+ ULONG l;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ l = wcstoul((wchar_t*)teststr, &end, 10);
+
+ if (l != result)
+ {
+ Fail("ERROR: Expected wcstoul to return %u, got %u\n", result, l);
+ }
+
+ if (end != teststr + 5)
+ {
+ Fail("ERROR: Expected wcstoul to give an end value of %p, got %p\n",
+ teststr + 5, end);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/wcstoul/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/wcstoul/test2/testinfo.dat
new file mode 100644
index 0000000000..b7e301f423
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstoul/test2/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = wcstoul
+Name = Positive Test for wcstoul
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Tests wcstoul with base 10 and a completely valid string.
diff --git a/src/pal/tests/palsuite/c_runtime/wcstoul/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstoul/test3/CMakeLists.txt
new file mode 100644
index 0000000000..aae268ac59
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstoul/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_wcstoul_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wcstoul_test3 coreclrpal)
+
+target_link_libraries(paltest_wcstoul_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/wcstoul/test3/test3.c b/src/pal/tests/palsuite/c_runtime/wcstoul/test3/test3.c
new file mode 100644
index 0000000000..eac46615e2
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstoul/test3/test3.c
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test3.c
+**
+** Purpose: Test #3 for the wcstoul function
+**
+**
+**==========================================================================*/
+#include <palsuite.h>
+
+/*
+ * Notes: wcstoul should depend on the current locale's LC_NUMERIC category,
+ * this is not currently tested.
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR str[] = {'Z',0};
+ WCHAR *end;
+ ULONG l;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ l = wcstoul(str, &end, 10);
+
+ if (l != 0)
+ {
+ Fail("ERROR: Expected wcstoul to return %u, got %u\n", 0, l);
+ }
+
+ if (end != str)
+ {
+ Fail("ERROR: Expected wcstoul to give an end value of %p, got %p\n",
+ str, end);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/wcstoul/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/wcstoul/test3/testinfo.dat
new file mode 100644
index 0000000000..f7f6302d79
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstoul/test3/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = wcstoul
+Name = Positive Test for wcstoul
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Tests wcstoul with a completely invalid string (base 10).
diff --git a/src/pal/tests/palsuite/c_runtime/wcstoul/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstoul/test4/CMakeLists.txt
new file mode 100644
index 0000000000..bd8073023f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstoul/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_wcstoul_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wcstoul_test4 coreclrpal)
+
+target_link_libraries(paltest_wcstoul_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/wcstoul/test4/test4.c b/src/pal/tests/palsuite/c_runtime/wcstoul/test4/test4.c
new file mode 100644
index 0000000000..0261da4275
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstoul/test4/test4.c
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test4.c
+**
+** Purpose: Test #4 for the wcstoul function
+**
+**
+**==========================================================================*/
+#include <palsuite.h>
+
+/*
+ * Notes: wcstoul should depend on the current locale's LC_NUMERIC category,
+ * this is not currently tested.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR maxstr[] = {'4','2','9','4','9','6','7','2','9','5',0};
+ ULONG max = 4294967295ul;
+ WCHAR *end;
+ ULONG l;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ errno = 0;
+
+ l = wcstoul(maxstr, &end, 10);
+ if (l != max)
+ {
+ Fail("ERROR: Expected wcstoul to return %u, got %u\n", max, l);
+ }
+ if (end != maxstr + 10)
+ {
+ Fail("ERROR: Expected wcstoul to give an end value of %p, got %p\n",
+ maxstr + 10, end);
+ }
+ if (errno != 0)
+ {
+ Fail("ERROR: wcstoul set errno to non-zero (%d)\n", errno);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/wcstoul/test4/testinfo.dat b/src/pal/tests/palsuite/c_runtime/wcstoul/test4/testinfo.dat
new file mode 100644
index 0000000000..301178be3a
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstoul/test4/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = wcstoul
+Name = Positive Test for wcstoul
+TYPE = DEFAULT
+EXE1 = test4
+Description
+= Tests wcstoul with base 10 and the highest possible value.
diff --git a/src/pal/tests/palsuite/c_runtime/wcstoul/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstoul/test5/CMakeLists.txt
new file mode 100644
index 0000000000..1451e6ad57
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstoul/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test5.c
+)
+
+add_executable(paltest_wcstoul_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wcstoul_test5 coreclrpal)
+
+target_link_libraries(paltest_wcstoul_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/wcstoul/test5/test5.c b/src/pal/tests/palsuite/c_runtime/wcstoul/test5/test5.c
new file mode 100644
index 0000000000..00287cf7f4
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstoul/test5/test5.c
@@ -0,0 +1,69 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test5.c
+**
+** Purpose: Test #5 for the wcstoul function
+**
+**
+**==========================================================================*/
+#include <palsuite.h>
+
+/*
+ * Notes: wcstoul should depend on the current locale's LC_NUMERIC category,
+ * this is not currently tested.
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR overstr[] = {'4','2','9','4','9','6','7','2','9','6',0};
+ WCHAR understr[] = {'-','1',0};
+ WCHAR *end;
+ ULONG l;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ errno = 0;
+ l = wcstoul(overstr, &end, 10);
+
+ if (l != ULONG_MAX)
+ {
+ Fail("ERROR: Expected wcstoul to return %u, got %u\n", ULONG_MAX, l);
+ }
+ if (end != overstr + 10)
+ {
+ Fail("ERROR: Expected wcstoul to give an end value of %p, got %p\n",
+ overstr + 10, end);
+ }
+ if (errno != ERANGE)
+ {
+ Fail("ERROR: wcstoul did not set errno to ERANGE (%d)\n", errno);
+ }
+
+ errno = 0;
+ l = wcstoul(understr, &end, 10);
+
+ if (l != ULONG_MAX)
+ {
+ Fail("ERROR: Expected wcstoul to return %u, got %u\n", ULONG_MAX, l);
+ }
+ if (end != understr + 2)
+ {
+ Fail("ERROR: Expected wcstoul to give an end value of %p, got %p\n",
+ understr + 2, end);
+ }
+ if (errno != 0)
+ {
+ Fail("ERROR: wcstoul set errno to non-zero (%d)\n", errno);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/wcstoul/test5/testinfo.dat b/src/pal/tests/palsuite/c_runtime/wcstoul/test5/testinfo.dat
new file mode 100644
index 0000000000..bf7b2b6fe0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstoul/test5/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = wcstoul
+Name = Positive Test for wcstoul
+TYPE = DEFAULT
+EXE1 = test5
+Description
+= Tests wcstoul (base 10) with underflowing and overflowing.
+= Chesks that errno gets set to ERANGE.
diff --git a/src/pal/tests/palsuite/c_runtime/wcstoul/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstoul/test6/CMakeLists.txt
new file mode 100644
index 0000000000..15518bdcf8
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstoul/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test6.c
+)
+
+add_executable(paltest_wcstoul_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wcstoul_test6 coreclrpal)
+
+target_link_libraries(paltest_wcstoul_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/wcstoul/test6/test6.c b/src/pal/tests/palsuite/c_runtime/wcstoul/test6/test6.c
new file mode 100644
index 0000000000..28397ec73f
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstoul/test6/test6.c
@@ -0,0 +1,83 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test6.c
+**
+** Purpose: Test #6 for the wcstoul function. Tests strings with octal/hex
+** number specifers
+**
+**
+**==========================================================================*/
+#include <palsuite.h>
+
+
+/*
+ * Notes: wcstoul should depend on the current locale's LC_NUMERIC category,
+ * this is not currently tested.
+ */
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR test1[] = {'0','x','1','2', 0};
+ WCHAR test2[] = {'0','1','2',0};
+ WCHAR *end;
+ ULONG l;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ l = wcstoul(test1, &end, 16);
+ if (l != 0x12)
+ {
+ Fail("ERROR: Expected wcstoul to return %u, got %u\n", 0x12, l);
+ }
+ if (end != test1 + 4)
+ {
+ Fail("ERROR: Expected wcstoul to give an end value of %p, got %p\n",
+ test1 + 4, end);
+ }
+
+ l = wcstoul(test1, &end, 10);
+ if (l != 0)
+ {
+ Fail("ERROR: Expected wcstoul to return %u, got %u\n", 0, l);
+ }
+ if (end != test1+1)
+ {
+ Fail("ERROR: Expected wcstoul to give an end value of %p, got %p\n",
+ test1+1, end);
+ }
+
+ l = wcstoul(test2, &end, 8);
+ if (l != 10)
+ {
+ Fail("ERROR: Expected wcstoul to return %u, got %u\n", 10, l);
+ }
+ if (end != test2 + 3)
+ {
+ Fail("ERROR: Expected wcstoul to give an end value of %p, got %p\n",
+ test2 + 3, end);
+ }
+
+ l = wcstoul(test2, &end, 10);
+ if (l != 12)
+ {
+ Fail("ERROR: Expected wcstoul to return %u, got %u\n", 12, l);
+ }
+
+ if (end != test2 + 3)
+ {
+ Fail("ERROR: Expected wcstoul to give an end value of %p, got %p\n",
+ test2 + 3, end);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/c_runtime/wcstoul/test6/testinfo.dat b/src/pal/tests/palsuite/c_runtime/wcstoul/test6/testinfo.dat
new file mode 100644
index 0000000000..40e18d540d
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wcstoul/test6/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = wcstoul
+Name = Positive Test for wcstoul
+TYPE = DEFAULT
+EXE1 = test6
+Description
+= Tests wcstoul with hex and octal strings, with different bases.
diff --git a/src/pal/tests/palsuite/c_runtime/wprintf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wprintf/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wprintf/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/c_runtime/wprintf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wprintf/test1/CMakeLists.txt
new file mode 100644
index 0000000000..701bbe4160
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wprintf/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_wprintf_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wprintf_test1 coreclrpal)
+
+target_link_libraries(paltest_wprintf_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/wprintf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/wprintf/test1/test1.c
new file mode 100644
index 0000000000..d99dc8cf93
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wprintf/test1/test1.c
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test #1 for the wprintf function. A single, basic, test
+** case with no formatting.
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+#include "../wprintf.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+ char checkstr[] = "hello world";
+ WCHAR *wcheckstr;
+ int ret;
+
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ wcheckstr = convert(checkstr);
+
+ ret = wprintf(wcheckstr);
+
+ if (ret != wcslen(wcheckstr))
+ {
+ Fail("Expected wprintf to return %d, got %d.\n",
+ wcslen(wcheckstr), ret);
+
+ }
+
+ free(wcheckstr);
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/wprintf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/wprintf/test1/testinfo.dat
new file mode 100644
index 0000000000..02946361b0
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wprintf/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = wprintf
+Name = Positive Test for wprintf
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= General test to see if wprintf works correctly
diff --git a/src/pal/tests/palsuite/c_runtime/wprintf/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wprintf/test2/CMakeLists.txt
new file mode 100644
index 0000000000..55c3d11913
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wprintf/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_wprintf_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wprintf_test2 coreclrpal)
+
+target_link_libraries(paltest_wprintf_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/c_runtime/wprintf/test2/test2.c b/src/pal/tests/palsuite/c_runtime/wprintf/test2/test2.c
new file mode 100644
index 0000000000..254e98a394
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wprintf/test2/test2.c
@@ -0,0 +1,45 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test2.c
+**
+** Purpose: Test #2 for the wprintf function. Tests the string specifier
+** (%s).
+**
+**
+**==========================================================================*/
+
+
+#include <palsuite.h>
+#include "../wprintf.h"
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ DoStrTest(u"foo %s", u"bar", u"foo bar");
+ DoStrTest(u"foo %ws", u"bar", u"foo bar");
+ DoStrTest(u"foo %ls", u"bar", u"foo bar");
+ DoStrTest(u"foo %ws", u"bar", u"foo bar");
+ DoStrTest(u"foo %Ls", u"bar", u"foo bar");
+ DoStrTest(u"foo %I64s", u"bar", u"foo bar");
+ DoStrTest(u"foo %5s", u"bar", u"foo bar");
+ DoStrTest(u"foo %.2s", u"bar", u"foo ba");
+ DoStrTest(u"foo %5.2s", u"bar", u"foo ba");
+ DoStrTest(u"foo %-5s", u"bar", u"foo bar ");
+ DoStrTest(u"foo %05s", u"bar", u"foo 00bar");
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/c_runtime/wprintf/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/wprintf/test2/testinfo.dat
new file mode 100644
index 0000000000..7808c069dd
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wprintf/test2/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = wprintf
+Name = Positive Test for wprintf
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Tests wprintf with strings
diff --git a/src/pal/tests/palsuite/c_runtime/wprintf/wprintf.h b/src/pal/tests/palsuite/c_runtime/wprintf/wprintf.h
new file mode 100644
index 0000000000..7d3caf1b02
--- /dev/null
+++ b/src/pal/tests/palsuite/c_runtime/wprintf/wprintf.h
@@ -0,0 +1,171 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: wprintf.h
+**
+** Purpose: Containts common testing functions for wprintf
+**
+**
+**==========================================================================*/
+
+#ifndef __wprintf_H__
+#define __wprintf_H__
+
+void DoStrTest(WCHAR *formatstr, WCHAR* param, WCHAR *checkstr)
+{
+ int ret;
+
+ ret = wprintf(formatstr, param);
+ if (ret != wcslen(checkstr))
+ {
+ Fail("DoStrTest:Expected wprintf to return %d, got %d.\n",
+ wcslen(checkstr), ret);
+ }
+}
+
+
+void DoPointerTest(WCHAR *formatstr, void* param, WCHAR* paramstr,
+ WCHAR *checkstr1)
+{
+ int ret;
+
+ ret = wprintf(formatstr, param);
+ if (ret != wcslen(checkstr1))
+ {
+ Fail("DoPointerTest:Expected wprintf to return %d, got %d.\n",
+ wcslen(checkstr1), ret);
+ }
+}
+
+void DoCountTest(WCHAR *formatstr, int param, WCHAR *checkstr)
+{
+ int ret;
+ int n = -1;
+
+ ret = wprintf(formatstr, &n);
+
+ if (n != param)
+ {
+ Fail("DoCountTest:Expected count parameter to resolve to %d, got %d\n", param, n);
+ }
+
+ if (ret != wcslen(checkstr))
+ {
+ Fail("DoCountTest:Expected wprintf to return %d, got %d.\n",
+ wcslen(checkstr), ret);
+ }
+}
+
+void DoShortCountTest(WCHAR *formatstr, int param, WCHAR *checkstr)
+{
+ int ret;
+ short int n = -1;
+
+ ret = wprintf(formatstr, &n);
+
+ if (n != param)
+ {
+ Fail("DoShortCountTest:Expected count parameter to resolve to %d, got %d\n", param, n);
+ }
+
+ if (ret != wcslen(checkstr))
+ {
+ Fail("DoShortCountTest:Expected wprintf to return %d, got %d.\n",
+ wcslen(checkstr), ret);
+ }
+}
+
+
+void DoCharTest(WCHAR *formatstr, WCHAR param, WCHAR *checkstr)
+{
+ int ret;
+
+ ret = wprintf(formatstr, param);
+ if (ret != wcslen(checkstr))
+ {
+ Fail("DoCharTest:Expected wprintf to return %d, got %d.\n",
+ wcslen(checkstr), ret);
+ }
+}
+
+void DoWCharTest(WCHAR *formatstr, WCHAR param, WCHAR *checkstr)
+{
+ int ret;
+
+ ret = wprintf(formatstr, param);
+ if (ret != wcslen(checkstr))
+ {
+ Fail("DoWCharTest:Expected wprintf to return %d, got %d.\n",
+ wcslen(checkstr), ret);
+ }
+}
+
+void DoNumTest(WCHAR *formatstr, int param, WCHAR *checkstr)
+{
+ int ret;
+
+ ret = wprintf(formatstr, param);
+ if (ret != wcslen(checkstr))
+ {
+ Fail("DoNumTest:Expected wprintf to return %d, got %d.\n",
+ wcslen(checkstr), ret);
+ }
+}
+
+void DoI64Test(WCHAR *formatstr, INT64 param, WCHAR *valuestr,
+ WCHAR *checkstr1)
+{
+ int ret;
+
+ ret = wprintf(formatstr, param);
+ if (ret != wcslen(checkstr1))
+ {
+ Fail("DoI64Test:Expected wprintf to return %d, got %d.\n",
+ wcslen(checkstr1), ret);
+ }
+}
+
+void DoDoubleTest(WCHAR *formatstr, double param,
+ WCHAR *checkstr1, WCHAR *checkstr2)
+{
+ int ret;
+
+ ret = wprintf(formatstr, param);
+ if (ret != wcslen(checkstr1) && ret != wcslen(checkstr2))
+ {
+ Fail("DoDoubleTest:Expected wprintf to return %d or %d, got %d.\n",
+ wcslen(checkstr1), wcslen(checkstr2), ret);
+ }
+}
+
+void DoArgumentPrecTest(WCHAR *formatstr, int precision, void *param,
+ WCHAR *paramstr, WCHAR *checkstr1, WCHAR *checkstr2)
+{
+ int ret;
+
+ ret = wprintf(formatstr, precision, param);
+ if (ret != wcslen(checkstr1) && ret != wcslen(checkstr2))
+ {
+ Fail("DoArgumentPrecTest:Expected wprintf to return %d or %d, got %d.\n",
+ wcslen(checkstr1), wcslen(checkstr2), ret);
+ }
+}
+
+void DoArgumentPrecDoubleTest(WCHAR *formatstr, int precision, double param,
+ WCHAR *checkstr1, WCHAR *checkstr2)
+{
+ int ret;
+
+ ret = wprintf(formatstr, precision, param);
+ if (ret != wcslen(checkstr1) && ret != wcslen(checkstr2))
+ {
+ Fail("DoArgumentPrecDoubleTest:Expected wprintf to return %d or %d, got %d.\n",
+ wcslen(checkstr1), wcslen(checkstr2), ret);
+ }
+}
+
+#endif
+
diff --git a/src/pal/tests/palsuite/common/ResultBuffer.cpp b/src/pal/tests/palsuite/common/ResultBuffer.cpp
new file mode 100644
index 0000000000..e38c324187
--- /dev/null
+++ b/src/pal/tests/palsuite/common/ResultBuffer.cpp
@@ -0,0 +1,69 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//#include "stdafx.h"
+#include "resultbuffer.h"
+//
+//#using <mscorlib.dll>
+//
+//using namespace System;
+
+
+ResultBuffer:: ResultBuffer(int ThreadCount, int ThreadLogSize)
+ {
+ // Declare an internal status variable
+ int Status=0;
+
+ // Update the maximum thread count
+ MaxThreadCount = ThreadCount;
+
+ // Allocate the memory buffer based on the passed in thread and process counts
+ // and the specified size of the thread specific buffer
+ buffer = NULL;
+ buffer = (char*)malloc(ThreadCount*ThreadLogSize);
+ // Check to see if the buffer memory was allocated
+ if (buffer == NULL)
+ Status = -1;
+ // Initialize the buffer to 0 to prevent bogus data
+ memset(buffer,0,ThreadCount*ThreadLogSize);
+
+ // The ThreadOffset is equal to the total number of bytes that will be stored per thread
+ ThreadOffset = ThreadLogSize;
+
+ }
+
+
+ int ResultBuffer::LogResult(int Thread, char* Data)
+ {
+ // Declare an internal status flad
+ int status = 0;
+
+ // Declare an object to store the offset address into the buffer
+ int Offset;
+
+ // Check to make sure the Thread index is not out of range
+ if(Thread > MaxThreadCount)
+ {
+ Trace("Thread index is out of range, Value of Thread[%d], Value of MaxThreadCount[%d]\n", Thread, MaxThreadCount);
+ status = -1;
+ return(status);
+ }
+
+ // Caculate the offset into the shared buffer based on the process and thread indices
+ Offset = (Thread)*ThreadOffset;
+
+ // Write the passed in data to the reserved buffer
+ memcpy(buffer+Offset,Data,ThreadOffset);
+
+ return(status);
+ }
+
+
+ char* ResultBuffer::getResultBuffer(int threadId)
+ {
+
+ return (buffer + threadId*ThreadOffset);
+
+ }
+
diff --git a/src/pal/tests/palsuite/common/ResultBuffer.h b/src/pal/tests/palsuite/common/ResultBuffer.h
new file mode 100644
index 0000000000..c59d421e2d
--- /dev/null
+++ b/src/pal/tests/palsuite/common/ResultBuffer.h
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//#include <stdio.h>
+//#include <iostream>
+//#include <assert.h>
+#ifndef _RESULT_BUFFER_H_
+#define _RESULT_BUFFER_H_
+
+#include <palsuite.h>
+
+struct ResultData
+{
+ int value;
+ int size;
+// ResultData* NextResult;
+};
+
+ class ResultBuffer
+{
+ // Declare a pointer to a memory buffer to store the logged results
+ char* buffer;
+ // Declare an object to store the maximum Thread count
+ int MaxThreadCount;
+ // Declare and internal data object to store the calculated offset between adjacent threads data sets
+ int ThreadOffset;
+
+ // Declare a linked list object to store the parameter values
+public:
+
+ // Declare a constructor for the single process case
+ ResultBuffer(int ThreadCount, int ThreadLogSize);
+ // Declare a method to log data for the single process instance
+ int LogResult(int Thread, char* Data);
+
+ char* getResultBuffer(int threadId);
+};
+
+#include "resultbuffer.cpp"
+#endif // _RESULT_BUFFER_H_
+
+
diff --git a/src/pal/tests/palsuite/common/ResultTime.h b/src/pal/tests/palsuite/common/ResultTime.h
new file mode 100644
index 0000000000..df706e7a64
--- /dev/null
+++ b/src/pal/tests/palsuite/common/ResultTime.h
@@ -0,0 +1,103 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#ifndef _RESULT_TIME_H_
+#define _RESULT_TIME_H_
+
+#include <palsuite.h>
+
+#define DWORD_MAX ((DWORD) 0xFFFFFFFF)
+const char *szDotNetInstallEnvVar = "DOTNET_INSTALL";
+const char *szQASupportDirEnvVar = "QA_SUPPORT_DIR";
+
+#ifdef PLATFORM_UNIX
+#define SEPERATOR "/"
+#else
+#define SEPERATOR "\\"
+#endif
+char *getBuildNumber()
+{
+ char *szBuildFileName = "buildinfo.txt";
+ char *pDirectoryName = NULL;
+ char szBuildFileLoc[256];
+
+ char szTemp[100];
+ // buildinfo.txt contains information in key/value pair
+ char szTempKey[100];
+ char *szTempValue;
+ FILE *fp;
+
+ szTempValue = (char *) malloc (sizeof(char) *100);
+ if (szTempValue == NULL)
+ {
+ Fail("ERROR: Couldn't allocate enough memory to potentially store build number\n");
+ }
+
+#ifndef PLATFORM_UNIX
+ pDirectoryName = getenv(szDotNetInstallEnvVar);
+ if (pDirectoryName == NULL)
+ {
+ /* This condition may exist if the test is being run in say the Dev environment.*/
+ Trace("WARNING: Coriolis Test Environment may not be setup correctly. Variable DOTNET_INSTALL not set\n");
+ _snprintf(szTempValue, 99, "0000.00");
+ return szTempValue;
+ }
+#else
+ pDirectoryName = getenv(szQASupportDirEnvVar);
+ if (pDirectoryName == NULL)
+ {
+ Trace("WARNING: Coriolis Test Environment may not be setup correctly. Variable QA_SUPPORT_DIR not set\n");
+ _snprintf(szTempValue, 99, "0000.00");
+ return szTempValue;
+ }
+
+#endif //PLATFORM_UNIX
+
+#ifndef PLATFORM_UNIX
+ _snprintf(szBuildFileLoc, MAX_PATH, "%s%s%s", pDirectoryName, SEPERATOR, szBuildFileName);
+#else
+ // To avoid buffer overruns for pDirectoryName
+ _snprintf(szBuildFileLoc, MAX_PATH, "%s/../1.0%s%s", pDirectoryName, SEPERATOR, szBuildFileName);
+#endif //PLATFORM_UNIX
+ fp = fopen( szBuildFileLoc, "r");
+ if( fp == NULL)
+ {
+ Trace("WARNING: Couldn't open szBuildFileLoc [%s]\n", szBuildFileLoc);
+ _snprintf(szTempValue, 99, "0000.00");
+ return szTempValue;
+ }
+
+ while( fgets( szTemp, 100, fp ) != NULL)
+ {
+ sscanf(szTemp, "%s %s\n", szTempKey, szTempValue);
+ if(strcmp(szTempKey, "Build-Number:") == 0)
+ {
+ fclose(fp);
+ return szTempValue;
+ }
+ }
+
+ fclose(fp);
+ return szTempValue;
+
+}
+
+DWORD GetTimeDiff( DWORD dwStartTime)
+{
+ DWORD dwDiffTime = 0;
+ DWORD dwEndTime = GetTickCount();
+
+ if( dwEndTime < dwStartTime)
+ {
+ // To account for overflow, we add one
+ dwDiffTime = dwEndTime + (DWORD_MAX - dwStartTime) + 1;
+ }
+ else
+ {
+ dwDiffTime = dwEndTime - dwStartTime;
+ }
+
+ return dwDiffTime;
+}
+#endif // _RESULT_TIME_H_
diff --git a/src/pal/tests/palsuite/common/pal_stdclib.h b/src/pal/tests/palsuite/common/pal_stdclib.h
new file mode 100644
index 0000000000..61963db67c
--- /dev/null
+++ b/src/pal/tests/palsuite/common/pal_stdclib.h
@@ -0,0 +1,24 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: pal_stdlib.h
+**
+** Purpose:
+**
+**
+**==========================================================================*/
+
+
+#ifndef __PAL_STDCLIB_H__
+#define __PAL_STDCLIB_H__
+
+/*
+ * <stdio.h> definitions & functions
+ */
+
+#define EOF (-1)
+
+#endif // __PAL_STDCLIB_H__
diff --git a/src/pal/tests/palsuite/common/palsuite.h b/src/pal/tests/palsuite/common/palsuite.h
new file mode 100644
index 0000000000..ef644ad8e5
--- /dev/null
+++ b/src/pal/tests/palsuite/common/palsuite.h
@@ -0,0 +1,182 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: palsuite.h
+**
+** Purpose: Define constants and implement functions that are useful to
+** multiple function categories. If common functions are useful
+** only amongst the test cases for a particular function, a separate
+** header file is placed in the root of those test cases.
+**
+**
+**==========================================================================*/
+
+#ifndef __PALSUITE_H__
+#define __PALSUITE_H__
+
+#include <pal_assert.h>
+#include <pal.h>
+#include <palprivate.h>
+
+enum
+{
+ PASS = 0,
+ FAIL = 1
+};
+
+
+void Trace(const char *format, ...)
+{
+ va_list arglist;
+
+ va_start(arglist, format);
+
+ vprintf(format, arglist);
+
+ va_end(arglist);
+}
+
+void Fail(const char *format, ...)
+{
+ va_list arglist;
+
+ va_start(arglist, format);
+
+ vprintf(format, arglist);
+
+ va_end(arglist);
+ printf("\n");
+
+ // This will exit the test process
+ PAL_TerminateEx(FAIL);
+}
+
+#ifdef PAL_PERF
+
+int __cdecl Test_Main(int argc, char **argv);
+int PAL_InitializeResult = 0;
+static const char PALTEST_LOOP_ENV[]="PALTEST_LOOP_COUNT";
+
+int __cdecl main(int argc, char **argv)
+{
+ int lastMainResult=0;
+
+ int loopCount=1; // default: run the test's main once
+ int loopIndex=0;
+ char *szPerfLoopEnv = NULL;
+
+ // Run PAL_Initialize once, save off the result. Any failures here
+ // will be detected later by calls to PAL_Initialize in the test's main.
+ PAL_InitializeResult = PAL_Initialize(argc, argv);
+
+ // Check the environment to see if we need to run the test's main
+ // multiple times. Ideally, we want to do this before PAL_Initialize so
+ // that the overhead of checking the environment is not included in the
+ // time between PAL_Initialize and PAL_Terminate. However, getenv in PAL
+ // can be run only after PAL_Initialize.
+ szPerfLoopEnv = getenv(PALTEST_LOOP_ENV);
+ if (szPerfLoopEnv != NULL)
+ {
+ loopCount = atoi(szPerfLoopEnv);
+ if (loopCount <= 0) loopCount = 1;
+ }
+
+ // call the test's actual main in a loop
+ for(loopIndex=0; loopIndex<loopCount; loopIndex++) {
+ lastMainResult = Test_Main(argc, argv);
+ }
+
+ // call PAL_Terminate for real
+ PAL_TerminateEx(lastMainResult);
+
+ return lastMainResult;
+}
+
+// Test's calls to PAL_Initialize and PAL_Terminate are redirected
+// to these bogus functions. These rely on PAL_Initialize and PAL_Terminate
+// being called by the 'main' above.
+#define PAL_Initialize(a, b) Bogus_PAL_Initialize(a, b)
+#define PAL_Terminate() Bogus_PAL_Terminate()
+int Bogus_PAL_Initialize(int argc, char* argv[])
+{
+ // PAL_Initialize has already been called by the real main.
+ // Just return the result.
+ return PAL_InitializeResult;
+}
+
+void Bogus_PAL_Terminate()
+{
+ // Don't call PAL_Terminate. It will be called later by the
+ // real main.
+ return;
+}
+
+// Rename the main provided by the test case
+#define main Test_Main
+
+#endif // PAL_PERF
+
+#ifdef BIGENDIAN
+inline ULONG VAL32(ULONG x)
+{
+ return( ((x & 0xFF000000L) >> 24) |
+ ((x & 0x00FF0000L) >> 8) |
+ ((x & 0x0000FF00L) << 8) |
+ ((x & 0x000000FFL) << 24) );
+}
+#define th_htons(w) (w)
+#else // BIGENDIAN
+#define VAL32(x) (x)
+#define th_htons(w) (((w) >> 8) | ((w) << 8))
+#endif // BIGENDIAN
+
+
+
+WCHAR* convert(char * aString)
+{
+ int size;
+ WCHAR* wideBuffer;
+
+ size = MultiByteToWideChar(CP_ACP,0,aString,-1,NULL,0);
+ wideBuffer = (WCHAR*) malloc(size*sizeof(WCHAR));
+ if (wideBuffer == NULL)
+ {
+ Fail("ERROR: Unable to allocate memory!\n");
+ }
+ MultiByteToWideChar(CP_ACP,0,aString,-1,wideBuffer,size);
+ return wideBuffer;
+}
+
+char* convertC(WCHAR * wString)
+{
+ int size;
+ char * MultiBuffer = NULL;
+
+ size = WideCharToMultiByte(CP_ACP,0,wString,-1,MultiBuffer,0,NULL,NULL);
+ MultiBuffer = (char*) malloc(size);
+ if (MultiBuffer == NULL)
+ {
+ Fail("ERROR: Unable to allocate memory!\n");
+ }
+ WideCharToMultiByte(CP_ACP,0,wString,-1,MultiBuffer,size,NULL,NULL);
+ return MultiBuffer;
+}
+
+UINT64 GetHighPrecisionTimeStamp(LARGE_INTEGER performanceFrequency)
+{
+ LARGE_INTEGER ts;
+ if (!QueryPerformanceCounter(&ts))
+ {
+ Fail("ERROR: Unable to query performance counter!\n");
+ }
+
+ return ts.QuadPart / (performanceFrequency.QuadPart / 1000);
+}
+
+#endif
+
+
+
diff --git a/src/pal/tests/palsuite/composite/CMakeLists.txt b/src/pal/tests/palsuite/composite/CMakeLists.txt
new file mode 100644
index 0000000000..220b8cc18f
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(object_management)
+add_subdirectory(synchronization)
+add_subdirectory(threading)
+add_subdirectory(wfmo)
+
diff --git a/src/pal/tests/palsuite/composite/object_management/CMakeLists.txt b/src/pal/tests/palsuite/composite/object_management/CMakeLists.txt
new file mode 100644
index 0000000000..5fd88b0046
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/object_management/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(event)
+add_subdirectory(mutex)
+add_subdirectory(semaphore)
+
diff --git a/src/pal/tests/palsuite/composite/object_management/event/CMakeLists.txt b/src/pal/tests/palsuite/composite/object_management/event/CMakeLists.txt
new file mode 100644
index 0000000000..2534564f95
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/object_management/event/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(nonshared)
+add_subdirectory(shared)
+
diff --git a/src/pal/tests/palsuite/composite/object_management/event/nonshared/CMakeLists.txt b/src/pal/tests/palsuite/composite/object_management/event/nonshared/CMakeLists.txt
new file mode 100644
index 0000000000..c6c00377e1
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/object_management/event/nonshared/CMakeLists.txt
@@ -0,0 +1,21 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ event.c
+ main.c
+)
+
+add_executable(paltest_event_nonshared
+ ${SOURCES}
+)
+
+add_dependencies(paltest_event_nonshared coreclrpal)
+
+target_link_libraries(paltest_event_nonshared
+ pthread
+ rt
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/composite/object_management/event/nonshared/event.c b/src/pal/tests/palsuite/composite/object_management/event/nonshared/event.c
new file mode 100644
index 0000000000..69ad9a30e3
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/object_management/event/nonshared/event.c
@@ -0,0 +1,358 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source Code: main.c and event.c
+** main.c creates process and waits for all processes to get over
+** event.c creates a event and then calls threads which will contend for the event
+**
+** This test is for Object Management Test case for event where Object type is shareable.
+** Algorithm
+** o Main Process Creates OBJECT_TYPE Object
+** o Create PROCESS_COUNT processes aware of the Shared Object
+**
+** Author: ShamitP
+**
+**
+**============================================================
+*/
+
+#include <palsuite.h>
+#include "resultbuffer.h"
+#include "resulttime.h"
+
+#define TIMEOUT 5000
+/* Test Input Variables */
+unsigned int USE_PROCESS_COUNT = 0;
+unsigned int THREAD_COUNT = 0;
+unsigned int REPEAT_COUNT = 0;
+unsigned int RELATION_ID= 0;
+
+/* Event variables */
+//unsigned long lInitialCount = 1; /* Signaled */
+//unsigned long lMaximumCount = 1; /* Maximum value of 1 */
+
+/* Capture statistics at per thread basis */
+struct statistics{
+ unsigned int processId;
+ unsigned int operationsFailed;
+ unsigned int operationsPassed;
+ unsigned int operationsTotal;
+ DWORD operationTime;
+ unsigned int relationId;
+};
+
+struct ProcessStats{
+ unsigned int processId;
+ DWORD operationTime;
+ unsigned int relationId;
+};
+
+HANDLE StartTestsEvHandle = NULL;
+HANDLE hEventHandle = NULL;
+
+/* Results Buffer */
+ResultBuffer *resultBuffer = NULL;
+
+int testStatus;
+
+const char sTmpEventName[MAX_PATH_FNAME] = "StartTestEvent";
+
+void PALAPI Run_Thread(LPVOID lpParam);
+
+int GetParameters( int argc, char **argv)
+{
+ if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?"))
+ || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H"))
+ {
+ printf("PAL -Composite Object Management Event Test\n");
+ printf("Usage:\n");
+ printf("Event\n\t[USE_PROCESS_COUNT [greater than 1] \n");
+ printf("\t[THREAD_COUNT [greater than 1] \n");
+ printf("\t[REPEAT_COUNT [greater than 1]\n");
+ printf("\t[RELATION_ID [greater than or Equal to 1]\n");
+
+ return -1;
+ }
+
+ // Trace("Args 1 is [%s], Arg 2 is [%s], Arg 3 is [%s]\n", argv[1], argv[2], argv[3]);
+
+ USE_PROCESS_COUNT = atoi(argv[1]);
+ if( USE_PROCESS_COUNT < 0)
+ {
+ printf("\nInvalid USE_PROCESS_COUNT number, Pass greater than 1\n");
+ return -1;
+ }
+
+ THREAD_COUNT = atoi(argv[2]);
+ if( (THREAD_COUNT < 1) || (THREAD_COUNT > MAXIMUM_WAIT_OBJECTS) )
+ {
+ printf("\nInvalid THREAD_COUNT number, Pass greater than 1 and less than %d\n", MAXIMUM_WAIT_OBJECTS);
+ return -1;
+ }
+
+ REPEAT_COUNT = atoi(argv[3]);
+ if( REPEAT_COUNT < 1)
+ {
+ printf("\nInvalid REPEAT_COUNT number, Pass greater than 1\n");
+ return -1;
+ }
+
+ RELATION_ID = atoi(argv[4]);
+ if( RELATION_ID < 1)
+ {
+ printf("\nMain Process:Invalid RELATION_ID number, Pass greater than 1\n");
+ return -1;
+ }
+
+
+ return 0;
+}
+
+ int __cdecl main(INT argc, CHAR **argv)
+{
+ unsigned int i = 0;
+ HANDLE hThread[MAXIMUM_WAIT_OBJECTS];
+ DWORD threadId[MAXIMUM_WAIT_OBJECTS];
+ int returnCode = 0;
+
+ DWORD dwParam = 0;
+
+ /* Variables to capture the file name and the file pointer at thread level*/
+ char fileName[MAX_LONGPATH];
+ FILE *pFile = NULL;
+ struct statistics* buffer = NULL;
+ int statisticsSize = 0;
+
+ /* Variables to capture the file name and the file pointer at process level*/
+ char processFileName[MAX_LONGPATH];
+ FILE *pProcessFile = NULL;
+ struct ProcessStats processStats;
+ DWORD dwStartTime;
+
+ testStatus = PASS;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ if(GetParameters(argc, argv))
+ {
+ Fail("Error in obtaining the parameters\n");
+ }
+// Trace("Process created, value of process count is [%d]\n", USE_PROCESS_COUNT);
+
+ /* Register the start time */
+ dwStartTime = GetTickCount();
+ processStats.relationId = RELATION_ID;
+ processStats.processId = USE_PROCESS_COUNT;
+
+ _snprintf(processFileName, MAX_LONGPATH, "%d_process_event_%d_.txt", USE_PROCESS_COUNT, RELATION_ID);
+ pProcessFile = fopen(processFileName, "w+");
+ if(pProcessFile == NULL)
+ {
+ Fail("Error in opening process File file for write for process [%d]\n", USE_PROCESS_COUNT);
+ }
+
+ statisticsSize = sizeof(struct statistics);
+
+ _snprintf(fileName, MAX_LONGPATH, "%d_thread_event_%d_.txt", USE_PROCESS_COUNT, RELATION_ID);
+ pFile = fopen(fileName, "w+");
+
+ if(pFile == NULL)
+ {
+ Fail("Error in opening thread File for write for process [%d]\n", USE_PROCESS_COUNT);
+ }
+ // For each thread we will log operations failed (int), passed (int), total (int)
+ // and number of ticks (DWORD) for the operations
+ resultBuffer = new ResultBuffer( THREAD_COUNT, statisticsSize);
+
+ StartTestsEvHandle = CreateEvent(
+ NULL, /* lpEventAttributes*/
+ TRUE, /* bManualReset */
+ FALSE, /* bInitialState */
+ NULL /* name of Event */
+ );
+
+ if( StartTestsEvHandle == NULL )
+ {
+ Fail("Error:%d: Unexpected failure "
+ "to create %s Event for process count %d\n", GetLastError(), sTmpEventName, USE_PROCESS_COUNT );
+
+ }
+
+ /* Create StartTest Event */
+
+ hEventHandle = CreateEvent(
+ NULL, /* lpEventAttributes, inheritable to child processes*/
+ TRUE, /* bAutomaticReset */
+ TRUE, /* bInitialState */
+ NULL
+ );
+
+ if( hEventHandle == NULL)
+ {
+ Fail("Unable to create Event handle for process id [%d], returned error [%d]\n", i, GetLastError());
+ }
+ /* We already assume that the Event was created previously*/
+
+ for( i = 0; i < THREAD_COUNT; i++ )
+ {
+ dwParam = (int) i;
+ //Create thread
+ hThread[i] = CreateThread(
+ NULL, /* no security attributes */
+ 0, /* use default stack size */
+ (LPTHREAD_START_ROUTINE)Run_Thread,/* thread function */
+ (LPVOID)dwParam, /* argument to thread function */
+ 0, /* use default creation flags */
+ &threadId[i] /* returns the thread identifier*/
+ );
+
+
+ if(hThread[i] == NULL)
+ {
+ Fail("Create Thread failed for %d process, and GetLastError value is %d\n", USE_PROCESS_COUNT, GetLastError());
+ }
+
+ }
+
+ if (!SetEvent(StartTestsEvHandle))
+ {
+ Fail("Set Event for Start Tests failed for %d process, and GetLastError value is %d\n", USE_PROCESS_COUNT, GetLastError());
+ }
+ /* Test running */
+ returnCode = WaitForMultipleObjects( THREAD_COUNT, hThread, TRUE, INFINITE);
+
+ if( WAIT_OBJECT_0 != returnCode )
+ {
+ Trace("Wait for Object(s) for %d process returned %d, and GetLastError value is %d\n", USE_PROCESS_COUNT, returnCode, GetLastError());
+ testStatus = FAIL;
+ }
+
+ processStats.operationTime = GetTimeDiff(dwStartTime);
+
+ /* Write to a file*/
+ if(pFile!= NULL)
+ {
+ for( i = 0; i < THREAD_COUNT; i++ )
+ {
+ buffer = (struct statistics *)resultBuffer->getResultBuffer(i);
+ returnCode = fprintf(pFile, "%d,%d,%d,%d,%lu,%d\n", buffer->processId, buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime, buffer->relationId );
+ //Trace("Iteration %d over\n", i);
+
+ }
+ }
+ if(fclose(pFile))
+ {
+ Trace("Error: fclose failed for pFile\n");
+ testStatus = FAIL;
+ }
+
+ fprintf(pProcessFile, "%d,%d,%d\n", USE_PROCESS_COUNT, processStats.operationTime, processStats.relationId );
+ if(fclose(pProcessFile))
+ {
+ Trace("Error: fclose failed for pProcessFile at Process %d\n", USE_PROCESS_COUNT);
+ testStatus = FAIL;
+ }
+
+ /* Logging for the test case over, clean up the handles */
+
+// Trace("Test Thread %d done\n", USE_PROCESS_COUNT);
+ /* Clean Up */
+ for( i = 0; i < THREAD_COUNT; i++ )
+ {
+ if(!CloseHandle(hThread[i]) )
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hThread[%d]\n", GetLastError(), USE_PROCESS_COUNT, i);
+ testStatus = FAIL;
+ }
+ }
+
+ if(!CloseHandle(StartTestsEvHandle))
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] StartTestsEvHandle\n", GetLastError(), USE_PROCESS_COUNT);
+ testStatus = FAIL;
+ }
+
+ if(!CloseHandle(hEventHandle))
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hEventHandle\n", GetLastError(), USE_PROCESS_COUNT);
+ testStatus = FAIL;
+ }
+
+ PAL_Terminate();
+ return testStatus;
+
+}
+
+void PALAPI Run_Thread (LPVOID lpParam)
+{
+ unsigned int i = 0;
+ DWORD dwWaitResult;
+
+ struct statistics stats;
+ DWORD dwStartTime;
+
+ stats.relationId = RELATION_ID;
+ stats.processId = USE_PROCESS_COUNT;
+ stats.operationsFailed = 0;
+ stats.operationsPassed = 0;
+ stats.operationsTotal = 0;
+ stats.operationTime = 0;
+
+ int Id=(int)lpParam;
+
+ dwWaitResult = WaitForSingleObject(
+ StartTestsEvHandle, // handle to start test handle
+ TIMEOUT);
+
+ if(dwWaitResult != WAIT_OBJECT_0)
+ {
+ Fail("Error while waiting for StartTest Event@ thread %d, RC is %d, Error is %d\n", Id, dwWaitResult, GetLastError());
+ }
+
+ dwStartTime = GetTickCount();
+
+ for( i = 0; i < REPEAT_COUNT; i++ )
+ {
+ dwWaitResult = WaitForSingleObject(
+ hEventHandle, // handle to Event
+ TIMEOUT);
+
+ if(dwWaitResult != WAIT_OBJECT_0)
+ {
+// Trace("Error while waiting for onject @ thread %d, # iter %d, RC is %d, Error is %d\n", Id, i, dwWaitResult, GetLastError());
+ stats.operationsFailed += 1;
+ stats.operationsTotal += 1;
+ testStatus = FAIL;
+ continue;
+ }
+
+ if (! SetEvent(hEventHandle))
+ {
+ // Deal with error.
+// Trace("Error while setting Event @ thread %d # iter %d\n", Id, i);
+ stats.operationsFailed += 1;
+ stats.operationsTotal += 1;
+ // Do we need to have while true loop to attempt to set event?
+ testStatus = FAIL;
+ continue;
+ }
+
+ stats.operationsTotal += 1;
+ stats.operationsPassed += 1;
+// Trace("Successs while setting Event @ iteration %d -> thread %d -> Process %d\n", i, Id, USE_PROCESS_COUNT);
+
+ }
+
+ stats.operationTime = GetTimeDiff(dwStartTime);
+ if(resultBuffer->LogResult(Id, (char *)&stats))
+ {
+ Fail("Error:%d: while writing to shared memory, Thread Id is[%d] and Process id is [%d]\n", GetLastError(), Id, USE_PROCESS_COUNT);
+ }
+ //Trace("Thread %d over for process %d\n", Id, USE_PROCESS_COUNT);
+}
diff --git a/src/pal/tests/palsuite/composite/object_management/event/nonshared/main.c b/src/pal/tests/palsuite/composite/object_management/event/nonshared/main.c
new file mode 100644
index 0000000000..7b61e91737
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/object_management/event/nonshared/main.c
@@ -0,0 +1,228 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source Code: main.c and event.c
+** main.c creates process and waits for all processes to get over
+** event.c creates a event and then calls threads which will contend for the event
+**
+** This test is for Object Management Test case for event where Object type is not shareable.
+** Algorithm
+** o Create PROCESS_COUNT processes.
+** o Main Thread of each process creates OBJECT_TYPE Object
+**
+** Author: ShamitP
+**============================================================
+*/
+
+#include <palsuite.h>
+#include "resulttime.h"
+
+/* Test Input Variables */
+unsigned int PROCESS_COUNT = 10;
+unsigned int THREAD_COUNT = 20;
+unsigned int REPEAT_COUNT = 20000;
+unsigned int RELATION_ID = 1001;
+
+
+struct TestStats{
+ DWORD operationTime;
+ unsigned int relationId;
+ unsigned int processCount;
+ unsigned int threadCount;
+ unsigned int repeatCount;
+ char* buildNumber;
+
+};
+
+
+int GetParameters( int argc, char **argv)
+{
+ if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?"))
+ || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H"))
+ {
+ printf("PAL -Composite Object Management event Test\n");
+ printf("Usage:\n");
+ printf("main\n\t[PROCESS_COUNT [greater than 1] \n");
+ printf("\t[THREAD_COUNT [greater than 1] \n");
+ printf("\t[REPEAT_COUNT [greater than 1]\n");
+ printf("\t[RELATION_ID [greater than or Equal to 1]\n");
+ return -1;
+ }
+
+ PROCESS_COUNT = atoi(argv[1]);
+ if( (PROCESS_COUNT < 1) || (PROCESS_COUNT > MAXIMUM_WAIT_OBJECTS) )
+ {
+ printf("\nMain Process:Invalid PROCESS_COUNT number, Pass greater than 1 and less than PROCESS_COUNT %d\n", MAXIMUM_WAIT_OBJECTS);
+ return -1;
+ }
+
+ THREAD_COUNT = atoi(argv[2]);
+ if( (THREAD_COUNT < 1) || (THREAD_COUNT > MAXIMUM_WAIT_OBJECTS) )
+ {
+ printf("\nInvalid THREAD_COUNT number, Pass greater than 1 and less than %d\n", MAXIMUM_WAIT_OBJECTS);
+ return -1;
+ }
+
+ REPEAT_COUNT = atoi(argv[3]);
+ if( REPEAT_COUNT < 1)
+ {
+ printf("\nMain Process:Invalid REPEAT_COUNT number, Pass greater than 1\n");
+ return -1;
+ }
+
+ RELATION_ID = atoi(argv[4]);
+ if( RELATION_ID < 1)
+ {
+ printf("\nMain Process:Invalid RELATION_ID number, Pass greater than 1\n");
+ return -1;
+ }
+
+
+ return 0;
+}
+
+ int __cdecl main(INT argc, CHAR **argv)
+{
+ unsigned int i = 0;
+ HANDLE hProcess[MAXIMUM_WAIT_OBJECTS];
+
+ STARTUPINFO si[MAXIMUM_WAIT_OBJECTS];
+ PROCESS_INFORMATION pi[MAXIMUM_WAIT_OBJECTS];
+
+ char lpCommandLine[MAX_LONGPATH] = "";
+ const char *ObjName = "Event";
+
+ int returnCode = 0;
+ DWORD processReturnCode = 0;
+ int testReturnCode = PASS;
+
+ char fileName[MAX_LONGPATH];
+ FILE *pFile = NULL;
+ DWORD dwStartTime = 0;
+ struct TestStats testStats;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ if(GetParameters(argc, argv))
+ {
+ Fail("Error in obtaining the parameters\n");
+ }
+
+ /* Register the start time */
+ dwStartTime = GetTickCount();
+ testStats.relationId = RELATION_ID;
+ testStats.processCount = PROCESS_COUNT;
+ testStats.threadCount = THREAD_COUNT;
+ testStats.repeatCount = REPEAT_COUNT;
+ testStats.buildNumber = getBuildNumber();
+
+
+ _snprintf(fileName, MAX_LONGPATH, "main_event_%d_.txt", RELATION_ID);
+ pFile = fopen(fileName, "w+");
+ if(pFile == NULL)
+ {
+ Fail("Error in opening main file for write\n");
+ }
+
+ for( i = 0; i < PROCESS_COUNT; i++ )
+ {
+
+ ZeroMemory( lpCommandLine, MAX_PATH );
+ if ( _snprintf( lpCommandLine, MAX_LONGPATH-1, "event %d %d %d %d", i, THREAD_COUNT, REPEAT_COUNT, RELATION_ID) < 0 )
+ {
+ Fail ("Error: Insufficient Event name string length for %s for iteration [%d]\n", ObjName, i);
+ }
+
+ /* Zero the data structure space */
+ ZeroMemory ( &pi[i], sizeof(pi[i]) );
+ ZeroMemory ( &si[i], sizeof(si[i]) );
+
+ /* Set the process flags and standard io handles */
+ si[i].cb = sizeof(si[i]);
+
+ //Create Process
+ if(!CreateProcess( NULL, /* lpApplicationName*/
+ lpCommandLine, /* lpCommandLine */
+ NULL, /* lpProcessAttributes */
+ NULL, /* lpThreadAttributes */
+ TRUE, /* bInheritHandles */
+ 0, /* dwCreationFlags, */
+ NULL, /* lpEnvironment */
+ NULL, /* pCurrentDirectory */
+ &si[i], /* lpStartupInfo */
+ &pi[i] /* lpProcessInformation */
+ ))
+ {
+ Fail("Process Not created for [%d], the error code is [%d]\n", i, GetLastError());
+ }
+ else
+ {
+ hProcess[i] = pi[i].hProcess;
+ //Trace("Process created for [%d]\n", i);
+
+ }
+
+ }
+
+ returnCode = WaitForMultipleObjects( PROCESS_COUNT, hProcess, TRUE, INFINITE);
+ if( WAIT_OBJECT_0 != returnCode )
+ {
+ Trace("Wait for Object(s) @ Main thread for %d processes returned %d, and GetLastError value is %d\n", PROCESS_COUNT, returnCode, GetLastError());
+ testReturnCode = FAIL;
+ }
+
+ for( i = 0; i < PROCESS_COUNT; i++ )
+ {
+ /* check the exit code from the process */
+ if( ! GetExitCodeProcess( pi[i].hProcess, &processReturnCode ) )
+ {
+ Trace( "GetExitCodeProcess call failed for iteration %d with error code %u\n",
+ i, GetLastError() );
+
+ testReturnCode = FAIL;
+ }
+
+ if(processReturnCode == FAIL)
+ {
+ Trace( "Process [%d] failed and returned FAIL\n", i);
+ testReturnCode = FAIL;
+ }
+
+ if(!CloseHandle(pi[i].hThread))
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hThread\n", GetLastError(), i);
+ testReturnCode = FAIL;
+ }
+
+ if(!CloseHandle(pi[i].hProcess) )
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hProcess\n", GetLastError(), i);
+ testReturnCode = FAIL;
+ }
+ }
+
+ testStats.operationTime = GetTimeDiff(dwStartTime);
+ fprintf(pFile, "%d,%d,%d,%d,%d,%s\n", testStats.operationTime, testStats.relationId, testStats.processCount, testStats.threadCount, testStats.repeatCount, testStats.buildNumber);
+ if(fclose(pFile))
+ {
+ Trace("Error: fclose failed for pFile\n");
+ testReturnCode = FAIL;
+ }
+
+ if( testReturnCode == PASS)
+ {
+ Trace("Test Passed\n");
+ }
+ else
+ {
+ Trace("Test Failed\n");
+ }
+ PAL_Terminate();
+ return testReturnCode;
+}
diff --git a/src/pal/tests/palsuite/composite/object_management/event/shared/CMakeLists.txt b/src/pal/tests/palsuite/composite/object_management/event/shared/CMakeLists.txt
new file mode 100644
index 0000000000..d326e3a42b
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/object_management/event/shared/CMakeLists.txt
@@ -0,0 +1,21 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ event.c
+ main.c
+)
+
+add_executable(paltest_event_shared
+ ${SOURCES}
+)
+
+add_dependencies(paltest_event_shared coreclrpal)
+
+target_link_libraries(paltest_event_shared
+ pthread
+ rt
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/composite/object_management/event/shared/event.c b/src/pal/tests/palsuite/composite/object_management/event/shared/event.c
new file mode 100644
index 0000000000..83d5fce27e
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/object_management/event/shared/event.c
@@ -0,0 +1,373 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source Code: main.c and event.c
+** main.c creates process and waits for all processes to get over
+** event.c creates a event and then calls threads which will contend for the event
+**
+** This test is for Object Management Test case for event where Object type is shareable.
+** Algorithm
+** o Main Process Creates OBJECT_TYPE Object
+** o Create PROCESS_COUNT processes aware of the Shared Object
+**
+** Author: ShamitP
+** Author: ShamitP
+**
+**
+**============================================================
+*/
+
+#include <palsuite.h>
+#include "resultbuffer.h"
+#include "resulttime.h"
+
+#define TIMEOUT 5000
+/* Test Input Variables */
+unsigned int USE_PROCESS_COUNT = 0;
+unsigned int THREAD_COUNT = 0;
+unsigned int REPEAT_COUNT = 0;
+unsigned int RELATION_ID = 0;
+
+/* Capture statistics at per thread basis */
+struct statistics{
+ unsigned int processId;
+ unsigned int operationsFailed;
+ unsigned int operationsPassed;
+ unsigned int operationsTotal;
+ DWORD operationTime;
+ unsigned int relationId;
+};
+
+struct ProcessStats{
+ unsigned int processId;
+ DWORD operationTime;
+ unsigned int relationId;
+};
+
+HANDLE StartTestsEvHandle = NULL;
+HANDLE hEventHandle = NULL;
+
+/* Results Buffer */
+ResultBuffer *resultBuffer= NULL;
+
+int testStatus;
+
+const char sTmpEventName[MAX_PATH] = "StartTestEvent";
+char objectSuffix[MAX_PATH];
+
+void PALAPI Run_Thread(LPVOID lpParam);
+
+int GetParameters( int argc, char **argv)
+{
+ if( (!((argc == 5) || (argc == 6) ) )|| ((argc == 1) && !strcmp(argv[1],"/?"))
+ || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H"))
+ {
+ printf("PAL -Composite Object Management event Test\n");
+ printf("Usage:\n");
+ printf("main\n\t[USE_PROCESS_COUNT (greater than 1)] \n");
+ printf("\t[THREAD_COUNT (greater than 1)] \n");
+ printf("\t[REPEAT_COUNT (greater than 1)]\n");
+ printf("\t[RELATION_ID [greater than or equal to 1]\n");
+ printf("\t[Object Name Suffix]\n");
+
+ return -1;
+ }
+
+ // Trace("Args 1 is [%s], Arg 2 is [%s], Arg 3 is [%s]\n", argv[1], argv[2], argv[3]);
+
+ USE_PROCESS_COUNT = atoi(argv[1]);
+ if( USE_PROCESS_COUNT < 0)
+ {
+ printf("\nInvalid USE_PROCESS_COUNT number, Pass greater than 1\n");
+ return -1;
+ }
+
+ THREAD_COUNT = atoi(argv[2]);
+ if( (THREAD_COUNT < 1) || (THREAD_COUNT > MAXIMUM_WAIT_OBJECTS) )
+ {
+ printf("\nInvalid THREAD_COUNT number, Pass greater than 1 and less than %d\n", MAXIMUM_WAIT_OBJECTS);
+ return -1;
+ }
+
+ REPEAT_COUNT = atoi(argv[3]);
+ if( REPEAT_COUNT < 1)
+ {
+ printf("\nInvalid REPEAT_COUNT number, Pass greater than 1\n");
+ return -1;
+ }
+
+ RELATION_ID = atoi(argv[4]);
+ if( RELATION_ID < 1)
+ {
+ printf("\nMain Process:Invalid RELATION_ID number, Pass greater than 1\n");
+ return -1;
+ }
+
+ if(argc == 6)
+ {
+ strncpy(objectSuffix, argv[5], MAX_PATH-1);
+ }
+
+ return 0;
+}
+
+ int __cdecl main(INT argc, CHAR **argv)
+{
+ unsigned int i = 0;
+ HANDLE hThread[MAXIMUM_WAIT_OBJECTS];
+ DWORD threadId[MAXIMUM_WAIT_OBJECTS];
+
+ WCHAR *wcObjName = NULL;
+
+ char ObjName[MAX_PATH] = "SHARED_EVENT";
+ DWORD dwParam = 0;
+
+ int returnCode = 0;
+
+ /* Variables to capture the file name and the file pointer at thread level*/
+ char fileName[MAX_PATH];
+ FILE *pFile = NULL;
+ struct statistics* buffer = NULL;
+ int statisticsSize = 0;
+
+ /* Variables to capture the file name and the file pointer at process level*/
+ char processFileName[MAX_PATH];
+ FILE *pProcessFile = NULL;
+ struct ProcessStats processStats;
+ DWORD dwStartTime;
+
+ testStatus = PASS;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ ZeroMemory( objectSuffix, MAX_PATH );
+
+ if(GetParameters(argc, argv))
+ {
+ Fail("Error in obtaining the parameters\n");
+ }
+// Trace("Process created, value of process count is [%d]\n", USE_PROCESS_COUNT);
+
+ if(argc == 5)
+ {
+ strncat(ObjName, objectSuffix, MAX_PATH - (sizeof(ObjName) + 1) );
+ }
+
+ /* Register the start time */
+ dwStartTime = GetTickCount();
+ processStats.relationId = RELATION_ID;
+ processStats.processId = USE_PROCESS_COUNT;
+
+ _snprintf(processFileName, MAX_PATH, "%d_process_event_%d_.txt", USE_PROCESS_COUNT, RELATION_ID);
+ pProcessFile = fopen(processFileName, "w+");
+ if(pProcessFile == NULL)
+ {
+ Fail("Error:%d: in opening Process File for write for process [%d]\n", GetLastError(), USE_PROCESS_COUNT);
+ }
+
+ statisticsSize = sizeof(struct statistics);
+
+ _snprintf(fileName, MAX_PATH, "%d_thread_event_%d_.txt", USE_PROCESS_COUNT, RELATION_ID);
+ pFile = fopen(fileName, "w+");
+
+ if(pFile == NULL)
+ {
+ Fail("Error:%d: in opening thread file for write for process [%d]\n", GetLastError(), USE_PROCESS_COUNT);
+ }
+ // For each thread we will log operations failed (int), passed (int), total (int)
+ // and number of ticks (DWORD) for the operations
+ resultBuffer = new ResultBuffer( THREAD_COUNT, statisticsSize);
+
+ wcObjName = convert(ObjName);
+
+ StartTestsEvHandle = CreateEvent( NULL, /* lpEventAttributes*/
+ TRUE, /* bManualReset */
+ FALSE, /* bInitialState */
+ NULL); /* name of Event */
+
+ if( StartTestsEvHandle == NULL )
+ {
+ Fail("Error:%d: Unexpected failure "
+ "to create %s Event for process count %d\n", GetLastError(), sTmpEventName, USE_PROCESS_COUNT );
+
+ }
+
+ /* Create StartTest Event */
+
+ hEventHandle = OpenEventW(
+ EVENT_ALL_ACCESS, /* lpEventAttributes, inheritable to child processes*/
+ FALSE, /* bAutomaticReset */
+ wcObjName
+ );
+
+ if( hEventHandle == NULL)
+ {
+ Fail("Unable to create Event handle for process id [%d], returned error [%d]\n", i, GetLastError());
+ }
+ /* We already assume that the Event was created previously*/
+
+ for( i = 0; i < THREAD_COUNT; i++ )
+ {
+ dwParam = (int) i;
+ //Create thread
+ hThread[i] = CreateThread(
+ NULL, /* no security attributes */
+ 0, /* use default stack size */
+ (LPTHREAD_START_ROUTINE)Run_Thread,/* thread function */
+ (LPVOID)dwParam, /* argument to thread function */
+ 0, /* use default creation flags */
+ &threadId[i] /* returns the thread identifier*/
+ );
+
+ if(hThread[i] == NULL)
+ {
+ Fail("Create Thread failed for %d process, and GetLastError value is %d\n", USE_PROCESS_COUNT, GetLastError());
+ }
+
+ }
+
+ if (!SetEvent(StartTestsEvHandle))
+ {
+ Fail("Set Event for Start Tests failed for %d process, and GetLastError value is %d\n", USE_PROCESS_COUNT, GetLastError());
+ }
+
+ /* Test running */
+ returnCode = WaitForMultipleObjects( THREAD_COUNT, hThread, TRUE, INFINITE);
+
+ if( WAIT_OBJECT_0 != returnCode )
+ {
+ Trace("Wait for Object(s) for %d process returned %d, and GetLastError value is %d\n", USE_PROCESS_COUNT, returnCode, GetLastError());
+ testStatus = FAIL;
+ }
+
+ processStats.operationTime = GetTimeDiff(dwStartTime);
+
+ /* Write to a file*/
+ if(pFile!= NULL)
+ {
+ for( i = 0; i < THREAD_COUNT; i++ )
+ {
+ buffer = (struct statistics *)resultBuffer->getResultBuffer(i);
+ returnCode = fprintf(pFile, "%d,%d,%d,%d,%lu,%d\n", buffer->processId, buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime, buffer->relationId );
+// Trace("Iteration %d over\n", i);
+
+ }
+ }
+
+ if(fclose(pFile))
+ {
+ Trace("Error: fclose failed for pFile at Process %d\n", USE_PROCESS_COUNT);
+ testStatus = FAIL;
+ }
+
+ fprintf(pProcessFile, "%d,%d,%d\n", USE_PROCESS_COUNT, processStats.operationTime, processStats.relationId );
+ if(fclose(pProcessFile))
+ {
+ Trace("Error: fclose failed for pProcessFile at Process %d\n", USE_PROCESS_COUNT);
+ testStatus = FAIL;
+ }
+ /* Logging for the test case over, clean up the handles */
+
+// Trace("Test Thread %d done\n", USE_PROCESS_COUNT);
+
+ for( i = 0; i < THREAD_COUNT; i++ )
+ {
+ if(!CloseHandle(hThread[i]) )
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hThread[%d]\n", GetLastError(), USE_PROCESS_COUNT, i);
+ testStatus = FAIL;
+ }
+ }
+
+ if(!CloseHandle(StartTestsEvHandle))
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] StartTestsEvHandle\n", GetLastError(), USE_PROCESS_COUNT);
+ testStatus = FAIL;
+ }
+
+ if(!CloseHandle(hEventHandle))
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hEventHandle\n", GetLastError(), USE_PROCESS_COUNT);
+ testStatus = FAIL;
+ }
+
+ free(wcObjName);
+ PAL_Terminate();
+ return testStatus;
+}
+
+void PALAPI Run_Thread (LPVOID lpParam)
+{
+ unsigned int i = 0;
+ DWORD dwWaitResult;
+
+ struct statistics stats;
+ DWORD dwStartTime;
+
+ stats.relationId = RELATION_ID;
+ stats.processId = USE_PROCESS_COUNT;
+ stats.operationsFailed = 0;
+ stats.operationsPassed = 0;
+ stats.operationsTotal = 0;
+ stats.operationTime = 0;
+
+ int Id=(int)lpParam;
+
+ dwWaitResult = WaitForSingleObject(
+ StartTestsEvHandle, // handle to start test handle
+ TIMEOUT);
+
+ if(dwWaitResult != WAIT_OBJECT_0)
+ {
+ Trace("Error:%d: while waiting for StartTest Event@ thread %d\n", GetLastError(), Id);
+ testStatus = FAIL;
+ }
+
+ dwStartTime = GetTickCount();
+
+ for( i = 0; i < REPEAT_COUNT; i++ )
+ {
+ dwWaitResult = WaitForSingleObject(
+ hEventHandle, // handle to Event
+ TIMEOUT);
+
+ if(dwWaitResult != WAIT_OBJECT_0)
+ {
+ //Trace("Error:%d: while waiting for onject @ thread %d, # iter %d\n", GetLastError(), Id, i);
+ stats.operationsFailed += 1;
+ stats.operationsTotal += 1;
+ testStatus = FAIL;
+ continue;
+ }
+
+ if (! SetEvent(hEventHandle))
+ {
+ // Deal with error.
+// Trace("Error while setting Event @ thread %d # iter %d\n", Id, i);
+ stats.operationsFailed += 1;
+ stats.operationsTotal += 1;
+ // do we need to have while true loop to attempt to set event...?
+ testStatus = FAIL;
+ continue;
+ }
+
+ stats.operationsTotal += 1;
+ stats.operationsPassed += 1;
+ // Trace("Successs while setting Event @ iteration %d -> thread %d -> Process %d for handle %d\n", i, Id, USE_PROCESS_COUNT, hEventHandle);
+
+ }
+
+ stats.operationTime = GetTimeDiff(dwStartTime);
+ //Trace("OPeration time is %d", stats.operationTime );
+ if(resultBuffer->LogResult(Id, (char *)&stats))
+ {
+ Fail("Error:%d: while writing to shared memory, Thread Id is[%d] and Process id is [%d]\n", GetLastError(), Id, USE_PROCESS_COUNT);
+ }
+ //Trace("Thread %d over for process %d\n", Id, USE_PROCESS_COUNT);
+}
diff --git a/src/pal/tests/palsuite/composite/object_management/event/shared/main.c b/src/pal/tests/palsuite/composite/object_management/event/shared/main.c
new file mode 100644
index 0000000000..c4a4067b5d
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/object_management/event/shared/main.c
@@ -0,0 +1,265 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source Code: main.c and event.c
+** main.c creates process and waits for all processes to get over
+** event.c creates a event and then calls threads which will contend for the event
+**
+** This test is for Object Management Test case for event where Object type is shareable.
+** Algorithm
+** o Main Process Creates OBJECT_TYPE Object
+** o Create PROCESS_COUNT processes aware of the Shared Object
+**
+** Author: ShamitP
+**
+**
+**============================================================
+*/
+#include <palsuite.h>
+#include "resulttime.h"
+
+/* Test Input Variables */
+unsigned int PROCESS_COUNT = 2;
+unsigned int THREAD_COUNT = 20;
+unsigned int REPEAT_COUNT = 200;
+unsigned int RELATION_ID = 1001;
+
+
+char objectSuffix[MAX_PATH_FNAME];
+
+struct TestStats{
+ DWORD operationTime;
+ unsigned int relationId;
+ unsigned int processCount;
+ unsigned int threadCount;
+ unsigned int repeatCount;
+ char* buildNumber;
+
+};
+
+int GetParameters( int argc, char **argv)
+{
+ if( (!((argc == 5) || (argc == 6) ) )|| ((argc == 1) && !strcmp(argv[1],"/?"))
+ || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H"))
+ {
+ printf("PAL -Composite Object Management event Test\n");
+ printf("Usage:\n");
+ printf("main\n\t[PROCESS_COUNT (greater than 1)] \n");
+ printf("\t[THREAD_COUNT (greater than 1)] \n");
+ printf("\t[REPEAT_COUNT (greater than 1)]\n");
+ printf("\t[RELATION_ID [greater than or equal to 1]\n");
+ printf("\t[Object Name Suffix]\n");
+ return -1;
+ }
+
+ PROCESS_COUNT = atoi(argv[1]);
+ if( (PROCESS_COUNT < 1) || (PROCESS_COUNT > MAXIMUM_WAIT_OBJECTS) )
+ {
+ printf("\nMain Process:Invalid PROCESS_COUNT number, Pass greater than 1 and less than PROCESS_COUNT %d\n", MAXIMUM_WAIT_OBJECTS);
+ return -1;
+ }
+
+ THREAD_COUNT = atoi(argv[2]);
+ if( (THREAD_COUNT < 1) || (THREAD_COUNT > MAXIMUM_WAIT_OBJECTS) )
+ {
+ printf("\nInvalid THREAD_COUNT number, Pass greater than 1 and less than %d\n", MAXIMUM_WAIT_OBJECTS);
+ return -1;
+ }
+
+ REPEAT_COUNT = atoi(argv[3]);
+ if( REPEAT_COUNT < 1)
+ {
+ printf("\nMain Process:Invalid REPEAT_COUNT number, Pass greater than 1\n");
+ return -1;
+ }
+
+ RELATION_ID = atoi(argv[4]);
+ if( RELATION_ID < 1)
+ {
+ printf("\nMain Process:Invalid RELATION_ID number, Pass greater than 1\n");
+ return -1;
+ }
+
+
+ if(argc == 6)
+ {
+ strncpy(objectSuffix, argv[5], MAX_PATH_FNAME-1);
+ }
+
+ return 0;
+}
+
+ int __cdecl main(INT argc, CHAR **argv)
+{
+ unsigned int i = 0;
+ HANDLE hProcess[MAXIMUM_WAIT_OBJECTS];
+ HANDLE hEventHandle;
+
+ STARTUPINFO si[MAXIMUM_WAIT_OBJECTS];
+ PROCESS_INFORMATION pi[MAXIMUM_WAIT_OBJECTS];
+
+ char lpCommandLine[MAX_LONGPATH] = "";
+ char ObjName[MAX_PATH_FNAME] = "SHARED_EVENT";
+
+ int returnCode = 0;
+ DWORD processReturnCode = 0;
+ int testReturnCode = PASS;
+
+ char fileName[MAX_PATH_FNAME];
+ FILE *pFile = NULL;
+ DWORD dwStartTime;
+ struct TestStats testStats;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ ZeroMemory( objectSuffix, MAX_PATH_FNAME );
+
+ if(GetParameters(argc, argv))
+ {
+ Fail("Error in obtaining the parameters\n");
+ }
+
+ if(argc == 5)
+ {
+ strncat(ObjName, objectSuffix, MAX_PATH_FNAME - (sizeof(ObjName) + 1) );
+ }
+
+ /* Register the start time */
+ dwStartTime = GetTickCount();
+ testStats.relationId = RELATION_ID;
+ testStats.processCount = PROCESS_COUNT;
+ testStats.threadCount = THREAD_COUNT;
+ testStats.repeatCount = REPEAT_COUNT;
+ testStats.buildNumber = getBuildNumber();
+
+
+ _snprintf(fileName, MAX_PATH_FNAME, "main_event_%d_.txt", RELATION_ID);
+ pFile = fopen(fileName, "w+");
+ if(pFile == NULL)
+ {
+ Fail("Error in opening main file for write\n");
+ }
+
+ hEventHandle = CreateEvent(
+ NULL, /* lpEventAttributes, inheritable to child processes*/
+ TRUE, /* bAutomaticReset */
+ TRUE, /* bInitialState */
+ ObjName
+ );
+
+ if( hEventHandle == NULL)
+ {
+ Fail("Unable to create Event handle, returned error [%d]\n", GetLastError());
+ }
+
+ for( i = 0; i < PROCESS_COUNT; i++ )
+ {
+
+ ZeroMemory( lpCommandLine, MAX_PATH_FNAME );
+ if ( _snprintf( lpCommandLine, MAX_PATH_FNAME-1, "event %d %d %d %d %s", i, THREAD_COUNT, REPEAT_COUNT, RELATION_ID, objectSuffix) < 0 )
+ {
+ Fail ("Error: Insufficient Event name string length for %s for iteration [%d]\n", ObjName, i);
+ }
+
+ /* Zero the data structure space */
+ ZeroMemory ( &pi[i], sizeof(pi[i]) );
+ ZeroMemory ( &si[i], sizeof(si[i]) );
+
+ /* Set the process flags and standard io handles */
+ si[i].cb = sizeof(si[i]);
+
+ if(!CreateProcess( NULL, /* lpApplicationName*/
+ lpCommandLine, /* lpCommandLine */
+ NULL, /* lpProcessAttributes */
+ NULL, /* lpThreadAttributes */
+ TRUE, /* bInheritHandles */
+ 0, /* dwCreationFlags, */
+ NULL, /* lpEnvironment */
+ NULL, /* pCurrentDirectory */
+ &si[i], /* lpStartupInfo */
+ &pi[i] /* lpProcessInformation */
+ ))
+ {
+ Fail("Process Not created for [%d], the error code is [%d]\n", i, GetLastError());
+ }
+ else
+ {
+ hProcess[i] = pi[i].hProcess;
+// Trace("Process created for [%d]\n", i);
+
+ }
+
+ //Create Process
+
+ }
+
+ returnCode = WaitForMultipleObjects( PROCESS_COUNT, hProcess, TRUE, INFINITE);
+ if( WAIT_OBJECT_0 != returnCode )
+ {
+ Trace("Wait for Object(s) @ Main thread for %d processes returned %d, and GetLastError value is %d\n", PROCESS_COUNT, returnCode, GetLastError());
+ testReturnCode = FAIL;
+ }
+
+// Trace("Test over\n");
+ for( i = 0; i < PROCESS_COUNT; i++ )
+ {
+ /* check the exit code from the process */
+ if( ! GetExitCodeProcess( pi[i].hProcess, &processReturnCode ) )
+ {
+ Trace( "GetExitCodeProcess call failed for iteration %d with error code %u\n",
+ i, GetLastError() );
+
+ testReturnCode = FAIL;
+ }
+
+ if(processReturnCode == FAIL)
+ {
+ Trace( "Process [%d] failed and returned FAIL\n", i);
+ testReturnCode = FAIL;
+ }
+
+ if(!CloseHandle(pi[i].hThread))
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hThread\n", GetLastError(), i);
+ testReturnCode = FAIL;
+ }
+
+ if(!CloseHandle(pi[i].hProcess) )
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hProcess\n", GetLastError(), i);
+ testReturnCode = FAIL;
+ }
+ }
+
+ testStats.operationTime = GetTimeDiff(dwStartTime);
+ fprintf(pFile, "%d,%d,%d,%d,%d,%s\n", testStats.operationTime, testStats.relationId, testStats.processCount, testStats.threadCount, testStats.repeatCount, testStats.buildNumber);
+ if(fclose(pFile))
+ {
+ Trace("Error: fclose failed for pFile\n");
+ testReturnCode = FAIL;
+ }
+
+ if(!CloseHandle(hEventHandle))
+ {
+ Trace("Error:%d: CloseHandle failed for hEventHandle\n", GetLastError());
+ testReturnCode = FAIL;
+ }
+
+ if( testReturnCode == PASS)
+ {
+ Trace("Test Passed\n");
+ }
+ else
+ {
+ Trace("Test Failed\n");
+ }
+
+ PAL_Terminate();
+ return testReturnCode;
+}
diff --git a/src/pal/tests/palsuite/composite/object_management/mutex/CMakeLists.txt b/src/pal/tests/palsuite/composite/object_management/mutex/CMakeLists.txt
new file mode 100644
index 0000000000..2534564f95
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/object_management/mutex/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(nonshared)
+add_subdirectory(shared)
+
diff --git a/src/pal/tests/palsuite/composite/object_management/mutex/nonshared/CMakeLists.txt b/src/pal/tests/palsuite/composite/object_management/mutex/nonshared/CMakeLists.txt
new file mode 100644
index 0000000000..7859cd4653
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/object_management/mutex/nonshared/CMakeLists.txt
@@ -0,0 +1,21 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ main.c
+ mutex.c
+)
+
+add_executable(paltest_mutex_nonshared
+ ${SOURCES}
+)
+
+add_dependencies(paltest_mutex_nonshared coreclrpal)
+
+target_link_libraries(paltest_mutex_nonshared
+ pthread
+ rt
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/composite/object_management/mutex/nonshared/main.c b/src/pal/tests/palsuite/composite/object_management/mutex/nonshared/main.c
new file mode 100644
index 0000000000..80f31aad6e
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/object_management/mutex/nonshared/main.c
@@ -0,0 +1,230 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source Code: main.c and mutex.c
+** main.c creates process and waits for all processes to get over
+** mutex.c creates a mutex and then calls threads which will contend for the mutex
+**
+** This test is for Object Management Test case for Mutex where Object type is not shareable.
+** Algorithm
+** o Create PROCESS_COUNT processes.
+** o Main Thread of each process creates OBJECT_TYPE Object
+**
+** Author: ShamitP
+**============================================================
+*/
+
+#include <palsuite.h>
+#include "resulttime.h"
+
+/* Test Input Variables */
+unsigned int PROCESS_COUNT = 2;
+unsigned int THREAD_COUNT = 20;
+unsigned int REPEAT_COUNT = 4000;
+unsigned int RELATION_ID = 1001;
+
+
+struct TestStats{
+ DWORD operationTime;
+ unsigned int relationId;
+ unsigned int processCount;
+ unsigned int threadCount;
+ unsigned int repeatCount;
+ char* buildNumber;
+
+};
+
+int GetParameters( int argc, char **argv)
+{
+ if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?"))
+ || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H"))
+ {
+ printf("PAL -Composite Object Management Mutex Test\n");
+ printf("Usage:\n");
+ printf("main\n\t[PROCESS_COUNT [greater than 1] \n");
+ printf("\t[THREAD_COUNT [greater than 1] \n");
+ printf("\t[REPEAT_COUNT [greater than 1]\n");
+ printf("\t[RELATION_ID [greater than 1]\n");
+
+
+ return -1;
+ }
+
+ PROCESS_COUNT = atoi(argv[1]);
+ if( (PROCESS_COUNT < 1) || (PROCESS_COUNT > MAXIMUM_WAIT_OBJECTS) )
+ {
+ printf("\nMain Process:Invalid PROCESS_COUNT number, Pass greater than 1 and less than PROCESS_COUNT %d\n", MAXIMUM_WAIT_OBJECTS);
+ return -1;
+ }
+
+ THREAD_COUNT = atoi(argv[2]);
+ if( (THREAD_COUNT < 1) || (THREAD_COUNT > MAXIMUM_WAIT_OBJECTS) )
+ {
+ printf("\nInvalid THREAD_COUNT number, Pass greater than 1 and less than %d\n", MAXIMUM_WAIT_OBJECTS);
+ return -1;
+ }
+
+ REPEAT_COUNT = atoi(argv[3]);
+ if( REPEAT_COUNT < 1)
+ {
+ printf("\nMain Process:Invalid REPEAT_COUNT number, Pass greater than 1\n");
+ return -1;
+ }
+
+ RELATION_ID = atoi(argv[4]);
+ if( RELATION_ID < 1)
+ {
+ printf("\nMain Process:Invalid RELATION_ID number, Pass greater than 1\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+ int __cdecl main(INT argc, CHAR **argv)
+{
+ unsigned int i = 0;
+ HANDLE hProcess[MAXIMUM_WAIT_OBJECTS];
+ HANDLE hMutexHandle[MAXIMUM_WAIT_OBJECTS];
+
+ STARTUPINFO si[MAXIMUM_WAIT_OBJECTS];
+ PROCESS_INFORMATION pi[MAXIMUM_WAIT_OBJECTS];
+
+ const char *ObjName = "Mutex";
+ char lpCommandLine[MAX_PATH] = "";
+
+ int returnCode = 0;
+ DWORD processReturnCode = 0;
+ int testReturnCode = PASS;
+
+ char fileName[MAX_PATH];
+ FILE *pFile = NULL;
+ DWORD dwStartTime;
+ struct TestStats testStats;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ if(GetParameters(argc, argv))
+ {
+ Fail("Error in obtaining the parameters\n");
+ }
+
+ /* Register the start time */
+ dwStartTime = GetTickCount();
+ testStats.relationId = RELATION_ID;
+ testStats.processCount = PROCESS_COUNT;
+ testStats.threadCount = THREAD_COUNT;
+ testStats.repeatCount = REPEAT_COUNT;
+ testStats.buildNumber = getBuildNumber();
+
+
+ _snprintf(fileName, MAX_PATH, "main_mutex_%d_.txt", RELATION_ID);
+ pFile = fopen(fileName, "w+");
+ if(pFile == NULL)
+ {
+ Fail("Error in opening main file for write\n");
+ }
+
+ for( i = 0; i < PROCESS_COUNT; i++ )
+ {
+ ZeroMemory( lpCommandLine, MAX_PATH );
+ if ( _snprintf( lpCommandLine, MAX_PATH-1, "mutex %d %d %d %d", i, THREAD_COUNT, REPEAT_COUNT, RELATION_ID) < 0 )
+ {
+ Fail("Error Insufficient mutex name string length for %s for iteration [%d]\n", ObjName, i);
+ }
+
+ /* Zero the data structure space */
+ ZeroMemory ( &pi[i], sizeof(pi[i]) );
+ ZeroMemory ( &si[i], sizeof(si[i]) );
+
+ /* Set the process flags and standard io handles */
+ si[i].cb = sizeof(si[i]);
+
+ if(!CreateProcess( NULL, /* lpApplicationName*/
+ lpCommandLine, /* lpCommandLine */
+ NULL, /* lpProcessAttributes */
+ NULL, /* lpThreadAttributes */
+ TRUE, /* bInheritHandles */
+ 0, /* dwCreationFlags, */
+ NULL, /* lpEnvironment */
+ NULL, /* pCurrentDirectory */
+ &si[i], /* lpStartupInfo */
+ &pi[i] /* lpProcessInformation */
+ ))
+ {
+ Fail("Process Not created for [%d], the error code is [%d]\n", i, GetLastError());
+ }
+ else
+ {
+ hProcess[i] = pi[i].hProcess;
+// Trace("Process created for [%d]\n", i);
+
+ }
+
+ //Create Process
+
+ }
+
+ returnCode = WaitForMultipleObjects( PROCESS_COUNT, hProcess, TRUE, INFINITE);
+ if( WAIT_OBJECT_0 != returnCode )
+ {
+ Trace("Wait for Object(s) @ Main thread for %d processes returned %d, and GetLastError value is %d\n", PROCESS_COUNT, returnCode, GetLastError());
+ testReturnCode = FAIL;
+ }
+
+ for( i = 0; i < PROCESS_COUNT; i++ )
+ {
+ /* check the exit code from the process */
+ if( ! GetExitCodeProcess( pi[i].hProcess, &processReturnCode ) )
+ {
+ Trace( "GetExitCodeProcess call failed for iteration %d with error code %u\n",
+ i, GetLastError() );
+
+ testReturnCode = FAIL;
+ }
+
+ if(processReturnCode == FAIL)
+ {
+ Trace( "Process [%d] failed and returned FAIL\n", i);
+ testReturnCode = FAIL;
+ }
+
+ if(!CloseHandle(pi[i].hThread))
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hThread\n", GetLastError(), i);
+ testReturnCode = FAIL;
+ }
+
+ if(!CloseHandle(pi[i].hProcess) )
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hProcess\n", GetLastError(), i);
+ testReturnCode = FAIL;
+ }
+ }
+
+ testStats.operationTime = GetTimeDiff(dwStartTime);
+ fprintf(pFile, "%d,%d,%d,%d,%d,%s\n", testStats.operationTime, testStats.relationId, testStats.processCount, testStats.threadCount, testStats.repeatCount, testStats.buildNumber);
+ if(fclose(pFile))
+ {
+ Trace("Error: fclose failed for pFile\n");
+ testReturnCode = FAIL;
+ }
+
+ if( testReturnCode == PASS)
+ {
+ Trace("Test Passed\n");
+ }
+ else
+ {
+ Trace("Test Failed\n");
+ }
+
+ PAL_Terminate();
+ return testReturnCode;
+}
diff --git a/src/pal/tests/palsuite/composite/object_management/mutex/nonshared/mutex.c b/src/pal/tests/palsuite/composite/object_management/mutex/nonshared/mutex.c
new file mode 100644
index 0000000000..7f1f659f92
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/object_management/mutex/nonshared/mutex.c
@@ -0,0 +1,340 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source Code: main.c and mutex.c
+** main.c creates process and waits for all processes to get over
+** mutex.c creates a mutex and then calls threads which will contend for the mutex
+**
+** This test is for Object Management Test case for Mutex where Object type is not shareable.
+** Algorithm
+** o Create PROCESS_COUNT processes.
+** o Main Thread of each process creates OBJECT_TYPE Object
+**
+** Author: ShamitP
+**============================================================
+*/
+
+#include <palsuite.h>
+#include "resultbuffer.h"
+#include "resulttime.h"
+
+#define TIMEOUT 5000
+/* Test Input Variables */
+unsigned int USE_PROCESS_COUNT = 0;
+unsigned int THREAD_COUNT = 0;
+unsigned int REPEAT_COUNT = 0;
+unsigned int RELATION_ID = 1001;
+
+/* Capture statistics at per thread basis */
+struct statistics{
+ unsigned int processId;
+ unsigned int operationsFailed;
+ unsigned int operationsPassed;
+ unsigned int operationsTotal;
+ DWORD operationTime;
+ unsigned int relationId;
+};
+
+struct ProcessStats{
+ unsigned int processId;
+ DWORD operationTime;
+ unsigned int relationId;
+};
+
+HANDLE StartTestsEvHandle = NULL;
+HANDLE hMutexHandle = NULL;
+
+/* Results Buffer */
+ResultBuffer *resultBuffer = NULL;
+
+int testStatus;
+
+void PALAPI Run_Thread(LPVOID lpParam);
+
+int GetParameters( int argc, char **argv)
+{
+ if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?"))
+ || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H"))
+ {
+ printf("PAL -Composite Object Management Mutex Test\n");
+ printf("Usage:\n");
+ printf("mutex\n\t[USE_PROCESS_COUNT ( greater than 1] \n");
+ printf("\t[THREAD_COUNT ( greater than 1] \n");
+ printf("\t[REPEAT_COUNT ( greater than 1]\n");
+ printf("\t[RELATION_ID [greater than 1]\n");
+ return -1;
+ }
+
+ // Trace("Args 1 is [%s], Arg 2 is [%s], Arg 3 is [%s]\n", argv[1], argv[2], argv[3]);
+
+ USE_PROCESS_COUNT = atoi(argv[1]);
+ if( USE_PROCESS_COUNT < 0)
+ {
+ printf("\nInvalid USE_PROCESS_COUNT number, Pass greater than 1\n");
+ return -1;
+ }
+
+ THREAD_COUNT = atoi(argv[2]);
+ if( (THREAD_COUNT < 1) || (THREAD_COUNT > MAXIMUM_WAIT_OBJECTS) )
+ {
+ printf("\nInvalid THREAD_COUNT number, Pass greater than 1 and less than %d\n", MAXIMUM_WAIT_OBJECTS);
+ return -1;
+ }
+
+ REPEAT_COUNT = atoi(argv[3]);
+ if( REPEAT_COUNT < 1)
+ {
+ printf("\nInvalid REPEAT_COUNT number, Pass greater than 1\n");
+ return -1;
+ }
+
+ RELATION_ID = atoi(argv[4]);
+ if( RELATION_ID < 1)
+ {
+ printf("\nMain Process:Invalid RELATION_ID number, Pass greater than 1\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+ int __cdecl main(INT argc, CHAR **argv)
+{
+ unsigned int i = 0;
+ HANDLE hThread[MAXIMUM_WAIT_OBJECTS];
+ DWORD threadId[MAXIMUM_WAIT_OBJECTS];
+
+ const char sTmpEventName[MAX_PATH] = "StartTestEvent";
+
+ DWORD dwParam = 0;
+
+ int returnCode = 0;
+
+ /* Variables to capture the file name and the file pointer at thread level*/
+ char fileName[MAX_PATH];
+ FILE *pFile = NULL;
+ struct statistics* buffer = NULL;
+ int statisticsSize = 0;
+
+ /* Variables to capture the file name and the file pointer at process level*/
+ char processFileName[MAX_PATH];
+ FILE *pProcessFile = NULL;
+ struct ProcessStats processStats;
+ DWORD dwStartTime;
+
+ testStatus = PASS;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ if(GetParameters(argc, argv))
+ {
+ Fail("Error in obtaining the parameters\n");
+ }
+// Trace("Process created, value of process count is [%d]\n", USE_PROCESS_COUNT);
+
+ /* Register the start time */
+ dwStartTime = GetTickCount();
+ processStats.relationId = RELATION_ID;
+ processStats.processId = USE_PROCESS_COUNT;
+
+ _snprintf(processFileName, MAX_PATH, "%d_process_mutex_%d_.txt", USE_PROCESS_COUNT,RELATION_ID);
+ pProcessFile = fopen(processFileName, "w+");
+ if(pProcessFile == NULL)
+ {
+ Fail("Error in opening process File file for write for process [%d]\n", USE_PROCESS_COUNT);
+ }
+
+ statisticsSize = sizeof(struct statistics);
+
+ _snprintf(fileName, MAX_PATH, "%d_thread_mutex_%d_.txt", USE_PROCESS_COUNT, RELATION_ID);
+ pFile = fopen(fileName, "w+");
+ if(pFile == NULL)
+ {
+ Fail("Error in opening file for write for process [%d]\n", USE_PROCESS_COUNT);
+ }
+ // For each thread we will log operations failed (int), passed (int), total (int)
+ // and number of ticks (DWORD) for the operations
+ resultBuffer = new ResultBuffer( THREAD_COUNT, statisticsSize);
+
+ StartTestsEvHandle = CreateEvent( NULL, /* lpEventAttributes*/
+ TRUE, /* bManualReset */
+ FALSE, /* bInitialState */
+ NULL
+ ); /* name of Event */
+
+ if( StartTestsEvHandle == NULL )
+ {
+ Fail("Error:%d: Unexpected failure "
+ "to create %s Event for process count %d\n", GetLastError(), sTmpEventName, USE_PROCESS_COUNT );
+
+ }
+
+ /* Create StartTest Event */
+
+ hMutexHandle = CreateMutex(
+ NULL,
+ FALSE, /* bInitialOwner, owns initially */
+ NULL
+ );
+
+ if( hMutexHandle == NULL)
+ {
+ Fail("Unable to create Mutex handle for process id [%d], returned error [%d]\n", i, GetLastError());
+ }
+ /* We already assume that the mutex was created previously*/
+
+ for( i = 0; i < THREAD_COUNT; i++ )
+ {
+ dwParam = (int) i;
+ //Create thread
+ hThread[i] = CreateThread(
+ NULL, /* no security attributes */
+ 0, /* use default stack size */
+ (LPTHREAD_START_ROUTINE)Run_Thread,/* thread function */
+ (LPVOID)dwParam, /* argument to thread function */
+ 0, /* use default creation flags */
+ &threadId[i] /* returns the thread identifier*/
+ );
+
+ if(hThread[i] == NULL)
+ {
+ Fail("Create Thread failed for %d process, and GetLastError value is %d\n", USE_PROCESS_COUNT, GetLastError());
+ }
+
+ }
+
+ if (!SetEvent(StartTestsEvHandle))
+ {
+ Fail("Set Event for Start Tests failed for %d process, and GetLastError value is %d\n", USE_PROCESS_COUNT, GetLastError());
+ }
+
+ /* Test running */
+ returnCode = WaitForMultipleObjects( THREAD_COUNT, hThread, TRUE, INFINITE);
+
+ if( WAIT_OBJECT_0 != returnCode )
+ {
+ Trace("Wait for Object(s) for %d process returned %d, and GetLastError value is %d\n", USE_PROCESS_COUNT, returnCode, GetLastError());
+ testStatus = FAIL;
+ }
+
+ processStats.operationTime = GetTimeDiff(dwStartTime);
+
+ /* Write to a file*/
+ if(pFile!= NULL)
+ {
+ for( i = 0; i < THREAD_COUNT; i++ )
+ {
+ buffer = (struct statistics *)resultBuffer->getResultBuffer(i);
+ returnCode = fprintf(pFile, "%d,%d,%d,%d,%lu,%d\n", buffer->processId, buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime, buffer->relationId );
+// Trace("Iteration %d over\n", i);
+
+ }
+ }
+ fclose(pFile);
+
+ fprintf(pProcessFile, "%d,%d,%d\n", USE_PROCESS_COUNT, processStats.operationTime, processStats.relationId );
+ fclose(pProcessFile);
+
+ /* Logging for the test case over, clean up the handles */
+
+// Trace("Test Thread %d done\n", USE_PROCESS_COUNT);
+
+
+ for( i = 0; i < THREAD_COUNT; i++ )
+ {
+ if(!CloseHandle(hThread[i]) )
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hThread[%d]\n", GetLastError(), USE_PROCESS_COUNT, i);
+ testStatus = FAIL;
+ }
+ }
+
+ if(!CloseHandle(StartTestsEvHandle))
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] StartTestsEvHandle\n", GetLastError(), USE_PROCESS_COUNT);
+ testStatus = FAIL;
+ }
+
+ if(!CloseHandle(hMutexHandle))
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hMutexHandle\n", GetLastError(), USE_PROCESS_COUNT);
+ testStatus = FAIL;
+ }
+
+ PAL_Terminate();
+ return testStatus;
+}
+
+void PALAPI Run_Thread (LPVOID lpParam)
+{
+ unsigned int i = 0;
+ DWORD dwWaitResult;
+
+ struct statistics stats;
+ DWORD dwStartTime;
+
+ stats.relationId = RELATION_ID;
+ stats.processId = USE_PROCESS_COUNT;
+ stats.operationsFailed = 0;
+ stats.operationsPassed = 0;
+ stats.operationsTotal = 0;
+ stats.operationTime = 0;
+
+ int Id=(int)lpParam;
+
+ dwWaitResult = WaitForSingleObject(
+ StartTestsEvHandle, // handle to mutex
+ TIMEOUT);
+
+ if(dwWaitResult != WAIT_OBJECT_0)
+ {
+ Trace("Error while waiting for StartTest Event@ thread %d\n", Id);
+ testStatus = FAIL;
+ }
+
+ dwStartTime = GetTickCount();
+
+ for( i = 0; i < REPEAT_COUNT; i++ )
+ {
+ dwWaitResult = WaitForSingleObject(
+ hMutexHandle, // handle to mutex
+ TIMEOUT);
+
+ if(dwWaitResult != WAIT_OBJECT_0)
+ {
+// Trace("Error while waiting for onject @ thread %d, # iter %d\n", Id, i);
+ stats.operationsFailed += 1;
+ stats.operationsTotal += 1;
+ testStatus = FAIL;
+ continue;
+ }
+ if (! ReleaseMutex(hMutexHandle))
+ {
+ // Deal with error.
+// Trace("Error while releasing mutex @ thread %d # iter %d\n", Id, i);
+ stats.operationsFailed += 1;
+ stats.operationsTotal += 1;
+ // Probably need to have while true loop to attempt to release mutex...
+ testStatus = FAIL;
+ continue;
+ }
+
+ stats.operationsTotal += 1;
+ stats.operationsPassed += 1;
+ // Trace("Successs while releasing mutex @ iteration %d -> thread %d -> Process %d\n", i, Id, USE_PROCESS_COUNT);
+
+ }
+
+ stats.operationTime = GetTimeDiff(dwStartTime);
+ //Trace("OPeration time is %d", stats.operationTime );
+ if(resultBuffer->LogResult(Id, (char *)&stats))
+ {
+ Fail("Error:%d: while writing to shared memory, Thread Id is[%d] and Process id is [%d]\n", GetLastError(), Id, USE_PROCESS_COUNT);
+ }
+}
diff --git a/src/pal/tests/palsuite/composite/object_management/mutex/shared/CMakeLists.txt b/src/pal/tests/palsuite/composite/object_management/mutex/shared/CMakeLists.txt
new file mode 100644
index 0000000000..cf33d0b464
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/object_management/mutex/shared/CMakeLists.txt
@@ -0,0 +1,21 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ main.c
+ mutex.c
+)
+
+add_executable(paltest_mutex_shared
+ ${SOURCES}
+)
+
+add_dependencies(paltest_mutex_shared coreclrpal)
+
+target_link_libraries(paltest_mutex_shared
+ pthread
+ rt
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/composite/object_management/mutex/shared/main.c b/src/pal/tests/palsuite/composite/object_management/mutex/shared/main.c
new file mode 100644
index 0000000000..aa98855565
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/object_management/mutex/shared/main.c
@@ -0,0 +1,265 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** This test is for Object Management Test case for Mutex where Object type is shareable.
+**
+** Source Code: main.c and mutex.c
+** main.c creates a mutex, creates processes and waits for all processes to get over
+** mutex.c create threads which will contend for the mutex
+**
+** This test is for Object Management Test case for Mutex where Object type is not shareable.
+** Algorithm
+** o Main Process Creates OBJECT_TYPE Object
+** o Create PROCESS_COUNT processes aware of the Shared Object
+**
+** Author: ShamitP
+**
+**
+**============================================================
+*/
+
+#include <palsuite.h>
+#include "resulttime.h"
+
+/* Test Input Variables */
+unsigned int PROCESS_COUNT = 2;
+unsigned int THREAD_COUNT = 2;
+unsigned int REPEAT_COUNT = 40000;
+unsigned int RELATION_ID = 1001;
+
+
+char objectSuffix[MAX_PATH];
+
+struct TestStats{
+ DWORD operationTime;
+ unsigned int relationId;
+ unsigned int processCount;
+ unsigned int threadCount;
+ unsigned int repeatCount;
+ char* buildNumber;
+
+};
+
+int GetParameters( int argc, char **argv)
+{
+ if( (!((argc == 5) || (argc == 6) ) )|| ((argc == 1) && !strcmp(argv[1],"/?"))
+ || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H"))
+ {
+ printf("PAL -Composite Object Management event Test\n");
+ printf("Usage:\n");
+ printf("main\n\t[PROCESS_COUNT (greater than 1)] \n");
+ printf("\t[THREAD_COUNT (greater than 1)] \n");
+ printf("\t[REPEAT_COUNT (greater than 1)]\n");
+ printf("\t[RELATION_ID [greater than 1]\n");
+ printf("\t[Object Name Suffix]\n");
+ return -1;
+ }
+
+ PROCESS_COUNT = atoi(argv[1]);
+ if( (PROCESS_COUNT < 1) || (PROCESS_COUNT > MAXIMUM_WAIT_OBJECTS) )
+ {
+ printf("\nMain Process:Invalid PROCESS_COUNT number, Pass greater than 1 and less than PROCESS_COUNT %d\n", MAXIMUM_WAIT_OBJECTS);
+ return -1;
+ }
+
+ THREAD_COUNT = atoi(argv[2]);
+ if( (THREAD_COUNT < 1) || (THREAD_COUNT > MAXIMUM_WAIT_OBJECTS) )
+ {
+ printf("\nInvalid THREAD_COUNT number, Pass greater than 1 and less than %d\n", MAXIMUM_WAIT_OBJECTS);
+ return -1;
+ }
+
+ REPEAT_COUNT = atoi(argv[3]);
+ if( REPEAT_COUNT < 1)
+ {
+ printf("\nMain Process:Invalid REPEAT_COUNT number, Pass greater than 1\n");
+ return -1;
+ }
+
+ RELATION_ID = atoi(argv[4]);
+ if( RELATION_ID < 1)
+ {
+ printf("\nMain Process:Invalid RELATION_ID number, Pass greater than 1\n");
+ return -1;
+ }
+
+ if(argc == 6)
+ {
+ strncpy(objectSuffix, argv[5], MAX_PATH-1);
+ }
+
+ return 0;
+}
+
+ int __cdecl main(INT argc, CHAR **argv)
+{
+ unsigned int i = 0;
+ HANDLE hProcess[MAXIMUM_WAIT_OBJECTS];
+ HANDLE hMutexHandle;
+
+ STARTUPINFO si[MAXIMUM_WAIT_OBJECTS];
+ PROCESS_INFORMATION pi[MAXIMUM_WAIT_OBJECTS];
+
+ char ObjName[MAX_PATH] = "SHARED_MUTEX";
+ char lpCommandLine[MAX_PATH] = "";
+
+ int returnCode = 0;
+ DWORD processReturnCode = 0;
+ int testReturnCode = PASS;
+
+ char fileName[MAX_PATH];
+ FILE *pFile = NULL;
+ DWORD dwStartTime;
+ struct TestStats testStats;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ ZeroMemory( objectSuffix, MAX_PATH );
+
+ if(GetParameters(argc, argv))
+ {
+ Fail("Error in obtaining the parameters\n");
+ }
+
+ if(argc == 5)
+ {
+ strncat(ObjName, objectSuffix, MAX_PATH - (sizeof(ObjName) + 1) );
+ }
+
+ /* Register the start time */
+ dwStartTime = GetTickCount();
+ testStats.relationId = RELATION_ID;
+ testStats.processCount = PROCESS_COUNT;
+ testStats.threadCount = THREAD_COUNT;
+ testStats.repeatCount = REPEAT_COUNT;
+ testStats.buildNumber = getBuildNumber();
+
+
+ _snprintf(fileName, MAX_PATH, "main_mutex_%d_.txt", RELATION_ID);
+ pFile = fopen(fileName, "w+");
+ if(pFile == NULL)
+ {
+ Fail("Error in opening main file for write\n");
+ }
+
+ hMutexHandle = CreateMutex(
+ NULL,
+ FALSE, /* bInitialOwner, owns initially */
+ ObjName
+ );
+
+ if( hMutexHandle == NULL)
+ {
+ Fail("Unable to create Mutex handle for Main thread returned error [%d]\n", GetLastError());
+ }
+
+ for( i = 0; i < PROCESS_COUNT; i++ )
+ {
+ ZeroMemory( lpCommandLine, MAX_PATH );
+ if ( _snprintf( lpCommandLine, MAX_PATH-1, "mutex %d %d %d %d %s", i, THREAD_COUNT, REPEAT_COUNT, RELATION_ID, objectSuffix) < 0 )
+ {
+ Fail ("Error Insufficient mutex name string length for %s for iteration [%d]\n", ObjName, i);
+ }
+
+
+ /* Zero the data structure space */
+ ZeroMemory ( &pi[i], sizeof(pi[i]) );
+ ZeroMemory ( &si[i], sizeof(si[i]) );
+
+ /* Set the process flags and standard io handles */
+ si[i].cb = sizeof(si[i]);
+
+ //Create Process
+ if(!CreateProcess( NULL, /* lpApplicationName*/
+ lpCommandLine, /* lpCommandLine */
+ NULL, /* lpProcessAttributes */
+ NULL, /* lpThreadAttributes */
+ TRUE, /* bInheritHandles */
+ 0, /* dwCreationFlags, */
+ NULL, /* lpEnvironment */
+ NULL, /* pCurrentDirectory */
+ &si[i], /* lpStartupInfo */
+ &pi[i] /* lpProcessInformation */
+ ))
+ {
+ Fail("Process Not created for [%d], the error code is [%d]\n", i, GetLastError());
+ }
+ else
+ {
+ hProcess[i] = pi[i].hProcess;
+// Trace("Process created for [%d]\n", i);
+
+ }
+ }
+
+ returnCode = WaitForMultipleObjects( PROCESS_COUNT, hProcess, TRUE, INFINITE);
+ if( WAIT_OBJECT_0 != returnCode )
+ {
+ Trace("Wait for Object(s) @ Main thread for %d processes returned %d, and GetLastError value is %d\n", PROCESS_COUNT, returnCode, GetLastError());
+ testReturnCode = FAIL;
+ }
+
+ for( i = 0; i < PROCESS_COUNT; i++ )
+ {
+ /* check the exit code from the process */
+ if( ! GetExitCodeProcess( pi[i].hProcess, &processReturnCode ) )
+ {
+ Trace( "GetExitCodeProcess call failed for iteration %d with error code %u\n",
+ i, GetLastError() );
+
+ testReturnCode = FAIL;
+ }
+
+ if(processReturnCode == FAIL)
+ {
+ Trace( "Process [%d] failed and returned FAIL\n", i);
+ testReturnCode = FAIL;
+ }
+
+ if(!CloseHandle(pi[i].hThread))
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hThread\n", GetLastError(), i);
+ testReturnCode = FAIL;
+ }
+
+ if(!CloseHandle(pi[i].hProcess) )
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hProcess\n", GetLastError(), i);
+ testReturnCode = FAIL;
+ }
+ }
+
+ testStats.operationTime = GetTimeDiff(dwStartTime);
+ fprintf(pFile, "%d,%d,%d,%d,%d,%s\n", testStats.operationTime, testStats.relationId, testStats.processCount, testStats.threadCount, testStats.repeatCount, testStats.buildNumber );
+ if(fclose(pFile))
+ {
+ Trace("Error: fclose failed for pFile\n");
+ testReturnCode = FAIL;
+ }
+
+ if(!CloseHandle(hMutexHandle))
+ {
+ Trace("Error:%d: CloseHandle failed for hMutexHandle\n", GetLastError());
+ testReturnCode = FAIL;
+
+ }
+
+ if( testReturnCode == PASS)
+ {
+ Trace("Test Passed\n");
+ }
+ else
+ {
+ Trace("Test Failed\n");
+ }
+
+ PAL_Terminate();
+ return testReturnCode;
+}
+
diff --git a/src/pal/tests/palsuite/composite/object_management/mutex/shared/mutex.c b/src/pal/tests/palsuite/composite/object_management/mutex/shared/mutex.c
new file mode 100644
index 0000000000..ec5d9b37ac
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/object_management/mutex/shared/mutex.c
@@ -0,0 +1,354 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** This test is for Object Management Test case for Mutex where Object type is shareable.
+**
+** Source Code: main.c and mutex.c
+** main.c creates a mutex, creates processes and waits for all processes to get over
+** mutex.c create threads which will contend for the mutex
+**
+** This test is for Object Management Test case for Mutex where Object type is not shareable.
+** Algorithm
+** o Main Process Creates OBJECT_TYPE Object
+** o Create PROCESS_COUNT processes aware of the Shared Object
+**
+** Author: ShamitP
+**
+**
+**============================================================
+*/
+
+#include <palsuite.h>
+#include "resultbuffer.h"
+#include "resulttime.h"
+
+#define TIMEOUT 5000
+/* Test Input Variables */
+unsigned int USE_PROCESS_COUNT = 0;
+unsigned int THREAD_COUNT = 0;
+unsigned int REPEAT_COUNT = 0;
+unsigned int RELATION_ID = 0;
+
+
+/* Capture statistics at per thread basis */
+struct statistics{
+ unsigned int processId;
+ unsigned int operationsFailed;
+ unsigned int operationsPassed;
+ unsigned int operationsTotal;
+ DWORD operationTime;
+ unsigned int relationId;
+};
+
+struct ProcessStats{
+ unsigned int processId;
+ DWORD operationTime;
+ unsigned int relationId;
+};
+
+HANDLE StartTestsEvHandle = NULL;
+HANDLE hMutexHandle = NULL;
+
+/* Results Buffer */
+ResultBuffer *resultBuffer = NULL;
+
+int testStatus;
+
+const char sTmpEventName[MAX_PATH] = "StartTestEvent";
+char objectSuffix[MAX_PATH];
+
+void PALAPI Run_Thread(LPVOID lpParam);
+
+int GetParameters( int argc, char **argv)
+{
+ if( (!((argc == 5) || (argc == 6) ) )|| ((argc == 1) && !strcmp(argv[1],"/?"))
+ || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H"))
+ {
+ printf("PAL -Composite Object Management event Test\n");
+ printf("Usage:\n");
+ printf("main\n\t[USE_PROCESS_COUNT (greater than 1)] \n");
+ printf("\t[THREAD_COUNT (greater than 1)] \n");
+ printf("\t[REPEAT_COUNT (greater than 1)]\n");
+ printf("\t[RELATION_ID [greater than 1]\n");
+ printf("\t[Object Name Suffix]\n");
+
+ return -1;
+ }
+
+ // Trace("Args 1 is [%s], Arg 2 is [%s], Arg 3 is [%s]\n", argv[1], argv[2], argv[3]);
+
+ USE_PROCESS_COUNT = atoi(argv[1]);
+ if( USE_PROCESS_COUNT < 0)
+ {
+ printf("\nInvalid USE_PROCESS_COUNT number, Pass greater than 1\n");
+ return -1;
+ }
+
+ THREAD_COUNT = atoi(argv[2]);
+ if( (THREAD_COUNT < 1) || (THREAD_COUNT > MAXIMUM_WAIT_OBJECTS) )
+ {
+ printf("\nInvalid THREAD_COUNT number, Pass greater than 1 and less than %d\n", MAXIMUM_WAIT_OBJECTS);
+ return -1;
+ }
+
+ REPEAT_COUNT = atoi(argv[3]);
+ if( REPEAT_COUNT < 1)
+ {
+ printf("\nInvalid REPEAT_COUNT number, Pass greater than 1\n");
+ return -1;
+ }
+
+ RELATION_ID = atoi(argv[4]);
+ if( RELATION_ID < 1)
+ {
+ printf("\nMain Process:Invalid RELATION_ID number, Pass greater than 1\n");
+ return -1;
+ }
+
+ if(argc == 6)
+ {
+ strncpy(objectSuffix, argv[5], MAX_PATH-1);
+ }
+
+ return 0;
+}
+
+ int __cdecl main(INT argc, CHAR **argv)
+{
+ unsigned int i = 0;
+ HANDLE hThread[MAXIMUM_WAIT_OBJECTS];
+ DWORD threadId[MAXIMUM_WAIT_OBJECTS];
+
+ char ObjName[MAX_PATH] = "SHARED_MUTEX";
+ DWORD dwParam = 0;
+
+ int returnCode = 0;
+
+ /* Variables to capture the file name and the file pointer*/
+ char fileName[MAX_PATH];
+ FILE *pFile = NULL;
+ struct statistics* buffer = NULL;
+ int statisticsSize = 0;
+
+ /* Variables to capture the file name and the file pointer at process level*/
+ char processFileName[MAX_PATH];
+ FILE *pProcessFile = NULL;
+ struct ProcessStats processStats;
+ DWORD dwStartTime;
+
+ testStatus = PASS;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ ZeroMemory( objectSuffix, MAX_PATH );
+
+ if(GetParameters(argc, argv))
+ {
+ Fail("Error in obtaining the parameters\n");
+ }
+// Trace("Process created, value of process count is [%d]\n", USE_PROCESS_COUNT);
+
+ if(argc == 5)
+ {
+ strncat(ObjName, objectSuffix, MAX_PATH - (sizeof(ObjName) + 1) );
+ }
+
+ /* Register the start time */
+ dwStartTime = GetTickCount();
+ processStats.relationId = RELATION_ID;
+ processStats.processId = USE_PROCESS_COUNT;
+
+ _snprintf(processFileName, MAX_PATH, "%d_process_mutex_%d_.txt", USE_PROCESS_COUNT, RELATION_ID);
+ pProcessFile = fopen(processFileName, "w+");
+ if(pProcessFile == NULL)
+ {
+ Fail("Error in opening process File file for write for process [%d]\n", USE_PROCESS_COUNT);
+ } statisticsSize = sizeof(struct statistics);
+
+ _snprintf(fileName, MAX_PATH, "%d_thread_mutex_%d_.txt", USE_PROCESS_COUNT, RELATION_ID);
+ pFile = fopen(fileName, "w+");
+ if(pFile == NULL)
+ {
+ Fail("Error in opening file for write for process [%d]\n", USE_PROCESS_COUNT);
+ }
+ // For each thread we will log operations failed (int), passed (int), total (int)
+ // and number of ticks (DWORD) for the operations
+ resultBuffer = new ResultBuffer( THREAD_COUNT, statisticsSize);
+
+ /* Create StartTest Event */
+ StartTestsEvHandle = CreateEvent( NULL, /* lpEventAttributes*/
+ TRUE, /* bManualReset */
+ FALSE, /* bInitialState */
+ NULL); /* name of Event */
+
+ if( StartTestsEvHandle == NULL )
+ {
+ Fail("Error:%d: Unexpected failure "
+ "to create %s Event for process count %d\n", GetLastError(), sTmpEventName, USE_PROCESS_COUNT );
+
+ }
+
+ hMutexHandle = CreateMutex(
+ NULL,
+ FALSE, /* bInitialOwner, owns initially */
+ ObjName
+ );
+
+ if( (hMutexHandle == NULL)|| (GetLastError() != ERROR_ALREADY_EXISTS))
+ {
+ Fail("Unable to create Mutex handle for process id [%d], returned error [%d], expected ERROR_ALREADY_EXISTS\n", i, GetLastError());
+ }
+ /* We already assume that the mutex was created previously*/
+
+ for( i = 0; i < THREAD_COUNT; i++ )
+ {
+ dwParam = (int) i;
+ //Create thread
+ hThread[i] = CreateThread(
+ NULL, /* no security attributes */
+ 0, /* use default stack size */
+ (LPTHREAD_START_ROUTINE)Run_Thread,/* thread function */
+ (LPVOID)dwParam, /* argument to thread function */
+ 0, /* use default creation flags */
+ &threadId[i] /* returns the thread identifier*/
+ );
+
+ if(hThread[i] == NULL)
+ {
+ Fail("Create Thread failed for %d process, and GetLastError value is %d\n", USE_PROCESS_COUNT, GetLastError());
+ }
+
+ }
+
+ if (!SetEvent(StartTestsEvHandle))
+ {
+ Fail("Set Event for Start Tests failed for %d process, and GetLastError value is %d\n", USE_PROCESS_COUNT, GetLastError());
+ }
+
+ /* Test running */
+ returnCode = WaitForMultipleObjects( THREAD_COUNT, hThread, TRUE, INFINITE);
+
+ if( WAIT_OBJECT_0 != returnCode )
+ {
+ Trace("Wait for Object(s) for %d process returned %d, and GetLastError value is %d\n", USE_PROCESS_COUNT, returnCode, GetLastError());
+ testStatus = FAIL;
+ }
+
+ processStats.operationTime = GetTimeDiff(dwStartTime);
+
+ /* Write to a file*/
+ if(pFile!= NULL)
+ {
+ for( i = 0; i < THREAD_COUNT; i++ )
+ {
+ buffer = (struct statistics *)resultBuffer->getResultBuffer(i);
+ returnCode = fprintf(pFile, "%d,%d,%d,%d,%lu,%d\n", buffer->processId, buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime, buffer->relationId );
+// Trace("Iteration %d over\n", i);
+
+ }
+ }
+ fclose(pFile);
+
+ fprintf(pProcessFile, "%d,%d,%d\n", USE_PROCESS_COUNT, processStats.operationTime, processStats.relationId );
+ fclose(pProcessFile);
+
+ /* Logging for the test case over, clean up the handles */
+
+// Trace("Process Count %d over\n",USE_PROCESS_COUNT);
+
+ for( i = 0; i < THREAD_COUNT; i++ )
+ {
+ if(!CloseHandle(hThread[i]) )
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hThread[%d]\n", GetLastError(), USE_PROCESS_COUNT, i);
+ testStatus = FAIL;
+ }
+ }
+
+ if(!CloseHandle(StartTestsEvHandle))
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] StartTestsEvHandle\n", GetLastError(), USE_PROCESS_COUNT);
+ testStatus = FAIL;
+ }
+
+ if(!CloseHandle(hMutexHandle))
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hMutexHandle\n", GetLastError(), USE_PROCESS_COUNT);
+ testStatus = FAIL;
+ }
+
+ PAL_Terminate();
+ return testStatus;
+}
+
+void PALAPI Run_Thread (LPVOID lpParam)
+{
+ unsigned int i = 0;
+ DWORD dwWaitResult;
+
+ struct statistics stats;
+ DWORD dwStartTime;
+
+ stats.relationId = RELATION_ID;
+ stats.processId = USE_PROCESS_COUNT;
+ stats.operationsFailed = 0;
+ stats.operationsPassed = 0;
+ stats.operationsTotal = 0;
+ stats.operationTime = 0;
+
+ int Id=(int)lpParam;
+
+ dwWaitResult = WaitForSingleObject(
+ StartTestsEvHandle, // handle to mutex
+ TIMEOUT);
+
+ if(dwWaitResult != WAIT_OBJECT_0)
+ {
+ Trace("Error while waiting for StartTest Event@ thread %d\n", Id);
+ testStatus = FAIL;
+ }
+
+ dwStartTime = GetTickCount();
+
+ for( i = 0; i < REPEAT_COUNT; i++ )
+ {
+ dwWaitResult = WaitForSingleObject(
+ hMutexHandle, // handle to mutex
+ TIMEOUT);
+
+ if(dwWaitResult != WAIT_OBJECT_0)
+ {
+// Trace("Error while waiting for onject @ thread %d, # iter %d, Error Returned [%d]\n", Id, i, GetLastError());
+ stats.operationsFailed += 1;
+ stats.operationsTotal += 1;
+ testStatus = FAIL;
+ continue;
+ }
+ if (! ReleaseMutex(hMutexHandle))
+ {
+ // Deal with error.
+// Trace("Error while releasing mutex @ thread %d # iter %d\n", Id, i);
+ stats.operationsFailed += 1;
+ stats.operationsTotal += 1;
+ // Probably need to have while true loop to attempt to release mutex...
+ testStatus = FAIL;
+ continue;
+ }
+
+ stats.operationsTotal += 1;
+ stats.operationsPassed += 1;
+// Trace("Successs while releasing mutex @ iteration %d -> thread %d -> Process count %d\n", i, Id, USE_PROCESS_COUNT);
+
+ }
+ stats.operationTime = GetTimeDiff(dwStartTime);
+ if(resultBuffer->LogResult(Id, (char *)&stats))
+ {
+ Fail("Error:%d: while writing to shared memory, Thread Id is[%d] and Process id is [%d]\n", GetLastError(), Id, USE_PROCESS_COUNT);
+ }
+}
diff --git a/src/pal/tests/palsuite/composite/object_management/readme.txt b/src/pal/tests/palsuite/composite/object_management/readme.txt
new file mode 100644
index 0000000000..6bae5f105d
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/object_management/readme.txt
@@ -0,0 +1,29 @@
+To compile:
+
+1) create a dat file (say object_management.dat) with contents:
+
+PAL,Composite,palsuite\composite\object_management\mutex\nonshared,mutex=main.c mutex.c,<SUPPORTEXE>,<TESTLANGCPP>,<COMPILEONLY>
+PAL,Composite,palsuite\composite\object_management\mutex\shared,mutex=main.c mutex.c,<SUPPORTEXE>,<TESTLANGCPP>,<COMPILEONLY>
+PAL,Composite,palsuite\composite\object_management\semaphore\nonshared,semaphore=main.c semaphore.c,<SUPPORTEXE>,<TESTLANGCPP>,<COMPILEONLY>
+PAL,Composite,palsuite\composite\object_management\semaphore\shared,semaphore=main.c semaphore.c,<SUPPORTEXE>,<TESTLANGCPP>,<COMPILEONLY>
+PAL,Composite,palsuite\composite\object_management\event\nonshared,event=main.c event.c,<SUPPORTEXE>,<TESTLANGCPP>,<COMPILEONLY>
+PAL,Composite,palsuite\composite\object_management\event\shared,event=main.c event.c,<SUPPORTEXE>,<TESTLANGCPP>,<COMPILEONLY>
+
+
+2) perl rrunmod.pl -r object_management.dat
+
+
+To execute:
+For each of the test cases,
+main [PROCESS_COUNT] [THREAD_COUNT] [REPEAT_COUNT]
+
+
+Output:
+The performance numbers will be in <process_logical_id>_[event|semaphore|mutex].txt
+(will be at palsuite\composite\object_management\[mutex|event|semaphore]\[shared|nonshared]\obj[r|c|d] directory if u use rrunmod.pl)
+
+So if process_count is 3, you will have files 0_mutex.txt, 1_mutex.txt and so on…
+
+For each process txt file created,
+each row represents a thread data (process id, number of failures, number of pass, total number of repeated operations and an integer that will be used to identify a run
+(currently zero)).
diff --git a/src/pal/tests/palsuite/composite/object_management/semaphore/CMakeLists.txt b/src/pal/tests/palsuite/composite/object_management/semaphore/CMakeLists.txt
new file mode 100644
index 0000000000..2534564f95
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/object_management/semaphore/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(nonshared)
+add_subdirectory(shared)
+
diff --git a/src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/CMakeLists.txt b/src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/CMakeLists.txt
new file mode 100644
index 0000000000..6efa228fbb
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/CMakeLists.txt
@@ -0,0 +1,21 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ main.c
+ semaphore.c
+)
+
+add_executable(paltest_semaphore_nonshared
+ ${SOURCES}
+)
+
+add_dependencies(paltest_semaphore_nonshared coreclrpal)
+
+target_link_libraries(paltest_semaphore_nonshared
+ pthread
+ rt
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/main.c b/src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/main.c
new file mode 100644
index 0000000000..854809c8f8
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/main.c
@@ -0,0 +1,228 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source Code: main.c and semaphore.c
+** main.c creates process and waits for all processes to get over
+** semaphore.c creates a semaphore and then calls threads which will contend for the semaphore
+**
+** This test is for Object Management Test case for semaphore where Object type is not shareable.
+** Algorithm
+** o Create PROCESS_COUNT processes.
+** o Main Thread of each process creates OBJECT_TYPE Object
+**
+** Author: ShamitP
+**
+**
+**============================================================
+*/
+
+#include <palsuite.h>
+#include "resulttime.h"
+
+/* Test Input Variables */
+unsigned int PROCESS_COUNT = 2;
+unsigned int THREAD_COUNT = 15;
+unsigned int REPEAT_COUNT = 40000;
+unsigned int RELATION_ID = 1001;
+
+
+
+struct TestStats{
+ DWORD operationTime;
+ unsigned int relationId;
+ unsigned int processCount;
+ unsigned int threadCount;
+ unsigned int repeatCount;
+ char* buildNumber;
+};
+
+int GetParameters( int argc, char **argv)
+{
+ if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?"))
+ || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H"))
+ {
+ printf("PAL -Composite Object Management Semaphore Test\n");
+ printf("Usage:\n");
+ printf("main\n\t[PROCESS_COUNT [greater than 1] \n");
+ printf("\t[THREAD_COUNT [greater than 1] \n");
+ printf("\t[REPEAT_COUNT [greater than 1]\n");
+ printf("\t[RELATION_ID [greater than 1]\n");
+ return -1;
+ }
+
+ PROCESS_COUNT = atoi(argv[1]);
+ if( (PROCESS_COUNT < 1) || (PROCESS_COUNT > MAXIMUM_WAIT_OBJECTS) )
+ {
+ printf("\nMain Process:Invalid PROCESS_COUNT number, Pass greater than 1 and less than PROCESS_COUNT %d\n", MAXIMUM_WAIT_OBJECTS);
+ return -1;
+ }
+
+ THREAD_COUNT = atoi(argv[2]);
+ if( (THREAD_COUNT < 1) || (THREAD_COUNT > MAXIMUM_WAIT_OBJECTS) )
+ {
+ printf("\nInvalid THREAD_COUNT number, Pass greater than 1 and less than %d\n", MAXIMUM_WAIT_OBJECTS);
+ return -1;
+ }
+
+ REPEAT_COUNT = atoi(argv[3]);
+ if( REPEAT_COUNT < 1)
+ {
+ printf("\nMain Process:Invalid REPEAT_COUNT number, Pass greater than 1\n");
+ return -1;
+ }
+
+ RELATION_ID = atoi(argv[4]);
+ if( RELATION_ID < 1)
+ {
+ printf("\nMain Process:Invalid RELATION_ID number, Pass greater than or Equal to 1\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+ int __cdecl main(INT argc, CHAR **argv)
+{
+ unsigned int i = 0;
+ HANDLE hProcess[MAXIMUM_WAIT_OBJECTS];
+ HANDLE hSemaphoreHandle[MAXIMUM_WAIT_OBJECTS];
+
+ STARTUPINFO si[MAXIMUM_WAIT_OBJECTS];
+ PROCESS_INFORMATION pi[MAXIMUM_WAIT_OBJECTS];
+
+ const char *ObjName = "Semaphore";
+ char lpCommandLine[MAX_PATH] = "";
+
+ int returnCode = 0;
+ DWORD processReturnCode = 0;
+ int testReturnCode = PASS;
+
+ char fileName[MAX_PATH];
+ FILE *pFile = NULL;
+ DWORD dwStartTime;
+ struct TestStats testStats;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ if(GetParameters(argc, argv))
+ {
+ Fail("Error in obtaining the parameters\n");
+ }
+
+ /* Register the start time */
+ dwStartTime = GetTickCount();
+ testStats.relationId = RELATION_ID;
+ testStats.processCount = PROCESS_COUNT;
+ testStats.threadCount = THREAD_COUNT;
+ testStats.repeatCount = REPEAT_COUNT;
+ testStats.buildNumber = getBuildNumber();
+
+
+ _snprintf(fileName, MAX_PATH, "main_semaphore_%d_.txt", RELATION_ID);
+ pFile = fopen(fileName, "w+");
+ if(pFile == NULL)
+ {
+ Fail("Error in opening main file for write\n");
+ }
+
+ for( i = 0; i < PROCESS_COUNT; i++ )
+ {
+ ZeroMemory( lpCommandLine, MAX_PATH );
+ if ( _snprintf( lpCommandLine, MAX_PATH-1, "semaphore %d %d %d %d", i, THREAD_COUNT, REPEAT_COUNT, RELATION_ID) < 0 )
+ {
+ Fail("Error Insufficient semaphore name string length for %s for iteration [%d]\n", ObjName, i);
+ }
+
+ /* Zero the data structure space */
+ ZeroMemory ( &pi[i], sizeof(pi[i]) );
+ ZeroMemory ( &si[i], sizeof(si[i]) );
+
+ /* Set the process flags and standard io handles */
+ si[i].cb = sizeof(si[i]);
+
+ //Create Process
+ if(!CreateProcess( NULL, /* lpApplicationName*/
+ lpCommandLine, /* lpCommandLine */
+ NULL, /* lpProcessAttributes */
+ NULL, /* lpThreadAttributes */
+ TRUE, /* bInheritHandles */
+ 0, /* dwCreationFlags, */
+ NULL, /* lpEnvironment */
+ NULL, /* pCurrentDirectory */
+ &si[i], /* lpStartupInfo */
+ &pi[i] /* lpProcessInformation */
+ ))
+ {
+ Fail("Process Not created for [%d], the error code is [%d]\n", i, GetLastError());
+ }
+ else
+ {
+ hProcess[i] = pi[i].hProcess;
+// Trace("Process created for [%d]\n", i);
+
+ }
+ }
+
+ returnCode = WaitForMultipleObjects( PROCESS_COUNT, hProcess, TRUE, INFINITE);
+ if( WAIT_OBJECT_0 != returnCode )
+ {
+ Trace("Wait for Object(s) @ Main thread for %d processes returned %d, and GetLastError value is %d\n", PROCESS_COUNT, returnCode, GetLastError());
+ testReturnCode = FAIL;
+ }
+
+ for( i = 0; i < PROCESS_COUNT; i++ )
+ {
+ /* check the exit code from the process */
+ if( ! GetExitCodeProcess( pi[i].hProcess, &processReturnCode ) )
+ {
+ Trace( "GetExitCodeProcess call failed for iteration %d with error code %u\n",
+ i, GetLastError() );
+
+ testReturnCode = FAIL;
+ }
+
+ if(processReturnCode == FAIL)
+ {
+ Trace( "Process [%d] failed and returned FAIL\n", i);
+ testReturnCode = FAIL;
+ }
+
+ if(!CloseHandle(pi[i].hThread))
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hThread\n", GetLastError(), i);
+ testReturnCode = FAIL;
+ }
+
+ if(!CloseHandle(pi[i].hProcess) )
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hProcess\n", GetLastError(), i);
+ testReturnCode = FAIL;
+ }
+ }
+
+ testStats.operationTime = GetTimeDiff(dwStartTime);
+ fprintf(pFile, "%d,%d,%d,%d,%d,%s\n", testStats.operationTime, testStats.relationId,testStats.processCount, testStats.threadCount, testStats.repeatCount, testStats.buildNumber );
+ if(fclose(pFile))
+ {
+ Trace("Error: fclose failed for pFile\n");
+ testReturnCode = FAIL;
+ }
+
+ if( testReturnCode == PASS)
+ {
+ Trace("Test Passed\n");
+ }
+ else
+ {
+ Trace("Test Failed\n");
+ }
+
+ PAL_Terminate();
+ return testReturnCode;
+}
diff --git a/src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/semaphore.c b/src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/semaphore.c
new file mode 100644
index 0000000000..0e487f2c17
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/semaphore.c
@@ -0,0 +1,342 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source Code: main.c and semaphore.c
+** main.c creates process and waits for all processes to get over
+** semaphore.c creates a semaphore and then calls threads which will contend for the semaphore
+**
+** This test is for Object Management Test case for semaphore where Object type is not shareable.
+** Algorithm
+** o Create PROCESS_COUNT processes.
+** o Main Thread of each process creates OBJECT_TYPE Object
+**
+** Author: ShamitP
+**
+**
+**============================================================
+*/
+
+#include <palsuite.h>
+#include "resultbuffer.h"
+#include "resulttime.h"
+
+#define TIMEOUT 5000
+/* Test Input Variables */
+unsigned int USE_PROCESS_COUNT = 0;
+unsigned int THREAD_COUNT = 0;
+unsigned int REPEAT_COUNT = 0;
+unsigned int RELATION_ID = 0;
+
+/* Capture statistics at per thread basis */
+struct statistics{
+ unsigned int processId;
+ unsigned int operationsFailed;
+ unsigned int operationsPassed;
+ unsigned int operationsTotal;
+ DWORD operationTime;
+ unsigned int relationId;
+};
+
+struct ProcessStats{
+ unsigned int processId;
+ DWORD operationTime;
+ unsigned int relationId;
+};
+
+/* Semaphore variables */
+unsigned long lInitialCount = 1; /* Signaled */
+unsigned long lMaximumCount = 1; /* Maximum value of 1 */
+
+HANDLE StartTestsEvHandle = NULL;
+HANDLE hSemaphoreHandle = NULL;
+
+/* Results Buffer */
+ResultBuffer *resultBuffer = NULL;
+
+int testStatus;
+
+const char sTmpEventName[MAX_PATH] = "StartTestEvent";
+
+void PALAPI Run_Thread(LPVOID lpParam);
+
+int GetParameters( int argc, char **argv)
+{
+ if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?"))
+ || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H"))
+ {
+ printf("PAL -Composite Object Management Semaphore Test\n");
+ printf("Usage:\n");
+ printf("semaphore\n\t[USE_PROCESS_COUNT ( greater than 1] \n");
+ printf("\t[THREAD_COUNT ( greater than 1] \n");
+ printf("\t[REPEAT_COUNT ( greater than 1]\n");
+ printf("\t[RELATION_ID [greater than 1]\n");
+ return -1;
+ }
+
+ // Trace("Args 1 is [%s], Arg 2 is [%s], Arg 3 is [%s]\n", argv[1], argv[2], argv[3]);
+
+ USE_PROCESS_COUNT = atoi(argv[1]);
+ if( USE_PROCESS_COUNT < 0)
+ {
+ printf("\nInvalid USE_PROCESS_COUNT number, Pass greater than 1\n");
+ return -1;
+ }
+
+ THREAD_COUNT = atoi(argv[2]);
+ if( (THREAD_COUNT < 1) || (THREAD_COUNT > MAXIMUM_WAIT_OBJECTS) )
+ {
+ printf("\nInvalid THREAD_COUNT number, Pass greater than 1 and less than %d\n", MAXIMUM_WAIT_OBJECTS);
+ return -1;
+ }
+
+ REPEAT_COUNT = atoi(argv[3]);
+ if( REPEAT_COUNT < 1)
+ {
+ printf("\nInvalid REPEAT_COUNT number, Pass greater than 1\n");
+ return -1;
+ }
+
+ RELATION_ID = atoi(argv[4]);
+ if( RELATION_ID < 1)
+ {
+ printf("\nMain Process:Invalid RELATION_ID number, Pass greater than or Equal to 1\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+ int __cdecl main(INT argc, CHAR **argv)
+{
+ unsigned int i = 0;
+ HANDLE hThread[MAXIMUM_WAIT_OBJECTS];
+ DWORD threadId[MAXIMUM_WAIT_OBJECTS];
+
+ const char *ObjName = "Semaphore";
+
+ DWORD dwParam = 0;
+
+ int returnCode = 0;
+
+ /* Variables to capture the file name and the file pointer at thread level*/
+ char fileName[MAX_PATH];
+ FILE *pFile = NULL;
+ struct statistics* buffer = NULL;
+ int statisticsSize = 0;
+
+ /* Variables to capture the file name and the file pointer at process level*/
+ char processFileName[MAX_PATH];
+ FILE *pProcessFile = NULL;
+ struct ProcessStats processStats;
+ DWORD dwStartTime;
+
+ testStatus = PASS;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ if(GetParameters(argc, argv))
+ {
+ Fail("Error in obtaining the parameters\n");
+ }
+ // Trace("Process created, value of process count is [%d]\n", USE_PROCESS_COUNT);
+
+ /* Register the start time */
+ dwStartTime = GetTickCount();
+ processStats.relationId = RELATION_ID;
+ processStats.processId = USE_PROCESS_COUNT;
+
+ _snprintf(processFileName, MAX_PATH, "%d_process_semaphore_%d_.txt", USE_PROCESS_COUNT, RELATION_ID);
+ pProcessFile = fopen(processFileName, "w+");
+ if(pProcessFile == NULL)
+ {
+ Fail("Error in opening process File file for write for process [%d]\n", USE_PROCESS_COUNT);
+ }
+
+ statisticsSize = sizeof(struct statistics);
+
+ _snprintf(fileName, MAX_PATH, "%d_thread_semaphore_%d_.txt", USE_PROCESS_COUNT, RELATION_ID);
+ pFile = fopen(fileName, "w+");
+ if(pFile == NULL)
+ {
+ Fail("Error in opening file for write for process [%d]\n", USE_PROCESS_COUNT);
+ }
+ // For each thread we will log operations failed (int), passed (int), total (int)
+ // and number of ticks (DWORD) for the operations
+ resultBuffer = new ResultBuffer( THREAD_COUNT, statisticsSize);
+
+ StartTestsEvHandle = CreateEvent( NULL, /* lpEventAttributes*/
+ TRUE, /* bManualReset */
+ FALSE, /* bInitialState */
+ NULL); /* name of Event */
+
+ if( StartTestsEvHandle == NULL )
+ {
+ Fail("Error:%d: Unexpected failure "
+ "to create %s Event for process count %d\n", GetLastError(), sTmpEventName, USE_PROCESS_COUNT );
+
+ }
+
+ /* Create StartTest Event */
+ hSemaphoreHandle = CreateSemaphore(
+ NULL, /* lpSemaphoreAttributes */
+ lInitialCount, /*lInitialCount*/
+ lMaximumCount, /*lMaximumCount */
+ NULL
+ );
+
+ if( hSemaphoreHandle == NULL)
+ {
+ Fail("Unable to create Semaphore handle for process id [%d], returned error [%d]\n", i, GetLastError());
+ }
+ /* We already assume that the Semaphore was created previously*/
+
+ for( i = 0; i < THREAD_COUNT; i++ )
+ {
+ dwParam = (int) i;
+ //Create thread
+ hThread[i] = CreateThread(
+ NULL, /* no security attributes */
+ 0, /* use default stack size */
+ (LPTHREAD_START_ROUTINE)Run_Thread,/* thread function */
+ (LPVOID)dwParam, /* argument to thread function */
+ 0, /* use default creation flags */
+ &threadId[i] /* returns the thread identifier*/
+ );
+
+
+ if(hThread[i] == NULL)
+ {
+ Fail("Create Thread failed for %d process, and GetLastError value is %d\n", USE_PROCESS_COUNT, GetLastError());
+ }
+
+ }
+
+ if (!SetEvent(StartTestsEvHandle))
+ {
+ Fail("Set Event for Start Tests failed for %d process, and GetLastError value is %d\n", USE_PROCESS_COUNT, GetLastError());
+ }
+
+ /* Test running */
+ returnCode = WaitForMultipleObjects( THREAD_COUNT, hThread, TRUE, INFINITE);
+
+ if( WAIT_OBJECT_0 != returnCode )
+ {
+ Trace("Wait for Object(s) for %d process returned %d, and GetLastError value is %d\n", USE_PROCESS_COUNT, returnCode, GetLastError());
+ testStatus = FAIL;
+ }
+
+ processStats.operationTime = GetTimeDiff(dwStartTime);
+
+ /* Write to a file*/
+ if(pFile!= NULL)
+ {
+ for( i = 0; i < THREAD_COUNT; i++ )
+ {
+ buffer = (struct statistics *)resultBuffer->getResultBuffer(i);
+ returnCode = fprintf(pFile, "%d,%d,%d,%d,%lu,%d\n", buffer->processId, buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime, buffer->relationId );
+ //Trace("Iteration %d over\n", i);
+
+ }
+ }
+ fclose(pFile);
+ /* Logging for the test case over, clean up the handles */
+
+// Trace("Test Thread %d done\n", USE_PROCESS_COUNT);
+
+ for( i = 0; i < THREAD_COUNT; i++ )
+ {
+ if(!CloseHandle(hThread[i]) )
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hThread[%d]\n", GetLastError(), USE_PROCESS_COUNT, i);
+ testStatus = FAIL;
+ }
+ }
+
+ if(!CloseHandle(StartTestsEvHandle))
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] StartTestsEvHandle\n", GetLastError(), USE_PROCESS_COUNT);
+ testStatus = FAIL;
+ }
+
+ if(!CloseHandle(hSemaphoreHandle))
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hSemaphoreHandle\n", GetLastError(), USE_PROCESS_COUNT);
+ testStatus = FAIL;
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+void PALAPI Run_Thread (LPVOID lpParam)
+{
+ unsigned int i = 0;
+ DWORD dwWaitResult;
+
+ int Id=(int)lpParam;
+
+ struct statistics stats;
+ DWORD dwStartTime;
+
+ stats.relationId = RELATION_ID;
+ stats.processId = USE_PROCESS_COUNT;
+ stats.operationsFailed = 0;
+ stats.operationsPassed = 0;
+ stats.operationsTotal = 0;
+ stats.operationTime = 0;
+
+ dwWaitResult = WaitForSingleObject(
+ StartTestsEvHandle, // handle to start test handle
+ TIMEOUT);
+
+ if(dwWaitResult != WAIT_OBJECT_0)
+ {
+ Fail("Error while waiting for StartTest Event@ thread %d, RC is %d, Error is %d\n", Id, dwWaitResult, GetLastError());
+ }
+
+ dwStartTime = GetTickCount();
+
+ for( i = 0; i < REPEAT_COUNT; i++ )
+ {
+ dwWaitResult = WaitForSingleObject(
+ hSemaphoreHandle, // handle to Semaphore
+ TIMEOUT);
+
+ if(dwWaitResult != WAIT_OBJECT_0)
+ {
+// Trace("Error while waiting for onject @ thread %d, # iter %d, RC is %d, Error is %d\n", Id, i, dwWaitResult, GetLastError());
+ stats.operationsFailed += 1;
+ stats.operationsTotal += 1;
+ testStatus = FAIL;
+ continue;
+ }
+ if (! ReleaseSemaphore(hSemaphoreHandle, 1, NULL))
+ {
+ // Deal with error.
+ // Trace("Error while releasing Semaphore @ thread %d # iter %d\n", Id, i);
+ stats.operationsFailed += 1;
+ stats.operationsTotal += 1;
+ // Probably need to have while true loop to attempt to release semaphore...
+ testStatus = FAIL;
+ continue;
+ }
+
+ stats.operationsTotal += 1;
+ stats.operationsPassed += 1;
+// Trace("Successs while releasing Semaphore @ iteration %d -> thread %d -> Process %d\n", i, Id, USE_PROCESS_COUNT);
+
+ }
+
+ stats.operationTime = GetTimeDiff(dwStartTime);
+ if(resultBuffer->LogResult(Id, (char *)&stats))
+ {
+ Fail("Error:%d: while writing to shared memory, Thread Id is[%d] and Process id is [%d]\n", GetLastError(), Id, USE_PROCESS_COUNT);
+ }
+ // Trace("Thread %d over for process %d\n", Id, USE_PROCESS_COUNT);
+}
diff --git a/src/pal/tests/palsuite/composite/object_management/semaphore/shared/CMakeLists.txt b/src/pal/tests/palsuite/composite/object_management/semaphore/shared/CMakeLists.txt
new file mode 100644
index 0000000000..12d3ca867e
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/object_management/semaphore/shared/CMakeLists.txt
@@ -0,0 +1,21 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ main.c
+ semaphore.c
+)
+
+add_executable(paltest_semaphore_shared
+ ${SOURCES}
+)
+
+add_dependencies(paltest_semaphore_shared coreclrpal)
+
+target_link_libraries(paltest_semaphore_shared
+ pthread
+ rt
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/composite/object_management/semaphore/shared/main.c b/src/pal/tests/palsuite/composite/object_management/semaphore/shared/main.c
new file mode 100644
index 0000000000..deb8252b70
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/object_management/semaphore/shared/main.c
@@ -0,0 +1,278 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source Code: main.c and semaphore.c
+** main.c creates process and waits for all processes to get over
+** semaphore.c creates a semaphore and then calls threads which will contend for the semaphore
+**
+** This test is for Object Management Test case for semaphore where Object type is shareable.
+** Algorithm
+** o Main Process Creates OBJECT_TYPE Object
+** o Create PROCESS_COUNT processes aware of the Shared Object
+**
+**
+**
+**============================================================
+*/
+
+#include <palsuite.h>
+#include "resulttime.h"
+
+/* Test Input Variables */
+unsigned int PROCESS_COUNT = 1;
+unsigned int THREAD_COUNT = 1;
+unsigned int REPEAT_COUNT = 4;
+unsigned int RELATION_ID = 1001;
+
+
+unsigned long lInitialCount = 1; /* Signaled */
+unsigned long lMaximumCount = 1; /* Maximum value of 1 */
+
+char objectSuffix[MAX_PATH];
+
+struct TestStats{
+ DWORD operationTime;
+ unsigned int relationId;
+ unsigned int processCount;
+ unsigned int threadCount;
+ unsigned int repeatCount;
+ char* buildNumber;
+
+};
+
+int GetParameters( int argc, char **argv)
+{
+ if( (!((argc == 5) || (argc == 6) ) )|| ((argc == 1) && !strcmp(argv[1],"/?"))
+ || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H"))
+ {
+ printf("PAL -Composite Object Management event Test\n");
+ printf("Usage:\n");
+ printf("main\n\t[PROCESS_COUNT (greater than 1)] \n");
+ printf("\t[THREAD_COUNT (greater than 1)] \n");
+ printf("\t[REPEAT_COUNT (greater than 1)]\n");
+ printf("\t[RELATION_ID [greater than or equal to 1]\n");
+ printf("\t[Object Name Suffix]\n");
+ return -1;
+ }
+
+ PROCESS_COUNT = atoi(argv[1]);
+ if( (PROCESS_COUNT < 1) || (PROCESS_COUNT > MAXIMUM_WAIT_OBJECTS) )
+ {
+ printf("\nMain Process:Invalid PROCESS_COUNT number, Pass greater than 1 and less than PROCESS_COUNT %d\n", MAXIMUM_WAIT_OBJECTS);
+ return -1;
+ }
+
+ THREAD_COUNT = atoi(argv[2]);
+ if( (THREAD_COUNT < 1) || (THREAD_COUNT > MAXIMUM_WAIT_OBJECTS) )
+ {
+ printf("\nInvalid THREAD_COUNT number, Pass greater than 1 and less than %d\n", MAXIMUM_WAIT_OBJECTS);
+ return -1;
+ }
+
+ REPEAT_COUNT = atoi(argv[3]);
+ if( REPEAT_COUNT < 1)
+ {
+ printf("\nMain Process:Invalid REPEAT_COUNT number, Pass greater than 1\n");
+ return -1;
+ }
+
+ RELATION_ID = atoi(argv[4]);
+ if( RELATION_ID < 1)
+ {
+ printf("\nMain Process:Invalid RELATION_ID number, Pass greater than 1\n");
+ return -1;
+ }
+
+
+ if(argc == 6)
+ {
+ strncpy(objectSuffix, argv[5], MAX_PATH-1);
+ }
+
+ return 0;
+}
+
+ int __cdecl main(INT argc, CHAR **argv)
+{
+ unsigned int i = 0;
+ HANDLE hProcess[MAXIMUM_WAIT_OBJECTS];
+ HANDLE hSemaphoreHandle;
+
+ STARTUPINFO si[MAXIMUM_WAIT_OBJECTS];
+ PROCESS_INFORMATION pi[MAXIMUM_WAIT_OBJECTS];
+
+ char lpCommandLine[MAX_PATH] = "";
+ char ObjName[MAX_PATH] = "SHARED_SEMAPHORE";
+
+ int returnCode = 0;
+ DWORD processReturnCode = 0;
+ int testReturnCode = PASS;
+
+ char fileName[MAX_PATH];
+ FILE *pFile = NULL;
+ DWORD dwStartTime;
+ struct TestStats testStats;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+/*
+"While the new PAL does support named semaphore it's unclear
+if we should change the Windows PAL, since we share that w/ Rotor
+and they are still using the old PAL. For the time being it may
+make the most sense to just skip the named semaphore test on Windows
+- from an object management perspective it doesn't really gain
+us anything over what we already have."
+*/
+#ifdef PLATFORM_UNIX
+
+ ZeroMemory( objectSuffix, MAX_PATH );
+
+ if(GetParameters(argc, argv))
+ {
+ Fail("Error in obtaining the parameters\n");
+ }
+
+ if(argc == 6)
+ {
+ strncat(ObjName, objectSuffix, MAX_PATH - (sizeof(ObjName) + 1) );
+ }
+
+ /* Register the start time */
+ dwStartTime = GetTickCount();
+ testStats.relationId = RELATION_ID;
+ testStats.processCount = PROCESS_COUNT;
+ testStats.threadCount = THREAD_COUNT;
+ testStats.repeatCount = REPEAT_COUNT;
+ testStats.buildNumber = getBuildNumber();
+
+ _snprintf(fileName, MAX_PATH, "main_semaphore_%d_.txt", RELATION_ID);
+ pFile = fopen(fileName, "w+");
+ if(pFile == NULL)
+ {
+ Fail("Error in opening main file for write\n");
+ }
+
+ hSemaphoreHandle = CreateSemaphore(
+ NULL, /* lpSemaphoreAttributes */
+ lInitialCount, /*lInitialCount*/
+ lMaximumCount, /*lMaximumCount */
+ ObjName
+ );
+
+ if( hSemaphoreHandle == NULL)
+ {
+ Fail("Unable to create shared Semaphore handle @ Main returned error [%d]\n", GetLastError());
+ }
+
+ for( i = 0; i < PROCESS_COUNT; i++ )
+ {
+
+
+ ZeroMemory( lpCommandLine, MAX_PATH );
+ if ( _snprintf( lpCommandLine, MAX_PATH-1, "semaphore %d %d %d %d %s", i, THREAD_COUNT, REPEAT_COUNT, RELATION_ID, objectSuffix) < 0 )
+ {
+ Fail("Error: Insufficient semaphore name string length for %s for iteration [%d]\n", ObjName, i);
+ }
+
+
+ /* Zero the data structure space */
+ ZeroMemory ( &pi[i], sizeof(pi[i]) );
+ ZeroMemory ( &si[i], sizeof(si[i]) );
+
+ /* Set the process flags and standard io handles */
+ si[i].cb = sizeof(si[i]);
+
+ if(!CreateProcess( NULL, /* lpApplicationName*/
+ lpCommandLine, /* lpCommandLine */
+ NULL, /* lpProcessAttributes */
+ NULL, /* lpThreadAttributes */
+ TRUE, /* bInheritHandles */
+ 0, /* dwCreationFlags, */
+ NULL, /* lpEnvironment */
+ NULL, /* pCurrentDirectory */
+ &si[i], /* lpStartupInfo */
+ &pi[i] /* lpProcessInformation */
+ ))
+ {
+ Fail("Process Not created for [%d], the error code is [%d]\n", i, GetLastError());
+ }
+ else
+ {
+ hProcess[i] = pi[i].hProcess;
+// Trace("Process created for [%d]\n", i);
+
+ }
+
+ }
+
+ returnCode = WaitForMultipleObjects( PROCESS_COUNT, hProcess, TRUE, INFINITE);
+ if( WAIT_OBJECT_0 != returnCode )
+ {
+ Trace("Wait for Object(s) @ Main thread for %d processes returned %d, and GetLastError value is %d\n", PROCESS_COUNT, returnCode, GetLastError());
+ testReturnCode = FAIL;
+ }
+
+ for( i = 0; i < PROCESS_COUNT; i++ )
+ {
+ /* check the exit code from the process */
+ if( ! GetExitCodeProcess( pi[i].hProcess, &processReturnCode ) )
+ {
+ Trace( "GetExitCodeProcess call failed for iteration %d with error code %u\n",
+ i, GetLastError() );
+
+ testReturnCode = FAIL;
+ }
+
+ if(processReturnCode == FAIL)
+ {
+ Trace( "Process [%d] failed and returned FAIL\n", i);
+ testReturnCode = FAIL;
+ }
+
+ if(!CloseHandle(pi[i].hThread))
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hThread\n", GetLastError(), i);
+ testReturnCode = FAIL;
+ }
+
+ if(!CloseHandle(pi[i].hProcess) )
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hProcess\n", GetLastError(), i);
+ testReturnCode = FAIL;
+ }
+ }
+
+ testStats.operationTime = GetTimeDiff(dwStartTime);
+ fprintf(pFile, "%d,%d,%d,%d,%d,%s\n", testStats.operationTime, testStats.relationId, testStats.processCount, testStats.threadCount, testStats.repeatCount, testStats.buildNumber);
+ if(fclose(pFile))
+ {
+ Trace("Error: fclose failed for pFile\n");
+ testReturnCode = FAIL;
+ };
+
+ if(!CloseHandle(hSemaphoreHandle))
+ {
+ Trace("Error:%d: CloseHandle failed for hSemaphoreHandle\n", GetLastError());
+ testReturnCode = FAIL;
+
+ }
+
+ if( testReturnCode == PASS)
+ {
+ Trace("Test Passed\n");
+ }
+ else
+ {
+ Trace("Test Failed\n");
+ }
+
+#endif //PLATFORM_UNIX
+ PAL_Terminate();
+ return testReturnCode;
+}
diff --git a/src/pal/tests/palsuite/composite/object_management/semaphore/shared/semaphore.c b/src/pal/tests/palsuite/composite/object_management/semaphore/shared/semaphore.c
new file mode 100644
index 0000000000..5143c55143
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/object_management/semaphore/shared/semaphore.c
@@ -0,0 +1,351 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source Code: main.c and semaphore.c
+** main.c creates process and waits for all processes to get over
+** semaphore.c creates a semaphore and then calls threads which will contend for the semaphore
+**
+** This test is for Object Management Test case for semaphore where Object type is shareable.
+** Algorithm
+** o Main Process Creates OBJECT_TYPE Object
+** o Create PROCESS_COUNT processes aware of the Shared Object
+**
+**
+**
+**============================================================
+*/
+
+#include <palsuite.h>
+#include "resultbuffer.h"
+#include "resulttime.h"
+
+#define TIMEOUT 5000
+/* Test Input Variables */
+unsigned int USE_PROCESS_COUNT = 0;
+unsigned int THREAD_COUNT = 0;
+unsigned int REPEAT_COUNT = 0;
+unsigned int RELATION_ID= 0;
+
+/* Capture statistics at per thread basis */
+struct statistics{
+ unsigned int processId;
+ unsigned int operationsFailed;
+ unsigned int operationsPassed;
+ unsigned int operationsTotal;
+ DWORD operationTime;
+ unsigned int relationId;
+};
+
+struct ProcessStats{
+ unsigned int processId;
+ DWORD operationTime;
+ unsigned int relationId;
+};
+
+/* Semaphore variables */
+unsigned long lInitialCount = 1; /* Signaled */
+unsigned long lMaximumCount = 1; /* Maximum value of 1 */
+
+HANDLE StartTestsEvHandle = NULL;
+HANDLE hSemaphoreHandle = NULL;
+
+/* Results Buffer */
+ResultBuffer *resultBuffer = NULL;
+
+int testStatus;
+
+const char sTmpEventName[MAX_PATH] = "StartTestEvent";
+char objectSuffix[MAX_PATH];
+
+void PALAPI Run_Thread(LPVOID lpParam);
+
+int GetParameters( int argc, char **argv)
+{
+ if( (!((argc == 5) || (argc == 6) ) )|| ((argc == 1) && !strcmp(argv[1],"/?"))
+ || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H"))
+ {
+ printf("PAL -Composite Object Management event Test\n");
+ printf("Usage:\n");
+ printf("main\n\t[PROCESS_COUNT (greater than 1)] \n");
+ printf("\t[THREAD_COUNT (greater than 1)] \n");
+ printf("\t[REPEAT_COUNT (greater than 1)]\n");
+ printf("\t[RELATION_ID [greater than or equal to 1]\n");
+ printf("\t[Object Name Suffix]\n");
+ return -1;
+ }
+
+ USE_PROCESS_COUNT = atoi(argv[1]);
+ if(USE_PROCESS_COUNT < 0)
+ {
+ printf("\nMain Process:Invalid PROCESS_COUNT number, Pass greater than 0 \n");
+ return -1;
+ }
+
+ THREAD_COUNT = atoi(argv[2]);
+ if( (THREAD_COUNT < 1) || (THREAD_COUNT > MAXIMUM_WAIT_OBJECTS) )
+ {
+ printf("\nInvalid THREAD_COUNT number, Pass greater than 1 and less than %d\n", MAXIMUM_WAIT_OBJECTS);
+ return -1;
+ }
+
+ REPEAT_COUNT = atoi(argv[3]);
+ if( REPEAT_COUNT < 1)
+ {
+ printf("\nMain Process:Invalid REPEAT_COUNT number, Pass greater than 1\n");
+ return -1;
+ }
+
+ RELATION_ID = atoi(argv[4]);
+ if( RELATION_ID < 1)
+ {
+ printf("\nMain Process:Invalid RELATION_ID number, Pass greater than 1\n");
+ return -1;
+ }
+
+ if(argc == 6)
+ {
+ strncpy(objectSuffix, argv[5], MAX_PATH-1);
+ }
+
+ return 0;
+}
+
+ int __cdecl main(INT argc, CHAR **argv)
+{
+ unsigned int i = 0;
+ HANDLE hThread[MAXIMUM_WAIT_OBJECTS];
+ DWORD threadId[MAXIMUM_WAIT_OBJECTS];
+
+ char ObjName[MAX_PATH] = "SHARED_SEMAPHORE";
+ DWORD dwParam = 0;
+
+ int returnCode = 0;
+
+ /* Variables to capture the file name and the file pointer at thread level*/
+ char fileName[MAX_PATH];
+ FILE *pFile = NULL;
+ struct statistics* buffer = NULL;
+ int statisticsSize = 0;
+
+ /* Variables to capture the file name and the file pointer at process level*/
+ char processFileName[MAX_PATH];
+ FILE *pProcessFile = NULL;
+ struct ProcessStats processStats;
+ DWORD dwStartTime;
+
+ testStatus = PASS;
+
+ ZeroMemory( objectSuffix, MAX_PATH );
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ if(GetParameters(argc, argv))
+ {
+ Fail("Error in obtaining the parameters\n");
+ }
+// Trace("Process created, value of process count is [%d]\n", USE_PROCESS_COUNT);
+
+ if(argc == 6)
+ {
+ strncat(ObjName , objectSuffix, MAX_PATH - (sizeof(ObjName) + 1) );
+ }
+
+ /* Register the start time */
+ dwStartTime = GetTickCount();
+ processStats.relationId = RELATION_ID;
+ processStats.processId = USE_PROCESS_COUNT;
+
+ _snprintf(processFileName, MAX_PATH, "%d_process_semaphore_%d_.txt", USE_PROCESS_COUNT, RELATION_ID);
+ pProcessFile = fopen(processFileName, "w+");
+ if(pProcessFile == NULL)
+ {
+ Fail("Error in opening process File file for write for process [%d]\n", USE_PROCESS_COUNT);
+ }
+
+ statisticsSize = sizeof(struct statistics);
+
+ _snprintf(fileName, MAX_PATH, "%d_thread_semaphore_%d_.txt", USE_PROCESS_COUNT, RELATION_ID);
+ pFile = fopen(fileName, "w+");
+ if(pFile == NULL)
+ {
+ Fail("Error in opening file for write for process [%d]\n", USE_PROCESS_COUNT);
+ }
+ // For each thread we will log operations failed (int), passed (int), total (int)
+ // and number of ticks (DWORD) for the operations
+ resultBuffer = new ResultBuffer( THREAD_COUNT, statisticsSize);
+
+ /* Create Start Tests event */
+ StartTestsEvHandle = CreateEvent( NULL, /* lpEventAttributes*/
+ TRUE, /* bManualReset */
+ FALSE, /* bInitialState */
+ NULL); /* name of Event */
+
+ if( StartTestsEvHandle == NULL )
+ {
+ Fail("Error:%d: Unexpected failure "
+ "to create %s Event for process count %d\n", GetLastError(), sTmpEventName, USE_PROCESS_COUNT );
+
+ }
+
+ hSemaphoreHandle = CreateSemaphore(
+ NULL, /* lpSemaphoreAttributes */
+ lInitialCount, /*lInitialCount*/
+ lMaximumCount, /*lMaximumCount */
+ ObjName
+ );
+
+
+ if( (hSemaphoreHandle == NULL) || (GetLastError() != ERROR_ALREADY_EXISTS) )
+ {
+ Fail("Unable to create Semaphore handle for process id [%d], returned error [%d], expected ERROR_ALREADY_EXISTS\n", i, GetLastError());
+ }
+
+ /* We already assume that the Semaphore was created previously*/
+
+ for( i = 0; i < THREAD_COUNT; i++ )
+ {
+ dwParam = (int) i;
+ //Create thread
+ hThread[i] = CreateThread(
+ NULL, /* no security attributes */
+ 0, /* use default stack size */
+ (LPTHREAD_START_ROUTINE)Run_Thread,/* thread function */
+ (LPVOID)dwParam, /* argument to thread function */
+ 0, /* use default creation flags */
+ &threadId[i] /* returns the thread identifier*/
+ );
+
+ if(hThread[i] == NULL)
+ {
+ Fail("Create Thread failed for %d process, and GetLastError value is %d\n", USE_PROCESS_COUNT, GetLastError());
+ }
+ }
+
+ if (!SetEvent(StartTestsEvHandle))
+ {
+ Fail("Set Event for Start Tests failed for %d process, and GetLastError value is %d\n", USE_PROCESS_COUNT, GetLastError());
+ }
+
+ /* Test running */
+ returnCode = WaitForMultipleObjects( THREAD_COUNT, hThread, TRUE, INFINITE);
+
+ if( WAIT_OBJECT_0 != returnCode )
+ {
+ Trace("Wait for Object(s) for %d process returned %d, and GetLastError value is %d\n", USE_PROCESS_COUNT, returnCode, GetLastError());
+ testStatus = FAIL;
+ }
+
+ processStats.operationTime = GetTimeDiff(dwStartTime);
+
+ /* Write to a file*/
+ if(pFile!= NULL)
+ {
+ for( i = 0; i < THREAD_COUNT; i++ )
+ {
+ buffer = (struct statistics *)resultBuffer->getResultBuffer(i);
+ returnCode = fprintf(pFile, "%d,%d,%d,%d,%lu,%d\n", buffer->processId, buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime, buffer->relationId );
+// Trace("Iteration %d over\n", i);
+
+ }
+ }
+ fclose(pFile);
+ /* Logging for the test case over, clean up the handles */
+
+// Trace("Test Thread %d done\n", USE_PROCESS_COUNT);
+ for( i = 0; i < THREAD_COUNT; i++ )
+ {
+ if(!CloseHandle(hThread[i]) )
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hThread[%d]\n", GetLastError(), USE_PROCESS_COUNT, i);
+ testStatus = FAIL;
+ }
+ }
+
+ if(!CloseHandle(StartTestsEvHandle))
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] StartTestsEvHandle\n", GetLastError(), USE_PROCESS_COUNT);
+ testStatus = FAIL;
+ }
+
+ if(!CloseHandle(hSemaphoreHandle))
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hSemaphoreHandle\n", GetLastError(), USE_PROCESS_COUNT);
+ testStatus = FAIL;
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+void PALAPI Run_Thread (LPVOID lpParam)
+{
+ unsigned int i = 0;
+ DWORD dwWaitResult;
+
+ int Id=(int)lpParam;
+
+ struct statistics stats;
+ DWORD dwStartTime;
+
+ stats.relationId = RELATION_ID;
+ stats.processId = USE_PROCESS_COUNT;
+ stats.operationsFailed = 0;
+ stats.operationsPassed = 0;
+ stats.operationsTotal = 0;
+ stats.operationTime = 0;
+
+ dwWaitResult = WaitForSingleObject(
+ StartTestsEvHandle, // handle to start test handle
+ TIMEOUT);
+
+ if(dwWaitResult != WAIT_OBJECT_0)
+ {
+ Fail("Error while waiting for StartTest Event@ thread %d, RC is %d, Error is %d\n", Id, dwWaitResult, GetLastError());
+ }
+
+ dwStartTime = GetTickCount();
+
+ for( i = 0; i < REPEAT_COUNT; i++ )
+ {
+ dwWaitResult = WaitForSingleObject(
+ hSemaphoreHandle, // handle to Semaphore
+ TIMEOUT);
+
+ if(dwWaitResult != WAIT_OBJECT_0)
+ {
+// Trace("Error while waiting for onject @ thread %d, # iter %d, RC is %d, Error is %d\n", Id, i, dwWaitResult, GetLastError());
+ stats.operationsFailed += 1;
+ stats.operationsTotal += 1;
+ testStatus = FAIL;
+ continue;
+ }
+ if (! ReleaseSemaphore(hSemaphoreHandle, 1, NULL))
+ {
+ // Deal with error.
+ // Trace("Error while releasing Semaphore @ thread %d # iter %d\n", Id, i);
+ stats.operationsFailed += 1;
+ stats.operationsTotal += 1;
+ // Probably need to have while true loop to attempt to release semaphore..
+ testStatus = FAIL;
+ continue;
+ }
+
+ stats.operationsTotal += 1;
+ stats.operationsPassed += 1;
+// Trace("Successs while releasing Semaphore @ iteration %d -> thread %d -> Process %d\n", i, Id, USE_PROCESS_COUNT);
+
+ }
+
+ stats.operationTime = GetTimeDiff(dwStartTime);
+ if(resultBuffer->LogResult(Id, (char *)&stats))
+ {
+ Fail("Error:%d: while writing to shared memory, Thread Id is[%d] and Process id is [%d]\n", GetLastError(), Id, USE_PROCESS_COUNT);
+ }
+ // Trace("Thread %d over for process %d\n", Id, USE_PROCESS_COUNT);
+}
diff --git a/src/pal/tests/palsuite/composite/synchronization/CMakeLists.txt b/src/pal/tests/palsuite/composite/synchronization/CMakeLists.txt
new file mode 100644
index 0000000000..cffb4f78ab
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/synchronization/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(criticalsection)
+add_subdirectory(nativecriticalsection)
+add_subdirectory(nativecs_interlocked)
+
diff --git a/src/pal/tests/palsuite/composite/synchronization/criticalsection/CMakeLists.txt b/src/pal/tests/palsuite/composite/synchronization/criticalsection/CMakeLists.txt
new file mode 100644
index 0000000000..936c0fe82d
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/synchronization/criticalsection/CMakeLists.txt
@@ -0,0 +1,20 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ criticalsection.c
+ mainWrapper.c
+)
+
+add_executable(paltest_synchronization_criticalsection
+ ${SOURCES}
+)
+
+add_dependencies(paltest_synchronization_criticalsection coreclrpal)
+
+target_link_libraries(paltest_synchronization_criticalsection
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/composite/synchronization/criticalsection/criticalsection.c b/src/pal/tests/palsuite/composite/synchronization/criticalsection/criticalsection.c
new file mode 100644
index 0000000000..2fcd363e8a
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/synchronization/criticalsection/criticalsection.c
@@ -0,0 +1,418 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: criticalsection.c
+**
+** Purpose: Test Critical Section Reengineering PAL Effort
+**
+** PseudoCode:
+ Preparation:
+ Create PROCESS_COUNT processes.
+ In each process create a Critical Section
+
+ Test:
+ Create THREAD_COUNT threads.
+ In a loop repeated REPEAT_COUNT times:
+ Enter Critical Section
+ Do Work
+ Leave Critical Section
+ The main thread waits for all of the created threads to exit (WFMO wait all on the created thread handles) and call DeleteCriticalSection
+
+ Parameters:
+ PROCESS_COUNT: Number of processes
+ THREAD_COUNT: Number of threads in each process
+ REPEAT_COUNT: The number of times to execute the loop..
+
+ Statistics Captured:
+ Total elapsed time
+ MTBF
+
+ Scenario:
+ Single Process with Multiple threads. Main thread creates critical section.
+ All other threads call EnterCriticalSection. When thread enters critical section
+ it does some work and leaves critical section.
+
+** Dependencies:
+ CreateThread
+** InitializeCriticalSection
+** EnterCriticalSection
+** LeaveCriticalSection
+** DeleteCriticalSection
+** WaitForSingleObject
+**
+** Author: rameshg
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+#include "resultbuffer.h"
+
+//Global Variables
+DWORD dwThreadId;
+long long GLOBAL_COUNTER ;
+HANDLE g_hEvent;
+
+/* Test Input Variables */
+unsigned int USE_PROCESS_COUNT = 0;
+unsigned int THREAD_COUNT = 0;
+unsigned int REPEAT_COUNT = 0;
+unsigned int SLEEP_LENGTH = 0;
+unsigned int RELATION_ID = 0;
+
+
+CRITICAL_SECTION CriticalSectionM; /* Critical Section Object (used as mutex) */
+
+
+/* Capture statistics for each worker thread */
+struct statistics{
+ unsigned int processId;
+ unsigned int operationsFailed;
+ unsigned int operationsPassed;
+ unsigned int operationsTotal;
+ DWORD operationTime; //Milliseconds
+ unsigned int relationId;
+};
+
+
+/*Capture Statistics at a Process level*/
+struct processStatistics{
+ unsigned int processId;
+ DWORD operationTime; //Milliseconds
+ unsigned int relationId;
+};
+
+
+ResultBuffer *resultBuffer;
+
+//function declarations
+int GetParameters( int , char **);
+void setup (void);
+void cleanup(void);
+void incrementCounter(void);
+DWORD PALAPI enterandleavecs( LPVOID );
+
+
+/*
+*Setup for the test case
+*/
+
+VOID
+setup(VOID)
+{
+
+g_hEvent = CreateEvent(NULL,TRUE,FALSE, NULL);
+if(g_hEvent == NULL)
+{
+ Fail("Create Event Failed\n"
+ "GetLastError returned %d\n", GetLastError());
+}
+
+GLOBAL_COUNTER=0;
+/*
+* Create mutual exclusion mechanisms
+*/
+InitializeCriticalSection ( &CriticalSectionM );
+
+}
+
+
+/*
+* Cleanup for the test case
+*/
+VOID
+cleanup(VOID)
+{
+ /*
+ * Clean up Critical Section object
+ */
+ DeleteCriticalSection(&CriticalSectionM);
+ PAL_Terminate();
+}
+
+
+/*function that increments a counter*/
+VOID
+incrementCounter(VOID)
+{
+
+ if (INT_MAX==GLOBAL_COUNTER)
+ GLOBAL_COUNTER=0;
+
+ GLOBAL_COUNTER++;
+
+}
+
+/*
+ * Enter and Leave Critical Section
+ */
+DWORD
+PALAPI
+enterandleavecs( LPVOID lpParam )
+{
+
+ struct statistics stats;
+ int loopcount = REPEAT_COUNT;
+ int i;
+ DWORD dwStart =0;
+
+ int Id=(int)lpParam;
+
+ //initialize strucutre to hold thread level statistics
+ stats.relationId = RELATION_ID;
+ stats.processId = USE_PROCESS_COUNT;
+ stats.operationsFailed = 0;
+ stats.operationsPassed = 0;
+ stats.operationsTotal = 0;
+ stats.operationTime = 0;
+
+ //Wait for main thread to signal event
+ if (WAIT_OBJECT_0 != WaitForSingleObject(g_hEvent,INFINITE))
+ {
+ Fail ("readfile: Wait for Single Object (g_hEvent) failed. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+ //Collect operation start time
+ dwStart = GetTickCount();
+
+ //Operation starts loopcount times
+ for(i = 0; i < loopcount; i++)
+ {
+
+ EnterCriticalSection(&CriticalSectionM);
+ /*
+ *Do Some Thing once you enter critical section
+ */
+ incrementCounter();
+ LeaveCriticalSection(&CriticalSectionM);
+
+ stats.operationsPassed++;
+ stats.operationsTotal++;
+ }
+ //collect operation end time
+ stats.operationTime = GetTickCount() - dwStart;
+
+ /*Trace("\n\n\n\nOperation Time %d\n", stats.operationTime);
+ Trace("Operation Passed %d\n", stats.operationsPassed);
+ Trace("Operation Total %d\n", stats.operationsTotal);
+ Trace("Operation Failed %d\n", stats.operationsFailed); */
+
+ if(resultBuffer->LogResult(Id, (char *)&stats))
+ {
+ Fail("Error while writing to shared memory, Thread Id is[%d] and Process id is [%d]\n", Id, USE_PROCESS_COUNT);
+ }
+
+
+ return 0;
+}
+
+
+int __cdecl main (int argc, char **argv)
+{
+
+/*
+* Parameter to the threads that will be created
+*/
+DWORD dwThrdParam = 0;
+HANDLE hThread[64];
+unsigned int i = 0;
+DWORD dwStart;
+
+/* Variables to capture the file name and the file pointer*/
+char fileName[MAX_PATH_FNAME];
+char processFileName[MAX_PATH_FNAME];
+FILE *hFile,*hProcessFile;
+struct processStatistics processStats;
+
+struct statistics* buffer;
+int statisticsSize = 0;
+
+/*
+* PAL Initialize
+*/
+if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+if(GetParameters(argc, argv))
+ {
+ Fail("Error in obtaining the parameters\n");
+ }
+
+
+/*setup file for process result collection */
+_snprintf(processFileName, MAX_PATH_FNAME, "%d_process_criticalsection_%d_.txt", USE_PROCESS_COUNT, RELATION_ID);
+hProcessFile = fopen(processFileName, "w+");
+if(hProcessFile == NULL)
+ {
+ Fail("Error in opening file to write process results for process [%d]\n", USE_PROCESS_COUNT);
+ }
+
+//Initialize Process Stats Variables
+processStats.operationTime = 0;
+processStats.processId = USE_PROCESS_COUNT;
+processStats.relationId = RELATION_ID; //Will change later
+
+//Start Process Time Capture
+dwStart = GetTickCount();
+
+//setup file for thread result collection
+statisticsSize = sizeof(struct statistics);
+_snprintf(fileName, MAX_PATH_FNAME, "%d_thread_criticalsection_%d_.txt", USE_PROCESS_COUNT, RELATION_ID);
+hFile = fopen(fileName, "w+");
+if(hFile == NULL)
+{
+ Fail("Error in opening file for write for process [%d]\n", USE_PROCESS_COUNT);
+}
+
+// For each thread we will log operations failed (int), passed (int), total (int)
+// and number of ticks (DWORD) for the operations
+resultBuffer = new ResultBuffer( THREAD_COUNT, statisticsSize);
+
+/*
+* Call the Setup Routine
+*/
+setup();
+
+//Create Thread Count Worker Threads
+
+while (i< THREAD_COUNT)
+{
+ dwThrdParam = i;
+
+ hThread[i] = CreateThread(
+ NULL,
+ 0,
+ enterandleavecs,
+ (LPVOID)dwThrdParam,
+ 0,
+ &dwThreadId);
+
+ if ( NULL == hThread[i] )
+ {
+ Fail ( "CreateThread() returned NULL. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+ i++;
+}
+
+/*
+* Set Event to signal all threads to start using the CS
+*/
+
+if (0==SetEvent(g_hEvent))
+{
+ Fail ( "SetEvent returned Zero. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+}
+
+/*
+ * Wait for worker threads to complete
+ *
+ */
+if ( WAIT_OBJECT_0 != WaitForMultipleObjects (THREAD_COUNT,hThread,TRUE, INFINITE))
+{
+ Fail ( "WaitForMultipleObject Failed. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+}
+
+
+//Get the end time of the process
+processStats.operationTime = GetTickCount() - dwStart;
+
+//Write Process Result Contents to File
+if(hProcessFile!= NULL)
+ {
+ fprintf(hProcessFile, "%d,%lu,%d\n", processStats.processId, processStats.operationTime, processStats.relationId );
+ }
+
+if (0!=fclose(hProcessFile))
+{
+ Fail("Unable to write process results to file"
+ "GetLastError returned %d\n", GetLastError());
+}
+
+
+/*Write Threads Results to a file*/
+if(hFile!= NULL)
+{
+ for( i = 0; i < THREAD_COUNT; i++ )
+ {
+ buffer = (struct statistics *)resultBuffer->getResultBuffer(i);
+ fprintf(hFile, "%d,%d,%d,%d,%lu,%d\n", buffer->processId, buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime, buffer->relationId );
+ //Trace("Iteration %d over\n", i);
+ }
+}
+
+if (0!=fclose(hFile))
+{
+ Fail("Unable to write thread results to file"
+ "GetLastError returned %d\n", GetLastError());
+}
+
+ /* Logging for the test case over, clean up the handles */
+ //Trace("Contents of the buffer are [%s]\n", resultBuffer->getResultBuffer());
+
+
+//Call Cleanup for Test Case
+cleanup();
+
+//Trace("Value of GLOBAL COUNTER %d \n", GLOBAL_COUNTER);
+return (PASS);
+
+}
+
+
+int GetParameters( int argc, char **argv)
+{
+
+ if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?"))
+ || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H"))
+ {
+ printf("PAL -Composite Critical Section Test\n");
+ printf("Usage:\n");
+ printf("\t[PROCESS_COUNT] Greater than or Equal to 1 \n");
+ printf("\t[WORKER_THREAD_MULTIPLIER_COUNT] Greater than or Equal to 1 and Less than or Equal to 64 \n");
+ printf("\t[REPEAT_COUNT] Greater than or Equal to 1\n");
+ printf("\t[RELATION_ID [Greater than or Equal to 1]\n");
+ return -1;
+ }
+
+// Trace("Args 1 is [%s], Arg 2 is [%s], Arg 3 is [%s]\n", argv[1], argv[2], argv[3]);
+
+ USE_PROCESS_COUNT = atoi(argv[1]);
+ if( USE_PROCESS_COUNT < 0)
+ {
+ printf("\nPROCESS_COUNT to greater than or equal to 1\n");
+ return -1;
+ }
+
+ THREAD_COUNT = atoi(argv[2]);
+ if( THREAD_COUNT < 1 || THREAD_COUNT > 64)
+ {
+ printf("\nTHREAD_COUNT to be greater than or equal to 1 or less than or equal to 64\n");
+ return -1;
+ }
+
+ REPEAT_COUNT = atoi(argv[3]);
+ if( REPEAT_COUNT < 1)
+ {
+ printf("\nREPEAT_COUNT to greater than or equal to 1\n");
+ return -1;
+ }
+
+ RELATION_ID = atoi(argv[4]);
+ if( RELATION_ID < 1)
+ {
+ printf("\nMain Process:Invalid RELATION_ID number, Pass greater than 1\n");
+ return -1;
+ }
+
+ return 0;
+}
+
diff --git a/src/pal/tests/palsuite/composite/synchronization/criticalsection/mainWrapper.c b/src/pal/tests/palsuite/composite/synchronization/criticalsection/mainWrapper.c
new file mode 100644
index 0000000000..4bc2f3d834
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/synchronization/criticalsection/mainWrapper.c
@@ -0,0 +1,255 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*
+Source Code: mainWrapper.c
+
+mainWrapper.c creates Composite Test Case Processes and waits for all processes to get over
+
+Algorithm
+o Create PROCESS_COUNT processes.
+
+Author: RameshG
+*/
+
+#include <palsuite.h>
+#include "resulttime.h"
+
+/* Test Input Variables */
+unsigned int USE_PROCESS_COUNT = 0; //default
+unsigned int THREAD_COUNT = 0; //default
+unsigned int REPEAT_COUNT = 0; //default
+unsigned int SLEEP_LENGTH = 0; //default
+unsigned int RELATION_ID = 1001;
+
+
+//Strucuture to capture application wide statistics
+struct applicationStatistics{
+ DWORD operationTime;
+ unsigned int relationId;
+ unsigned int processCount;
+ unsigned int threadCount;
+ unsigned int repeatCount;
+ char* buildNumber;
+
+};
+
+
+//Get parameters from the commandline
+int GetParameters( int argc, char **argv)
+{
+
+ if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?"))
+ || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H"))
+ {
+ printf("Main Wrapper PAL -Composite Critical Section Test\n");
+ printf("Usage:\n");
+ printf("\t[PROCESS_COUNT] Greater than or Equal to 1 \n");
+ printf("\t[THREAD_COUNT] Greater than or Equal to 1 and Less than or Equal to 64 \n");
+ printf("\t[REPEAT_COUNT] Greater than or Equal to 1\n");
+ printf("\t[RELATION_ID [Greater than or Equal to 1]\n");
+
+ return -1;
+ }
+
+ USE_PROCESS_COUNT = atoi(argv[1]);
+ if( USE_PROCESS_COUNT < 0)
+ {
+ printf("\nPROCESS_COUNT to greater than or equal to 1\n");
+ return -1;
+ }
+
+ THREAD_COUNT = atoi(argv[2]);
+ if( THREAD_COUNT < 1 || THREAD_COUNT > 64)
+ {
+ printf("\nTHREAD_COUNT to be greater than or equal to 1 or less than or equal to 64\n");
+ return -1;
+ }
+
+ REPEAT_COUNT = atoi(argv[3]);
+ if( REPEAT_COUNT < 1)
+ {
+ printf("\nREPEAT_COUNT to greater than or equal to 1\n");
+ return -1;
+ }
+
+ RELATION_ID = atoi(argv[4]);
+ if( RELATION_ID < 1)
+ {
+ printf("\nMain Process:Invalid RELATION_ID number, Pass greater than 1\n");
+ return -1;
+ }
+
+
+
+
+ return 0;
+}
+
+//Main entry point for the application
+ int __cdecl main(INT argc, CHAR **argv)
+{
+ unsigned int i = 0;
+ HANDLE hProcess[MAXIMUM_WAIT_OBJECTS]; //Array to hold Process handles
+ DWORD processReturnCode = 0;
+ int testReturnCode = PASS;
+ STARTUPINFO si[MAXIMUM_WAIT_OBJECTS];
+ PROCESS_INFORMATION pi[MAXIMUM_WAIT_OBJECTS];
+ FILE *hFile; //handle to application results file
+ char fileName[MAX_PATH]; //file name of the application results file
+ struct applicationStatistics appStats;
+ DWORD dwStart=0; //to store the tick count
+ char lpCommandLine[MAX_PATH] = "";
+ int returnCode = 0;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+
+
+
+ if(GetParameters(argc, argv))
+ {
+ Fail("Error in obtaining the parameters\n");
+ }
+
+ //Initialize Application Statistics Strucuture
+ appStats.operationTime=0;
+ appStats.relationId = RELATION_ID;
+ appStats.processCount = USE_PROCESS_COUNT;
+ appStats.threadCount = THREAD_COUNT;
+ appStats.repeatCount = REPEAT_COUNT;
+ appStats.buildNumber = getBuildNumber();
+
+
+_snprintf(fileName, MAX_PATH, "main_criticalsection_%d_.txt", RELATION_ID);
+
+hFile = fopen(fileName, "w+");
+
+if(hFile == NULL)
+ {
+ Fail("Error in opening file to write application results for Critical Section Test, and error code is %d\n", GetLastError());
+ }
+
+//Start Process Time Capture
+dwStart = GetTickCount();
+
+for( i = 0; i < USE_PROCESS_COUNT; i++ )
+ {
+
+ ZeroMemory( lpCommandLine, MAX_PATH );
+ if ( _snprintf( lpCommandLine, MAX_PATH-1, "criticalsection %d %d %d %d", i, THREAD_COUNT, REPEAT_COUNT, RELATION_ID) < 0 )
+ {
+ Trace ("Error: Insufficient commandline string length for for iteration [%d]\n", i);
+ }
+
+ /* Zero the data structure space */
+ ZeroMemory ( &pi[i], sizeof(pi[i]) );
+ ZeroMemory ( &si[i], sizeof(si[i]) );
+
+ /* Set the process flags and standard io handles */
+ si[i].cb = sizeof(si[i]);
+
+ //Printing the Command Line
+ //Trace("Command Line \t %s \n", lpCommandLine);
+
+ //Create Process
+ if(!CreateProcess( NULL, /* lpApplicationName*/
+ lpCommandLine, /* lpCommandLine */
+ NULL, /* lpProcessAttributes */
+ NULL, /* lpThreadAttributes */
+ TRUE, /* bInheritHandles */
+ 0, /* dwCreationFlags, */
+ NULL, /* lpEnvironment */
+ NULL, /* pCurrentDirectory */
+ &si[i], /* lpStartupInfo */
+ &pi[i] /* lpProcessInformation */
+ ))
+ {
+ Fail("Process Not created for [%d] and failed with error code %d\n", i, GetLastError());
+ }
+ else
+ {
+ hProcess[i] = pi[i].hProcess;
+ //Trace("Process created for [%d]\n", i);
+ }
+
+ }
+
+ returnCode = WaitForMultipleObjects( USE_PROCESS_COUNT, hProcess, TRUE, INFINITE);
+ if( WAIT_OBJECT_0 != returnCode )
+ {
+ Trace("Wait for Object(s) @ Main thread for %d processes returned %d, and GetLastError value is %d\n", USE_PROCESS_COUNT, returnCode, GetLastError());
+ testReturnCode = FAIL;
+ }
+
+ for( i = 0; i < USE_PROCESS_COUNT; i++ )
+ {
+ /* check the exit code from the process */
+ if( ! GetExitCodeProcess( pi[i].hProcess, &processReturnCode ) )
+ {
+ Trace( "GetExitCodeProcess call failed for iteration %d with error code %u\n",
+ i, GetLastError() );
+
+ testReturnCode = FAIL;
+ }
+
+ if(processReturnCode == FAIL)
+ {
+ Trace( "Process [%d] failed and returned FAIL\n", i);
+ testReturnCode = FAIL;
+ }
+
+ if(!CloseHandle(pi[i].hThread))
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hThread\n", GetLastError(), i);
+ testReturnCode = FAIL;
+ }
+
+ if(!CloseHandle(pi[i].hProcess) )
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hProcess\n", GetLastError(), i);
+ testReturnCode = FAIL;
+ }
+ }
+
+//Get the end time of the process
+appStats.operationTime = GetTickCount() - dwStart;
+
+if( testReturnCode == PASS)
+ {
+ Trace("Test Passed\n");
+
+ }
+ else
+ {
+ Fail("Test Failed\n");
+
+ }
+
+//Write Process Result Contents to File
+if(hFile!= NULL)
+ {
+ fprintf(hFile, "%lu,%d,%d,%d,%d,%s\n", appStats.operationTime, appStats.relationId,appStats.processCount, appStats.threadCount, appStats.repeatCount, appStats.buildNumber);
+ }
+
+if (0!=fclose(hFile))
+{
+ Trace("Error:%d: fclose failed for file %s\n", GetLastError(), fileName);
+}
+
+ PAL_Terminate();
+
+if( testReturnCode == PASS)
+{
+ return PASS;
+}
+else
+{
+ return FAIL;
+}
+
+}
diff --git a/src/pal/tests/palsuite/composite/synchronization/criticalsection/readme.txt b/src/pal/tests/palsuite/composite/synchronization/criticalsection/readme.txt
new file mode 100644
index 0000000000..af6ef5d230
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/synchronization/criticalsection/readme.txt
@@ -0,0 +1,11 @@
+To compile:
+
+1) create a dat file (say criticalsection.dat) with contents:
+PAL,Composite,palsuite\composite\syncronization\criticalsection,criticalsection=mainWrapper.c,criticalsection.c,<SUPPORTEXE>,<TESTLANGCPP>,<COMPILEONLY>
+
+2) perl rrunmod.pl -r criticalsection.dat
+
+
+To execute:
+mainwrapper [PROCESS_COUNT] [WORKER_THREAD_MULTIPLIER_COUNT] [REPEAT_COUNT]
+
diff --git a/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/CMakeLists.txt b/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/CMakeLists.txt
new file mode 100644
index 0000000000..d01b1064f6
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/CMakeLists.txt
@@ -0,0 +1,21 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ mtx_critsect.cpp
+ pal_composite_native_cs.c
+ resultbuffer.cpp
+)
+
+add_executable(paltest_synchronization_nativecriticalsection
+ ${SOURCES}
+)
+
+add_dependencies(paltest_synchronization_nativecriticalsection coreclrpal)
+
+target_link_libraries(paltest_synchronization_nativecriticalsection
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/mtx_critsect.cpp b/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/mtx_critsect.cpp
new file mode 100644
index 0000000000..790c89f966
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/mtx_critsect.cpp
@@ -0,0 +1,111 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//#include <stdio.h>
+#include <assert.h>
+#include "mtx_critsect.h"
+
+CsWaiterReturnState MTXWaitOnCS(LPCRITICAL_SECTION lpCriticalSection);
+void MTXDoActualWait(LPCRITICAL_SECTION lpCriticalSection);
+void MTXWakeUpWaiter(LPCRITICAL_SECTION lpCriticalSection);
+
+/*extern "C" {
+ LONG InterlockedCompareExchange(
+ LONG volatile *Destination,
+ LONG Exchange,
+ LONG Comperand);
+}
+*/
+int MTXInitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
+{
+ int retcode = 0;
+
+ lpCriticalSection->DebugInfo = NULL;
+ lpCriticalSection->LockCount = 0;
+ lpCriticalSection->RecursionCount = 0;
+ lpCriticalSection->SpinCount = 0;
+ lpCriticalSection->OwningThread = NULL;
+
+ lpCriticalSection->LockSemaphore = (HANDLE)&lpCriticalSection->NativeData;
+
+ if (0!= pthread_mutex_init(&lpCriticalSection->NativeData.Mutex, NULL))
+ {
+ printf("Error Initializing Critical Section\n");
+ retcode = -1;
+ }
+
+
+ lpCriticalSection->InitCount = CS_INITIALIZED;
+ return retcode;
+}
+
+int MTXDeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
+{
+ int retcode = 0;
+
+ if (lpCriticalSection->InitCount == CS_INITIALIZED)
+ {
+
+ if (0!=pthread_mutex_destroy(&lpCriticalSection->NativeData.Mutex))
+ {
+ printf("Error Deleting Critical Section\n");
+ retcode = -1;
+ }
+ }
+
+ lpCriticalSection->InitCount = CS_NOT_INIZIALIZED;
+ return retcode;
+}
+
+int MTXEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
+{
+
+ DWORD thread_id;
+ int retcode = 0;
+
+ thread_id = (DWORD)THREADSilentGetCurrentThreadId();
+
+ /* check if the current thread already owns the criticalSection */
+ if (lpCriticalSection->OwningThread == (HANDLE)thread_id)
+ {
+ lpCriticalSection->RecursionCount++;
+ //Check if this is a failure condition
+ return 0;
+ }
+
+ if (0!= pthread_mutex_lock(&lpCriticalSection->NativeData.Mutex))
+ {
+ //Error Condition
+ printf("Error Entering Critical Section\n");
+ retcode = -1;
+ }
+ else
+ {
+ lpCriticalSection->OwningThread = (HANDLE)thread_id;
+ lpCriticalSection->RecursionCount = 1;
+ }
+
+ return retcode;
+}
+
+int MTXLeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
+{
+ int retcode = 0;
+
+ if (--lpCriticalSection->RecursionCount > 0)
+ //*****check this *****
+ return 0;
+
+ lpCriticalSection->OwningThread = 0;
+
+ if (0!= pthread_mutex_unlock(&lpCriticalSection->NativeData.Mutex))
+ {
+ //Error Condition
+ printf("Error Leaving Critical Section\n");
+ retcode = -1;
+ }
+
+ return retcode;
+}
+
diff --git a/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/mtx_critsect.h b/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/mtx_critsect.h
new file mode 100644
index 0000000000..bc44ad8ecd
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/mtx_critsect.h
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#include <pthread.h>
+
+typedef void VOID;
+typedef unsigned long DWORD;
+typedef long LONG;
+typedef unsigned long ULONG;
+typedef void* HANDLE;
+typedef unsigned long ULONG_PTR;
+
+#define FALSE 0
+#define TRUE 1
+
+#define CSBIT_CS_IS_LOCKED 1
+#define CSBIT_NEW_WAITER 2
+
+typedef enum CsInitState { CS_NOT_INIZIALIZED, CS_INITIALIZED, CS_FULLY_INITIALIZED } CsInitState;
+typedef enum _CsWaiterReturnState { CS_WAITER_WOKEN_UP, CS_WAITER_DIDNT_WAIT } CsWaiterReturnState;
+
+typedef struct _CRITICAL_SECTION_DEBUG_INFO {
+ LONG volatile ContentionCount;
+ LONG volatile InternalContentionCount;
+ ULONG volatile AcquireCount;
+ ULONG volatile EnterCount;
+} CRITICAL_SECTION_DEBUG_INFO, *PCRITICAL_SECTION_DEBUG_INFO;
+
+typedef struct _CRITICAL_SECTION_NATIVE_DATA {
+ pthread_mutex_t Mutex;
+} CRITICAL_SECTION_NATIVE_DATA, *PCRITICAL_SECTION_NATIVE_DATA;
+
+typedef struct _CRITICAL_SECTION {
+
+ CsInitState InitCount;
+ PCRITICAL_SECTION_DEBUG_INFO DebugInfo;
+ LONG LockCount;
+ LONG RecursionCount;
+ HANDLE OwningThread;
+ HANDLE LockSemaphore;
+ ULONG_PTR SpinCount;
+ CRITICAL_SECTION_NATIVE_DATA NativeData;
+
+} CRITICAL_SECTION, *PCRITICAL_SECTION, *LPCRITICAL_SECTION;
+
+int MTXInitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
+int MTXDeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
+int MTXEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
+int MTXLeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
+
diff --git a/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/pal_composite_native_cs.c b/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/pal_composite_native_cs.c
new file mode 100644
index 0000000000..40efacd7c9
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/pal_composite_native_cs.c
@@ -0,0 +1,471 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+//#include <pthread.h>
+#include "mtx_critsect.cpp"
+//#include "mtx_critsect.h"
+#include "resultbuffer.h"
+
+
+
+#define LONGLONG long long
+#define ULONGLONG unsigned LONGLONG
+/*Defining Global Variables*/
+
+int THREAD_COUNT=0;
+int REPEAT_COUNT=0;
+int GLOBAL_COUNTER=0;
+int USE_PROCESS_COUNT = 0;
+int RELATION_ID =0;
+int g_counter = 0;
+int MAX_PATH = 256;
+LONGLONG callibrationValue = 0;
+
+pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t g_cv = PTHREAD_COND_INITIALIZER;
+pthread_cond_t g_cv2 = PTHREAD_COND_INITIALIZER;
+CRITICAL_SECTION g_cs;
+
+/* Capture statistics for each worker thread */
+struct statistics{
+ unsigned int processId;
+ unsigned int operationsFailed;
+ unsigned int operationsPassed;
+ unsigned int operationsTotal;
+ DWORD operationTime;
+ unsigned int relationId;
+};
+
+
+struct applicationStatistics{
+ DWORD operationTime;
+ unsigned int relationId;
+ unsigned int processCount;
+ unsigned int threadCount;
+ unsigned int repeatCount;
+ char* buildNumber;
+
+};
+
+ResultBuffer *resultBuffer;
+
+
+void* waitforworkerthreads(void*);
+void starttests(int);
+int setuptest(void);
+int cleanuptest(void);
+int GetParameters( int , char **);
+void incrementCounter(void);
+ULONGLONG GetTicks(void);
+ULONGLONG getPerfCallibrationValue(void);
+
+
+
+extern int main(int argc, char **argv)
+ {
+ //Variable Declaration
+ pthread_t pthreads[640];
+ int threadID[640];
+ int i=0;
+ int j=0;
+ int rtn=0;
+ ULONGLONG startTicks = 0;
+
+ /* Variables to capture the file name and the file pointer*/
+ char fileName[MAX_PATH];
+ FILE *hFile;
+ struct statistics* buffer;
+ int statisticsSize = 0;
+
+ /*Variable to Captutre Information at the Application Level*/
+ struct applicationStatistics appStats;
+ char mainFileName[MAX_PATH];
+ FILE *hMainFile;
+
+ //Get perfCallibrationValue
+
+ callibrationValue = getPerfCallibrationValue();
+ printf("Callibration Value for this Platform %llu \n", callibrationValue);
+
+
+ //Get Parameters
+ if(GetParameters(argc, argv))
+ {
+ printf("Error in obtaining the parameters\n");
+ exit(-1);
+ }
+
+ //Assign Values to Application Statistics Members
+ appStats.relationId=RELATION_ID;
+ appStats.operationTime=0;
+ appStats.buildNumber = "999.99";
+ appStats.processCount = USE_PROCESS_COUNT;
+ appStats.threadCount = THREAD_COUNT;
+ appStats.repeatCount = REPEAT_COUNT;
+
+ printf("RELATION ID : %d\n", appStats.relationId);
+ printf("Process Count : %d\n", appStats.processCount);
+ printf("Thread Count : %d\n", appStats.threadCount);
+ printf("Repeat Count : %d\n", appStats.repeatCount);
+
+
+ //Open file for Application Statistics Collection
+ snprintf(mainFileName, MAX_PATH, "main_nativecriticalsection_%d_.txt",appStats.relationId);
+ hMainFile = fopen(mainFileName, "w+");
+
+ if(hMainFile == NULL)
+ {
+ printf("Error in opening main file for write\n");
+ }
+
+
+ for (i=0;i<THREAD_COUNT;i++)
+ {
+ threadID[i] = i;
+ }
+
+ statisticsSize = sizeof(struct statistics);
+
+ snprintf(fileName, MAX_PATH, "%d_thread_nativecriticalsection_%d_.txt", USE_PROCESS_COUNT, RELATION_ID);
+ hFile = fopen(fileName, "w+");
+
+ if(hFile == NULL)
+ {
+ printf("Error in opening file for write for process [%d]\n", USE_PROCESS_COUNT);
+ }
+
+
+ // For each thread we will log operations failed (int), passed (int), total (int)
+ // and number of ticks (DWORD) for the operations
+ resultBuffer = new ResultBuffer( THREAD_COUNT, statisticsSize);
+
+ //Call Test Case Setup Routine
+ if (0!=setuptest())
+ {
+ //Error Condition
+ printf("Error Initializing Test Case\n");
+ exit(-1);
+ }
+
+ //Accquire Lock
+ if (0!=pthread_mutex_lock(&g_mutex))
+ {
+ //Error Condition
+ printf("Error Accquiring Lock\n");
+ exit(-1);
+ }
+
+ //USE NATIVE METHOD TO GET TICK COUNT
+ startTicks = GetTicks();
+
+ /*Loop to create number THREAD_COUNT number of threads*/
+ for (i=0;i< THREAD_COUNT;i++)
+ {
+
+ //printf("Creating Thread Count %d\n", i);
+ //printf("Thread arrary value = %d\n", threadID[i]);
+ rtn=pthread_create(&pthreads[i], NULL, waitforworkerthreads, &threadID[i]);
+ if (0 != rtn)
+ { /* ERROR Condition */
+ printf("Error: pthread Creat, %s \n", strerror(rtn));
+ exit(-1);
+ }
+
+ }
+
+
+ //printf("Main Thread waits to recevie signal when all threads are done\n");
+ pthread_cond_wait(&g_cv2,&g_mutex);
+
+ //printf("Main thread has received signal\n");
+
+ /*Signal Threads to Start Working*/
+ //printf("Raise signal for all threads to start working\n");
+
+
+
+ if (0!=pthread_cond_broadcast(&g_cv))
+ {
+ //Error Condition
+ printf("Error Broadcasting Conditional Event\n");
+ exit(-1);
+ }
+
+ //Release the lock
+ if (0!=pthread_mutex_unlock(&g_mutex))
+ {
+ //Error Condition
+ printf("Error Releasing Lock\n");
+ exit(-1);
+ }
+
+ /*Join Threads */
+ while (j < THREAD_COUNT)
+ {
+ if (0 != pthread_join(pthreads[j],NULL))
+ {
+ //Error Condition
+ printf("Error Joining Threads\n");
+ exit(-1);
+ }
+ j++;
+ }
+
+
+ /*Write Application Results to File*/
+ //CAPTURE NATIVE TICK COUNT HERE
+ appStats.operationTime = (DWORD)(GetTicks() - startTicks)/callibrationValue;
+
+
+ /* Write Results to a file*/
+ if(hFile!= NULL)
+ {
+ for( i = 0; i < THREAD_COUNT; i++ )
+ {
+ buffer = (struct statistics *)resultBuffer->getResultBuffer(i);
+ fprintf(hFile, "%d,%d,%d,%d,%lu,%d\n", buffer->processId, buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime, buffer->relationId );
+ //printf("Iteration %d over\n", i);
+ }
+ }
+ fclose(hFile);
+
+
+
+ //Call Test Case Cleanup Routine
+ if (0!=cleanuptest())
+ {
+ //Error Condition
+ printf("Error Cleaning up Test Case");
+ exit(-1);
+ }
+
+
+ if(hMainFile!= NULL)
+ {
+ printf("Writing to Main File \n");
+ fprintf(hMainFile, "%lu,%d,%d,%d,%d,%s\n", appStats.operationTime, appStats.relationId, appStats.processCount, appStats.threadCount, appStats.repeatCount, appStats.buildNumber);
+
+ }
+ fclose(hMainFile);
+ return 0;
+ }
+
+void * waitforworkerthreads(void * threadId)
+{
+
+ int *threadParam = (int*) threadId;
+
+// printf("Thread ID : %d \n", *threadParam);
+
+ //Accquire Lock
+ if (0!=pthread_mutex_lock(&g_mutex))
+ {
+ //Error Condition
+ printf("Error Accquiring Mutex Lock in Wait for Worker Thread\n");
+ exit(-1);
+ }
+
+ //Increment Global Counter
+ GLOBAL_COUNTER++;
+
+
+ //If global counter is equal to thread count then signal main thread
+ if (GLOBAL_COUNTER == THREAD_COUNT)
+ {
+ if (0!=pthread_cond_signal(&g_cv2))
+ {
+ //Error Condition
+ printf("Error in setting conditional variable\n");
+ exit(-1);
+ }
+ }
+
+ //Wait for main thread to signal
+ if (0!=pthread_cond_wait(&g_cv,&g_mutex))
+ {
+ //Error Condition
+ printf("Error waiting on conditional variable in Worker Thread\n");
+ exit(-1);
+ }
+
+ //Release the mutex lock
+ if (0!=pthread_mutex_unlock(&g_mutex))
+ {
+ //Error Condition
+ printf("Error Releasing Mutex Lock in Worker Thread\n");
+ exit(-1);
+ }
+
+ //Start the test
+ starttests(*threadParam);
+
+}
+
+void starttests(int threadID)
+{
+ /*All threads beign executing tests cases*/
+ int i = 0;
+ int Id = threadID;
+ struct statistics stats;
+ ULONGLONG startTime = 0;
+ ULONGLONG endTime = 0;
+
+
+ stats.relationId = RELATION_ID;
+ stats.processId = USE_PROCESS_COUNT;
+ stats.operationsFailed = 0;
+ stats.operationsPassed = 0;
+ stats.operationsTotal = 0;
+ stats.operationTime = 0;
+
+ //Enter and Leave Critical Section in a loop REPEAT_COUNT Times
+
+ startTime = GetTicks();
+
+ for (i=0;i<REPEAT_COUNT;i++)
+ {
+ if (0!=MTXEnterCriticalSection(&g_cs))
+ {
+ stats.operationsFailed++;
+ stats.operationsTotal++;
+ continue;
+ }
+
+ incrementCounter();
+
+ if (0!=MTXLeaveCriticalSection(&g_cs))
+ {
+ stats.operationsFailed++;
+ stats.operationsTotal++;
+ continue;
+ }
+ stats.operationsPassed++;
+ stats.operationsTotal++;
+
+ }
+
+ stats.operationTime = (DWORD)(GetTicks() - startTime)/callibrationValue;
+
+// printf("Operation Time %d \n", stats.operationTime);
+
+ if(resultBuffer->LogResult(Id, (char *)&stats))
+ {
+ printf("Error while writing to shared memory, Thread Id is[??] and Process id is [%d]\n", USE_PROCESS_COUNT);
+ }
+
+}
+
+int setuptest(void)
+{
+
+ //Initalize Critical Section
+ if (0!=MTXInitializeCriticalSection( &g_cs))
+ {
+ return -1;
+ }
+ return 0;
+}
+
+int cleanuptest(void)
+{
+
+ //Delete Critical Section
+ if (0!=MTXDeleteCriticalSection(&g_cs))
+ {
+ return -1;
+ }
+ return 0;
+}
+
+int GetParameters( int argc, char **argv)
+{
+
+ if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?"))
+ || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H"))
+ {
+ printf("PAL -Composite Native Critical Section Test\n");
+ printf("Usage:\n");
+ printf("\t[PROCESS_ID ( greater than 1] \n");
+ printf("\t[THREAD_COUNT ( greater than 1] \n");
+ printf("\t[REPEAT_COUNT ( greater than 1]\n");
+ printf("\t[RELATION_ID [greater than or Equal to 1]\n");
+ return -1;
+ }
+
+
+ USE_PROCESS_COUNT = atoi(argv[1]);
+ if( USE_PROCESS_COUNT < 0)
+ {
+ printf("\nInvalid THREAD_COUNT number, Pass greater than 1\n");
+ return -1;
+ }
+
+ THREAD_COUNT = atoi(argv[2]);
+ if( THREAD_COUNT < 1)
+ {
+ printf("\nInvalid THREAD_COUNT number, Pass greater than 1\n");
+ return -1;
+ }
+
+ REPEAT_COUNT = atoi(argv[3]);
+ if( REPEAT_COUNT < 1)
+ {
+ printf("\nInvalid REPEAT_COUNT number, Pass greater than 1\n");
+ return -1;
+ }
+
+ RELATION_ID = atoi(argv[4]);
+ if( RELATION_ID < 1)
+ {
+ printf("\nInvalid RELATION_ID number, Pass greater than 1\n");
+ return -1;
+ }
+
+
+ return 0;
+}
+
+void incrementCounter(void)
+{
+ g_counter ++;
+}
+
+
+//Implementation borrowed from pertrace.c
+ULONGLONG GetTicks(void)
+{
+#ifdef i386
+ unsigned long a, d;
+ asm volatile("rdtsc":"=a" (a), "=d" (d));
+ return ((ULONGLONG)((unsigned int)(d)) << 32) | (unsigned int)(a);
+#else
+#if defined(__sparc__) || (defined (_HPUX_) && defined(__ia64__))
+ return (ULONGLONG)gethrtime();
+#else
+ // #error Don''t know how to get ticks on this platform
+ return (ULONGLONG)gethrtime();
+#endif // __sparc__
+#endif // _X86_
+}
+
+
+/**/
+ULONGLONG getPerfCallibrationValue(void)
+{
+ ULONGLONG startTicks;
+ ULONGLONG endTicks;
+
+ startTicks = GetTicks();
+ sleep(1);
+ endTicks = GetTicks();
+
+ return ((endTicks-startTicks)/1000); //Return number of Ticks in One Milliseconds
+
+}
+
diff --git a/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/readme.txt b/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/readme.txt
new file mode 100644
index 0000000000..8d83bf794c
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/readme.txt
@@ -0,0 +1,19 @@
+To compile:
+
+For FReeBSD Platform use the following to compile:
+gcc -pthread -lm -lgcc -lstdc++ -xc++ -Di386 pal_composite_native_cs.c
+
+For Solaris Platform use the following to compile:
+gcc -lpthread -lm -lgcc -lstdc++ -xc++ -D__sparc__ pal_composite_native_cs.c
+
+For HPUX Platform use the following to compile:
+gcc -lpthread -mlp64 -lm -lgcc -lstdc++ -xc++ -D_HPUX_ -D__ia64__ pal_composite_native_cs.c
+
+To execute:
+./a.out [PROCESS_COUNT] [THREAD_COUNT] [REPEAT_COUNT]
+
+
+ ./a.out 1 32 1000000 4102406
+
+
+
diff --git a/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/resultbuffer.cpp b/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/resultbuffer.cpp
new file mode 100644
index 0000000000..c9ed9435f1
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/resultbuffer.cpp
@@ -0,0 +1,69 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//#include "stdafx.h"
+#include "resultbuffer.h"
+//
+//#using <mscorlib.dll>
+//
+//using namespace System;
+
+
+ResultBuffer:: ResultBuffer(int ThreadCount, int ThreadLogSize)
+ {
+ // Declare an internal status variable
+ int Status=0;
+
+ // Update the maximum thread count
+ MaxThreadCount = ThreadCount;
+
+ // Allocate the memory buffer based on the passed in thread and process counts
+ // and the specified size of the thread specific buffer
+ buffer = NULL;
+ buffer = (char*)malloc(ThreadCount*ThreadLogSize);
+ // Check to see if the buffer memory was allocated
+ if (buffer == NULL)
+ Status = -1;
+ // Initialize the buffer to 0 to prevent bogus data
+ memset(buffer,0,ThreadCount*ThreadLogSize);
+
+ // The ThreadOffset is equal to the total number of bytes that will be stored per thread
+ ThreadOffset = ThreadLogSize;
+
+ }
+
+
+ int ResultBuffer::LogResult(int Thread, char* Data)
+ {
+ // Declare an internal status flad
+ int status = 0;
+
+ // Declare an object to store the offset address into the buffer
+ int Offset;
+
+ // Check to make sure the Thread index is not out of range
+ if(Thread > MaxThreadCount)
+ {
+ printf("Thread index is out of range, Value of Thread[%d], Value of MaxThreadCount[%d]\n", Thread, MaxThreadCount);
+ status = -1;
+ return(status);
+ }
+
+ // Caculate the offset into the shared buffer based on the process and thread indices
+ Offset = (Thread)*ThreadOffset;
+
+ // Write the passed in data to the reserved buffer
+ memcpy(buffer+Offset,Data,ThreadOffset);
+
+ return(status);
+ }
+
+
+ char* ResultBuffer::getResultBuffer(int threadId)
+ {
+
+ return (buffer + threadId*ThreadOffset);
+
+ }
+
diff --git a/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/resultbuffer.h b/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/resultbuffer.h
new file mode 100644
index 0000000000..8920958100
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/resultbuffer.h
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#include <stdio.h>
+#include <iostream>
+//#include <assert.h>
+#ifndef _RESULT_BUFFER_H_
+#define _RESULT_BUFFER_H_
+
+//#include <palsuite.h>
+
+struct ResultData
+{
+ int value;
+ int size;
+// ResultData* NextResult;
+};
+
+ class ResultBuffer
+{
+ // Declare a pointer to a memory buffer to store the logged results
+ char* buffer;
+ // Declare an object to store the maximum Thread count
+ int MaxThreadCount;
+ // Declare and internal data object to store the calculated offset between adjacent threads data sets
+ int ThreadOffset;
+
+ // Declare a linked list object to store the parameter values
+public:
+
+ // Declare a constructor for the single process case
+ ResultBuffer(int ThreadCount, int ThreadLogSize);
+ // Declare a method to log data for the single process instance
+ int LogResult(int Thread, char* Data);
+
+ char* getResultBuffer(int threadId);
+};
+
+#include "resultbuffer.cpp"
+#endif // _RESULT_BUFFER_H_
+
+
diff --git a/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/CMakeLists.txt b/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/CMakeLists.txt
new file mode 100644
index 0000000000..c4567f638c
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/CMakeLists.txt
@@ -0,0 +1,22 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ interlocked.cpp
+ mtx_critsect.cpp
+ pal_composite_native_cs.c
+ resultbuffer.cpp
+)
+
+add_executable(paltest_synchronization_nativecs_interlocked
+ ${SOURCES}
+)
+
+add_dependencies(paltest_synchronization_nativecs_interlocked coreclrpal)
+
+target_link_libraries(paltest_synchronization_nativecs_interlocked
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/hpitinterlock.s b/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/hpitinterlock.s
new file mode 100644
index 0000000000..062f4ebe6a
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/hpitinterlock.s
@@ -0,0 +1,168 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*++
+
+
+
+Module Name:
+
+ interlock.s
+
+Abstract:
+
+ Implementation of Interlocked functions (32 and 64 bits) for the HPUX/Itanium
+ platform. These functions are processor dependent.
+ See the i386 implementations for more information.
+
+--*/
+ .file "interlock.s"
+ .section .text, "ax", "progbits"
+ .align 16
+ .global InterlockedExchangeAdd#
+ .proc InterlockedExchangeAdd#
+InterlockedExchangeAdd:
+ .body
+ ld4.nt1 r8 = [r32]
+ ;;
+Iea10:
+ mov ar.ccv = r8
+ add r15 = r33, r8
+ mov r14 = r8
+ ;;
+ cmpxchg4.acq r8 = [r32], r15, ar.ccv
+ ;;
+ cmp.ne p6,p7 = r8, r14 // check if the target changes?
+(p6)br.cond.spnt.few Iea10 // if yes, go back to do it again
+(p7)br.ret.sptk.clr b0
+ ;;
+ .endp InterlockedExchangeAdd#
+
+ .align 16
+ .global InterlockedIncrement#
+ .proc InterlockedIncrement#
+InterlockedIncrement:
+ .body
+ fetchadd4.acq r8 = [r32], 1
+ ;;
+ adds r8 = 1, r8
+ br.ret.sptk b0
+ ;;
+ .endp InterlockedIncrement#
+
+ .align 16
+ .global InterlockedIncrement64#
+ .proc InterlockedIncrement64#
+InterlockedIncrement64:
+ .body
+ fetchadd8.acq r8 = [r32], 1
+ ;;
+ adds r8 = 1, r8
+ br.ret.sptk b0
+ ;;
+ .endp InterlockedIncrement64#
+
+ .align 16
+ .global InterlockedDecrement#
+ .proc InterlockedDecrement#
+InterlockedDecrement:
+ .body
+ fetchadd4.acq r8 = [r32], -1
+ ;;
+ adds r8 = -1, r8
+ br.ret.sptk b0
+ ;;
+ .endp InterlockedDecrement#
+
+ .align 16
+ .global InterlockedDecrement64#
+ .proc InterlockedDecrement64#
+InterlockedDecrement64:
+ .body
+ fetchadd8.acq r8 = [r32], -1
+ ;;
+ adds r8 = -1, r8
+ br.ret.sptk b0
+ ;;
+ .endp InterlockedDecrement64#
+
+ .align 16
+ .global InterlockedExchange#
+ .proc InterlockedExchange#
+InterlockedExchange:
+ .body
+ mf
+ zxt4 r33 = r33 // sanitize the upper 32 bits
+ ;;
+ xchg4 r8 = [r32], r33
+ br.ret.sptk b0
+ ;;
+ .endp InterlockedExchange#
+
+ .align 16
+ .global InterlockedExchange64#
+ .proc InterlockedExchange64#
+InterlockedExchange64:
+ .body
+ mf
+ xchg8 r8 = [r32], r33
+ br.ret.sptk b0
+ ;;
+ .endp InterlockedExchange64#
+
+ .align 16
+ .global InterlockedCompareExchange#
+ .proc InterlockedCompareExchange#
+InterlockedCompareExchange:
+ .body
+ mf
+ zxt4 r33 = r33 // sanitize the upper 32 bits
+ zxt4 r34 = r34 // sanitize the upper 32 bits
+ ;;
+ mov ar.ccv = r34
+ ;;
+ cmpxchg4.acq r8 = [r32], r33, ar.ccv
+ br.ret.sptk.clr b0
+ ;;
+ .endp InterlockedCompareExchange#
+
+ .align 16
+ .global InterlockedCompareExchange64#
+ .proc InterlockedCompareExchange64#
+InterlockedCompareExchange64:
+ .body
+ mf
+ mov ar.ccv = r34
+ ;;
+ cmpxchg8.acq r8 = [r32], r33, ar.ccv
+ br.ret.sptk.clr b0
+ ;;
+ .endp InterlockedCompareExchange64#
+
+/*++
+ DBG_DebugBreak is extracted from DbgBreakPoint function
+ in debugstb.s from win64.
+--*/
+ BREAKPOINT_STOP = 0x80016
+ .align 16
+ .global DBG_DebugBreak#
+ .proc DBG_DebugBreak#
+DBG_DebugBreak:
+ .body
+ flushrs
+ ;;
+ break.i BREAKPOINT_STOP
+ br.ret.sptk.clr b0
+ ;;
+ .endp DBG_DebugBreak#
+
+ .align 16
+ .global MemoryBarrier#
+ .proc MemoryBarrier#
+MemoryBarrier:
+ .body
+ mf
+ br.ret.sptk.clr b0
+ ;;
+ .endp MemoryBarrier#
diff --git a/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/interlocked.cpp b/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/interlocked.cpp
new file mode 100644
index 0000000000..b6c1dd7a8f
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/interlocked.cpp
@@ -0,0 +1,27 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+typedef long LONG;
+
+extern "C" {
+LONG InterlockedCompareExchange(
+ LONG volatile *Destination,
+ LONG Exchange,
+ LONG Comperand)
+{
+#ifdef i386
+ LONG result;
+
+ __asm__ __volatile__(
+ "lock; cmpxchgl %2,(%1)"
+ : "=a" (result)
+ : "r" (Destination), "r" (Exchange), "0" (Comperand)
+ : "memory"
+ );
+
+ return result;
+#endif
+}
+}
diff --git a/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/makefile b/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/makefile
new file mode 100644
index 0000000000..376745aafc
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/makefile
@@ -0,0 +1,70 @@
+#
+# Use gmake to build this project
+#
+
+
+OSNAME=$(shell uname -s)
+OSVER=$(shell uname -r | cut -c1-3)
+BASEOBJDIR=./obj
+TGTDIR=$(BASEOBJDIR)/$(shell uname -m)
+COMP=gcc
+DEBUGOPT=-D_DEBUG -g
+# DEBUGOPT=-DNDEBUG
+
+
+ifeq ($(OSNAME),SunOS)
+COPT=-DSUNOS -O2 -finline-functions $(DEBUGOPT) -xc++
+LOPT=-lpthread -lrt -O2 -finline-functions $(DEBUGOPT)
+INTERLOCK_OBJ=sparcinterloc.o
+else
+ ifeq ($(OSNAME),FreeBSD)
+ ifeq ($(OSVER),5.2)
+ COMP=g++
+ COPT=-DFREEBSD -Di386 -O2 -finline-functions $(DEBUGOPT) -xc++
+ LOPT=-lkse -O2 -finline-functions $(DEBUGOPT)
+ else
+ COPT=-DFREEBSD -Di386 -O2 -finline-functions $(DEBUGOPT)
+ LOPT=-pthread -O2 -finline-functions $(DEBUGOPT)
+ endif
+ INTERLOCK_OBJ=interlocked.o
+ else
+ ifeq ($(OSNAME),HP-UX)
+ COMP=g++
+ INTERLOCK_OBJ=hpitinterlock.o
+ COPT=-DHPUX -O2 -mlp64 -finline -fPIC -DPIC -DBIT64 -D_WIN64 -DLP64COMPATIBLE \
+ -D_POSIX_C_SOURCE=199506L -D_HPUX_ -D_XOPEN_SOURCE_EXTENDED -DBIT64 \
+ -DBIGENDIAN -D_WIN64 $(DEBUGOPT) -xc++
+ LOPT=-O2 -mlp64 -DBIT64 -D_WIN64 -lgcc -lpthread /usr/lib/hpux64/libunwind.so
+ endif
+ endif
+endif
+
+
+TARGET0=$(TGTDIR)/native_cs_interlocked
+
+all: dirs $(TARGET0) $(TARGET1) $(TARGET2) $(TARGET3) $(TARGET4)
+
+dirs:
+ @echo Target dir: $(TGTDIR)
+ @if [ \! -d $(BASEOBJDIR) ]; then mkdir $(BASEOBJDIR); fi
+ @if [ \! -d $(TGTDIR) ]; then mkdir $(TGTDIR); fi
+
+$(TGTDIR)/native_cs_interlocked: $(TGTDIR)/$(INTERLOCK_OBJ) $(TGTDIR)/native_cs_interlocked.o
+ $(COMP) $(LOPT) -o $(TARGET0) $(TGTDIR)/native_cs_interlocked.o $(TGTDIR)/$(INTERLOCK_OBJ)
+
+$(TGTDIR)/native_cs_interlocked.o: pal_composite_native_cs.c
+ $(COMP) $(COPT) -DFULL_CSIMPL -o $(TGTDIR)/native_cs_interlocked.o -c pal_composite_native_cs.c
+
+$(TGTDIR)/interlocked.o: interlocked.cpp
+ $(COMP) $(COPT) -c -o $(TGTDIR)/interlocked.o interlocked.cpp
+
+$(TGTDIR)/sparcinterloc.o: sparcinterloc.s
+ $(COMP) -x assembler-with-cpp -c -Wa,-Av9 -o $(TGTDIR)/sparcinterloc.o sparcinterloc.s
+
+$(TGTDIR)/hpitinterlock.o: hpitinterlock.s
+ $(COMP) $(COPT) -x assembler-with-cpp -c -fno-strict-aliasing -o $(TGTDIR)/hpitinterlock.o hpitinterlock.s
+
+clean:
+ @echo Cleaning
+ @rm -f $(TGTDIR)/*.o $(TARGET0) $(TARGET1) $(TARGET2) $(TARGET3) $(TARGET4)
+ @if [ -d $(TGTDIR) ]; then rmdir $(TGTDIR); fi
diff --git a/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/mtx_critsect.cpp b/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/mtx_critsect.cpp
new file mode 100644
index 0000000000..69c10e9078
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/mtx_critsect.cpp
@@ -0,0 +1,112 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#include <stdio.h>
+
+#include <assert.h>
+#include "mtx_critsect.h"
+
+CsWaiterReturnState MTXWaitOnCS(LPCRITICAL_SECTION lpCriticalSection);
+void MTXDoActualWait(LPCRITICAL_SECTION lpCriticalSection);
+void MTXWakeUpWaiter(LPCRITICAL_SECTION lpCriticalSection);
+
+/*extern "C" {
+ LONG InterlockedCompareExchange(
+ LONG volatile *Destination,
+ LONG Exchange,
+ LONG Comperand);
+}
+*/
+int MTXInitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
+{
+ int retcode = 0;
+
+ lpCriticalSection->DebugInfo = NULL;
+ lpCriticalSection->LockCount = 0;
+ lpCriticalSection->RecursionCount = 0;
+ lpCriticalSection->SpinCount = 0;
+ lpCriticalSection->OwningThread = NULL;
+
+ lpCriticalSection->LockSemaphore = (HANDLE)&lpCriticalSection->NativeData;
+
+ if (0!= pthread_mutex_init(&lpCriticalSection->NativeData.Mutex, NULL))
+ {
+ printf("Error Initializing Critical Section\n");
+ retcode = -1;
+ }
+
+
+ lpCriticalSection->InitCount = CS_INITIALIZED;
+ return retcode;
+}
+
+int MTXDeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
+{
+ int retcode = 0;
+
+ if (lpCriticalSection->InitCount == CS_INITIALIZED)
+ {
+
+ if (0!=pthread_mutex_destroy(&lpCriticalSection->NativeData.Mutex))
+ {
+ printf("Error Deleting Critical Section\n");
+ retcode = -1;
+ }
+ }
+
+ lpCriticalSection->InitCount = CS_NOT_INIZIALIZED;
+ return retcode;
+}
+
+int MTXEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
+{
+
+ DWORD thread_id;
+ int retcode = 0;
+
+ thread_id = (DWORD)THREADSilentGetCurrentThreadId();
+
+ /* check if the current thread already owns the criticalSection */
+ if (lpCriticalSection->OwningThread == (HANDLE)thread_id)
+ {
+ lpCriticalSection->RecursionCount++;
+ //Check if this is a failure condition
+ return 0;
+ }
+
+ if (0!= pthread_mutex_lock(&lpCriticalSection->NativeData.Mutex))
+ {
+ //Error Condition
+ printf("Error Entering Critical Section\n");
+ retcode = -1;
+ }
+ else
+ {
+ lpCriticalSection->OwningThread = (HANDLE)thread_id;
+ lpCriticalSection->RecursionCount = 1;
+ }
+
+ return retcode;
+}
+
+int MTXLeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
+{
+ int retcode = 0;
+
+ if (--lpCriticalSection->RecursionCount > 0)
+ //*****check this *****
+ return 0;
+
+ lpCriticalSection->OwningThread = 0;
+
+ if (0!= pthread_mutex_unlock(&lpCriticalSection->NativeData.Mutex))
+ {
+ //Error Condition
+ printf("Error Leaving Critical Section\n");
+ retcode = -1;
+ }
+
+ return retcode;
+}
+
diff --git a/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/mtx_critsect.h b/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/mtx_critsect.h
new file mode 100644
index 0000000000..becbf6f0ca
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/mtx_critsect.h
@@ -0,0 +1,67 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#include <pthread.h>
+
+typedef void VOID;
+typedef void* HANDLE;
+typedef unsigned long ULONG_PTR;
+
+#ifdef HPUX
+ typedef unsigned int DWORD;
+ typedef int LONG;
+ typedef unsigned int ULONG;
+#else
+ typedef unsigned long DWORD;
+ typedef long LONG;
+ typedef unsigned long ULONG;
+#endif
+
+
+
+
+#define FALSE 0
+#define TRUE 1
+
+#define CSBIT_CS_IS_LOCKED 1
+#define CSBIT_NEW_WAITER 2
+
+typedef enum CsInitState { CS_NOT_INIZIALIZED, CS_INITIALIZED, CS_FULLY_INITIALIZED } CsInitState;
+typedef enum _CsWaiterReturnState { CS_WAITER_WOKEN_UP, CS_WAITER_DIDNT_WAIT } CsWaiterReturnState;
+
+typedef struct _CRITICAL_SECTION_DEBUG_INFO {
+ LONG volatile ContentionCount;
+ LONG volatile InternalContentionCount;
+ ULONG volatile AcquireCount;
+ ULONG volatile EnterCount;
+} CRITICAL_SECTION_DEBUG_INFO, *PCRITICAL_SECTION_DEBUG_INFO;
+
+typedef struct _CRITICAL_SECTION_NATIVE_DATA {
+ pthread_mutex_t Mutex;
+} CRITICAL_SECTION_NATIVE_DATA, *PCRITICAL_SECTION_NATIVE_DATA;
+
+typedef struct _CRITICAL_SECTION {
+
+ CsInitState InitCount;
+ PCRITICAL_SECTION_DEBUG_INFO DebugInfo;
+ LONG LockCount;
+ LONG RecursionCount;
+ HANDLE OwningThread;
+ HANDLE LockSemaphore;
+ ULONG_PTR SpinCount;
+ CRITICAL_SECTION_NATIVE_DATA NativeData;
+
+} CRITICAL_SECTION, *PCRITICAL_SECTION, *LPCRITICAL_SECTION;
+
+int MTXInitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
+int MTXDeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
+int MTXEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
+int MTXLeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
+
+extern "C" {
+ LONG InterlockedCompareExchange(
+ LONG volatile *Destination,
+ LONG Exchange,
+ LONG Comperand);
+}
diff --git a/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/notes.txt b/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/notes.txt
new file mode 100644
index 0000000000..4882c3bd03
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/notes.txt
@@ -0,0 +1,15 @@
+gcc -O2 -finline-functions -D_DEBUG -g -DFULL_CSIMPL -o ./obj/sun4u/critsecttest.o -c critsecttest.cpp
+gcc -O2 -finline-functions -D_DEBUG -g -c -o ./obj/sun4u/cs.o cs.cpp
+gcc -x assembler-with-cpp -c -Wa,-Av9 -o ./obj/sun4u/sparcinterloc.o sparcinterloc.s
+gcc -lpthread -lrt -O2 -finline-functions -D_DEBUG -g -o ./obj/sun4u/critsecttest ./obj/sun4u/critsecttest.o ./obj/sun4u/cs.o ./obj/sun4u/sparcinterloc.o
+gcc -O2 -finline-functions -D_DEBUG -g -DCXNG_CSIMPL -o ./obj/sun4u/cxngtest.o -c critsecttest.cpp
+gcc -O2 -finline-functions -D_DEBUG -g -c -o ./obj/sun4u/cxng_critsect.o cxng_critsect.cpp
+gcc -lpthread -lrt -O2 -finline-functions -D_DEBUG -g -o ./obj/sun4u/cxngtest ./obj/sun4u/cxngtest.o ./obj/sun4u/cxng_critsect.o ./obj/sun4u/sparcinterloc.o
+gcc -O2 -finline-functions -D_DEBUG -g -DMTX_CSIMPL -o ./obj/sun4u/mtxtest.o -c critsecttest.cpp
+gcc -O2 -finline-functions -D_DEBUG -g -c -o ./obj/sun4u/mtx_critsect.o mtx_critsect.cpp
+gcc -lpthread -lrt -O2 -finline-functions -D_DEBUG -g -o ./obj/sun4u/mtxtest ./obj/sun4u/mtxtest.o ./obj/sun4u/mtx_critsect.o ./obj/sun4u/sparcinterloc.o
+gcc -O2 -finline-functions -D_DEBUG -g -DRECMTX_CSIMPL -o ./obj/sun4u/recmtxtest.o -c critsecttest.cpp
+gcc -O2 -finline-functions -D_DEBUG -g -c -o ./obj/sun4u/recmtx_critsect.o recmtx_critsect.cpp
+gcc -lpthread -lrt -O2 -finline-functions -D_DEBUG -g -o ./obj/sun4u/recmtxtest ./obj/sun4u/recmtxtest.o ./obj/sun4u/recmtx_critsect.o ./obj/sun4u/sparcinterloc.o
+gcc -O2 -finline-functions -D_DEBUG -g -DINLRECMTX_CSIMPL -o ./obj/sun4u/inlrecmtxtest.o -c critsecttest.cpp
+gcc -lpthread -lrt -O2 -finline-functions -D_DEBUG -g -o ./obj/sun4u/inlrecmtxtest ./obj/sun4u/inlrecmtxtest.o ./obj/sun4u/sparcinterloc.o
diff --git a/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/pal_composite_native_cs.c b/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/pal_composite_native_cs.c
new file mode 100644
index 0000000000..4c19d3b0de
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/pal_composite_native_cs.c
@@ -0,0 +1,475 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+//#include <pthread.h>
+//#include "mtx_critsect.cpp"
+#include "mtx_critsect.h"
+#include "resultbuffer.h"
+
+
+
+#define LONGLONG long long
+#define ULONGLONG unsigned LONGLONG
+/*Defining Global Variables*/
+
+int THREAD_COUNT=0;
+int REPEAT_COUNT=0;
+int GLOBAL_COUNTER=0;
+int USE_PROCESS_COUNT = 0;
+int RELATION_ID =0;
+int g_counter = 0;
+int MAX_PATH = 256;
+LONGLONG callibrationValue = 0;
+
+pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t g_cv = PTHREAD_COND_INITIALIZER;
+pthread_cond_t g_cv2 = PTHREAD_COND_INITIALIZER;
+CRITICAL_SECTION g_cs;
+
+/* Capture statistics for each worker thread */
+struct statistics{
+ unsigned int processId;
+ unsigned int operationsFailed;
+ unsigned int operationsPassed;
+ unsigned int operationsTotal;
+ DWORD operationTime;
+ unsigned int relationId;
+};
+
+
+struct applicationStatistics{
+ DWORD operationTime;
+ unsigned int relationId;
+ unsigned int processCount;
+ unsigned int threadCount;
+ unsigned int repeatCount;
+ char* buildNumber;
+
+};
+
+ResultBuffer *resultBuffer;
+
+
+void* waitforworkerthreads(void*);
+void starttests(int);
+int setuptest(void);
+int cleanuptest(void);
+int GetParameters( int , char **);
+void incrementCounter(void);
+ULONGLONG GetTicks(void);
+ULONGLONG getPerfCallibrationValue(void);
+
+
+
+extern int main(int argc, char **argv)
+ {
+ //Variable Declaration
+ pthread_t pthreads[640];
+ int threadID[640];
+ int i=0;
+ int j=0;
+ int rtn=0;
+ ULONGLONG startTicks = 0;
+
+ /* Variables to capture the file name and the file pointer*/
+ char fileName[MAX_PATH];
+ FILE *hFile;
+ struct statistics* buffer;
+ int statisticsSize = 0;
+
+ /*Variable to Captutre Information at the Application Level*/
+ struct applicationStatistics appStats;
+ char mainFileName[MAX_PATH];
+ FILE *hMainFile;
+
+ //Get perfCallibrationValue
+
+ callibrationValue = getPerfCallibrationValue();
+ printf("Callibration Value for this Platform %llu \n", callibrationValue);
+
+
+ //Get Parameters
+ if(GetParameters(argc, argv))
+ {
+ printf("Error in obtaining the parameters\n");
+ exit(-1);
+ }
+
+ //Assign Values to Application Statistics Members
+ appStats.relationId=RELATION_ID;
+ appStats.operationTime=0;
+ appStats.buildNumber = "999.99";
+ appStats.processCount = USE_PROCESS_COUNT;
+ appStats.threadCount = THREAD_COUNT;
+ appStats.repeatCount = REPEAT_COUNT;
+
+ printf("RELATION ID : %d\n", appStats.relationId);
+ printf("Process Count : %d\n", appStats.processCount);
+ printf("Thread Count : %d\n", appStats.threadCount);
+ printf("Repeat Count : %d\n", appStats.repeatCount);
+
+
+ //Open file for Application Statistics Collection
+ snprintf(mainFileName, MAX_PATH, "main_nativecriticalsection_%d_.txt",appStats.relationId);
+ hMainFile = fopen(mainFileName, "w+");
+
+ if(hMainFile == NULL)
+ {
+ printf("Error in opening main file for write\n");
+ }
+
+
+ for (i=0;i<THREAD_COUNT;i++)
+ {
+ threadID[i] = i;
+ }
+
+ statisticsSize = sizeof(struct statistics);
+
+ snprintf(fileName, MAX_PATH, "%d_thread_nativecriticalsection_%d_.txt", USE_PROCESS_COUNT, RELATION_ID);
+ hFile = fopen(fileName, "w+");
+
+ if(hFile == NULL)
+ {
+ printf("Error in opening file for write for process [%d]\n", USE_PROCESS_COUNT);
+ }
+
+
+ // For each thread we will log operations failed (int), passed (int), total (int)
+ // and number of ticks (DWORD) for the operations
+ resultBuffer = new ResultBuffer( THREAD_COUNT, statisticsSize);
+
+ //Call Test Case Setup Routine
+ if (0!=setuptest())
+ {
+ //Error Condition
+ printf("Error Initializing Test Case\n");
+ exit(-1);
+ }
+
+ //Accquire Lock
+ if (0!=pthread_mutex_lock(&g_mutex))
+ {
+ //Error Condition
+ printf("Error Accquiring Lock\n");
+ exit(-1);
+ }
+
+ //USE NATIVE METHOD TO GET TICK COUNT
+ startTicks = GetTicks();
+
+ /*Loop to create number THREAD_COUNT number of threads*/
+ for (i=0;i< THREAD_COUNT;i++)
+ {
+
+ //printf("Creating Thread Count %d\n", i);
+ //printf("Thread arrary value = %d\n", threadID[i]);
+ rtn=pthread_create(&pthreads[i], NULL, waitforworkerthreads, &threadID[i]);
+ if (0 != rtn)
+ { /* ERROR Condition */
+ printf("Error: pthread Creat, %s \n", strerror(rtn));
+ exit(-1);
+ }
+
+ }
+
+
+ //printf("Main Thread waits to recevie signal when all threads are done\n");
+ pthread_cond_wait(&g_cv2,&g_mutex);
+
+ //printf("Main thread has received signal\n");
+
+ /*Signal Threads to Start Working*/
+ //printf("Raise signal for all threads to start working\n");
+
+
+
+ if (0!=pthread_cond_broadcast(&g_cv))
+ {
+ //Error Condition
+ printf("Error Broadcasting Conditional Event\n");
+ exit(-1);
+ }
+
+ //Release the lock
+ if (0!=pthread_mutex_unlock(&g_mutex))
+ {
+ //Error Condition
+ printf("Error Releasing Lock\n");
+ exit(-1);
+ }
+
+ /*Join Threads */
+ while (j < THREAD_COUNT)
+ {
+ if (0 != pthread_join(pthreads[j],NULL))
+ {
+ //Error Condition
+ printf("Error Joining Threads\n");
+ exit(-1);
+ }
+ j++;
+ }
+
+
+ /*Write Application Results to File*/
+ //CAPTURE NATIVE TICK COUNT HERE
+ appStats.operationTime = (DWORD)(GetTicks() - startTicks)/callibrationValue;
+
+
+ /* Write Results to a file*/
+ if(hFile!= NULL)
+ {
+ for( i = 0; i < THREAD_COUNT; i++ )
+ {
+ buffer = (struct statistics *)resultBuffer->getResultBuffer(i);
+ fprintf(hFile, "%d,%d,%d,%d,%lu,%d\n", buffer->processId, buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime, buffer->relationId );
+ //printf("Iteration %d over\n", i);
+ }
+ }
+ fclose(hFile);
+
+
+
+ //Call Test Case Cleanup Routine
+ if (0!=cleanuptest())
+ {
+ //Error Condition
+ printf("Error Cleaning up Test Case");
+ exit(-1);
+ }
+
+
+ if(hMainFile!= NULL)
+ {
+ printf("Writing to Main File \n");
+ fprintf(hMainFile, "%lu,%d,%d,%d,%d,%s\n", appStats.operationTime, appStats.relationId, appStats.processCount, appStats.threadCount, appStats.repeatCount, appStats.buildNumber);
+
+ }
+ fclose(hMainFile);
+ return 0;
+ }
+
+void * waitforworkerthreads(void * threadId)
+{
+
+ int *threadParam = (int*) threadId;
+
+// printf("Thread ID : %d \n", *threadParam);
+
+ //Accquire Lock
+ if (0!=pthread_mutex_lock(&g_mutex))
+ {
+ //Error Condition
+ printf("Error Accquiring Mutex Lock in Wait for Worker Thread\n");
+ exit(-1);
+ }
+
+ //Increment Global Counter
+ GLOBAL_COUNTER++;
+
+
+ //If global counter is equal to thread count then signal main thread
+ if (GLOBAL_COUNTER == THREAD_COUNT)
+ {
+ if (0!=pthread_cond_signal(&g_cv2))
+ {
+ //Error Condition
+ printf("Error in setting conditional variable\n");
+ exit(-1);
+ }
+ }
+
+ //Wait for main thread to signal
+ if (0!=pthread_cond_wait(&g_cv,&g_mutex))
+ {
+ //Error Condition
+ printf("Error waiting on conditional variable in Worker Thread\n");
+ exit(-1);
+ }
+
+ //Release the mutex lock
+ if (0!=pthread_mutex_unlock(&g_mutex))
+ {
+ //Error Condition
+ printf("Error Releasing Mutex Lock in Worker Thread\n");
+ exit(-1);
+ }
+
+ //Start the test
+ starttests(*threadParam);
+
+}
+
+void starttests(int threadID)
+{
+ /*All threads beign executing tests cases*/
+ int i = 0;
+ int Id = threadID;
+ struct statistics stats;
+ ULONGLONG startTime = 0;
+ ULONGLONG endTime = 0;
+
+ LONG volatile Destination;
+ LONG Exchange;
+ LONG Comperand;
+ LONG result;
+
+ stats.relationId = RELATION_ID;
+ stats.processId = USE_PROCESS_COUNT;
+ stats.operationsFailed = 0;
+ stats.operationsPassed = 0;
+ stats.operationsTotal = 0;
+ stats.operationTime = 0;
+
+ //Enter and Leave Critical Section in a loop REPEAT_COUNT Times
+
+
+ startTime = GetTicks();
+
+ for (i=0;i<REPEAT_COUNT;i++)
+ {
+ Destination = (LONG volatile) threadID;
+ Exchange = (LONG) i;
+ Comperand = (LONG) threadID;
+ result = InterlockedCompareExchange(&Destination, Exchange, Comperand);
+
+ if( i != result )
+ {
+ stats.operationsFailed++;
+ stats.operationsTotal++;
+ continue;
+ }
+
+ }
+
+
+ stats.operationTime = (DWORD)(GetTicks() - startTime)/callibrationValue;
+
+// printf("Operation Time %d \n", stats.operationTime);
+
+ if(resultBuffer->LogResult(Id, (char *)&stats))
+ {
+ printf("Error while writing to shared memory, Thread Id is[??] and Process id is [%d]\n", USE_PROCESS_COUNT);
+ }
+
+}
+
+int setuptest(void)
+{
+
+ //Initalize Critical Section
+ /*
+ if (0!=MTXInitializeCriticalSection( &g_cs))
+ {
+ return -1;
+ }
+ */
+ return 0;
+}
+
+int cleanuptest(void)
+{
+
+ //Delete Critical Section
+ /*
+ if (0!=MTXDeleteCriticalSection(&g_cs))
+ {
+ return -1;
+ }
+ */
+ return 0;
+}
+
+int GetParameters( int argc, char **argv)
+{
+
+ if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?"))
+ || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H"))
+ {
+ printf("PAL -Composite Native Critical Section Test\n");
+ printf("Usage:\n");
+ printf("\t[PROCESS_ID ( greater than 1] \n");
+ printf("\t[THREAD_COUNT ( greater than 1] \n");
+ printf("\t[REPEAT_COUNT ( greater than 1]\n");
+ printf("\t[RELATION_ID [greater than or Equal to 1]\n");
+ return -1;
+ }
+
+
+ USE_PROCESS_COUNT = atoi(argv[1]);
+ if( USE_PROCESS_COUNT < 0)
+ {
+ printf("\nInvalid THREAD_COUNT number, Pass greater than 1\n");
+ return -1;
+ }
+
+ THREAD_COUNT = atoi(argv[2]);
+ if( THREAD_COUNT < 1)
+ {
+ printf("\nInvalid THREAD_COUNT number, Pass greater than 1\n");
+ return -1;
+ }
+
+ REPEAT_COUNT = atoi(argv[3]);
+ if( REPEAT_COUNT < 1)
+ {
+ printf("\nInvalid REPEAT_COUNT number, Pass greater than 1\n");
+ return -1;
+ }
+
+ RELATION_ID = atoi(argv[4]);
+ if( RELATION_ID < 1)
+ {
+ printf("\nInvalid RELATION_ID number, Pass greater than 1\n");
+ return -1;
+ }
+
+
+ return 0;
+}
+
+void incrementCounter(void)
+{
+ g_counter ++;
+}
+
+
+//Implementation borrowed from pertrace.c
+ULONGLONG GetTicks(void)
+{
+#ifdef i386
+ unsigned long a, d;
+ asm volatile("rdtsc":"=a" (a), "=d" (d));
+ return ((ULONGLONG)((unsigned int)(d)) << 32) | (unsigned int)(a);
+#else
+#if defined(__sparc__) || (defined (_HPUX_) && defined(__ia64__))
+ return (ULONGLONG)gethrtime();
+#else
+ // #error Don''t know how to get ticks on this platform
+ return (ULONGLONG)gethrtime();
+#endif // __sparc__
+#endif // _X86_
+}
+
+
+/**/
+ULONGLONG getPerfCallibrationValue(void)
+{
+ ULONGLONG startTicks;
+ ULONGLONG endTicks;
+
+ startTicks = GetTicks();
+ sleep(1);
+ endTicks = GetTicks();
+
+ return ((endTicks-startTicks)/1000); //Return number of Ticks in One Milliseconds
+
+}
+
diff --git a/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/readme.txt b/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/readme.txt
new file mode 100644
index 0000000000..a407e9f8b5
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/readme.txt
@@ -0,0 +1,39 @@
+To compile:
+
+For FReeBSD Platform use the following to compile:
+gcc -pthread -lm -lgcc -lstdc++ -xc++ -Di386 pal_composite_native_cs.c
+
+
+--------------------------------------------------------
+For Solaris Platform use the following to compile:
+ gcc -lpthread -lm -lgcc -lstdc++ -xc++ -D__sparc__ -mimpure-text -shared -o critsect.so mtx_critsect.cpp interlock.s
+gcc -lpthread -lm -lgcc -lstdc++ -xc++ -D__sparc__ pal_composite_native_cs.c
+
+
+setenv LD_LIBRARY_PATH /usr/lib/lwp:/usr/local/lib:/usr/lib:/opt/sfw/lib:.
+ gcc -lpthread -lm -lgcc -lstdc++ -lcritsect -xc++ -D__sparc__ pal_composite_native_cs.c
+ gcc -lpthread -lm -lgcc -lstdc++ -xc++ -D__sparc__ -mimpure-text -shared -o critsect.so mtx_critsect.cpp
+
+(pts/2):{4}% ldd critsect.so
+ libpthread.so.1 => /usr/lib/libpthread.so.1
+ libm.so.1 => /usr/lib/libm.so.1
+ libstdc++.so.2.10.0 => /usr/local/lib/libstdc++.so.2.10.0
+ libc.so.1 => /usr/lib/libc.so.1
+ libdl.so.1 => /usr/lib/libdl.so.1
+ libthread.so.1 => /usr/lib/libthread.so.1
+ /usr/platform/SUNW,Serverblade1/lib/libc_psr.so.1
+
+
+--------------------------------------------------------
+For HPUX Platform use the following to compile:
+gcc -lpthread -mlp64 -lm -lgcc -lstdc++ -xc++ -D_HPUX_ -D__ia64__ pal_composite_native_cs.c
+
+--------------------------------------------------------
+To execute:
+./a.out [PROCESS_COUNT] [THREAD_COUNT] [REPEAT_COUNT]
+
+
+ ./a.out 1 32 1000000 4102406
+
+
+
diff --git a/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/resultbuffer.cpp b/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/resultbuffer.cpp
new file mode 100644
index 0000000000..c9ed9435f1
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/resultbuffer.cpp
@@ -0,0 +1,69 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//#include "stdafx.h"
+#include "resultbuffer.h"
+//
+//#using <mscorlib.dll>
+//
+//using namespace System;
+
+
+ResultBuffer:: ResultBuffer(int ThreadCount, int ThreadLogSize)
+ {
+ // Declare an internal status variable
+ int Status=0;
+
+ // Update the maximum thread count
+ MaxThreadCount = ThreadCount;
+
+ // Allocate the memory buffer based on the passed in thread and process counts
+ // and the specified size of the thread specific buffer
+ buffer = NULL;
+ buffer = (char*)malloc(ThreadCount*ThreadLogSize);
+ // Check to see if the buffer memory was allocated
+ if (buffer == NULL)
+ Status = -1;
+ // Initialize the buffer to 0 to prevent bogus data
+ memset(buffer,0,ThreadCount*ThreadLogSize);
+
+ // The ThreadOffset is equal to the total number of bytes that will be stored per thread
+ ThreadOffset = ThreadLogSize;
+
+ }
+
+
+ int ResultBuffer::LogResult(int Thread, char* Data)
+ {
+ // Declare an internal status flad
+ int status = 0;
+
+ // Declare an object to store the offset address into the buffer
+ int Offset;
+
+ // Check to make sure the Thread index is not out of range
+ if(Thread > MaxThreadCount)
+ {
+ printf("Thread index is out of range, Value of Thread[%d], Value of MaxThreadCount[%d]\n", Thread, MaxThreadCount);
+ status = -1;
+ return(status);
+ }
+
+ // Caculate the offset into the shared buffer based on the process and thread indices
+ Offset = (Thread)*ThreadOffset;
+
+ // Write the passed in data to the reserved buffer
+ memcpy(buffer+Offset,Data,ThreadOffset);
+
+ return(status);
+ }
+
+
+ char* ResultBuffer::getResultBuffer(int threadId)
+ {
+
+ return (buffer + threadId*ThreadOffset);
+
+ }
+
diff --git a/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/resultbuffer.h b/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/resultbuffer.h
new file mode 100644
index 0000000000..8920958100
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/resultbuffer.h
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#include <stdio.h>
+#include <iostream>
+//#include <assert.h>
+#ifndef _RESULT_BUFFER_H_
+#define _RESULT_BUFFER_H_
+
+//#include <palsuite.h>
+
+struct ResultData
+{
+ int value;
+ int size;
+// ResultData* NextResult;
+};
+
+ class ResultBuffer
+{
+ // Declare a pointer to a memory buffer to store the logged results
+ char* buffer;
+ // Declare an object to store the maximum Thread count
+ int MaxThreadCount;
+ // Declare and internal data object to store the calculated offset between adjacent threads data sets
+ int ThreadOffset;
+
+ // Declare a linked list object to store the parameter values
+public:
+
+ // Declare a constructor for the single process case
+ ResultBuffer(int ThreadCount, int ThreadLogSize);
+ // Declare a method to log data for the single process instance
+ int LogResult(int Thread, char* Data);
+
+ char* getResultBuffer(int threadId);
+};
+
+#include "resultbuffer.cpp"
+#endif // _RESULT_BUFFER_H_
+
+
diff --git a/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/sparcinterloc.s b/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/sparcinterloc.s
new file mode 100644
index 0000000000..b9708bc770
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/sparcinterloc.s
@@ -0,0 +1,73 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*++
+
+
+
+ Module Name:
+
+ interlock.s
+
+Abstract:
+
+ Implementation of Interlocked functions for the SPARC
+ platform. These functions are processor dependent.
+ See the i386 implementations for more information.
+
+ --*/
+
+ // A handy macro for declaring a public function
+ // The first argument is the function name.
+ #define ASMFUNC(n,typename); \
+ .align 4 ; \
+ .global n ; \
+ .type n,typename ; \
+n: ;
+
+ .text
+ ASMFUNC(InterlockedIncrement,#function)
+ ld [%o0], %o1
+loopI:
+ mov %o1, %o2
+ add %o1, 1, %o1
+ cas [%o0], %o2, %o1
+ cmp %o2, %o1
+ bne loopI
+ nop
+ retl
+ add %o1, 1, %o0
+
+
+ ASMFUNC(InterlockedDecrement,#function)
+ ld [%o0], %o1
+loopD:
+ mov %o1, %o2
+ sub %o1, 1, %o1
+ cas [%o0], %o2, %o1
+ cmp %o2, %o1
+ bne loopD
+ nop
+ retl
+ sub %o1, 1, %o0
+
+
+ ASMFUNC(InterlockedExchange,#function)
+ swap [%o0], %o1
+ retl
+ mov %o1, %o0
+
+ ASMFUNC(InterlockedCompareExchange,#function)
+ cas [%o0], %o2, %o1
+ retl
+ mov %o1, %o0
+
+ ASMFUNC(MemoryBarrier,#function)
+ // ROTORTODO: SPARC
+ retl
+ nop
+
+ ASMFUNC(YieldProcessor,#function)
+ retl
+ nop
diff --git a/src/pal/tests/palsuite/composite/threading/CMakeLists.txt b/src/pal/tests/palsuite/composite/threading/CMakeLists.txt
new file mode 100644
index 0000000000..793f86c059
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/threading/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(threadsuspension)
+add_subdirectory(threadsuspension_switchthread)
+
diff --git a/src/pal/tests/palsuite/composite/threading/threadsuspension/CMakeLists.txt b/src/pal/tests/palsuite/composite/threading/threadsuspension/CMakeLists.txt
new file mode 100644
index 0000000000..134cce0809
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/threading/threadsuspension/CMakeLists.txt
@@ -0,0 +1,20 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ mainWrapper.c
+ threadsuspension.c
+)
+
+add_executable(paltest_threading_threadsuspension
+ ${SOURCES}
+)
+
+add_dependencies(paltest_threading_threadsuspension coreclrpal)
+
+target_link_libraries(paltest_threading_threadsuspension
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/composite/threading/threadsuspension/mainWrapper.c b/src/pal/tests/palsuite/composite/threading/threadsuspension/mainWrapper.c
new file mode 100644
index 0000000000..05a71191cf
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/threading/threadsuspension/mainWrapper.c
@@ -0,0 +1,274 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*
+Source Code: mainWrapper.c
+
+mainWrapper.c creates Composite Test Case Processes and waits for all processes to get over
+
+Algorithm
+o Create PROCESS_COUNT processes.
+
+Author: RameshG
+*/
+
+#include <palsuite.h>
+#include "resulttime.h"
+
+/* Test Input Variables */
+unsigned int USE_PROCESS_COUNT = 0; //default
+unsigned int WORKER_THREAD_MULTIPLIER_COUNT = 0; //default
+unsigned int REPEAT_COUNT = 0; //default
+unsigned int SLEEP_LENGTH = 0; //default
+unsigned int RELATION_ID = 0;//default
+unsigned int THREAD_COUNT = 1; //There is only one suspender and resume thread for this test case
+
+char *testCaseName;
+
+
+struct applicationStatistics{
+ DWORD operationTime;
+ unsigned int relationId;
+ unsigned int processCount;
+ unsigned int threadCount;
+ unsigned int repeatCount;
+ char* buildNumber;
+
+};
+
+
+int GetParameters( int argc, char **argv)
+{
+
+ if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?"))
+ || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H"))
+ {
+ printf("PAL -Composite Thread Suspension Test\n");
+ printf("Usage:\n");
+ printf("\t[PROCESS_COUNT] Greater than or Equal to 1 \n");
+ printf("\t[WORKER_THREAD_MULTIPLIER_COUNT] Greater than or Equal to 1 and Less than or Equal to %d \n", MAXIMUM_WAIT_OBJECTS);
+ printf("\t[REPEAT_COUNT] Greater than or Equal to 1\n");
+ printf("\t[RELATION_ID [greater than or Equal to 1]\n");
+ return -1;
+ }
+
+ // Trace("Args 1 is [%s], Arg 2 is [%s], Arg 3 is [%s]\n", argv[1], argv[2], argv[3]);
+
+ USE_PROCESS_COUNT = atoi(argv[1]);
+ if( USE_PROCESS_COUNT < 0)
+ {
+ printf("\nPROCESS_COUNT to greater than or equal to 1\n");
+ return -1;
+ }
+
+ WORKER_THREAD_MULTIPLIER_COUNT = atoi(argv[2]);
+ if( WORKER_THREAD_MULTIPLIER_COUNT < 1 || WORKER_THREAD_MULTIPLIER_COUNT > 64)
+ {
+ printf("\nWORKER_THREAD_MULTIPLIER_COUNT to be greater than or equal to 1 or less than or equal to 64\n");
+ return -1;
+ }
+
+ REPEAT_COUNT = atoi(argv[3]);
+ if( REPEAT_COUNT < 1)
+ {
+ printf("\nREPEAT_COUNT to greater than or equal to 1\n");
+ return -1;
+ }
+
+ RELATION_ID = atoi(argv[4]);
+ if( RELATION_ID < 1)
+ {
+ printf("\nRELATION_ID to be greater than or equal to 1\n");
+ return -1;
+ }
+
+
+
+ return 0;
+}
+
+ int __cdecl main(INT argc, CHAR **argv)
+{
+ unsigned int i = 0;
+ HANDLE hProcess[MAXIMUM_WAIT_OBJECTS];
+ DWORD processReturnCode = 0;
+ int testReturnCode = PASS;
+ STARTUPINFO si[MAXIMUM_WAIT_OBJECTS];
+ PROCESS_INFORMATION pi[MAXIMUM_WAIT_OBJECTS];
+
+ FILE *hFile;
+ char fileName[MAX_PATH];
+ struct applicationStatistics appStats;
+
+ DWORD dwStart=0;
+
+ char lpCommandLine[MAX_PATH] = "";
+
+ char build[] ="0000.00";
+ int returnCode = 0;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ //Initialize Application Statistics Strucuture
+ appStats.relationId=RELATION_ID;
+ appStats.operationTime=0;
+ appStats.buildNumber = getBuildNumber();
+ //appStats.buildNumber = build;
+ appStats.processCount = 0;
+ appStats.threadCount = 0;
+ appStats.repeatCount = 0;
+
+
+
+
+
+//Start Process Time Capture
+dwStart = GetTickCount();
+
+ if(GetParameters(argc, argv))
+ {
+ Fail("Error in obtaining the parameters\n");
+ }
+
+//Assign Correct Values to the Application Stats Structure
+ appStats.relationId=RELATION_ID;
+ appStats.processCount = USE_PROCESS_COUNT;
+ appStats.threadCount = THREAD_COUNT ;
+ appStats.repeatCount = REPEAT_COUNT;
+
+ Trace("Relation ID: %d \n", RELATION_ID);
+ Trace("USE_PROCESS_COUNT: %d \n", USE_PROCESS_COUNT);
+ Trace("WORKER_THREAD_MULTIPLIER_COUNT: %d \n", WORKER_THREAD_MULTIPLIER_COUNT);
+ Trace("REPEAT_COUNT: %d \n", REPEAT_COUNT);
+
+
+_snprintf(fileName, MAX_PATH, "main_threadsuspension_%d_.txt",appStats.relationId);
+
+ hFile = fopen(fileName, "w+");
+if(hFile == NULL)
+ {
+ Fail("Error in opening file to write application results for Thread Suspension Test with error code %d \n", GetLastError() );
+ }
+
+
+
+ for( i = 0; i < USE_PROCESS_COUNT; i++ )
+ {
+
+ ZeroMemory( lpCommandLine, MAX_PATH );
+ if ( _snprintf( lpCommandLine, MAX_PATH-1, "threadsuspension %d %d %d %d", i, WORKER_THREAD_MULTIPLIER_COUNT, REPEAT_COUNT, RELATION_ID) < 0 )
+ {
+ Trace ("Error: Insufficient commandline string length for for iteration [%d]\n", i);
+ }
+
+ /* Zero the data structure space */
+ ZeroMemory ( &pi[i], sizeof(pi[i]) );
+ ZeroMemory ( &si[i], sizeof(si[i]) );
+
+ /* Set the process flags and standard io handles */
+ si[i].cb = sizeof(si[i]);
+
+ //Printing the Command Line
+ //Trace("Command Line \t %s \n", lpCommandLine);
+
+ //Create Process
+ if(!CreateProcess( NULL, /* lpApplicationName*/
+ lpCommandLine, /* lpCommandLine */
+ NULL, /* lpProcessAttributes */
+ NULL, /* lpThreadAttributes */
+ TRUE, /* bInheritHandles */
+ 0, /* dwCreationFlags, */
+ NULL, /* lpEnvironment */
+ NULL, /* pCurrentDirectory */
+ &si[i], /* lpStartupInfo */
+ &pi[i] /* lpProcessInformation */
+ ))
+ {
+ Fail("Process Not created for [%d] and GetLastError value is %d\n", i, GetLastError());
+
+ }
+ else
+ {
+ hProcess[i] = pi[i].hProcess;
+ //Trace("Process created for [%d]\n", i);
+ }
+
+ }
+
+ returnCode = WaitForMultipleObjects( USE_PROCESS_COUNT, hProcess, TRUE, INFINITE);
+ if( WAIT_OBJECT_0 != returnCode )
+ {
+ Trace("Wait for Object(s) @ Main thread for %d processes returned %d, and GetLastError value is %d\n", USE_PROCESS_COUNT, returnCode, GetLastError());
+ testReturnCode = FAIL;
+ }
+
+ for( i = 0; i < USE_PROCESS_COUNT; i++ )
+ {
+ /* check the exit code from the process */
+ if( ! GetExitCodeProcess( pi[i].hProcess, &processReturnCode ) )
+ {
+ Trace( "GetExitCodeProcess call failed for iteration %d with error code %u\n",
+ i, GetLastError() );
+
+ testReturnCode = FAIL;
+ }
+
+ if(processReturnCode == FAIL)
+ {
+ Trace( "Process [%d] failed and returned FAIL\n", i);
+ testReturnCode = FAIL;
+ }
+
+ if(!CloseHandle(pi[i].hThread))
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hThread\n", GetLastError(), i);
+ testReturnCode = FAIL;
+ }
+
+ if(!CloseHandle(pi[i].hProcess) )
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hProcess\n", GetLastError(), i);
+ testReturnCode = FAIL;
+ }
+ }
+
+//Get the end time of the process
+appStats.operationTime = GetTickCount() - dwStart;
+
+if( testReturnCode == PASS)
+ {
+ Trace("Test Passed\n");
+ }
+ else
+ {
+ Trace("Test Failed\n");
+ }
+
+//Write Process Result Contents to File
+if(hFile!= NULL)
+ {
+ fprintf(hFile, "%lu,%d,%d,%d,%d,%s\n", appStats.operationTime, appStats.relationId, appStats.processCount, appStats.threadCount, appStats.repeatCount, appStats.buildNumber);
+ }
+
+if (0!=fclose(hFile))
+{
+ Trace("Error:%d: fclose failed for file %s\n", GetLastError(), fileName);
+}
+ PAL_Terminate();
+
+
+if( testReturnCode == PASS)
+ {
+ return PASS;
+ }
+ else
+ {
+ return FAIL;
+
+ }
+
+}
diff --git a/src/pal/tests/palsuite/composite/threading/threadsuspension/readme.txt b/src/pal/tests/palsuite/composite/threading/threadsuspension/readme.txt
new file mode 100644
index 0000000000..d722f1d127
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/threading/threadsuspension/readme.txt
@@ -0,0 +1,11 @@
+To compile:
+
+1) create a dat file (say threadsuspension.dat) with contents:
+PAL,Composite,palsuite\composite\threading\threadsuspension,wfmo=mainWrapper.c threadsuspension.c,<SUPPORTEXE>,<TESTLANGCPP>,<COMPILEONLY>
+
+2) perl rrunmod.pl -r threadsuspension.dat
+
+
+To execute:
+mainWrapper [PROCESS_COUNT] [THREAD_COUNT] [REPEAT_COUNT]
+
diff --git a/src/pal/tests/palsuite/composite/threading/threadsuspension/samplefile.dat b/src/pal/tests/palsuite/composite/threading/threadsuspension/samplefile.dat
new file mode 100644
index 0000000000..d6505f2549
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/threading/threadsuspension/samplefile.dat
@@ -0,0 +1,5124 @@
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense blackasdf dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
diff --git a/src/pal/tests/palsuite/composite/threading/threadsuspension/threadsuspension.c b/src/pal/tests/palsuite/composite/threading/threadsuspension/threadsuspension.c
new file mode 100644
index 0000000000..86ee4e2fc0
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/threading/threadsuspension/threadsuspension.c
@@ -0,0 +1,907 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: \composite\threading\threadsuspension\threadsuspension.c
+**
+** Purpose: To verify Thread Suspension Reegneering effort for this milestone
+
+ PsedoCode:
+
+ Preparation:
+ Create PROCESS_COUNT processes.
+ Test:
+ Create Worker Thread
+ Start Reading and writing to a File
+
+ Create Worker Thread
+ In an infinite loop do the following
+ Enter Critical Section
+ Increment Counter
+ Leave Critical Section
+
+ Create Worker Thread
+ Allocate Memory and Free Memory
+
+ Create Worker Thread
+ In a tight loop add numbers
+
+ In a loop repeated REPEAT_COUNT times
+
+ Create Thread
+
+ Suspend all worker threads
+ Resume all worker threads
+
+ At the end of the loop call PAL_Shutdown
+
+ Parameters:
+ PROCESS_COUNT: Number of processes
+ WORKER_THREAD_MULTIPLIER_COUNT: Number of instances of worker threads in each process
+ REPEAT_COUNT: The number of times to execute the loop.
+
+ Statistics Captured:
+ Total elapsed time
+ MTBF
+
+
+ Scenario:
+**
+ One thread suspends all remaining threads which are in the middle of doing some work and resume all threads
+ Thread 1: Reading and Writing File
+ Thread 2: Enter and Leave Critical Section
+ Thread 3: Allocating chunks of memory
+ Thread 4: Perform Unsafe Operation (printf, malloc)
+ Thread 5: Suspends Thread 1 to Thread 4 and resumes them
+
+**
+**
+**
+** Dependencies:
+**
+**
+
+**
+**=========================================================*/
+
+#include <palsuite.h>
+#include "resultbuffer.h"
+
+#define BUFSIZE 4096
+#define NUMBER_OF_WORKER_THREAD_TYPES 4
+#define THREAD_MAX 64
+
+#define TEST_FAIL 1
+#define TEST_PASS 0
+
+
+DWORD GLOBAL_COUNTER ;
+DWORD UNIQUE_FILE_NUMBER=0;
+HANDLE g_hEvent;
+
+bool failFlag = false; //To Track failure at the Operation Level
+
+// 2 dimensional array to hold thread handles for each worker thread
+HANDLE hThread[NUMBER_OF_WORKER_THREAD_TYPES][THREAD_MAX];
+
+/*unsigned int g_readfileoperation;
+unsigned int g_enterleavecsoperation;
+unsigned int g_allocatefreeoperation;
+unsigned int g_doworintightloop;
+*/
+
+int TYPES_OF_WORKER_THREAD = NUMBER_OF_WORKER_THREAD_TYPES;
+
+int testStatus=TEST_PASS; //Indicates test failure
+
+
+struct statistics{
+ unsigned int processId;
+ unsigned int operationsFailed;
+ unsigned int operationsPassed;
+ unsigned int operationsTotal;
+ DWORD operationTime;
+ unsigned int relationId;
+};
+
+struct processStatistics{
+ unsigned int processId;
+ DWORD operationTime;
+ unsigned int relationId;
+};
+
+/* Results Buffer */
+ResultBuffer *resultBuffer;
+
+
+/* Test Input Variables */
+unsigned int USE_PROCESS_COUNT = 0; //Identifies the Process number. There could potentially
+unsigned int WORKER_THREAD_MULTIPLIER_COUNT = 0; //In this test case this represents the number of worker thread instances
+unsigned int REPEAT_COUNT = 0; //Number of Suspend Resume operation of worker threads
+unsigned int RELATION_ID = 0;
+
+
+
+CRITICAL_SECTION CriticalSectionM; /* Critical Section Object (used as mutex) */
+CRITICAL_SECTION g_csUniqueFileName;
+
+void PALAPI setup(void);
+void PALAPI cleanup(void);
+void PALAPI incrementCounter(void);
+DWORD PALAPI readfile( LPVOID);
+DWORD PALAPI enterandleave_cs( LPVOID);
+DWORD PALAPI allocateandfree_memory( LPVOID);
+DWORD PALAPI doworkintightloop_cs( LPVOID);
+DWORD PALAPI suspendandresumethreads( LPVOID);
+int GetParameters(int, char * *);
+
+
+//Main Entry for the Thread Suspension Test Case
+int __cdecl main (int argc, char **argv)
+{
+
+/*
+* Parameter to the threads that will be created
+*/
+
+
+DWORD dwThrdParam = 0;
+DWORD dwStart;
+
+/* Variables to capture the file name and the file pointer*/
+char fileName[MAX_PATH];
+char processFileName[MAX_PATH];
+
+FILE *hFile, *hProcessFile;
+struct statistics* buffer;
+struct processStatistics *processBuffer;
+
+struct processStatistics processStats;
+
+struct statistics* tmpBuf = NULL;
+int statisticsSize = 0;
+
+DWORD dwThreadId=0;
+HANDLE hMainThread;
+unsigned int i = 0;
+int j = 0;
+
+
+/*
+* PAL Initialize
+*/
+
+if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+
+//Get Parameters
+if(GetParameters(argc, argv))
+ {
+ Fail("Error in obtaining the parameters\n");
+ }
+
+
+//Setup for Process Result Collection
+statisticsSize = sizeof(struct statistics);
+_snprintf(processFileName, MAX_PATH, "%d_process_threadsuspension_%d_.txt", USE_PROCESS_COUNT, RELATION_ID);
+hProcessFile = fopen(processFileName, "w+");
+
+if(hProcessFile == NULL)
+ {
+ Fail("Error in opening file to write process results for process [%d]\n", USE_PROCESS_COUNT);
+ }
+
+//Initialize Process Stats Variables
+processStats.operationTime = 0;
+processStats.processId = USE_PROCESS_COUNT;
+processStats.relationId = RELATION_ID;
+
+//Start Process Time Capture
+dwStart = GetTickCount();
+
+//Setup for Thread Result Collection
+statisticsSize = sizeof(struct statistics);
+_snprintf(fileName, MAX_PATH, "%d_thread_threadsuspension_%d_.txt", USE_PROCESS_COUNT,RELATION_ID);
+hFile = fopen(fileName, "w+");
+
+if(hFile == NULL)
+ {
+ Fail("Error in opening file to write thread results for process [%d]\n", USE_PROCESS_COUNT);
+ }
+
+// For each thread we will log relationid (int), processid (int), operations failed (int), passed (int), total (int)
+// and number of ticks (DWORD) for the operations
+resultBuffer = new ResultBuffer( 1, statisticsSize);
+
+/*
+* Call the Setup Routine
+*/
+setup();
+
+Trace("WORKER_THREAD_MULTIPLIER_COUNT: %d \n", WORKER_THREAD_MULTIPLIER_COUNT);
+
+//Create WORKER_THREAD_MULTIPLIER_COUNT Instances of each type of worker thread
+for (i=0;i<WORKER_THREAD_MULTIPLIER_COUNT;i++)
+{
+
+ /*
+ * Create readfile thread
+ */
+ hThread[0][i] = CreateThread(
+ NULL,
+ 0,
+ readfile,
+ NULL,
+ 0,
+ &dwThreadId);
+
+ if ( NULL == hThread[0][i] )
+ {
+ Fail ( "CreateThread() returned NULL. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+
+
+ /*
+ * Create Enter and Leave Critical Section Thread
+ */
+ hThread[1][i] = CreateThread(
+ NULL,
+ 0,
+ enterandleave_cs,
+ NULL,
+ 0,
+ &dwThreadId);
+
+ if ( NULL == hThread[1][i] )
+ {
+ Fail ( "CreateThread() returned NULL. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+
+
+ /*
+ * Create Allocate and Free Memory Thread
+ */
+ hThread[2][i] = CreateThread(
+ NULL,
+ 0,
+ allocateandfree_memory,
+ NULL,
+ 0,
+ &dwThreadId);
+
+ if ( NULL == hThread[2][i])
+ {
+ Fail ( "CreateThread() returned NULL. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+
+
+ /*
+ * Create Work in tight Loop thread
+ */
+ hThread[3][i] = CreateThread(
+ NULL,
+ 0,
+ doworkintightloop_cs,
+ NULL,
+ 0,
+ &dwThreadId);
+
+ if ( NULL == hThread[3][i])
+ {
+ Fail ( "CreateThread() returned NULL. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+
+
+}
+
+
+
+
+
+/*
+ * Create Main test case thread that Suspends and Resumes Threads
+ */
+ hMainThread = CreateThread(
+ NULL,
+ 0,
+ suspendandresumethreads,
+ (LPVOID)dwThrdParam,
+ 0,
+ &dwThreadId);
+
+ if ( NULL == hMainThread )
+ {
+ Fail ( "CreateThread() returned NULL. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+
+
+
+/*
+* Set Event to allow all threads to start
+*/
+
+if (0==SetEvent(g_hEvent))
+{
+ Fail ( "SetEvent returned Zero. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+}
+
+/*
+ * Wait for main thread to complete
+ *
+ */
+ if (WAIT_OBJECT_0 != WaitForSingleObject (hMainThread, INFINITE))
+ {
+ Fail ("Main: Wait for Single Object (mainThread) failed. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+//Get the end time of the process
+processStats.operationTime = GetTickCount() - dwStart;
+
+//Write Process Result Contents to File
+if(hProcessFile!= NULL)
+ {
+ fprintf(hProcessFile, "%d,%lu,%d\n", processStats.processId, processStats.operationTime, processStats.relationId );
+ }
+
+if (0!=fclose(hProcessFile))
+{
+ Fail("Unable to write process results to file"
+ "GetLastError returned %d\n", GetLastError());
+}
+
+
+//Write to log file
+//Trace("# of Read File Operations %d\n", g_readfileoperation);
+//Trace("# of Enter and Leace CS Operations %d\n", g_enterleavecsoperation);
+//Trace("# of Do Work In Tight Loop Operations %d\n", g_doworintightloop);
+//Trace("# of Allocate and Free Operations %d\n", g_allocatefreeoperation);
+
+
+//Write Thread Result Contents to File
+if(hFile!= NULL)
+ {
+ for( i = 0; i < 1; i++ )
+ {
+ buffer = (struct statistics *)resultBuffer->getResultBuffer(i);
+ fprintf(hFile, "%d,%d,%d,%d,%lu,%d\n", buffer->processId, buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime, buffer->relationId );
+ }
+ }
+
+if (0!=fclose(hFile))
+{
+ Fail("Unable to write thread results to file"
+ "GetLastError returned %d\n", GetLastError());
+}
+
+cleanup();
+
+if (failFlag == TRUE)
+{
+ return FAIL;
+}
+else
+{
+ return PASS;
+}
+}
+
+
+/*
+* Setup for the test case
+*/
+
+VOID
+setup(VOID)
+{
+ /*Delete All Temporary Files Created by the previous execution of the test case*/
+ HANDLE hSearch;
+ BOOL fFinished = FALSE;
+ WIN32_FIND_DATA FileData;
+
+ //Start searching for .tmp files in the current directory.
+ hSearch = FindFirstFile("*.tmp*", &FileData);
+ if (hSearch == INVALID_HANDLE_VALUE)
+ {
+ //No Files That Matched Criteria
+ fFinished = TRUE;
+ }
+
+ //Delete all files that match the pattern
+ while (!fFinished)
+ {
+ if (!DeleteFile(FileData.cFileName))
+ {
+ Trace("Setup: Could not delete temporary file %s\n",FileData.cFileName );
+ Fail ("GetLastError returned %d\n", GetLastError());
+ }
+ if (!FindNextFile(hSearch, &FileData))
+ {
+ if (GetLastError() == ERROR_NO_MORE_FILES)
+ {
+ fFinished = TRUE;
+ }
+ else
+ {
+ Fail("Unable to Delete Temporary Files, GetLastError is %d \n", GetLastError());
+ }
+ }
+ }
+
+ // Close the search handle, only if HANDLE is Valid
+ if (hSearch != INVALID_HANDLE_VALUE)
+ {
+ if (!FindClose(hSearch))
+ {
+ Trace("Setup: Could not close search handle \n");
+ Fail ("GetLastError returned %d\n", GetLastError());
+ }
+ }
+
+ g_hEvent = CreateEvent(NULL,TRUE,FALSE, NULL);
+ if(g_hEvent == NULL)
+ {
+ Fail("Create Event Failed\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+ InitializeCriticalSection ( &g_csUniqueFileName);
+}
+
+/*
+* Cleanup for the test case
+*/
+
+VOID
+cleanup(VOID)
+{
+ //DeleteCriticalSection(&g_csUniqueFileName);
+ PAL_Terminate();
+}
+
+
+VOID
+incrementCounter(VOID)
+{
+
+ if (INT_MAX == GLOBAL_COUNTER)
+ {
+ GLOBAL_COUNTER = 0;
+ }
+
+ GLOBAL_COUNTER++;
+}
+
+/*
+ * Worker Thread
+ * Read File: Read from a file and write to a temporary file and then delete the temp file
+ */
+DWORD
+PALAPI
+readfile( LPVOID lpParam )
+{
+
+ // Declaring Local Variables
+ HANDLE hFile,hTempfile;
+ char buffer[BUFSIZE];
+ DWORD dwBytesRead, dwBytesWritten, dwBufSize=BUFSIZE;
+ DWORD dwWaitResult=0;
+ char filename[MAX_PATH];
+
+ //Wait for event to signal to start test
+ dwWaitResult = WaitForSingleObject(g_hEvent,INFINITE);
+ if (WAIT_OBJECT_0 != dwWaitResult)
+ {
+ Fail ("readfile: Wait for Single Object (g_hEvent) failed. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+
+ /*Start Operation*/
+
+ // Open the existing file.
+ while(TRUE)
+ {
+
+ hFile = CreateFile("samplefile.dat", // file name
+ GENERIC_READ, // open for reading
+ FILE_SHARE_READ, // Share the file for read
+ NULL, // default security
+ OPEN_EXISTING, // existing file only
+ FILE_ATTRIBUTE_NORMAL, // normal file
+ NULL); // no template
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Trace("Could not open file \n");
+ Fail ( "GetLastError returned %d\n", GetLastError());
+ }
+
+ //Generate Unique File Name to Write
+ //Enter CS
+ EnterCriticalSection(&g_csUniqueFileName);
+
+ //Increment Number and assign to local variable
+ UNIQUE_FILE_NUMBER++;
+ _snprintf(filename, MAX_PATH, "%d_%d_tempfile.tmp", USE_PROCESS_COUNT,UNIQUE_FILE_NUMBER);
+ //filename = itoa(UNIQUE_FILE_NUMBER);
+ //Leave CS
+ LeaveCriticalSection(&g_csUniqueFileName);
+
+
+ // Create a temporary file with name generate above
+ hTempfile = CreateFile(filename, // file name
+ GENERIC_WRITE, // open for read/write
+ 0, // do not share
+ NULL, // default security
+ CREATE_ALWAYS, // overwrite existing file
+ FILE_ATTRIBUTE_NORMAL, // normal file
+ NULL); // no template
+
+
+ if (hTempfile == INVALID_HANDLE_VALUE)
+ {
+ Trace("Could not create temporary file\n");
+ Fail ( "GetLastError returned %d\n", GetLastError());
+ }
+
+ // Read 4K blocks to the buffer.
+ // Change all characters in the buffer to upper case.
+ // Write the buffer to the temporary file.
+
+ do
+ {
+ if (ReadFile(hFile, buffer, 4096,
+ &dwBytesRead, NULL))
+ {
+
+ WriteFile(hTempfile, buffer, dwBytesRead,
+ &dwBytesWritten, NULL);
+ }
+ } while (dwBytesRead == BUFSIZE);
+
+
+
+ // Close both files.
+ if (0==CloseHandle(hFile))
+ {
+ Trace("Could not handle hFile\n");
+ Fail ( "GetLastError returned %d\n", GetLastError());
+ }
+
+ if (0==CloseHandle(hTempfile))
+ {
+ Trace("Could not handle hTempFile\n");
+ Fail ( "GetLastError returned %d\n", GetLastError());
+ }
+
+ //Delete the file that was created
+ if (!DeleteFile(filename))
+ {
+ Trace("Could not delete temporary file %s\n", filename);
+ Fail ( "GetLastError returned %d\n", GetLastError());
+
+ }
+
+ //g_readfileoperation++;
+ }
+
+/*End Operation*/
+
+ return 0;
+}
+
+
+/* Worker Thread
+ * Enter and Leave Nested Critical Sections
+ */
+DWORD
+PALAPI
+enterandleave_cs( LPVOID lpParam )
+{
+
+ //Declare Local Variables
+
+ CRITICAL_SECTION lcs;
+ CRITICAL_SECTION lcsNested;
+
+ DWORD dwWaitResult;
+
+ //Intialize Critical Section Structures
+ InitializeCriticalSection ( &lcs);
+ InitializeCriticalSection ( &lcsNested);
+
+
+ //Wait for event to signal to start test
+ dwWaitResult = WaitForSingleObject(g_hEvent,INFINITE);
+ if (WAIT_OBJECT_0 != dwWaitResult)
+ {
+ Fail ("enterandleave_cs: Wait for Single Object (g_hEvent) failed. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+ //Trace("Critical Section Started\n");
+
+ while(TRUE)
+ {
+ EnterCriticalSection(&lcs);
+
+ EnterCriticalSection(&lcsNested);
+
+ incrementCounter();
+
+ LeaveCriticalSection(&lcsNested);
+
+ LeaveCriticalSection(&lcs);
+ //g_enterleavecsoperation++;
+ }
+
+ //Delete Critical Section Structures
+
+ DeleteCriticalSection(&lcs);
+ DeleteCriticalSection(&lcsNested);
+
+
+ return 0;
+}
+
+
+/*
+ * Allocate and Free Memory
+ */
+DWORD
+PALAPI
+allocateandfree_memory( LPVOID lpParam )
+{
+
+
+ int i;
+ char *textArrPtr[64];
+ DWORD dwWaitResult;
+
+ //Wait for event to signal to start test
+ dwWaitResult = WaitForSingleObject(g_hEvent,INFINITE);
+ if (WAIT_OBJECT_0 != dwWaitResult)
+ {
+ Fail ("allocateandfree_memory: Wait for Single Object (g_hEvent) failed. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+
+ while(TRUE)
+ {
+
+ //do allocate and free operation
+
+ for (i=0;i<64;i++)
+ {
+ textArrPtr[i] = (char*) malloc(BUFSIZE);
+ if (textArrPtr[i] == NULL)
+ {
+ Fail("Insufficient Memory Available, GetLastError is %d \n", GetLastError());
+ testStatus = TEST_FAIL;
+ }
+ }
+
+ for (i=0;i<64;i++)
+ {
+ free(textArrPtr[i]);
+ }
+ //g_allocatefreeoperation++;
+ }
+
+
+
+
+ return 0;
+}
+
+/*
+ * Do work in a tight loop
+ */
+DWORD
+PALAPI
+doworkintightloop_cs( LPVOID lpParam )
+{
+
+ unsigned int i;
+ DWORD dwWaitResult;
+
+ //Wait for event to signal to start test
+ dwWaitResult = WaitForSingleObject(g_hEvent,INFINITE);
+ if (WAIT_OBJECT_0 != dwWaitResult)
+ {
+ Fail ("doworkintightloop_cs: Wait for Single Object (g_hEvent) failed. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+ i= 0;
+ while (TRUE)
+ {
+
+ if (INT_MAX == i)
+ i =0;
+ i++;
+ //g_doworintightloop++;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Main Test Case worker thread which will suspend and resume all other worker threads
+ */
+DWORD
+PALAPI
+suspendandresumethreads( LPVOID lpParam )
+{
+
+ unsigned int loopcount = REPEAT_COUNT;
+ int Id=(int)lpParam;
+ unsigned int i,j,k;
+ DWORD dwStart;
+ DWORD dwWaitResult=0;
+ DWORD dwLastError = 0;
+ struct statistics stats;
+ struct statistics* buffer;
+
+
+
+ //Initialize the Statistics Structure
+ stats.relationId = RELATION_ID;
+ stats.processId = USE_PROCESS_COUNT;
+ stats.operationsFailed = 0;
+ stats.operationsPassed = 0;
+ stats.operationsTotal = 0;
+ stats.operationTime = 0;
+
+
+
+ //Wait for event to signal to start test
+ WaitForSingleObject(g_hEvent,INFINITE);
+ if (WAIT_OBJECT_0 != dwWaitResult)
+ {
+ Fail ("suspendandresumethreads: Wait for Single Object (g_hEvent) failed. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+
+ //Capture Start Import
+ dwStart = GetTickCount();
+
+ for(i = 0; i < loopcount; i++)
+ {
+
+ failFlag = false;
+
+ //Suspend Worker Threads
+ for (k=0;k<WORKER_THREAD_MULTIPLIER_COUNT;k++)
+ {
+ for (j=0;j<4;j++)
+ {
+ if (-1 == SuspendThread(hThread[j][k]))
+ {
+ //If the operation indicate failure
+ failFlag = true;
+ }
+ }
+ }
+
+
+ //Resume Worker Threads
+ for (k=0;k<WORKER_THREAD_MULTIPLIER_COUNT;k++)
+ {
+ for (j=0;j<4;j++)
+ {
+
+ //Only suspend if not already in suspended state
+
+ if (-1 == ResumeThread(hThread[j][k]))
+ {
+ //If the operation indicate failure
+ failFlag = true;
+ }
+
+ }
+ }
+
+
+ //Check for Fail Flag. If set increment number of failures
+ // If Fail flag not set then increment number of operations and number of passe
+ if (failFlag == true)
+ {
+ stats.operationsFailed++;
+ }
+ else
+ {
+ stats.operationsPassed +=1;
+
+ }
+ stats.operationsTotal +=1;
+
+ }
+
+ stats.operationTime = GetTickCount() - dwStart;
+
+ /*Trace("\n\n\n\nOperation Time: %d milliseconds\n", stats.operationTime);
+ Trace("Operation Passed: %d\n", stats.operationsPassed);
+ Trace("Operation Total: %d\n", stats.operationsTotal);
+ Trace("Operation Failed: %d\n", stats.operationsFailed);
+ */
+ if(resultBuffer->LogResult(Id, (char *)&stats))
+ {
+ Fail("Error while writing to shared memory, Thread Id is[%d] and Process id is [%d]\n", Id, USE_PROCESS_COUNT);
+ }
+
+ buffer = (struct statistics *)resultBuffer->getResultBuffer(Id);
+ //Trace("\n%d,%d,%d,%lu\n", buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime );
+
+
+ return 0;
+}
+
+
+
+int GetParameters( int argc, char **argv)
+{
+
+ if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?"))
+ || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H"))
+ {
+ Trace("PAL -Composite Thread Suspension Test\n");
+ Trace("Usage:\n");
+ Trace("\t[PROCESS_COUNT] Greater than or Equal to 1 \n");
+ Trace("\t[WORKER_THREAD_MULTIPLIER_COUNT] Greater than or Equal to 1 and Less than or Equal to 64 \n");
+ Trace("\t[REPEAT_COUNT] Greater than or Equal to 1\n");
+ Trace("\t[RELATION_ID [greater than or Equal to 1]\n");
+ return -1;
+ }
+
+// Trace("Args 1 is [%s], Arg 2 is [%s], Arg 3 is [%s]\n", argv[1], argv[2], argv[3]);
+
+ USE_PROCESS_COUNT = atoi(argv[1]);
+ if( USE_PROCESS_COUNT < 0)
+ {
+ Trace("\nPROCESS_COUNT to greater than or equal to 1\n");
+ return -1;
+ }
+
+ WORKER_THREAD_MULTIPLIER_COUNT = atoi(argv[2]);
+ if( WORKER_THREAD_MULTIPLIER_COUNT < 1 || WORKER_THREAD_MULTIPLIER_COUNT > 64)
+ {
+ Trace("\nWORKER_THREAD_MULTIPLIER_COUNT to be greater than or equal to 1 or less than or equal to 64\n");
+ return -1;
+ }
+
+ REPEAT_COUNT = atoi(argv[3]);
+ if( REPEAT_COUNT < 1)
+ {
+ Trace("\nREPEAT_COUNT to greater than or equal to 1\n");
+ return -1;
+ }
+
+ RELATION_ID = atoi(argv[4]);
+ if( RELATION_ID < 1)
+ {
+ Trace("\nRELATION_ID to be greater than or equal to 1\n");
+ return -1;
+ }
+ return 0;
+}
diff --git a/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/CMakeLists.txt b/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/CMakeLists.txt
new file mode 100644
index 0000000000..5361a1cf0d
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/CMakeLists.txt
@@ -0,0 +1,20 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ mainWrapper.c
+ threadsuspension.c
+)
+
+add_executable(paltest_threading_threadsuspension_switchthread
+ ${SOURCES}
+)
+
+add_dependencies(paltest_threading_threadsuspension_switchthread coreclrpal)
+
+target_link_libraries(paltest_threading_threadsuspension_switchthread
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/mainWrapper.c b/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/mainWrapper.c
new file mode 100644
index 0000000000..05a71191cf
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/mainWrapper.c
@@ -0,0 +1,274 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*
+Source Code: mainWrapper.c
+
+mainWrapper.c creates Composite Test Case Processes and waits for all processes to get over
+
+Algorithm
+o Create PROCESS_COUNT processes.
+
+Author: RameshG
+*/
+
+#include <palsuite.h>
+#include "resulttime.h"
+
+/* Test Input Variables */
+unsigned int USE_PROCESS_COUNT = 0; //default
+unsigned int WORKER_THREAD_MULTIPLIER_COUNT = 0; //default
+unsigned int REPEAT_COUNT = 0; //default
+unsigned int SLEEP_LENGTH = 0; //default
+unsigned int RELATION_ID = 0;//default
+unsigned int THREAD_COUNT = 1; //There is only one suspender and resume thread for this test case
+
+char *testCaseName;
+
+
+struct applicationStatistics{
+ DWORD operationTime;
+ unsigned int relationId;
+ unsigned int processCount;
+ unsigned int threadCount;
+ unsigned int repeatCount;
+ char* buildNumber;
+
+};
+
+
+int GetParameters( int argc, char **argv)
+{
+
+ if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?"))
+ || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H"))
+ {
+ printf("PAL -Composite Thread Suspension Test\n");
+ printf("Usage:\n");
+ printf("\t[PROCESS_COUNT] Greater than or Equal to 1 \n");
+ printf("\t[WORKER_THREAD_MULTIPLIER_COUNT] Greater than or Equal to 1 and Less than or Equal to %d \n", MAXIMUM_WAIT_OBJECTS);
+ printf("\t[REPEAT_COUNT] Greater than or Equal to 1\n");
+ printf("\t[RELATION_ID [greater than or Equal to 1]\n");
+ return -1;
+ }
+
+ // Trace("Args 1 is [%s], Arg 2 is [%s], Arg 3 is [%s]\n", argv[1], argv[2], argv[3]);
+
+ USE_PROCESS_COUNT = atoi(argv[1]);
+ if( USE_PROCESS_COUNT < 0)
+ {
+ printf("\nPROCESS_COUNT to greater than or equal to 1\n");
+ return -1;
+ }
+
+ WORKER_THREAD_MULTIPLIER_COUNT = atoi(argv[2]);
+ if( WORKER_THREAD_MULTIPLIER_COUNT < 1 || WORKER_THREAD_MULTIPLIER_COUNT > 64)
+ {
+ printf("\nWORKER_THREAD_MULTIPLIER_COUNT to be greater than or equal to 1 or less than or equal to 64\n");
+ return -1;
+ }
+
+ REPEAT_COUNT = atoi(argv[3]);
+ if( REPEAT_COUNT < 1)
+ {
+ printf("\nREPEAT_COUNT to greater than or equal to 1\n");
+ return -1;
+ }
+
+ RELATION_ID = atoi(argv[4]);
+ if( RELATION_ID < 1)
+ {
+ printf("\nRELATION_ID to be greater than or equal to 1\n");
+ return -1;
+ }
+
+
+
+ return 0;
+}
+
+ int __cdecl main(INT argc, CHAR **argv)
+{
+ unsigned int i = 0;
+ HANDLE hProcess[MAXIMUM_WAIT_OBJECTS];
+ DWORD processReturnCode = 0;
+ int testReturnCode = PASS;
+ STARTUPINFO si[MAXIMUM_WAIT_OBJECTS];
+ PROCESS_INFORMATION pi[MAXIMUM_WAIT_OBJECTS];
+
+ FILE *hFile;
+ char fileName[MAX_PATH];
+ struct applicationStatistics appStats;
+
+ DWORD dwStart=0;
+
+ char lpCommandLine[MAX_PATH] = "";
+
+ char build[] ="0000.00";
+ int returnCode = 0;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ //Initialize Application Statistics Strucuture
+ appStats.relationId=RELATION_ID;
+ appStats.operationTime=0;
+ appStats.buildNumber = getBuildNumber();
+ //appStats.buildNumber = build;
+ appStats.processCount = 0;
+ appStats.threadCount = 0;
+ appStats.repeatCount = 0;
+
+
+
+
+
+//Start Process Time Capture
+dwStart = GetTickCount();
+
+ if(GetParameters(argc, argv))
+ {
+ Fail("Error in obtaining the parameters\n");
+ }
+
+//Assign Correct Values to the Application Stats Structure
+ appStats.relationId=RELATION_ID;
+ appStats.processCount = USE_PROCESS_COUNT;
+ appStats.threadCount = THREAD_COUNT ;
+ appStats.repeatCount = REPEAT_COUNT;
+
+ Trace("Relation ID: %d \n", RELATION_ID);
+ Trace("USE_PROCESS_COUNT: %d \n", USE_PROCESS_COUNT);
+ Trace("WORKER_THREAD_MULTIPLIER_COUNT: %d \n", WORKER_THREAD_MULTIPLIER_COUNT);
+ Trace("REPEAT_COUNT: %d \n", REPEAT_COUNT);
+
+
+_snprintf(fileName, MAX_PATH, "main_threadsuspension_%d_.txt",appStats.relationId);
+
+ hFile = fopen(fileName, "w+");
+if(hFile == NULL)
+ {
+ Fail("Error in opening file to write application results for Thread Suspension Test with error code %d \n", GetLastError() );
+ }
+
+
+
+ for( i = 0; i < USE_PROCESS_COUNT; i++ )
+ {
+
+ ZeroMemory( lpCommandLine, MAX_PATH );
+ if ( _snprintf( lpCommandLine, MAX_PATH-1, "threadsuspension %d %d %d %d", i, WORKER_THREAD_MULTIPLIER_COUNT, REPEAT_COUNT, RELATION_ID) < 0 )
+ {
+ Trace ("Error: Insufficient commandline string length for for iteration [%d]\n", i);
+ }
+
+ /* Zero the data structure space */
+ ZeroMemory ( &pi[i], sizeof(pi[i]) );
+ ZeroMemory ( &si[i], sizeof(si[i]) );
+
+ /* Set the process flags and standard io handles */
+ si[i].cb = sizeof(si[i]);
+
+ //Printing the Command Line
+ //Trace("Command Line \t %s \n", lpCommandLine);
+
+ //Create Process
+ if(!CreateProcess( NULL, /* lpApplicationName*/
+ lpCommandLine, /* lpCommandLine */
+ NULL, /* lpProcessAttributes */
+ NULL, /* lpThreadAttributes */
+ TRUE, /* bInheritHandles */
+ 0, /* dwCreationFlags, */
+ NULL, /* lpEnvironment */
+ NULL, /* pCurrentDirectory */
+ &si[i], /* lpStartupInfo */
+ &pi[i] /* lpProcessInformation */
+ ))
+ {
+ Fail("Process Not created for [%d] and GetLastError value is %d\n", i, GetLastError());
+
+ }
+ else
+ {
+ hProcess[i] = pi[i].hProcess;
+ //Trace("Process created for [%d]\n", i);
+ }
+
+ }
+
+ returnCode = WaitForMultipleObjects( USE_PROCESS_COUNT, hProcess, TRUE, INFINITE);
+ if( WAIT_OBJECT_0 != returnCode )
+ {
+ Trace("Wait for Object(s) @ Main thread for %d processes returned %d, and GetLastError value is %d\n", USE_PROCESS_COUNT, returnCode, GetLastError());
+ testReturnCode = FAIL;
+ }
+
+ for( i = 0; i < USE_PROCESS_COUNT; i++ )
+ {
+ /* check the exit code from the process */
+ if( ! GetExitCodeProcess( pi[i].hProcess, &processReturnCode ) )
+ {
+ Trace( "GetExitCodeProcess call failed for iteration %d with error code %u\n",
+ i, GetLastError() );
+
+ testReturnCode = FAIL;
+ }
+
+ if(processReturnCode == FAIL)
+ {
+ Trace( "Process [%d] failed and returned FAIL\n", i);
+ testReturnCode = FAIL;
+ }
+
+ if(!CloseHandle(pi[i].hThread))
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hThread\n", GetLastError(), i);
+ testReturnCode = FAIL;
+ }
+
+ if(!CloseHandle(pi[i].hProcess) )
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hProcess\n", GetLastError(), i);
+ testReturnCode = FAIL;
+ }
+ }
+
+//Get the end time of the process
+appStats.operationTime = GetTickCount() - dwStart;
+
+if( testReturnCode == PASS)
+ {
+ Trace("Test Passed\n");
+ }
+ else
+ {
+ Trace("Test Failed\n");
+ }
+
+//Write Process Result Contents to File
+if(hFile!= NULL)
+ {
+ fprintf(hFile, "%lu,%d,%d,%d,%d,%s\n", appStats.operationTime, appStats.relationId, appStats.processCount, appStats.threadCount, appStats.repeatCount, appStats.buildNumber);
+ }
+
+if (0!=fclose(hFile))
+{
+ Trace("Error:%d: fclose failed for file %s\n", GetLastError(), fileName);
+}
+ PAL_Terminate();
+
+
+if( testReturnCode == PASS)
+ {
+ return PASS;
+ }
+ else
+ {
+ return FAIL;
+
+ }
+
+}
diff --git a/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/readme.txt b/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/readme.txt
new file mode 100644
index 0000000000..d722f1d127
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/readme.txt
@@ -0,0 +1,11 @@
+To compile:
+
+1) create a dat file (say threadsuspension.dat) with contents:
+PAL,Composite,palsuite\composite\threading\threadsuspension,wfmo=mainWrapper.c threadsuspension.c,<SUPPORTEXE>,<TESTLANGCPP>,<COMPILEONLY>
+
+2) perl rrunmod.pl -r threadsuspension.dat
+
+
+To execute:
+mainWrapper [PROCESS_COUNT] [THREAD_COUNT] [REPEAT_COUNT]
+
diff --git a/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/samplefile.dat b/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/samplefile.dat
new file mode 100644
index 0000000000..d6505f2549
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/samplefile.dat
@@ -0,0 +1,5124 @@
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense blackasdf dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
+By Patricia Reaney
+LONDON (Reuters) - Europe, Africa and the Middle East are the best vantage points to see the first transit of Venus across the sun in more than a century on Tuesday, scientists said.
+
+Mostly clear skies are forecast in many parts of the three regions, but people were urged to be careful if they watch the rare event when it begins at 1:19 a.m. EDT because it could cause blindness. Views will be restricted from Asia and the Americas.
+
+Unlike a solar eclipse by the moon that is over in two or three minutes, Venus's transit -- which last occurred in 1882 -- will go on for six hours.
+
+The planet will appear as an intense black dot on the solar disc.
+
+Most of the sun will be visible as Venus crosses to the right from the bottom left side of the solar disc. Venus will be 26.7 million miles from earth.
+
+"Venus will be about 1/30 the size of the diameter of the sun, but it will be much darker and more intense than sunspots," said Dr Robert Walsh, of the University of Central Lancashire's Center for Astrophysics in northern England.
+
+Scientists recommend some form of indirect projection as the safest way to observe the phenomenon.
+
+"Never ever look directly at the sun with the naked eye or any sort of optical equipment -- telescope, binoculars or even digital camera," said Walsh.
+
+"Even if you glance at the sun for a short period of time you can damage your eye and lose some of your sight," he said.
+
+Internet sites will be covering the transit and observatories around the world have organized viewings.
+
+"Mainly Western Europe could see some high cloud that might prevent people from seeing it," said a spokesman for Britain's Meteorological Office. "The rest of Europe shouldn't be too bad. It should be fine."
+
+German astronomer Johannes Kepler first predicted a transit of Venus in 1627 but he died before he could witness one. English astronomer Jeremiah Horrocks first observed it in 1639.
+
+The transit occurs four times in every 243 years. There are two December transits, eight years apart, and then 121.5 years later there are two June transits, also eight years apart. After another 105.5 years the cycle begins again.
+
+The next transit will occur in 2012 when it will be visible from parts of Asia and the Pacific but not Europe.
diff --git a/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/threadsuspension.c b/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/threadsuspension.c
new file mode 100644
index 0000000000..a117b86174
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/threadsuspension.c
@@ -0,0 +1,914 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: \composite\threading\threadsuspension\threadsuspension.c
+**
+** Purpose: To verify Thread Suspension Reegneering effort for this milestone
+
+ PsedoCode:
+
+ Preparation:
+ Create PROCESS_COUNT processes.
+ Test:
+ Create Worker Thread
+ Start Reading and writing to a File
+
+ Create Worker Thread
+ In an infinite loop do the following
+ Enter Critical Section
+ Increment Counter
+ Leave Critical Section
+
+ Create Worker Thread
+ Allocate Memory and Free Memory
+
+ Create Worker Thread
+ In a tight loop add numbers
+
+ In a loop repeated REPEAT_COUNT times
+
+ Create Thread
+
+ Suspend all worker threads
+ Resume all worker threads
+
+ At the end of the loop call PAL_Shutdown
+
+ Parameters:
+ PROCESS_COUNT: Number of processes
+ WORKER_THREAD_MULTIPLIER_COUNT: Number of instances of worker threads in each process
+ REPEAT_COUNT: The number of times to execute the loop.
+
+ Statistics Captured:
+ Total elapsed time
+ MTBF
+
+
+ Scenario:
+**
+ One thread suspends all remaining threads which are in the middle of doing some work and resume all threads
+ Thread 1: Reading and Writing File
+ Thread 2: Enter and Leave Critical Section
+ Thread 3: Allocating chunks of memory
+ Thread 4: Perform Unsafe Operation (printf, malloc)
+ Thread 5: Suspends Thread 1 to Thread 4 and resumes them
+
+**
+**
+**
+** Dependencies:
+**
+**
+
+**
+**=========================================================*/
+
+#include <palsuite.h>
+#include "resultbuffer.h"
+
+#define BUFSIZE 4096
+#define NUMBER_OF_WORKER_THREAD_TYPES 4
+#define THREAD_MAX 64
+
+#define TEST_FAIL 1
+#define TEST_PASS 0
+
+
+DWORD GLOBAL_COUNTER ;
+DWORD UNIQUE_FILE_NUMBER=0;
+HANDLE g_hEvent;
+
+bool failFlag = false; //To Track failure at the Operation Level
+
+// 2 dimensional array to hold thread handles for each worker thread
+HANDLE hThread[NUMBER_OF_WORKER_THREAD_TYPES][THREAD_MAX];
+
+/*unsigned int g_readfileoperation;
+unsigned int g_enterleavecsoperation;
+unsigned int g_allocatefreeoperation;
+unsigned int g_doworintightloop;
+*/
+
+int TYPES_OF_WORKER_THREAD = NUMBER_OF_WORKER_THREAD_TYPES;
+
+int testStatus=TEST_PASS; //Indicates test failure
+
+
+struct statistics{
+ unsigned int processId;
+ unsigned int operationsFailed;
+ unsigned int operationsPassed;
+ unsigned int operationsTotal;
+ DWORD operationTime;
+ unsigned int relationId;
+};
+
+struct processStatistics{
+ unsigned int processId;
+ DWORD operationTime;
+ unsigned int relationId;
+};
+
+/* Results Buffer */
+ResultBuffer *resultBuffer;
+
+
+/* Test Input Variables */
+unsigned int USE_PROCESS_COUNT = 0; //Identifies the Process number. There could potentially
+unsigned int WORKER_THREAD_MULTIPLIER_COUNT = 0; //In this test case this represents the number of worker thread instances
+unsigned int REPEAT_COUNT = 0; //Number of Suspend Resume operation of worker threads
+unsigned int RELATION_ID = 0;
+
+
+
+CRITICAL_SECTION CriticalSectionM; /* Critical Section Object (used as mutex) */
+CRITICAL_SECTION g_csUniqueFileName;
+
+void PALAPI setup(void);
+void PALAPI cleanup(void);
+void PALAPI incrementCounter(void);
+DWORD PALAPI readfile( LPVOID);
+DWORD PALAPI enterandleave_cs( LPVOID);
+DWORD PALAPI allocateandfree_memory( LPVOID);
+DWORD PALAPI doworkintightloop_cs( LPVOID);
+DWORD PALAPI suspendandresumethreads( LPVOID);
+int GetParameters(int, char * *);
+
+
+//Main Entry for the Thread Suspension Test Case
+int __cdecl main (int argc, char **argv)
+{
+
+/*
+* Parameter to the threads that will be created
+*/
+
+
+DWORD dwThrdParam = 0;
+DWORD dwStart;
+
+/* Variables to capture the file name and the file pointer*/
+char fileName[MAX_PATH];
+char processFileName[MAX_PATH];
+
+FILE *hFile, *hProcessFile;
+struct statistics* buffer;
+struct processStatistics *processBuffer;
+
+struct processStatistics processStats;
+
+struct statistics* tmpBuf = NULL;
+int statisticsSize = 0;
+
+DWORD dwThreadId=0;
+HANDLE hMainThread;
+unsigned int i = 0;
+int j = 0;
+
+
+/*
+* PAL Initialize
+*/
+
+if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+
+//Get Parameters
+if(GetParameters(argc, argv))
+ {
+ Fail("Error in obtaining the parameters\n");
+ }
+
+
+//Setup for Process Result Collection
+statisticsSize = sizeof(struct statistics);
+_snprintf(processFileName, MAX_PATH, "%d_process_threadsuspension_%d_.txt", USE_PROCESS_COUNT, RELATION_ID);
+hProcessFile = fopen(processFileName, "w+");
+
+if(hProcessFile == NULL)
+ {
+ Fail("Error in opening file to write process results for process [%d]\n", USE_PROCESS_COUNT);
+ }
+
+//Initialize Process Stats Variables
+processStats.operationTime = 0;
+processStats.processId = USE_PROCESS_COUNT;
+processStats.relationId = RELATION_ID;
+
+//Start Process Time Capture
+dwStart = GetTickCount();
+
+//Setup for Thread Result Collection
+statisticsSize = sizeof(struct statistics);
+_snprintf(fileName, MAX_PATH, "%d_thread_threadsuspension_%d_.txt", USE_PROCESS_COUNT,RELATION_ID);
+hFile = fopen(fileName, "w+");
+
+if(hFile == NULL)
+ {
+ Fail("Error in opening file to write thread results for process [%d]\n", USE_PROCESS_COUNT);
+ }
+
+// For each thread we will log relationid (int), processid (int), operations failed (int), passed (int), total (int)
+// and number of ticks (DWORD) for the operations
+resultBuffer = new ResultBuffer( 1, statisticsSize);
+
+/*
+* Call the Setup Routine
+*/
+setup();
+
+Trace("WORKER_THREAD_MULTIPLIER_COUNT: %d \n", WORKER_THREAD_MULTIPLIER_COUNT);
+
+//Create WORKER_THREAD_MULTIPLIER_COUNT Instances of each type of worker thread
+for (i=0;i<WORKER_THREAD_MULTIPLIER_COUNT;i++)
+{
+
+ /*
+ * Create readfile thread
+ */
+ hThread[0][i] = CreateThread(
+ NULL,
+ 0,
+ readfile,
+ NULL,
+ 0,
+ &dwThreadId);
+
+ if ( NULL == hThread[0][i] )
+ {
+ Fail ( "CreateThread() returned NULL. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+
+
+ /*
+ * Create Enter and Leave Critical Section Thread
+ */
+ hThread[1][i] = CreateThread(
+ NULL,
+ 0,
+ enterandleave_cs,
+ NULL,
+ 0,
+ &dwThreadId);
+
+ if ( NULL == hThread[1][i] )
+ {
+ Fail ( "CreateThread() returned NULL. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+
+
+ /*
+ * Create Allocate and Free Memory Thread
+ */
+ hThread[2][i] = CreateThread(
+ NULL,
+ 0,
+ allocateandfree_memory,
+ NULL,
+ 0,
+ &dwThreadId);
+
+ if ( NULL == hThread[2][i])
+ {
+ Fail ( "CreateThread() returned NULL. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+
+
+ /*
+ * Create Work in tight Loop thread
+ */
+ hThread[3][i] = CreateThread(
+ NULL,
+ 0,
+ doworkintightloop_cs,
+ NULL,
+ 0,
+ &dwThreadId);
+
+ if ( NULL == hThread[3][i])
+ {
+ Fail ( "CreateThread() returned NULL. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+
+
+}
+
+
+
+
+
+/*
+ * Create Main test case thread that Suspends and Resumes Threads
+ */
+ hMainThread = CreateThread(
+ NULL,
+ 0,
+ suspendandresumethreads,
+ (LPVOID)dwThrdParam,
+ 0,
+ &dwThreadId);
+
+ if ( NULL == hMainThread )
+ {
+ Fail ( "CreateThread() returned NULL. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+
+
+
+/*
+* Set Event to allow all threads to start
+*/
+
+if (0==SetEvent(g_hEvent))
+{
+ Fail ( "SetEvent returned Zero. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+}
+
+/*
+ * Wait for main thread to complete
+ *
+ */
+ if (WAIT_OBJECT_0 != WaitForSingleObject (hMainThread, INFINITE))
+ {
+ Fail ("Main: Wait for Single Object (mainThread) failed. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+//Get the end time of the process
+processStats.operationTime = GetTickCount() - dwStart;
+
+//Write Process Result Contents to File
+if(hProcessFile!= NULL)
+ {
+ fprintf(hProcessFile, "%d,%lu,%d\n", processStats.processId, processStats.operationTime, processStats.relationId );
+ }
+
+if (0!=fclose(hProcessFile))
+{
+ Fail("Unable to write process results to file"
+ "GetLastError returned %d\n", GetLastError());
+}
+
+
+//Write to log file
+//Trace("# of Read File Operations %d\n", g_readfileoperation);
+//Trace("# of Enter and Leace CS Operations %d\n", g_enterleavecsoperation);
+//Trace("# of Do Work In Tight Loop Operations %d\n", g_doworintightloop);
+//Trace("# of Allocate and Free Operations %d\n", g_allocatefreeoperation);
+
+
+//Write Thread Result Contents to File
+if(hFile!= NULL)
+ {
+ for( i = 0; i < 1; i++ )
+ {
+ buffer = (struct statistics *)resultBuffer->getResultBuffer(i);
+ fprintf(hFile, "%d,%d,%d,%d,%lu,%d\n", buffer->processId, buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime, buffer->relationId );
+ }
+ }
+
+if (0!=fclose(hFile))
+{
+ Fail("Unable to write thread results to file"
+ "GetLastError returned %d\n", GetLastError());
+}
+
+cleanup();
+
+if (failFlag == TRUE)
+{
+ return FAIL;
+}
+else
+{
+ return PASS;
+}
+}
+
+
+/*
+* Setup for the test case
+*/
+
+VOID
+setup(VOID)
+{
+ /*Delete All Temporary Files Created by the previous execution of the test case*/
+ HANDLE hSearch;
+ BOOL fFinished = FALSE;
+ WIN32_FIND_DATA FileData;
+
+ //Start searching for .tmp files in the current directory.
+ hSearch = FindFirstFile("*.tmp*", &FileData);
+ if (hSearch == INVALID_HANDLE_VALUE)
+ {
+ //No Files That Matched Criteria
+ fFinished = TRUE;
+ }
+
+ //Delete all files that match the pattern
+ while (!fFinished)
+ {
+ if (!DeleteFile(FileData.cFileName))
+ {
+ Trace("Setup: Could not delete temporary file %s\n",FileData.cFileName );
+ Fail ("GetLastError returned %d\n", GetLastError());
+ }
+ if (!FindNextFile(hSearch, &FileData))
+ {
+ if (GetLastError() == ERROR_NO_MORE_FILES)
+ {
+ fFinished = TRUE;
+ }
+ else
+ {
+ Fail("Unable to Delete Temporary Files, GetLastError is %d \n", GetLastError());
+ }
+ }
+ }
+
+ // Close the search handle, only if HANDLE is Valid
+ if (hSearch != INVALID_HANDLE_VALUE)
+ {
+ if (!FindClose(hSearch))
+ {
+ Trace("Setup: Could not close search handle \n");
+ Fail ("GetLastError returned %d\n", GetLastError());
+ }
+ }
+
+ g_hEvent = CreateEvent(NULL,TRUE,FALSE, NULL);
+ if(g_hEvent == NULL)
+ {
+ Fail("Create Event Failed\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+ InitializeCriticalSection ( &g_csUniqueFileName);
+}
+
+/*
+* Cleanup for the test case
+*/
+
+VOID
+cleanup(VOID)
+{
+ //DeleteCriticalSection(&g_csUniqueFileName);
+ PAL_Terminate();
+}
+
+
+VOID
+incrementCounter(VOID)
+{
+
+ if (INT_MAX == GLOBAL_COUNTER)
+ {
+ GLOBAL_COUNTER = 0;
+ }
+
+ GLOBAL_COUNTER++;
+}
+
+/*
+ * Worker Thread
+ * Read File: Read from a file and write to a temporary file and then delete the temp file
+ */
+DWORD
+PALAPI
+readfile( LPVOID lpParam )
+{
+
+ // Declaring Local Variables
+ HANDLE hFile,hTempfile;
+ char buffer[BUFSIZE];
+ DWORD dwBytesRead, dwBytesWritten, dwBufSize=BUFSIZE;
+ DWORD dwWaitResult=0;
+ char filename[MAX_PATH];
+
+ //Wait for event to signal to start test
+ dwWaitResult = WaitForSingleObject(g_hEvent,INFINITE);
+ if (WAIT_OBJECT_0 != dwWaitResult)
+ {
+ Fail ("readfile: Wait for Single Object (g_hEvent) failed. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+
+ /*Start Operation*/
+
+ // Open the existing file.
+ while(TRUE)
+ {
+
+ hFile = CreateFile("samplefile.dat", // file name
+ GENERIC_READ, // open for reading
+ FILE_SHARE_READ, // Share the file for read
+ NULL, // default security
+ OPEN_EXISTING, // existing file only
+ FILE_ATTRIBUTE_NORMAL, // normal file
+ NULL); // no template
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Trace("Could not open file \n");
+ Fail ( "GetLastError returned %d\n", GetLastError());
+ }
+
+ //Generate Unique File Name to Write
+ //Enter CS
+ EnterCriticalSection(&g_csUniqueFileName);
+
+ //Increment Number and assign to local variable
+ UNIQUE_FILE_NUMBER++;
+ _snprintf(filename, MAX_PATH, "%d_%d_tempfile.tmp", USE_PROCESS_COUNT,UNIQUE_FILE_NUMBER);
+ //filename = itoa(UNIQUE_FILE_NUMBER);
+ //Leave CS
+ LeaveCriticalSection(&g_csUniqueFileName);
+
+
+ // Create a temporary file with name generate above
+ hTempfile = CreateFile(filename, // file name
+ GENERIC_WRITE, // open for read/write
+ 0, // do not share
+ NULL, // default security
+ CREATE_ALWAYS, // overwrite existing file
+ FILE_ATTRIBUTE_NORMAL, // normal file
+ NULL); // no template
+
+
+ if (hTempfile == INVALID_HANDLE_VALUE)
+ {
+ Trace("Could not create temporary file\n");
+ Fail ( "GetLastError returned %d\n", GetLastError());
+ }
+
+ // Read 4K blocks to the buffer.
+ // Change all characters in the buffer to upper case.
+ // Write the buffer to the temporary file.
+
+ do
+ {
+ if (ReadFile(hFile, buffer, 4096,
+ &dwBytesRead, NULL))
+ {
+
+ WriteFile(hTempfile, buffer, dwBytesRead,
+ &dwBytesWritten, NULL);
+ }
+ } while (dwBytesRead == BUFSIZE);
+
+
+
+ // Close both files.
+ if (0==CloseHandle(hFile))
+ {
+ Trace("Could not handle hFile\n");
+ Fail ( "GetLastError returned %d\n", GetLastError());
+ }
+
+ if (0==CloseHandle(hTempfile))
+ {
+ Trace("Could not handle hTempFile\n");
+ Fail ( "GetLastError returned %d\n", GetLastError());
+ }
+
+ //Delete the file that was created
+ if (!DeleteFile(filename))
+ {
+ Trace("Could not delete temporary file %s\n", filename);
+ Fail ( "GetLastError returned %d\n", GetLastError());
+
+ }
+
+ SwitchToThread();
+ //g_readfileoperation++;
+ }
+
+/*End Operation*/
+
+ return 0;
+}
+
+
+/* Worker Thread
+ * Enter and Leave Nested Critical Sections
+ */
+DWORD
+PALAPI
+enterandleave_cs( LPVOID lpParam )
+{
+
+ //Declare Local Variables
+
+ CRITICAL_SECTION lcs;
+ CRITICAL_SECTION lcsNested;
+
+ DWORD dwWaitResult;
+
+ //Intialize Critical Section Structures
+ InitializeCriticalSection ( &lcs);
+ InitializeCriticalSection ( &lcsNested);
+
+
+ //Wait for event to signal to start test
+ dwWaitResult = WaitForSingleObject(g_hEvent,INFINITE);
+ if (WAIT_OBJECT_0 != dwWaitResult)
+ {
+ Fail ("enterandleave_cs: Wait for Single Object (g_hEvent) failed. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+ //Trace("Critical Section Started\n");
+
+ while(TRUE)
+ {
+ EnterCriticalSection(&lcs);
+
+ EnterCriticalSection(&lcsNested);
+
+ incrementCounter();
+
+ LeaveCriticalSection(&lcsNested);
+
+ LeaveCriticalSection(&lcs);
+
+ SwitchToThread();
+ //g_enterleavecsoperation++;
+ }
+
+ //Delete Critical Section Structures
+
+ DeleteCriticalSection(&lcs);
+ DeleteCriticalSection(&lcsNested);
+
+
+ return 0;
+}
+
+
+/*
+ * Allocate and Free Memory
+ */
+DWORD
+PALAPI
+allocateandfree_memory( LPVOID lpParam )
+{
+
+
+ int i;
+ char *textArrPtr[64];
+ DWORD dwWaitResult;
+
+ //Wait for event to signal to start test
+ dwWaitResult = WaitForSingleObject(g_hEvent,INFINITE);
+ if (WAIT_OBJECT_0 != dwWaitResult)
+ {
+ Fail ("allocateandfree_memory: Wait for Single Object (g_hEvent) failed. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+
+ while(TRUE)
+ {
+
+ //do allocate and free operation
+
+ for (i=0;i<64;i++)
+ {
+ textArrPtr[i] = (char*) malloc(BUFSIZE);
+ if (textArrPtr[i] == NULL)
+ {
+ Fail("Insufficient Memory Available, GetLastError is %d \n", GetLastError());
+ testStatus = TEST_FAIL;
+ }
+ }
+
+ for (i=0;i<64;i++)
+ {
+ free(textArrPtr[i]);
+ }
+
+ SwitchToThread();
+ //g_allocatefreeoperation++;
+ }
+
+
+
+
+ return 0;
+}
+
+/*
+ * Do work in a tight loop
+ */
+DWORD
+PALAPI
+doworkintightloop_cs( LPVOID lpParam )
+{
+
+ unsigned int i;
+ DWORD dwWaitResult;
+
+ //Wait for event to signal to start test
+ dwWaitResult = WaitForSingleObject(g_hEvent,INFINITE);
+ if (WAIT_OBJECT_0 != dwWaitResult)
+ {
+ Fail ("doworkintightloop_cs: Wait for Single Object (g_hEvent) failed. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+ i= 0;
+ while (TRUE)
+ {
+
+ if (INT_MAX == i)
+ i =0;
+ i++;
+ //g_doworintightloop++;
+
+ SwitchToThread();
+ }
+
+ return 0;
+}
+
+
+/*
+ * Main Test Case worker thread which will suspend and resume all other worker threads
+ */
+DWORD
+PALAPI
+suspendandresumethreads( LPVOID lpParam )
+{
+
+ unsigned int loopcount = REPEAT_COUNT;
+ int Id=(int)lpParam;
+ unsigned int i,j,k;
+ DWORD dwStart;
+ DWORD dwWaitResult=0;
+ DWORD dwLastError = 0;
+ struct statistics stats;
+ struct statistics* buffer;
+
+
+
+ //Initialize the Statistics Structure
+ stats.relationId = RELATION_ID;
+ stats.processId = USE_PROCESS_COUNT;
+ stats.operationsFailed = 0;
+ stats.operationsPassed = 0;
+ stats.operationsTotal = 0;
+ stats.operationTime = 0;
+
+
+
+ //Wait for event to signal to start test
+ WaitForSingleObject(g_hEvent,INFINITE);
+ if (WAIT_OBJECT_0 != dwWaitResult)
+ {
+ Fail ("suspendandresumethreads: Wait for Single Object (g_hEvent) failed. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+
+ //Capture Start Import
+ dwStart = GetTickCount();
+
+ for(i = 0; i < loopcount; i++)
+ {
+
+ failFlag = false;
+
+ //Suspend Worker Threads
+ for (k=0;k<WORKER_THREAD_MULTIPLIER_COUNT;k++)
+ {
+ for (j=0;j<4;j++)
+ {
+ if (-1 == SuspendThread(hThread[j][k]))
+ {
+ //If the operation indicate failure
+ failFlag = true;
+ }
+ }
+ }
+
+
+ //Resume Worker Threads
+ for (k=0;k<WORKER_THREAD_MULTIPLIER_COUNT;k++)
+ {
+ for (j=0;j<4;j++)
+ {
+
+ //Only suspend if not already in suspended state
+
+ if (-1 == ResumeThread(hThread[j][k]))
+ {
+ //If the operation indicate failure
+ failFlag = true;
+ }
+
+ }
+ }
+
+
+ //Check for Fail Flag. If set increment number of failures
+ // If Fail flag not set then increment number of operations and number of passe
+ if (failFlag == true)
+ {
+ stats.operationsFailed++;
+ }
+ else
+ {
+ stats.operationsPassed +=1;
+
+ }
+ stats.operationsTotal +=1;
+
+ }
+
+ stats.operationTime = GetTickCount() - dwStart;
+
+ /*Trace("\n\n\n\nOperation Time: %d milliseconds\n", stats.operationTime);
+ Trace("Operation Passed: %d\n", stats.operationsPassed);
+ Trace("Operation Total: %d\n", stats.operationsTotal);
+ Trace("Operation Failed: %d\n", stats.operationsFailed);
+ */
+ if(resultBuffer->LogResult(Id, (char *)&stats))
+ {
+ Fail("Error while writing to shared memory, Thread Id is[%d] and Process id is [%d]\n", Id, USE_PROCESS_COUNT);
+ }
+
+ buffer = (struct statistics *)resultBuffer->getResultBuffer(Id);
+ //Trace("\n%d,%d,%d,%lu\n", buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime );
+
+
+ return 0;
+}
+
+
+
+int GetParameters( int argc, char **argv)
+{
+
+ if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?"))
+ || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H"))
+ {
+ Trace("PAL -Composite Thread Suspension Test\n");
+ Trace("Usage:\n");
+ Trace("\t[PROCESS_COUNT] Greater than or Equal to 1 \n");
+ Trace("\t[WORKER_THREAD_MULTIPLIER_COUNT] Greater than or Equal to 1 and Less than or Equal to 64 \n");
+ Trace("\t[REPEAT_COUNT] Greater than or Equal to 1\n");
+ Trace("\t[RELATION_ID [greater than or Equal to 1]\n");
+ return -1;
+ }
+
+// Trace("Args 1 is [%s], Arg 2 is [%s], Arg 3 is [%s]\n", argv[1], argv[2], argv[3]);
+
+ USE_PROCESS_COUNT = atoi(argv[1]);
+ if( USE_PROCESS_COUNT < 0)
+ {
+ Trace("\nPROCESS_COUNT to greater than or equal to 1\n");
+ return -1;
+ }
+
+ WORKER_THREAD_MULTIPLIER_COUNT = atoi(argv[2]);
+ if( WORKER_THREAD_MULTIPLIER_COUNT < 1 || WORKER_THREAD_MULTIPLIER_COUNT > 64)
+ {
+ Trace("\nWORKER_THREAD_MULTIPLIER_COUNT to be greater than or equal to 1 or less than or equal to 64\n");
+ return -1;
+ }
+
+ REPEAT_COUNT = atoi(argv[3]);
+ if( REPEAT_COUNT < 1)
+ {
+ Trace("\nREPEAT_COUNT to greater than or equal to 1\n");
+ return -1;
+ }
+
+ RELATION_ID = atoi(argv[4]);
+ if( RELATION_ID < 1)
+ {
+ Trace("\nRELATION_ID to be greater than or equal to 1\n");
+ return -1;
+ }
+ return 0;
+}
diff --git a/src/pal/tests/palsuite/composite/wfmo/CMakeLists.txt b/src/pal/tests/palsuite/composite/wfmo/CMakeLists.txt
new file mode 100644
index 0000000000..7dbddbc989
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/wfmo/CMakeLists.txt
@@ -0,0 +1,21 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ main.c
+ mutex.c
+)
+
+add_executable(paltest_composite_wfmo
+ ${SOURCES}
+)
+
+add_dependencies(paltest_composite_wfmo coreclrpal)
+
+target_link_libraries(paltest_composite_wfmo
+ pthread
+ rt
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/composite/wfmo/main.c b/src/pal/tests/palsuite/composite/wfmo/main.c
new file mode 100644
index 0000000000..d186aa7b8b
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/wfmo/main.c
@@ -0,0 +1,239 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+** Source Code: main.c and mutex.c
+** main.c creates process and waits for all processes to get over
+** mutex.c creates a mutex and then calls threads which will contend for the mutex
+**
+** This test is for WFMO Test case for Mutex
+** Algorithm
+** o Create PROCESS_COUNT processes.
+** o Main Thread of each process creates OBJECT_TYPE Object
+**
+** Author: ShamitP
+**
+**
+**============================================================
+*/
+
+#include <palsuite.h>
+#include "resulttime.h"
+
+/* Test Input Variables */
+unsigned int PROCESS_COUNT = 3;
+unsigned int THREAD_COUNT = 30;
+unsigned int REPEAT_COUNT = 40;
+unsigned int SLEEP_LENGTH = 4;
+unsigned int RELATION_ID = 1001;
+
+
+
+struct TestStats{
+ DWORD operationTime;
+ unsigned int relationId;
+ unsigned int processCount;
+ unsigned int threadCount;
+ unsigned int repeatCount;
+ char* buildNumber;
+
+};
+
+int GetParameters( int argc, char **argv)
+{
+ if( (argc != 6) || ((argc == 1) && !strcmp(argv[1],"/?"))
+ || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H"))
+ {
+ printf("PAL -Composite WFMO Test\n");
+ printf("Usage:\n");
+ printf("main\n\t[PROCESS_COUNT [greater than 0] \n");
+ printf("\t[THREAD_COUNT [greater than 0] \n");
+ printf("\t[REPEAT_COUNT [greater than 0]\n");
+ printf("\t[SLEEP_LENGTH [greater than 0]\n");
+ printf("\t[RELATION_ID [greater than 0]\n");
+
+
+
+ return -1;
+ }
+
+ PROCESS_COUNT = atoi(argv[1]);
+ if( (PROCESS_COUNT < 1) || (PROCESS_COUNT > MAXIMUM_WAIT_OBJECTS) )
+ {
+ printf("\nMain Process:Invalid PROCESS_COUNT number, Pass greater than 1 and less than PROCESS_COUNT %d\n", MAXIMUM_WAIT_OBJECTS);
+ return -1;
+ }
+
+ THREAD_COUNT = atoi(argv[2]);
+ if( (THREAD_COUNT < 1) || (THREAD_COUNT > MAXIMUM_WAIT_OBJECTS) )
+ {
+ printf("\nInvalid THREAD_COUNT number, Pass greater than 1 and less than %d\n", MAXIMUM_WAIT_OBJECTS);
+ return -1;
+ }
+
+ REPEAT_COUNT = atoi(argv[3]);
+ if( REPEAT_COUNT < 1)
+ {
+ printf("\nMain Process:Invalid REPEAT_COUNT number, Pass greater than 1\n");
+ return -1;
+ }
+
+ SLEEP_LENGTH = atoi(argv[4]);
+ if( SLEEP_LENGTH < 1)
+ {
+ printf("\nMain Process:Invalid SLEEP_LENGTH number, Pass greater than 1\n");
+ return -1;
+ }
+
+ RELATION_ID = atoi(argv[5]);
+ if( RELATION_ID < 1)
+ {
+ printf("\nMain Process:Invalid RELATION_ID number, Pass greater than 1\n");
+ return -1;
+ }
+
+
+
+ return 0;
+}
+
+ int __cdecl main(INT argc, CHAR **argv)
+{
+ unsigned int i = 0;
+ HANDLE hProcess[MAXIMUM_WAIT_OBJECTS];
+
+ STARTUPINFO si[MAXIMUM_WAIT_OBJECTS];
+ PROCESS_INFORMATION pi[MAXIMUM_WAIT_OBJECTS];
+
+ char lpCommandLine[MAX_PATH] = "";
+
+ int returnCode = 0;
+ DWORD processReturnCode = 0;
+ int testReturnCode = PASS;
+
+ char fileName[MAX_PATH];
+ FILE *pFile = NULL;
+ DWORD dwStartTime;
+ struct TestStats testStats;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ if(GetParameters(argc, argv))
+ {
+ Fail("Error in obtaining the parameters\n");
+ }
+
+ /* Register the start time */
+ dwStartTime = GetTickCount();
+ testStats.relationId = 0;
+ testStats.relationId = RELATION_ID;
+ testStats.processCount = PROCESS_COUNT;
+ testStats.threadCount = THREAD_COUNT;
+ testStats.repeatCount = REPEAT_COUNT;
+ testStats.buildNumber = getBuildNumber();
+
+
+
+ _snprintf(fileName, MAX_PATH, "main_wfmo_%d_.txt",testStats.relationId);
+ pFile = fopen(fileName, "w+");
+ if(pFile == NULL)
+ {
+ Fail("Error in opening main file for write\n");
+ }
+
+ for( i = 0; i < PROCESS_COUNT; i++ )
+ {
+
+ ZeroMemory( lpCommandLine, MAX_PATH );
+ if ( _snprintf( lpCommandLine, MAX_PATH-1, "mutex %d %d %d %d %d", i, THREAD_COUNT, REPEAT_COUNT, SLEEP_LENGTH, RELATION_ID) < 0 )
+ {
+ Trace ("Error: Insufficient commandline string length for for iteration [%d]\n", i);
+ }
+
+ /* Zero the data structure space */
+ ZeroMemory ( &pi[i], sizeof(pi[i]) );
+ ZeroMemory ( &si[i], sizeof(si[i]) );
+
+ /* Set the process flags and standard io handles */
+ si[i].cb = sizeof(si[i]);
+
+ //Create Process
+ if(!CreateProcess( NULL, /* lpApplicationName*/
+ lpCommandLine, /* lpCommandLine */
+ NULL, /* lpProcessAttributes */
+ NULL, /* lpThreadAttributes */
+ TRUE, /* bInheritHandles */
+ 0, /* dwCreationFlags, */
+ NULL, /* lpEnvironment */
+ NULL, /* pCurrentDirectory */
+ &si[i], /* lpStartupInfo */
+ &pi[i] /* lpProcessInformation */
+ ))
+ {
+ Fail("Process Not created for [%d], the error code is [%d]\n", i, GetLastError());
+ }
+ else
+ {
+ hProcess[i] = pi[i].hProcess;
+ // Trace("Process created for [%d]\n", i);
+ }
+
+ }
+
+ returnCode = WaitForMultipleObjects( PROCESS_COUNT, hProcess, TRUE, INFINITE);
+ if( WAIT_OBJECT_0 != returnCode )
+ {
+ Trace("Wait for Object(s) @ Main thread for %d processes returned %d, and GetLastError value is %d\n", PROCESS_COUNT, returnCode, GetLastError());
+ }
+
+ for( i = 0; i < PROCESS_COUNT; i++ )
+ {
+ /* check the exit code from the process */
+ if( ! GetExitCodeProcess( pi[i].hProcess, &processReturnCode ) )
+ {
+ Trace( "GetExitCodeProcess call failed for iteration %d with error code %u\n",
+ i, GetLastError() );
+
+ testReturnCode = FAIL;
+ }
+
+ if(processReturnCode == FAIL)
+ {
+ Trace( "Process [%d] failed and returned FAIL\n", i);
+ testReturnCode = FAIL;
+ }
+
+ if(!CloseHandle(pi[i].hThread))
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hThread\n", GetLastError(), i);
+ }
+
+ if(!CloseHandle(pi[i].hProcess) )
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hProcess\n", GetLastError(), i);
+ }
+ }
+
+ testStats.operationTime = GetTimeDiff(dwStartTime);
+ fprintf(pFile, "%d,%d,%d,%d,%d,%s\n", testStats.operationTime, testStats.relationId, testStats.processCount, testStats.threadCount, testStats.repeatCount, testStats.buildNumber);
+ if(fclose(pFile))
+ {
+ Trace("Error: fclose failed for pFile\n");
+ testReturnCode = FAIL;
+ }
+
+ if( testReturnCode == PASS)
+ {
+ Trace("Test Passed\n");
+ }
+ else
+ {
+ Trace("Test Failed\n");
+ }
+ PAL_Terminate();
+ return testReturnCode;
+}
diff --git a/src/pal/tests/palsuite/composite/wfmo/mutex.c b/src/pal/tests/palsuite/composite/wfmo/mutex.c
new file mode 100644
index 0000000000..c8ed01426c
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/wfmo/mutex.c
@@ -0,0 +1,365 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**Source Code: main.c and mutex.c
+** main.c creates process and waits for all processes to get over
+** mutex.c creates a mutex and then calls threads which will
+** contend for the mutex
+**
+** This test is for WFMO Test case for Mutex
+** Algorithm
+** o Create PROCESS_COUNT processes.
+** o Main Thread of each process creates OBJECT_TYPE Object
+**
+** Author: ShamitP
+**
+**
+**============================================================
+*/
+
+#include <palsuite.h>
+#include "resultbuffer.h"
+#include "resulttime.h"
+
+/* Test Input Variables */
+unsigned int USE_PROCESS_COUNT = 0;
+unsigned int THREAD_COUNT = 0;
+unsigned int REPEAT_COUNT = 0;
+unsigned int SLEEP_LENGTH = 0;
+unsigned int RELATION_ID = 1001;
+
+
+/* Capture statistics at per thread basis */
+struct statistics{
+ unsigned int processId;
+ unsigned int operationsFailed;
+ unsigned int operationsPassed;
+ unsigned int operationsTotal;
+ DWORD operationTime;
+ unsigned int relationId;
+
+};
+
+struct ProcessStats{
+ unsigned int processId;
+ DWORD operationTime;
+ unsigned int relationId;
+};
+
+/* Handle to signal threads to start the tests */
+HANDLE StartTestsEvHandle = NULL;
+/* Handle to mutex which will be contended by threads */
+HANDLE hMutexHandle = NULL;
+/* Results Buffer */
+ResultBuffer *resultBuffer = NULL;
+
+int testStatus;
+
+void PALAPI Run_Thread(LPVOID lpParam);
+
+int GetParameters( int argc, char **argv)
+{
+ if( (argc != 6) || ((argc == 1) && !strcmp(argv[1],"/?"))
+ || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H"))
+ {
+ printf("PAL -Composite WFMO Test\n");
+ printf("Usage:\n");
+ printf("mutex\n\t[USE_PROCESS_COUNT [greater than 0] \n");
+ printf("\t[THREAD_COUNT [greater than 0] \n");
+ printf("\t[REPEAT_COUNT [greater than 0]\n");
+ printf("\t[SLEEP_LENGTH [greater than 0]\n");
+ printf("\t[RELATION_ID [greater than 0]\n");
+
+
+ return -1;
+ }
+
+ // Trace("Args 1 is [%s], Arg 2 is [%s], Arg 3 is [%s]\n", argv[1], argv[2], argv[3]);
+
+ USE_PROCESS_COUNT = atoi(argv[1]);
+ if( USE_PROCESS_COUNT < 0)
+ {
+ printf("\nInvalid USE_PROCESS_COUNT number, Pass greater than 1\n");
+ return -1;
+ }
+
+ THREAD_COUNT = atoi(argv[2]);
+ if( (THREAD_COUNT < 1) || (THREAD_COUNT > MAXIMUM_WAIT_OBJECTS) )
+ {
+ printf("\nInvalid THREAD_COUNT number, Pass greater than 1 and less than %d\n", MAXIMUM_WAIT_OBJECTS);
+ return -1;
+ }
+
+ REPEAT_COUNT = atoi(argv[3]);
+ if( REPEAT_COUNT < 1)
+ {
+ printf("\nInvalid REPEAT_COUNT number, Pass greater than 1\n");
+ return -1;
+ }
+
+ SLEEP_LENGTH = atoi(argv[4]);
+ if( SLEEP_LENGTH < 1)
+ {
+ printf("\nMain Process:Invalid SLEEP_LENGTH number, Pass greater than 1\n");
+ return -1;
+ }
+
+ RELATION_ID = atoi(argv[5]);
+ if( RELATION_ID < 1)
+ {
+ printf("\nMain Process:Invalid RELATION_ID number, Pass greater than 1\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+ int __cdecl main(INT argc, CHAR **argv)
+{
+ unsigned int i = 0;
+ HANDLE hThread[MAXIMUM_WAIT_OBJECTS];
+ DWORD threadId[MAXIMUM_WAIT_OBJECTS];
+ int returnCode = 0;
+
+ DWORD dwParam = 0;
+
+ /* Variables to capture the file name and the file pointer at thread level*/
+ char fileName[MAX_PATH];
+ FILE *pFile = NULL;
+ struct statistics* buffer = NULL;
+ int statisticsSize = 0;
+
+ /* Variables to capture the file name and the file pointer at process level*/
+ char processFileName[MAX_PATH];
+ FILE *pProcessFile = NULL;
+ struct ProcessStats processStats;
+ DWORD dwStartTime;
+
+ testStatus = PASS;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ if(GetParameters(argc, argv))
+ {
+ Fail("Error in obtaining the parameters\n");
+ }
+// Trace("Process created, value of process count is [%d] and no. of threads is [%d]\n", USE_PROCESS_COUNT, THREAD_COUNT);
+
+ /* Register the start time */
+ dwStartTime = GetTickCount();
+ processStats.relationId = RELATION_ID;
+ processStats.processId = USE_PROCESS_COUNT;
+
+ _snprintf(processFileName, MAX_PATH, "%d_process_wfmo_%d_.txt", USE_PROCESS_COUNT, RELATION_ID);
+ pProcessFile = fopen(processFileName, "w+");
+ if(pProcessFile == NULL)
+ {
+ Fail("Error:%d: in opening Process File for write for process [%d]\n", GetLastError(), USE_PROCESS_COUNT);
+ }
+
+ statisticsSize = sizeof(struct statistics);
+
+ _snprintf(fileName, MAX_PATH, "%d_thread_wfmo_%d_.txt", USE_PROCESS_COUNT, RELATION_ID);
+ pFile = fopen(fileName, "w+");
+ if(pFile == NULL)
+ {
+ Fail("Error in opening file for write for process [%d], error [%d]\n", USE_PROCESS_COUNT, GetLastError());
+ }
+ // For each thread we will log operations failed (int), passed (int), total (int)
+ // and number of ticks (DWORD) for the operations
+ resultBuffer = new ResultBuffer( THREAD_COUNT, statisticsSize);
+
+ StartTestsEvHandle = CreateEvent( NULL, /* lpEventAttributes*/
+ TRUE, /* bManualReset */
+ FALSE, /* bInitialState */
+ NULL); /* name of Event */
+
+ if( StartTestsEvHandle == NULL )
+ {
+ Fail("Error:%d: Unexpected failure "
+ "to create start tests Event for process count %d\n", GetLastError(), USE_PROCESS_COUNT );
+
+ }
+
+ /* Create StartTest Event */
+ hMutexHandle = CreateMutex(
+ NULL,
+ FALSE, /* bInitialOwner, owns initially */
+ NULL
+ );
+
+ if( hMutexHandle == NULL)
+ {
+ Fail("Unable to create Mutex handle for process id [%d], returned error [%d]\n", i, GetLastError());
+ }
+
+ /* We already assume that the mutex was created previously*/
+ for( i = 0; i < THREAD_COUNT; i++ )
+ {
+ dwParam = (int) i;
+ //Create thread
+ hThread[i] = CreateThread(
+ NULL, /* no security attributes */
+ 0, /* use default stack size */
+ (LPTHREAD_START_ROUTINE)Run_Thread,/* thread function */
+ (LPVOID)dwParam, /* argument to thread function */
+ 0, /* use default creation flags */
+ &threadId[i] /* returns the thread identifier*/
+ );
+
+ if(hThread[i] == NULL)
+ {
+ Fail("Create Thread failed for %d process, and GetLastError value is %d\n", USE_PROCESS_COUNT, GetLastError());
+ }
+
+ }
+
+ if (!SetEvent(StartTestsEvHandle))
+ {
+ Fail("Set Event for Start Tests failed for %d process, and GetLastError value is %d\n", USE_PROCESS_COUNT, GetLastError());
+ }
+ /* Test running */
+
+ if( THREAD_COUNT != 1 )
+ {
+ returnCode = WaitForMultipleObjects(THREAD_COUNT, hThread, TRUE, INFINITE);
+ }
+ else
+ {
+ returnCode = WaitForSingleObject(hThread[0], INFINITE);
+ }
+
+ if( WAIT_OBJECT_0 != returnCode )
+ {
+ Trace("Wait for Object(s) for %d process returned %d, and GetLastError value is %d\n", USE_PROCESS_COUNT, returnCode, GetLastError());
+ testStatus = FAIL;
+ }
+
+ processStats.operationTime = GetTimeDiff(dwStartTime);
+
+ /* Write to a file*/
+ if(pFile!= NULL)
+ {
+ for( i = 0; i < THREAD_COUNT; i++ )
+ {
+ buffer = (struct statistics *)resultBuffer->getResultBuffer(i);
+ returnCode = fprintf(pFile, "%d,%d,%d,%d,%lu,%d\n", buffer->processId, buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime, buffer->relationId );
+ //Trace("Iteration %d over\n", i);
+
+ }
+ }
+ if(fclose(pFile))
+ {
+ Trace("Error: fclose failed for pFile at Process %d\n", USE_PROCESS_COUNT);
+ testStatus = FAIL;
+ }
+
+ fprintf(pProcessFile, "%d,%d,%d\n", USE_PROCESS_COUNT, processStats.operationTime, processStats.relationId );
+ if(fclose(pProcessFile))
+ {
+ Trace("Error: fclose failed for pProcessFile at Process %d\n", USE_PROCESS_COUNT);
+ testStatus = FAIL;
+ }
+
+ /* Logging for the test case over, clean up the handles */
+ // Trace("Test Process %d done\n", USE_PROCESS_COUNT);
+ //Trace("Contents of the buffer are [%s]\n", resultBuffer->getResultBuffer());
+ for( i = 0; i < THREAD_COUNT; i++ )
+ {
+ if(!CloseHandle(hThread[i]) )
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] hThread[%d]\n", GetLastError(), USE_PROCESS_COUNT, i);
+ testStatus = FAIL;
+ }
+ }
+
+ if(!CloseHandle(StartTestsEvHandle))
+ {
+ Trace("Error:%d: CloseHandle failed for Process [%d] StartTestsEvHandle\n", GetLastError(), USE_PROCESS_COUNT);
+ testStatus = FAIL;
+ }
+
+ PAL_Terminate();
+ return testStatus;
+}
+
+void PALAPI Run_Thread (LPVOID lpParam)
+{
+ unsigned int i = 0;
+ struct statistics stats;
+
+ DWORD dwWaitResult;
+ DWORD dwStartTime;
+
+ stats.relationId = RELATION_ID;
+ stats.processId = USE_PROCESS_COUNT;
+ stats.operationsFailed = 0;
+ stats.operationsPassed = 0;
+ stats.operationsTotal = 0;
+ stats.operationTime = 0;
+
+ int Id=(int)lpParam;
+
+ dwWaitResult = WaitForSingleObject(
+ StartTestsEvHandle, // handle to mutex
+ INFINITE);
+
+ if(dwWaitResult != WAIT_OBJECT_0)
+ {
+ Trace("Error:%d: while waiting for StartTest Event@ thread %d\n", GetLastError(), Id);
+ testStatus = FAIL;
+ }
+
+ /* Register the start time */
+ dwStartTime = GetTickCount();
+
+ /* Run the tests repeat count times */
+ for( i = 0; i < REPEAT_COUNT; i++ )
+ {
+ dwWaitResult = WaitForSingleObject(
+ hMutexHandle, // handle to mutex
+ INFINITE);
+
+ if(dwWaitResult != WAIT_OBJECT_0)
+ {
+ Trace("Error:%d: while waiting for onject @ thread %d, # iter %d\n", GetLastError(), Id, i);
+ stats.operationsFailed += 1;
+ stats.operationsTotal += 1;
+ testStatus = FAIL;
+ continue;
+ }
+
+ Sleep(SLEEP_LENGTH);
+
+ if (!ReleaseMutex(hMutexHandle))
+ {
+ // Deal with error.
+ Trace("Error:%d: while releasing mutex @ thread %d # iter %d\n", GetLastError(), Id, i);
+ stats.operationsFailed += 1;
+ stats.operationsTotal += 1;
+ // do we need to have while true loop to attempt to release mutex...?
+ testStatus = FAIL;
+ continue;
+ }
+
+ stats.operationsTotal += 1;
+ stats.operationsPassed += 1;
+
+// Trace("Successs while releasing mutex @ iteration %d -> thread %d -> Process %d\n", i, Id, USE_PROCESS_COUNT);
+
+ }
+
+ stats.operationTime = GetTimeDiff(dwStartTime);
+ // Trace("Operation Time %lu, Process Count [%d], ThreadCount[%d]\n", stats.operationTime, USE_PROCESS_COUNT, Id);
+
+ if(resultBuffer->LogResult(Id, (char *)&stats))
+ {
+ Fail("Error:%d: while writing to shared memory, Thread Id is[%d] and Process id is [%d]\n", GetLastError(), Id, USE_PROCESS_COUNT);
+ }
+ // Trace("Contents of the buffer are after thread [%d]\n", Id);
+}
diff --git a/src/pal/tests/palsuite/composite/wfmo/readme.txt b/src/pal/tests/palsuite/composite/wfmo/readme.txt
new file mode 100644
index 0000000000..6be55d8ff4
--- /dev/null
+++ b/src/pal/tests/palsuite/composite/wfmo/readme.txt
@@ -0,0 +1,22 @@
+To compile:
+
+1) create a dat file (say wfmo.dat) with contents:
+PAL,Composite,palsuite\composite\wfmo,wfmo=main.c mutex.c,<SUPPORTEXE>,<TESTLANGCPP>,<COMPILEONLY>
+
+2) perl rrunmod.pl -r wfmo.dat
+
+
+To execute:
+main [PROCESS_COUNT] [THREAD_COUNT] [REPEAT_COUNT] [SLEEP_LENGTH]
+
+Output:
+The performance numbers will be in <process_logical_id>_wfmo.txt
+(will be at palsuite\composite\wfmo\obj[r|c|d] directory if u use rrunmod.pl)
+
+So if process_count is 3, you will have files 0_wfmo.txt, 1_wfmo.txt and so on…
+
+For each process txt file created,
+each row represents a thread data (process id, number of failures, number of pass, total number of repeated operations and an integer that will be used to identify a run
+(currently zero)).
+
+
diff --git a/src/pal/tests/palsuite/debug_api/CMakeLists.txt b/src/pal/tests/palsuite/debug_api/CMakeLists.txt
new file mode 100644
index 0000000000..a568131d3f
--- /dev/null
+++ b/src/pal/tests/palsuite/debug_api/CMakeLists.txt
@@ -0,0 +1,9 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+# TODO: make these tests compile
+# add_subdirectory(DebugBreak)
+# add_subdirectory(WriteProcessMemory)
+
+add_subdirectory(OutputDebugStringA)
+add_subdirectory(OutputDebugStringW)
+
diff --git a/src/pal/tests/palsuite/debug_api/DebugBreak/CMakeLists.txt b/src/pal/tests/palsuite/debug_api/DebugBreak/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/debug_api/DebugBreak/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/debug_api/DebugBreak/test1/CMakeLists.txt b/src/pal/tests/palsuite/debug_api/DebugBreak/test1/CMakeLists.txt
new file mode 100644
index 0000000000..db66cbe1d0
--- /dev/null
+++ b/src/pal/tests/palsuite/debug_api/DebugBreak/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_debugbreak_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_debugbreak_test1 coreclrpal)
+
+target_link_libraries(paltest_debugbreak_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/debug_api/DebugBreak/test1/test1.c b/src/pal/tests/palsuite/debug_api/DebugBreak/test1/test1.c
new file mode 100644
index 0000000000..2b10b9ad9d
--- /dev/null
+++ b/src/pal/tests/palsuite/debug_api/DebugBreak/test1/test1.c
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests that DebugBreak works in the grossest fashion.
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ BOOL bTry = FALSE;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ PAL_TRY
+ {
+ DebugBreak();
+ if (!bTry)
+ {
+ Fail("DebugBreak: Continued in Try block.\n");
+ }
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ bTry = TRUE;
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Fail("DebugBreak: Did not reach the exception block.\n");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/debug_api/DebugBreak/test1/testinfo.dat b/src/pal/tests/palsuite/debug_api/DebugBreak/test1/testinfo.dat
new file mode 100644
index 0000000000..25c480eccb
--- /dev/null
+++ b/src/pal/tests/palsuite/debug_api/DebugBreak/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Debug
+Function = DebugBreak
+Name = DebugBreak test #1
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests that DebugBreak "works". This will require case by case
+= manual interpretation.
diff --git a/src/pal/tests/palsuite/debug_api/OutputDebugStringA/CMakeLists.txt b/src/pal/tests/palsuite/debug_api/OutputDebugStringA/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/debug_api/OutputDebugStringA/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/CMakeLists.txt b/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/CMakeLists.txt
new file mode 100644
index 0000000000..5bc7fdb6e9
--- /dev/null
+++ b/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/CMakeLists.txt
@@ -0,0 +1,38 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(TESTSOURCES
+ test1.c
+)
+
+add_executable(paltest_outputdebugstringa_test1
+ ${TESTSOURCES}
+)
+
+add_dependencies(paltest_outputdebugstringa_test1 coreclrpal)
+
+target_link_libraries(paltest_outputdebugstringa_test1
+ pthread
+ m
+ coreclrpal
+)
+
+
+set(HELPERSOURCES
+ helper.c
+)
+
+add_executable(paltest_outputdebugstringa_test1_helper
+ ${HELPERSOURCES}
+)
+
+add_dependencies(paltest_outputdebugstringa_test1_helper coreclrpal)
+
+target_link_libraries(paltest_outputdebugstringa_test1_helper
+ pthread
+ m
+ coreclrpal
+)
+
+
diff --git a/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/helper.c b/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/helper.c
new file mode 100644
index 0000000000..90073dfedd
--- /dev/null
+++ b/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/helper.c
@@ -0,0 +1,35 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: helper.c
+**
+** Purpose: Intended to be the child process of a debugger. Calls
+** OutputDebugStringA once with a normal string, once with an empty
+** string
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ OutputDebugStringA("Foo!\n");
+
+ OutputDebugStringA("");
+
+ /* give a chance to the debugger process to read the debug string before
+ exiting */
+ Sleep(1000);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/test1.c b/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/test1.c
new file mode 100644
index 0000000000..080c6ac53e
--- /dev/null
+++ b/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/test1.c
@@ -0,0 +1,94 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test1.c
+**
+** Purpose: Debugs the helper application. Checks that certain events, in
+** particular the OUTPUT_DEBUG_STRING_EVENT, is generated correctly
+** and gives the correct values.
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+
+const int DELAY_MS = 2000;
+
+struct OutputCheck
+{
+ DWORD ExpectedEventCode;
+ DWORD ExpectedUnicode;
+ char *ExpectedStr;
+};
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ PROCESS_INFORMATION pi;
+ STARTUPINFO si;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ ZeroMemory( &si, sizeof(si) );
+ si.cb = sizeof(si);
+ ZeroMemory( &pi, sizeof(pi) );
+
+ /* Create a new process. This is the process to be Debugged */
+ if(!CreateProcess( NULL, "helper", NULL, NULL,
+ FALSE, 0, NULL, NULL, &si, &pi))
+ {
+ Fail("ERROR: CreateProcess failed to load executable 'helper'. "
+ "GetLastError() returned %d.\n",GetLastError());
+ }
+
+ /* This is the main loop. It exits when the process which is being
+ debugged is finished executing.
+ */
+
+ while(1)
+ {
+ DWORD dwRet = 0;
+ dwRet = WaitForSingleObject(pi.hProcess,
+ DELAY_MS /* Wait for 2 seconds max*/
+ );
+
+ if (dwRet != WAIT_OBJECT_0)
+ {
+ Trace("WaitForSingleObjectTest:WaitForSingleObject "
+ "failed (%x) after waiting %d seconds for the helper\n",
+ GetLastError(), DELAY_MS / 1000);
+ }
+ else
+ {
+ DWORD dwExitCode;
+
+ /* check the exit code from the process */
+ if( ! GetExitCodeProcess( pi.hProcess, &dwExitCode ) )
+ {
+ DWORD dwError;
+
+ dwError = GetLastError();
+ CloseHandle ( pi.hProcess );
+ CloseHandle ( pi.hThread );
+ Fail( "GetExitCodeProcess call failed with error code %d\n",
+ dwError );
+ }
+
+ if(dwExitCode != STILL_ACTIVE) {
+ CloseHandle(pi.hThread);
+ CloseHandle(pi.hProcess);
+ break;
+ }
+ Trace("still executing %d..\n", dwExitCode);
+ }
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/testinfo.dat b/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/testinfo.dat
new file mode 100644
index 0000000000..d49e9048d1
--- /dev/null
+++ b/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Debug
+Function = OutputDebugStringA
+Name = OutputDebugStringA test #1
+TYPE = DEFAULT
+EXE1 = test1
+EXE2 = helper
+Description
+=Tests that OutputDebugString generates the correct debugging event behaviour.
diff --git a/src/pal/tests/palsuite/debug_api/OutputDebugStringW/CMakeLists.txt b/src/pal/tests/palsuite/debug_api/OutputDebugStringW/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/debug_api/OutputDebugStringW/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/CMakeLists.txt b/src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..9202baeaef
--- /dev/null
+++ b/src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_outputdebugstringw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_outputdebugstringw_test1 coreclrpal)
+
+target_link_libraries(paltest_outputdebugstringw_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/test1.c b/src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/test1.c
new file mode 100644
index 0000000000..88b55427bc
--- /dev/null
+++ b/src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/test1.c
@@ -0,0 +1,41 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test1.c
+**
+** Purpose: Intended to be the child process of a debugger. Calls
+** OutputDebugStringW once with a normal string, once with an empty
+** string
+**
+**
+**============================================================*/
+
+#define UNICODE
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR *str1;
+ WCHAR *str2;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ str1 = convert("Foo!");
+ str2 = convert("");
+
+ OutputDebugStringW(str1);
+
+ OutputDebugStringW(str2);
+
+ free(str1);
+ free(str2);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/testinfo.dat b/src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/testinfo.dat
new file mode 100644
index 0000000000..d6bc4ac5a1
--- /dev/null
+++ b/src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Debug
+Function = OutputDebugStringW
+Name = OutputDebugStringW test #1
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Tests that OutputDebugString generates the correct debugging event behaviour.
diff --git a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/CMakeLists.txt b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/CMakeLists.txt
new file mode 100644
index 0000000000..078b55691f
--- /dev/null
+++ b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test3)
+add_subdirectory(test4)
+
diff --git a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/CMakeLists.txt b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/CMakeLists.txt
new file mode 100644
index 0000000000..39130aac1c
--- /dev/null
+++ b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/CMakeLists.txt
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(TESTSOURCES
+ test1.c
+)
+
+add_executable(paltest_writeprocessmemory_test1
+ ${TESTSOURCES}
+)
+
+add_dependencies(paltest_writeprocessmemory_test1 coreclrpal)
+
+target_link_libraries(paltest_writeprocessmemory_test1
+ pthread
+ m
+ coreclrpal
+)
+
+
+set(HELPERSOURCES
+ helper.c
+)
+
+add_executable(paltest_writeprocessmemory_test1_helper
+ ${HELPERSOURCES}
+)
+
+add_dependencies(paltest_writeprocessmemory_test1_helper coreclrpal)
+
+target_link_libraries(paltest_writeprocessmemory_test1_helper
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/commonconsts.h b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/commonconsts.h
new file mode 100644
index 0000000000..eb7d511534
--- /dev/null
+++ b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/commonconsts.h
@@ -0,0 +1,46 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: commonconsts.h
+**
+**
+**============================================================*/
+
+#ifndef _COMMONCONSTS_H_
+#define _COMMONCONSTS_H_
+
+#include <pal.h>
+
+const int TIMEOUT = 40000;
+
+const WCHAR szcToHelperEvName[] = { 'T', 'o', '\0' };
+const WCHAR szcFromHelperEvName[] = { 'F', 'r', 'o', 'm', '\0' };
+
+const char initialValue = '-';
+const char nextValue = '|';
+const char guardValue = '*';
+const char *commsFileName = "AddrNLen.dat";
+
+/* PEDANTIC and PEDANTIC0 is a helper macro that just grumps about any
+ * zero return codes in a generic way. with little typing */
+#define PEDANTIC(function, parameters) \
+{ \
+ if (! (function parameters) ) \
+ { \
+ Trace("%s: NonFatal failure of %s%s for reasons %u and %u\n", \
+ __FILE__, #function, #parameters, GetLastError(), errno); \
+ } \
+}
+#define PEDANTIC1(function, parameters) \
+{ \
+ if ( (function parameters) ) \
+ { \
+ Trace("%s: NonFatal failure of %s%s for reasons %u and %u\n", \
+ __FILE__, #function, #parameters, GetLastError(), errno); \
+ } \
+}
+
+#endif
diff --git a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/helper.c b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/helper.c
new file mode 100644
index 0000000000..1a7318969c
--- /dev/null
+++ b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/helper.c
@@ -0,0 +1,243 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: helper.c
+**
+** Purpose: This helper process sets up a several blocks of memory,
+** then uses a file to tell its parent process where that memory is
+** So it can do a WriteProcessMemory on it. When the parent process is done
+** we check here that it was written properly.
+**
+**
+**============================================================*/
+
+#include "commonconsts.h"
+
+#include <palsuite.h>
+
+struct allhandles_t
+{
+ HANDLE hEvToHelper;
+ HANDLE hEvFromHelper;
+ char *valuesFileName;
+};
+
+
+/* function: wpmDoIt
+ *
+ * This is a general WriteProcessMemory testing function that sets up
+ * the RAM pointed to and tells the companion process on the other end
+ * of the handles in 'Comms' to attempt to alter 'lenDest' bytes at
+ * '*pDest'.
+ *
+ * '*pBuffer'[0..'lenBuffer'] is expected to be a guard region
+ * surrounding the '*pDest'[0..'lenDest'] region so that this function
+ * can verify that only the proper bytes were altered.
+ */
+
+int wpmDoIt(struct allhandles_t Comms,
+ char * pBuffer, unsigned int lenBuffer,
+ char * pDest, unsigned int lenDest,
+ const char* storageDescription)
+{
+ char *pCurr;
+ FILE *commsFile;
+ DWORD dwRet;
+
+ if (pBuffer > pDest || lenDest > lenBuffer)
+ {
+ Trace("WriteProcessMemory::DoIt() test implementation: "
+ "(pBuffer > pDest || lenDest > lenBuffer)\n");
+ return FALSE;
+ }
+
+ /* set up the storage */
+ memset(pBuffer, guardValue, lenBuffer);
+ memset(pDest, initialValue, lenDest);
+
+ /* tell the parent what RAM to adjust */
+ if(!(commsFile = fopen(Comms.valuesFileName, "w")))
+ {
+ Trace("WriteProcessMemory: fopen of '%S' failed (%u). \n",
+ Comms.valuesFileName, GetLastError());
+ return FALSE;
+ }
+ if (!fprintf(commsFile, "%u %u '%s'\n",
+ pDest, lenDest, storageDescription))
+ {
+ Trace("WriteProcessMemory: fprintf to '%S' failed (%u). \n",
+ Comms.valuesFileName, GetLastError());
+ return FALSE;
+ }
+ PEDANTIC1(fclose, (commsFile));
+
+ /* Tell the parent the data is ready for it to adjust */
+ PEDANTIC(ResetEvent, (Comms.hEvToHelper));
+ PEDANTIC(SetEvent, (Comms.hEvFromHelper));
+
+ dwRet = WaitForSingleObject(Comms.hEvToHelper, TIMEOUT); /* parent is done */
+ if (dwRet != WAIT_OBJECT_0)
+ {
+ Trace("helper WaitForSingleObjectTest: WaitForSingleObject "
+ "failed (%u)\n", GetLastError());
+ return FALSE;
+ }
+
+ /* check the stuff that SHOULD have changed */
+ for (pCurr = pDest; pCurr < (pDest + lenDest); pCurr++)
+ {
+ if ( *pCurr != nextValue)
+ {
+ Trace("When testing '%s': alteration test failed "
+ "at %u offset %u. Found '%c' instead of '%c'\n.",
+ storageDescription, pDest, pCurr - pDest, *pCurr, nextValue);
+ Trace(" 'Altered' string: '%.*s'\n",lenBuffer, pBuffer);
+ return FALSE;
+ }
+ }
+ /* check the stuff that should NOT have changed */
+ for (pCurr = pBuffer; pCurr < pDest; pCurr++ )
+ {
+ if ( *pCurr != guardValue)
+ {
+ Trace("When testing '%s': leading guard zone test failed "
+ "at %u offset %u. Found '%c' instead of '%c'\n.",
+ storageDescription, pDest, pCurr - pBuffer, *pCurr, guardValue);
+ Trace(" 'Altered' string: '%.*s'\n",lenBuffer, pBuffer);
+ return FALSE;
+ }
+ }
+ for (pCurr = pDest + lenDest; pCurr < (pBuffer + lenBuffer); pCurr++ )
+ {
+ if ( *pCurr != guardValue)
+ {
+ Trace("When testing '%s': trailing guard zone test failed "
+ "at %u offset %u. Found '%c' instead of '%c'\n.",
+ storageDescription, pDest + lenDest, pCurr - pBuffer, *pCurr, guardValue);
+ Trace(" 'Altered' string: '%.*s'\n",lenBuffer, pBuffer);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ BOOL success = TRUE; /* assume success */
+ struct allhandles_t Comms = {0,0,0} ;
+
+ /* variables to track storage to alter */
+ char *pTarget = NULL;
+ unsigned int sizeTarget;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* hook up with the events created by the parent */
+ Comms.hEvToHelper = OpenEventW(EVENT_ALL_ACCESS, 0, szcToHelperEvName);
+ if (!Comms.hEvToHelper)
+ {
+ Fail("WriteProcessMemory: OpenEvent of '%S' failed (%u). "
+ "(the event should already exist!)\n",
+ szcToHelperEvName, GetLastError());
+ }
+ Comms.hEvFromHelper = OpenEventW(EVENT_ALL_ACCESS, 0, szcFromHelperEvName);
+ if (!Comms.hEvToHelper)
+ {
+ Trace("WriteProcessMemory: OpenEvent of '%S' failed (%u). "
+ "(the event should already exist!)\n",
+ szcFromHelperEvName, GetLastError());
+ success = FALSE;
+ goto EXIT;
+ }
+ Comms.valuesFileName = argv[1];
+
+ {
+ char autoAllocatedOnStack[51];
+
+ /* Get the parent process to write to the local stack */
+ success &= wpmDoIt(Comms, autoAllocatedOnStack,
+ sizeof(autoAllocatedOnStack),
+ autoAllocatedOnStack + sizeof(int),
+ sizeof(autoAllocatedOnStack) - 2 * sizeof(int),
+ "const size array on stack with int sized guards");
+ }
+
+ /* Get the parent process to write to stuff on the heap */
+ sizeTarget = 2 * sizeof(int) + 23 ; /* 23 is just a random prime > 16 */
+ if (!(pTarget = malloc(sizeTarget)))
+ {
+ Trace("WriteProcessMemory helper: unable to allocate '%s'->%d bytes of memory"
+ "(%u).\n",
+ argv[3], sizeTarget, GetLastError());
+ success = FALSE;
+ goto EXIT;
+
+ }
+ success &= wpmDoIt(Comms, pTarget, sizeTarget,
+ pTarget + sizeof(int),
+ sizeTarget - 2 * sizeof(int),
+ "array on heap with int sized guards");
+
+ /* just to be nice try something 16 - 2 * sizeof(int) bytes long */
+ {
+ char autoAllocatedOnStack[16];
+
+ /* Get the parent process to write to the local stack */
+ success &= wpmDoIt(Comms, autoAllocatedOnStack,
+ sizeof(autoAllocatedOnStack),
+ autoAllocatedOnStack + sizeof(int),
+ sizeof(autoAllocatedOnStack) - 2 * sizeof(int),
+ "another 16 byte array on stack with int sized guards inside");
+ }
+
+ /* NOTE: Don't try 0 bytes long. Win32 WriteProcessMemory claims
+ * it writes 8 bytes in that case! */
+
+ /* and 1 byte long... */
+ {
+ char autoAllocatedOnStack[1+ 2 * sizeof(int)];
+
+ /* Get the parent process to write to the local stack */
+ success &= wpmDoIt(Comms, autoAllocatedOnStack,
+ sizeof(autoAllocatedOnStack),
+ autoAllocatedOnStack + sizeof(int),
+ 1,
+ "no bytes with int sized guards outside on stack");
+ }
+
+
+EXIT:
+ /* Tell the parent that we are done */
+ if (!DeleteFile(Comms.valuesFileName))
+ {
+ Trace("helper: DeleteFile failed so parent (test1) is unlikely "
+ "to exit cleanly\n");
+ }
+ PEDANTIC(ResetEvent, (Comms.hEvToHelper));
+ if (!SetEvent(Comms.hEvFromHelper))
+ {
+ Trace("helper: SetEvent failed so parent (test1) is unlikely "
+ "to exit cleanly\n");
+ }
+
+ free(pTarget);
+ PEDANTIC(CloseHandle, (Comms.hEvToHelper));
+ PEDANTIC(CloseHandle, (Comms.hEvFromHelper));
+
+ if (!success)
+ {
+ Fail("");
+ }
+
+ PAL_Terminate();
+
+ return success ? PASS : FAIL;
+}
diff --git a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/test1.c b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/test1.c
new file mode 100644
index 0000000000..8de029d973
--- /dev/null
+++ b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/test1.c
@@ -0,0 +1,189 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test1.c
+**
+** Purpose: Create a child process and some events for communications with it.
+** When the child gets back to us with a memory location and a length,
+** Call WriteProcessMemory on this location and check to see that it
+** writes successfully.
+**
+**
+**============================================================*/
+
+#define UNICODE
+
+#include "commonconsts.h"
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ PROCESS_INFORMATION pi;
+ STARTUPINFO si;
+ HANDLE hEvToHelper;
+ HANDLE hEvFromHelper;
+ DWORD dwExitCode;
+
+
+ DWORD dwRet;
+ char cmdComposeBuf[MAX_PATH];
+ PWCHAR uniString;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Create the signals we need for cross process communication */
+ hEvToHelper = CreateEvent(NULL, TRUE, FALSE, szcToHelperEvName);
+ if (!hEvToHelper)
+ {
+ Fail("WriteProcessMemory: CreateEvent of '%S' failed. "
+ "GetLastError() returned %d.\n", szcToHelperEvName,
+ GetLastError());
+ }
+ if (GetLastError() == ERROR_ALREADY_EXISTS)
+ {
+ Fail("WriteProcessMemory: CreateEvent of '%S' failed. "
+ "(already exists!)\n", szcToHelperEvName);
+ }
+ hEvFromHelper = CreateEvent(NULL, TRUE, FALSE, szcFromHelperEvName);
+ if (!hEvToHelper)
+ {
+ Fail("WriteProcessMemory: CreateEvent of '%S' failed. "
+ "GetLastError() returned %d.\n", szcFromHelperEvName,
+ GetLastError());
+ }
+ if (GetLastError() == ERROR_ALREADY_EXISTS)
+ {
+ Fail("WriteProcessMemory: CreateEvent of '%S' failed. "
+ "(already exists!)\n", szcFromHelperEvName);
+ }
+ ResetEvent(hEvFromHelper);
+ ResetEvent(hEvToHelper);
+
+ if (!sprintf(cmdComposeBuf, "helper %s", commsFileName))
+ {
+ Fail("Could not convert command line\n");
+ }
+ uniString = convert(cmdComposeBuf);
+
+ ZeroMemory( &si, sizeof(si) );
+ si.cb = sizeof(si);
+ ZeroMemory( &pi, sizeof(pi) );
+
+ /* Create a new process. This is the process that will ask for
+ * memory munging */
+ if(!CreateProcess( NULL, uniString, NULL, NULL,
+ FALSE, 0, NULL, NULL, &si, &pi))
+ {
+ Trace("ERROR: CreateProcess failed to load executable '%S'. "
+ "GetLastError() returned %u.\n",
+ uniString, GetLastError());
+ free(uniString);
+ Fail("");
+ }
+ free(uniString);
+
+ while(1)
+ {
+ FILE *commsFile;
+ char* pSrcMemory;
+ char* pDestMemory;
+ int Count;
+ SIZE_T wpmCount;
+ char incomingCMDBuffer[MAX_PATH + 1];
+
+ /* wait until the helper tells us that it has given us
+ * something to do */
+ dwRet = WaitForSingleObject(hEvFromHelper, TIMEOUT);
+ if (dwRet != WAIT_OBJECT_0)
+ {
+ Trace("test1 WaitForSingleObjectTest: WaitForSingleObject "
+ "failed (%u)\n", GetLastError());
+ break; /* no more work incoming */
+ }
+
+ /* get the parameters to test WriteProcessMemory with */
+ if (!(commsFile = fopen(commsFileName, "r")))
+ {
+ /* no file means there is no more work */
+ break;
+ }
+ if ( NULL == fgets(incomingCMDBuffer, MAX_PATH, commsFile))
+ {
+ Fail ("unable to read from communication file %s "
+ "for reasons %u & %u\n",
+ errno, GetLastError());
+ }
+ PEDANTIC1(fclose,(commsFile));
+ sscanf(incomingCMDBuffer, "%u %u", &pDestMemory, &Count);
+ if (argc > 1)
+ {
+ Trace("Preparing to write to %u bytes @ %u ('%s')\n",
+ Count, pDestMemory, incomingCMDBuffer);
+ }
+
+ /* compose some data to write to the client process */
+ if (!(pSrcMemory = malloc(Count)))
+ {
+ Trace("could not dynamically allocate memory to copy from "
+ "for reasons %u & %u\n",
+ errno, GetLastError());
+ goto doneIteration;
+ }
+ memset(pSrcMemory, nextValue, Count);
+
+ /* do the work */
+ dwRet = WriteProcessMemory(pi.hProcess,
+ pDestMemory,
+ pSrcMemory,
+ Count,
+ &wpmCount);
+ if (!dwRet)
+ {
+ Trace("%s: Problem: on a write to %u bytes @ %u ('%s')\n",
+ argv[0], Count, pDestMemory, incomingCMDBuffer);
+ Trace("test1 WriteProcessMemory returned a%u(!=0) (GLE=%u)\n",
+ GetLastError());
+ }
+ if(Count != wpmCount)
+ {
+ Trace("%s: Problem: on a write to %u bytes @ %u ('%s')\n",
+ argv[0], Count, pDestMemory, incomingCMDBuffer);
+ Trace("The number of bytes written should have been "
+ "%u, but was reported as %u.\n", Count, wpmCount);
+ }
+ free(pSrcMemory);
+
+ doneIteration:
+ PEDANTIC(ResetEvent, (hEvFromHelper));
+ PEDANTIC(SetEvent, (hEvToHelper));
+ }
+
+ /* wait for the child process to complete */
+ WaitForSingleObject ( pi.hProcess, TIMEOUT );
+ /* this may return a failure code on a success path */
+
+ /* check the exit code from the process */
+ if( ! GetExitCodeProcess( pi.hProcess, &dwExitCode ) )
+ {
+ Trace( "GetExitCodeProcess call failed with error code %u\n",
+ GetLastError() );
+ dwExitCode = FAIL;
+ }
+
+
+ PEDANTIC(CloseHandle, (hEvToHelper));
+ PEDANTIC(CloseHandle, (hEvFromHelper));
+ PEDANTIC(CloseHandle, (pi.hThread));
+ PEDANTIC(CloseHandle, (pi.hProcess));
+
+ PAL_TerminateEx(dwExitCode);
+ return dwExitCode;
+}
diff --git a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/testinfo.dat b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/testinfo.dat
new file mode 100644
index 0000000000..0946f8f138
--- /dev/null
+++ b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Debug
+Function = WriteProcessMemory
+Name = Check that writing text to process memory succeeds.
+TYPE = DEFAULT
+EXE1 = test1
+EXE2 = helper
+Description
+= Create a child process and attempt to write to its memory
+= at the places and lengths it specifies via a data file.
+= the child verifies that all the specified memory was altered
+= with no overruns.
diff --git a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/CMakeLists.txt b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/CMakeLists.txt
new file mode 100644
index 0000000000..ecc0e06dac
--- /dev/null
+++ b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/CMakeLists.txt
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(TESTSOURCES
+ test3.c
+)
+
+add_executable(paltest_writeprocessmemory_test3
+ ${TESTSOURCES}
+)
+
+add_dependencies(paltest_writeprocessmemory_test3 coreclrpal)
+
+target_link_libraries(paltest_writeprocessmemory_test3
+ pthread
+ m
+ coreclrpal
+)
+
+
+set(HELPERSOURCES
+ helper.c
+)
+
+add_executable(paltest_writeprocessmemory_test3_helper
+ ${HELPERSOURCES}
+)
+
+add_dependencies(paltest_writeprocessmemory_test3_helper coreclrpal)
+
+target_link_libraries(paltest_writeprocessmemory_test3_helper
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/commonconsts.h b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/commonconsts.h
new file mode 100644
index 0000000000..c1cec18e2d
--- /dev/null
+++ b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/commonconsts.h
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Header: commonconsts.h
+**
+**
+==============================================================*/
+
+#ifndef _COMMONCONSTS_H_
+#define _COMMONCONSTS_H_
+
+#include <pal.h>
+
+const int TIMEOUT = 40000;
+
+const WCHAR szcToHelperEvName[] = { 'T', 'o', '\0' };
+const WCHAR szcFromHelperEvName[] = { 'F', 'r', 'o', 'm', '\0' };
+
+const char initialValue = '-';
+const char nextValue = '|';
+const char guardValue = '*';
+const char *commsFileName = "AddrNLen.dat";
+
+/* PEDANTIC and PEDANTIC0 is a helper macro that just grumps about any
+ * zero return codes in a generic way. with little typing */
+#define PEDANTIC(function, parameters) \
+{ \
+ unsigned int retval = (function parameters); \
+ if ( !retval ) \
+ { \
+ Trace("%s: NonFatal failure of %s%s (returned %u) " \
+ "for reasons %u and %u.\n", \
+ __FILE__, #function, #parameters, retval, GetLastError(), errno); \
+ } \
+}
+#define PEDANTIC1(function, parameters) \
+{ \
+ unsigned int retval = (function parameters); \
+ if ( retval ) \
+ { \
+ Trace("%s: NonFatal failure of %s%s (returned %u) " \
+ "for reasons %u and %u\n", \
+ __FILE__, #function, #parameters, retval, GetLastError(), errno); \
+ } \
+}
+
+#endif
diff --git a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/helper.c b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/helper.c
new file mode 100644
index 0000000000..170e2064cb
--- /dev/null
+++ b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/helper.c
@@ -0,0 +1,256 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: helper.c
+
+**
+==============================================================*/
+
+
+/*
+**
+** Purpose: This helper process sets up a several blocks of memory
+** that should be unwritable from the parent process, then uses a file
+** to tell its parent process where that memory is so it can attempt a
+** WriteProcessMemory on it. When the parent process is done we check
+** here that it was (properly) unable to change the contents of the
+** memory.
+*/
+
+#include "commonconsts.h"
+
+#include <palsuite.h>
+
+struct allhandles_t
+{
+ HANDLE hEvToHelper;
+ HANDLE hEvFromHelper;
+ char *valuesFileName;
+};
+
+
+/* function: wpmVerifyCant
+ *
+ * This is a general WriteProcessMemory testing function that sets up
+ * the RAM pointed to and tells the companion process on the other end
+ * of the handles in 'Comms' to attempt to alter 'lenDest' bytes at
+ * '*pDest'.
+ *
+ * However, the memory at pDest[0..lenDest] is expected to be unwritable by
+ * the companion process. The companion is expects this. This function
+ * verifies that no bytes were affected
+ */
+
+int wpmVerifyCant(struct allhandles_t Comms,
+ char * pDest, unsigned int lenDest,
+ unsigned int lenLegitDest,
+ DWORD dwExpectedErrorCode,
+ const char* storageDescription)
+{
+ char *pCurr;
+ FILE *commsFile;
+ DWORD dwRet;
+
+ unsigned int lenSafe = min(lenDest, lenLegitDest);
+
+ PAL_TRY
+ {
+ memset(pDest, initialValue, lenSafe);
+ }
+ PAL_EXCEPT_EX (setup, EXCEPTION_EXECUTE_HANDLER)
+ {
+ Trace("WriteProcessMemory: bug in test values for '%s' (%p, %u, %u), "
+ "the initial memset threw an exception.\n",
+ storageDescription, pDest, lenDest, lenSafe);
+ }
+ PAL_ENDTRY;
+
+ /* tell the parent what RAM to attempt to adjust */
+ if(!(commsFile = fopen(Comms.valuesFileName, "w")))
+ {
+ Trace("WriteProcessMemory: fopen of '%S' failed (%u). \n",
+ Comms.valuesFileName, GetLastError());
+ return FALSE;
+ }
+ if (!fprintf(commsFile, "%u %u %u '%s'\n",
+ pDest, lenDest, dwExpectedErrorCode, storageDescription))
+ {
+ Trace("WriteProcessMemory: fprintf to '%S' failed (%u). \n",
+ Comms.valuesFileName, GetLastError());
+ return FALSE;
+ }
+ PEDANTIC1(fclose, (commsFile));
+
+ /* Tell the parent the data is ready for it to adjust */
+ PEDANTIC(ResetEvent, (Comms.hEvToHelper));
+ PEDANTIC(SetEvent, (Comms.hEvFromHelper));
+
+ dwRet = WaitForSingleObject(Comms.hEvToHelper, TIMEOUT);
+ if (dwRet != WAIT_OBJECT_0)
+ {
+ Trace("helper WaitForSingleObjectTest: WaitForSingleObject "
+ "failed (%u)\n", GetLastError());
+ return FALSE;
+ }
+
+ PAL_TRY
+ {
+ /* check the stuff (as much as we can) that should NOT have changed */
+ for (pCurr = pDest; pCurr < (pDest + lenSafe); pCurr++ )
+ {
+ if ( *pCurr != initialValue)
+ {
+ Trace("When testing '%s': real memory values preservation failed "
+ "at %u offset %u. Found '%c' instead of '%c'\n.",
+ storageDescription, pDest, pCurr - pDest,
+ *pCurr, initialValue);
+ return FALSE;
+ }
+ }
+ }
+ PAL_EXCEPT_EX (testing, EXCEPTION_EXECUTE_HANDLER)
+ {
+ Trace("WriteProcessMemory: bug in test values for '%s' (%p, %u, %u), "
+ "the verification pass threw an exception.\n",
+ storageDescription, pDest, lenDest, lenSafe);
+ }
+ PAL_ENDTRY;
+
+ return TRUE;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ BOOL success = TRUE; /* assume success */
+ struct allhandles_t Comms = {0,0,0} ;
+
+ SYSTEM_INFO sysinfo;
+
+ char* Memory;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* hook up with the events created by the parent */
+ Comms.hEvToHelper = OpenEventW(EVENT_ALL_ACCESS, 0, szcToHelperEvName);
+ if (!Comms.hEvToHelper)
+ {
+ Fail("WriteProcessMemory: OpenEvent of '%S' failed (%u). "
+ "(the event should already exist!)\n",
+ szcToHelperEvName, GetLastError());
+ success = FALSE;
+ goto EXIT;
+ }
+ Comms.hEvFromHelper = OpenEventW(EVENT_ALL_ACCESS, 0, szcFromHelperEvName);
+ if (!Comms.hEvToHelper)
+ {
+ Trace("WriteProcessMemory: OpenEvent of '%S' failed (%u). "
+ "(the event should already exist!)\n",
+ szcFromHelperEvName, GetLastError());
+ success = FALSE;
+ goto EXIT;
+ }
+ Comms.valuesFileName = argv[1];
+
+ /* test setup */
+ GetSystemInfo(&sysinfo);
+
+ {
+ unsigned int allocSize = sysinfo.dwPageSize * 2;
+ unsigned int writeLen = allocSize * 2;
+
+ /* First test: overrun the allocated memory */
+ Memory = (char*)VirtualAlloc(NULL, allocSize,
+ MEM_COMMIT, PAGE_READWRITE);
+
+ if(Memory == NULL)
+ {
+ Fail("ERROR: Attempted to commit two pages, but the "
+ " VirtualAlloc call failed. "
+ "GetLastError() returned %u.\n",GetLastError());
+ }
+ success &= wpmVerifyCant(Comms, Memory, writeLen, allocSize,
+ ERROR_INVALID_ADDRESS,
+ "should not write beyond committed allocation");
+
+ PEDANTIC1(VirtualFree, (Memory, allocSize,
+ MEM_DECOMMIT | MEM_RELEASE));
+ }
+
+ {
+ /* Allocate the memory as readonly */
+ unsigned int allocSize = sysinfo.dwPageSize * 2;
+ unsigned int writeLen = allocSize;
+
+ Memory = (char*)VirtualAlloc(NULL, allocSize,
+ MEM_COMMIT, PAGE_READONLY);
+
+ if(Memory == NULL)
+ {
+ Fail("ERROR: Attempted to commit two pages readonly, but the "
+ " VirtualAlloc call failed. "
+ "GetLastError() returned %u.\n",GetLastError());
+ }
+ success &= wpmVerifyCant(Comms, Memory, writeLen, 0,
+ ERROR_NOACCESS,
+ "should not write in READONLY allocation");
+
+ PEDANTIC1(VirtualFree, (Memory, allocSize,
+ MEM_DECOMMIT | MEM_RELEASE));
+ }
+
+
+ {
+ /* attempt to write to memory that is not committed yet */
+ unsigned int allocSize = sysinfo.dwPageSize * 2;
+ unsigned int writeLen = allocSize;
+
+ Memory = (char*)VirtualAlloc(NULL, allocSize,
+ MEM_RESERVE, PAGE_NOACCESS);
+
+ if(Memory == NULL)
+ {
+ Fail("ERROR: Attempted to reserve two pages, but the "
+ " VirtualAlloc call failed. "
+ "GetLastError() returned %u.\n",GetLastError());
+ }
+ success &= wpmVerifyCant(Comms, Memory, writeLen, 0,
+ ERROR_INVALID_ADDRESS,
+ "should not write in memory that is"
+ " RESERVED but not COMMITTED");
+
+ PEDANTIC1(VirtualFree, (Memory, allocSize, MEM_RELEASE));
+ }
+
+
+EXIT:
+ /* Tell the parent that we are done */
+ if (!DeleteFile(Comms.valuesFileName))
+ {
+ Trace("helper: DeleteFile failed so parent (test1) is unlikely "
+ "to exit cleanly\n");
+ }
+ PEDANTIC(ResetEvent, (Comms.hEvToHelper));
+ if (!SetEvent(Comms.hEvFromHelper))
+ {
+ Trace("helper: SetEvent failed so parent (test1) is unlikely "
+ "to exit cleanly\n");
+ }
+
+ PEDANTIC(CloseHandle, (Comms.hEvToHelper));
+ PEDANTIC(CloseHandle, (Comms.hEvFromHelper));
+
+ if (!success)
+ {
+ Fail("");
+ }
+
+ PAL_Terminate();
+
+ return success ? PASS : FAIL;
+}
diff --git a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/test3.c b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/test3.c
new file mode 100644
index 0000000000..063cb4cbec
--- /dev/null
+++ b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/test3.c
@@ -0,0 +1,205 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test3.c
+**
+** Purpose: Create a child process and debug it. When the child
+** raises an exception, it sends back a memory location. Call
+** WriteProcessMemory on the memory location, but attempt to write
+** more than the memory allows. This should cause an error and the
+** data should be unchanged.
+**
+**
+==============================================================*/
+
+#define UNICODE
+
+#include "commonconsts.h"
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ PROCESS_INFORMATION pi;
+ STARTUPINFO si;
+ HANDLE hEvToHelper;
+ HANDLE hEvFromHelper;
+ DWORD dwExitCode;
+
+
+ DWORD dwRet;
+ BOOL success = TRUE; /* assume success */
+ char cmdComposeBuf[MAX_PATH];
+ PWCHAR uniString;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Create the signals we need for cross process communication */
+ hEvToHelper = CreateEvent(NULL, TRUE, FALSE, szcToHelperEvName);
+ if (!hEvToHelper)
+ {
+ Fail("WriteProcessMemory: CreateEvent of '%S' failed. "
+ "GetLastError() returned %u.\n", szcToHelperEvName,
+ GetLastError());
+ }
+ if (GetLastError() == ERROR_ALREADY_EXISTS)
+ {
+ Fail("WriteProcessMemory: CreateEvent of '%S' failed. "
+ "(already exists!)\n", szcToHelperEvName);
+ }
+ hEvFromHelper = CreateEvent(NULL, TRUE, FALSE, szcFromHelperEvName);
+ if (!hEvToHelper)
+ {
+ Fail("WriteProcessMemory: CreateEvent of '%S' failed. "
+ "GetLastError() returned %u.\n", szcFromHelperEvName,
+ GetLastError());
+ }
+ if (GetLastError() == ERROR_ALREADY_EXISTS)
+ {
+ Fail("WriteProcessMemory: CreateEvent of '%S' failed. "
+ "(already exists!)\n", szcFromHelperEvName);
+ }
+
+ if (!sprintf(cmdComposeBuf, "helper %s", commsFileName))
+ {
+ Fail("Could not convert command line\n");
+ }
+ uniString = convert(cmdComposeBuf);
+
+ ZeroMemory( &si, sizeof(si) );
+ si.cb = sizeof(si);
+ ZeroMemory( &pi, sizeof(pi) );
+
+ /* Create a new process. This is the process that will ask for
+ * memory munging */
+ if(!CreateProcess( NULL, uniString, NULL, NULL,
+ FALSE, 0, NULL, NULL, &si, &pi))
+ {
+ Trace("ERROR: CreateProcess failed to load executable '%S'. "
+ "GetLastError() returned %u.\n",
+ uniString, GetLastError());
+ free(uniString);
+ Fail("");
+ }
+ free(uniString);
+
+ while(1)
+ {
+ FILE *commsFile;
+ char* pSrcMemory;
+ char* pDestMemory;
+ int Count;
+ SIZE_T wpmCount;
+ DWORD dwExpectedErrorCode;
+
+ char incomingCMDBuffer[MAX_PATH + 1];
+
+ /* wait until the helper tells us that it has given us
+ * something to do */
+ dwRet = WaitForSingleObject(hEvFromHelper, TIMEOUT);
+ if (dwRet != WAIT_OBJECT_0)
+ {
+ Trace("test1 WaitForSingleObjectTest: WaitForSingleObject "
+ "failed (%u)\n", GetLastError());
+ break; /* no more work incoming */
+ }
+
+ /* get the parameters to test WriteProcessMemory with */
+ if (!(commsFile = fopen(commsFileName, "r")))
+ {
+ /* no file means there is no more work */
+ break;
+ }
+ if ( NULL == fgets(incomingCMDBuffer, MAX_PATH, commsFile))
+ {
+ Trace ("unable to read from communication file %s "
+ "for reasons %u & %u\n",
+ errno, GetLastError());
+ success = FALSE;
+ PEDANTIC1(fclose,(commsFile));
+ /* it's not worth continuing this trial */
+ goto doneIteration;
+ }
+ PEDANTIC1(fclose,(commsFile));
+ sscanf(incomingCMDBuffer, "%u %u %u",
+ &pDestMemory, &Count, &dwExpectedErrorCode);
+ if (argc > 1)
+ {
+ Trace("Preparing to write to %u bytes @ %u ('%s')\n",
+ Count, pDestMemory, incomingCMDBuffer);
+ }
+
+ /* compose some data to write to the client process */
+ if (!(pSrcMemory = malloc(Count)))
+ {
+ Trace("could not dynamically allocate memory to copy from "
+ "for reasons %u & %u\n",
+ errno, GetLastError());
+ success = FALSE;
+ goto doneIteration;
+ }
+ memset(pSrcMemory, nextValue, Count);
+
+ /* do the work */
+ dwRet = WriteProcessMemory(pi.hProcess,
+ pDestMemory,
+ pSrcMemory,
+ Count,
+ &wpmCount);
+
+ if(dwRet != 0)
+ {
+ Trace("ERROR: Situation: '%s', return code: %u, bytes 'written': %u\n",
+ incomingCMDBuffer, dwRet, wpmCount);
+ Trace("ERROR: WriteProcessMemory did not fail as it should, as "
+ "it attempted to write to a range of memory which was "
+ "not completely accessible.\n");
+ success = FALSE;
+ }
+
+ if(GetLastError() != dwExpectedErrorCode)
+ {
+ Trace("ERROR: GetLastError() should have returned "
+ "%u , but instead it returned %u.\n",
+ dwExpectedErrorCode, GetLastError());
+ success = FALSE;
+ }
+ free(pSrcMemory);
+
+ doneIteration:
+ PEDANTIC(ResetEvent, (hEvFromHelper));
+ PEDANTIC(SetEvent, (hEvToHelper));
+ }
+
+
+ /* wait for the child process to complete */
+ WaitForSingleObject ( pi.hProcess, TIMEOUT );
+ /* this may return a failure code on a success path */
+
+ /* check the exit code from the process */
+ if( ! GetExitCodeProcess( pi.hProcess, &dwExitCode ) )
+ {
+ Trace( "GetExitCodeProcess call failed with error code %u\n",
+ GetLastError() );
+ dwExitCode = FAIL;
+ }
+ if(!success)
+ {
+ dwExitCode = FAIL;
+ }
+
+ PEDANTIC(CloseHandle, (hEvToHelper));
+ PEDANTIC(CloseHandle, (hEvFromHelper));
+ PEDANTIC(CloseHandle, (pi.hThread));
+ PEDANTIC(CloseHandle, (pi.hProcess));
+
+ PAL_Terminate(dwExitCode);
+ return dwExitCode;
+}
diff --git a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/testinfo.dat b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/testinfo.dat
new file mode 100644
index 0000000000..23ad3ae567
--- /dev/null
+++ b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Debug
+Function = WriteProcessMemory
+Name = Check that you can't write from writable to protected memory.
+TYPE = DEFAULT
+EXE1 = test3
+EXE2 = helper
+Description
+= Create a child process and debug it. When the child
+= raises an exception, it sends back a memory location. Call
+= WriteProcessMemory on the memory location, but attempt to write
+= more than the memory allows. This should cause an error and the
+= data should be unchanged.
diff --git a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/CMakeLists.txt b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/CMakeLists.txt
new file mode 100644
index 0000000000..cf1ce13862
--- /dev/null
+++ b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/CMakeLists.txt
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(TESTSOURCES
+ test4.c
+)
+
+add_executable(paltest_writeprocessmemory_test4
+ ${TESTSOURCES}
+)
+
+add_dependencies(paltest_writeprocessmemory_test4 coreclrpal)
+
+target_link_libraries(paltest_writeprocessmemory_test4
+ pthread
+ m
+ coreclrpal
+)
+
+
+set(HELPERSOURCES
+ helper.c
+)
+
+add_executable(paltest_writeprocessmemory_test4_helper
+ ${HELPERSOURCES}
+)
+
+add_dependencies(paltest_writeprocessmemory_test4_helper coreclrpal)
+
+target_link_libraries(paltest_writeprocessmemory_test4_helper
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/helper.c b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/helper.c
new file mode 100644
index 0000000000..b653ea5057
--- /dev/null
+++ b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/helper.c
@@ -0,0 +1,67 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: helper.c
+**
+** Purpose: This helper process sets up a block of memory, then
+** raises an exception to pass that memory location back to the
+** parent process. When the parent process is done calling WriteProcessMemory
+** we check here that it was written properly.
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+const int MY_EXCEPTION=999;
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ char* Memory;
+ char* TheArray[1];
+ int i;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ Memory = (char*)VirtualAlloc(NULL, 4096, MEM_COMMIT, PAGE_READONLY);
+
+ if(Memory == NULL)
+ {
+ Fail("ERROR: Attempted to allocate two pages, but the VirtualAlloc "
+ "call failed. GetLastError() returned %d.\n",GetLastError());
+ }
+
+
+ TheArray[0] = Memory;
+
+
+ /* Need to sleep for a couple seconds. Otherwise this process
+ won't be being debugged when the first exception is raised.
+ */
+ Sleep(4000);
+
+ RaiseException(MY_EXCEPTION, 0, 1, (ULONG_PTR*)TheArray);
+
+ for(i=0; i<4096; ++i)
+ {
+ if(Memory[i] != '\0')
+ {
+ Fail("ERROR: The memory should be unchanged after the "
+ "invalid call to WriteProcessMemory, but the char "
+ "at index %d has changed.\n",i);
+ }
+ }
+
+
+
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/test4.c b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/test4.c
new file mode 100644
index 0000000000..51db23499b
--- /dev/null
+++ b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/test4.c
@@ -0,0 +1,124 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test4.c
+**
+** Purpose: Create a child process and debug it. When the child
+** raises an exception, it sends back a memory location. Call
+** WriteProcessMemory on a restricted memory location and ensure that
+** it fails.
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+const int MY_EXCEPTION=999;
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ PROCESS_INFORMATION pi;
+ STARTUPINFO si;
+ DEBUG_EVENT DebugEv;
+ DWORD dwContinueStatus = DBG_CONTINUE;
+ int Count, ret;
+ char* DataBuffer[4096];
+ char* Memory;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ ZeroMemory( &si, sizeof(si) );
+ si.cb = sizeof(si);
+ ZeroMemory( &pi, sizeof(pi) );
+
+ memset(DataBuffer, 'z', 4096);
+
+ /* Create a new process. This is the process to be Debugged */
+ if(!CreateProcess( NULL, "helper", NULL, NULL,
+ FALSE, 0, NULL, NULL, &si, &pi))
+ {
+ Fail("ERROR: CreateProcess failed to load executable 'helper'. "
+ "GetLastError() returned %d.\n",GetLastError());
+ }
+
+ /* Call DebugActiveProcess, because the process wasn't created as a
+ debug process.
+ */
+ if(DebugActiveProcess(pi.dwProcessId) == 0)
+ {
+ Fail("ERROR: Failed calling DebugActiveProcess on the process "
+ "which was created to debug. GetLastError() returned %d.\n",
+ GetLastError());
+ }
+
+
+ /* Call WaitForDebugEvent, which will wait until the helper process
+ raises an exception.
+ */
+
+ while(1)
+ {
+ if(WaitForDebugEvent(&DebugEv, INFINITE) == 0)
+ {
+ Fail("ERROR: WaitForDebugEvent returned 0, indicating failure. "
+ "GetLastError() returned %d.\n",GetLastError());
+ }
+
+ /* We're waiting for the helper process to send this exception.
+ When it does, we call WriteProcess. If it gets called more than
+ once, it is ignored.
+ */
+
+ if(DebugEv.u.Exception.ExceptionRecord.ExceptionCode == MY_EXCEPTION)
+ {
+
+ Memory = (LPVOID)
+ DebugEv.u.Exception.ExceptionRecord.ExceptionInformation[0];
+
+ /* Write to this memory which we have no access to. */
+
+ ret = WriteProcessMemory(pi.hProcess,
+ Memory,
+ DataBuffer,
+ 4096,
+ &Count);
+
+ if(ret != 0)
+ {
+ Fail("ERROR: WriteProcessMemory should have failed, as "
+ "it attempted to write to a range of memory which was "
+ "not accessible.\n");
+ }
+
+ if(GetLastError() != ERROR_NOACCESS)
+ {
+ Fail("ERROR: GetLastError() should have returned "
+ "ERROR_NOACCESS , but intead it returned "
+ "%d.\n",GetLastError());
+ }
+ }
+
+ if(DebugEv.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
+ {
+ break;
+ }
+
+ if(ContinueDebugEvent(DebugEv.dwProcessId,
+ DebugEv.dwThreadId, dwContinueStatus) == 0)
+ {
+ Fail("ERROR: ContinueDebugEvent failed to continue the thread "
+ "which had a debug event. GetLastError() returned %d.\n",
+ GetLastError());
+ }
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/testinfo.dat b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/testinfo.dat
new file mode 100644
index 0000000000..c6f4edb5d6
--- /dev/null
+++ b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Debug
+Function = WriteProcessMemory
+Name = Check that you can't write to protected memory.
+TYPE = DEFAULT
+EXE1 = test4
+EXE2 = helper
+Description
+= Create a child process and debug it. When the child
+= raises an exception, it sends back a memory location. Call
+= WriteProcessMemory on a restricted memory location and ensure that
+= it fails.
+
diff --git a/src/pal/tests/palsuite/exception_handling/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/CMakeLists.txt
new file mode 100644
index 0000000000..d0de335427
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/CMakeLists.txt
@@ -0,0 +1,13 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(pal_sxs)
+#add_subdirectory(pal_except)
+#add_subdirectory(PAL_EXCEPT_FILTER)
+#add_subdirectory(PAL_EXCEPT_FILTER_EX)
+#add_subdirectory(pal_finally)
+#add_subdirectory(PAL_TRY_EXCEPT)
+#add_subdirectory(PAL_TRY_EXCEPT_EX)
+#add_subdirectory(PAL_TRY_LEAVE_FINALLY)
+add_subdirectory(RaiseException)
+#add_subdirectory(SetUnhandledExceptionFilter)
+
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/CMakeLists.txt
new file mode 100644
index 0000000000..1962ade358
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/CMakeLists.txt
new file mode 100644
index 0000000000..adbc8ae86a
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ PAL_EXCEPT_FILTER.c
+)
+
+add_executable(paltest_pal_except_filter_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_except_filter_test1 coreclrpal)
+
+target_link_libraries(paltest_pal_except_filter_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/PAL_EXCEPT_FILTER.c b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/PAL_EXCEPT_FILTER.c
new file mode 100644
index 0000000000..ee65f43d2c
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/PAL_EXCEPT_FILTER.c
@@ -0,0 +1,118 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: pal_except_filter.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the PAL_EXCEPT_FILTER. An
+** exception is forced and a known value is passed to the filter
+** fuction. The known value as well as booleans are tested to
+** ensure proper functioning.
+**
+**
+**===================================================================*/
+
+
+
+#include <palsuite.h>
+
+BOOL bFilter = FALSE;
+BOOL bTry = FALSE;
+const int nValidator = 12321;
+
+LONG ExitFilter(EXCEPTION_POINTERS* ep, LPVOID pnTestInt)
+{
+ int nTestInt = *(int *)pnTestInt;
+
+ /* let the main know we've hit the filter function */
+ bFilter = TRUE;
+
+ if (!bTry)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The filter was hit without PAL_TRY being hit.\n");
+ }
+
+ /* was the correct value passed? */
+ if (nValidator != nTestInt)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Parameter passed to filter function"
+ " should have been \"%d\" but was \"%d\".\n",
+ nValidator,
+ nTestInt);
+ }
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int* p = 0x00000000; /* pointer to NULL */
+ BOOL bExcept = FALSE;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /*
+ ** test to make sure we get into the exception block
+ */
+
+ PAL_TRY
+ {
+ if (bExcept)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER was hit before PAL_TRY.\n");
+ }
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+ *p = 13; /* causes an access violation exception */
+
+ Fail("PAL_EXCEPT_FILTER: ERROR -> code was executed after the "
+ "access violation.\n");
+ }
+ PAL_EXCEPT_FILTER(ExitFilter, (LPVOID)&nValidator)
+ {
+ if (!bTry)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER was hit without PAL_TRY being hit.\n");
+ }
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT_FILTER block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the PAL_TRY"
+ " block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the "
+ "PAL_EXCEPT_FILTER block was not executed.\n");
+ }
+
+ if (!bFilter)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the filter"
+ " function was not executed.\n");
+ }
+
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept || !bFilter)
+ {
+ Fail("");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/testinfo.dat b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/testinfo.dat
new file mode 100644
index 0000000000..b0b90d3ab4
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = exception_handling
+Function = PAL_EXCEPT_FILTER
+Name = Test for PAL_EXCEPT_FILTER
+Type = DEFAULT
+EXE1 = pal_except_filter
+LANG = cpp
+Description
+= Tests the PAL implementation of the PAL_EXCEPT_FILTER. An
+= exception is forced and a known value is passed to the filter
+= fuction. The known value as well as booleans are tested to
+= ensure proper functioning.
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/CMakeLists.txt
new file mode 100644
index 0000000000..62cda706d5
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ pal_except_filter.c
+)
+
+add_executable(paltest_pal_except_filter_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_except_filter_test2 coreclrpal)
+
+target_link_libraries(paltest_pal_except_filter_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/pal_except_filter.c b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/pal_except_filter.c
new file mode 100644
index 0000000000..ccf53fb0ba
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/pal_except_filter.c
@@ -0,0 +1,154 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: pal_except_filter.c (test 2)
+**
+** Purpose: Tests the PAL implementation of the PAL_EXCEPT_FILTER. An
+** exception is forced and the filter returns
+** EXCEPTION_CONTINUE_EXECUTION to allow execution to continue.
+**
+**
+**===================================================================*/
+
+
+#include <palsuite.h>
+
+char* p; /* pointer to be abused */
+
+BOOL bFilter = FALSE;
+BOOL bTry = FALSE;
+BOOL bTry2 = FALSE;
+BOOL bContinued = FALSE;
+const int nValidator = 12321;
+
+LONG ExitFilter(EXCEPTION_POINTERS* ep, LPVOID pnTestInt)
+{
+ int nTestInt = *(int *)pnTestInt;
+ void *Temp;
+
+ /* let the main know we've hit the filter function */
+ bFilter = TRUE;
+
+ if (!bTry)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The filter was hit without PAL_TRY being hit.\n");
+ }
+
+ /* was the correct value passed? */
+ if (nValidator != nTestInt)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Parameter passed to filter function"
+ " should have been \"%d\" but was \"%d\".\n",
+ nValidator,
+ nTestInt);
+ }
+
+ /* Are we dealing with the exception we expected? */
+ if (EXCEPTION_ACCESS_VIOLATION != ep->ExceptionRecord->ExceptionCode)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Unexpected Exception"
+ " should have been \"%x\" but was \"%x\".\n",
+ EXCEPTION_ACCESS_VIOLATION,
+ ep->ExceptionRecord->ExceptionCode);
+ }
+
+ /* attempt to correct the problem by commiting the page at address 'p' */
+ Temp= VirtualAlloc(p, 1, MEM_COMMIT, PAGE_READWRITE);
+ if (!Temp)
+ {
+ Fail("EXCEPTION_CONTINUE_EXECUTION: last error = %u - probably "
+ "out of memory. Unable to continue, not proof of exception "
+ "failure\n",
+ GetLastError());
+ }
+ /* The memory that 'p' points to is now valid */
+
+ return EXCEPTION_CONTINUE_EXECUTION;
+}
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ BOOL bExcept = FALSE;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /*
+ ** test to make sure we get into the exception block
+ */
+
+ PAL_TRY
+ {
+ if (bExcept)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER was hit before PAL_TRY.\n");
+ }
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+
+ /* reserve an address chunk for p to point to */
+ p = (char*) VirtualAlloc(0, 1, MEM_RESERVE, PAGE_READONLY);
+ if (!p)
+ {
+ Fail("EXCEPTION_CONTINUE_EXECUTION: test setup via "
+ "VirtualAlloc failed.\n");
+ }
+
+ *p = 13; /* causes an access violation exception */
+
+ bTry2 = TRUE;
+
+
+ }
+ PAL_EXCEPT_FILTER(ExitFilter, (LPVOID)&nValidator)
+ {
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT_FILTER block */
+ Fail("PAL_EXCEPT_FILTER: ERROR -> in handler despite filter's "
+ "continue choice\n");
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the PAL_TRY"
+ " block was not executed.\n");
+ }
+
+ if (bExcept)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the "
+ "PAL_EXCEPT_FILTER block was executed.\n");
+ }
+
+ if (!bFilter)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the filter"
+ " function was not executed.\n");
+ }
+
+
+ if (!bTry2)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the PAL_TRY"
+ " block after the exception causing statements was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || bExcept || !bFilter)
+ {
+ Fail("");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/testinfo.dat b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/testinfo.dat
new file mode 100644
index 0000000000..729d2a4c49
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = exception_handling
+Function = PAL_EXCEPT_FILTER
+Name = Test for PAL_EXCEPT_FILTER
+Type = DEFAULT
+EXE1 = pal_except_filter
+LANG = cpp
+Description
+= Tests the PAL implementation of the PAL_EXCEPT_FILTER. An
+= exception is forced and the filter returns
+= EXCEPTION_CONTINUE_EXECUTION to allow execution to continue.
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/CMakeLists.txt
new file mode 100644
index 0000000000..cc68fb031c
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ pal_except_filter.c
+)
+
+add_executable(paltest_pal_except_filter_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_except_filter_test3 coreclrpal)
+
+target_link_libraries(paltest_pal_except_filter_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/pal_except_filter.c b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/pal_except_filter.c
new file mode 100644
index 0000000000..20c36840b1
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/pal_except_filter.c
@@ -0,0 +1,206 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: pal_except_filter.c (test 3)
+**
+** Purpose: Tests the PAL implementation of the PAL_EXCEPT_FILTER in the
+** presence of a call stack. An
+** exception is forced and passed to two nested exception filters for
+** consideration. The first filter returns EXCEPTION_CONTINUE_SEARCH
+** so the second can run and return EXCEPTION_EXECUTE_HANDLER. The
+** initial exception handler should be skipped, and the second
+** executed
+**
+**
+**===================================================================*/
+
+
+
+#include <palsuite.h>
+
+BOOL bFilterCS = FALSE;
+BOOL bFilterEE = FALSE;
+BOOL bTry1 = FALSE;
+BOOL bTry2 = FALSE;
+BOOL bExcept1 = FALSE;
+BOOL bExcept2 = FALSE;
+BOOL bContinued = FALSE;
+const int nValidator = 12321;
+
+LONG ContSearchFilter(EXCEPTION_POINTERS* ep, LPVOID pnTestInt)
+{
+
+ /* let the main know we've hit the filter function */
+ bFilterCS = TRUE;
+
+ if (!bTry1 || !bTry2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The ContSearch filter was hit without PAL_TRY being hit.\n");
+ }
+
+ if (bFilterEE)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The ContSearch filter was hit after the ExecuteException "
+ "filter.\n");
+ }
+
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
+LONG ExecExeptionFilter(EXCEPTION_POINTERS* ep, LPVOID pnTestInt)
+{
+ /* let the main know we've hit the filter function */
+ bFilterEE = TRUE;
+
+ if (!bTry1 || !bTry2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The ContSearch filter was hit without PAL_TRY being hit.\n");
+ }
+
+ if (!bFilterCS)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The ExecExeption filter was hit before the ContSearch "
+ "filter.\n");
+ }
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+void NestedFunc1 (void)
+{
+ int* p = 0x00000000; /* pointer to NULL */
+
+ PAL_TRY
+ {
+ if (bExcept1 || bExcept2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER was hit before PAL_TRY.\n");
+ }
+ bTry2 = TRUE; /* indicate we hit the inner PAL_TRY block */
+ *p = 13; /* causes an access violation exception */
+
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " We executed beyond the trapping code.\n");
+ }
+ PAL_EXCEPT_FILTER(ContSearchFilter, (LPVOID)&nValidator)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The dummy handler was "
+ "being hit.\n");
+ bExcept2 = TRUE; /* indicate we hit the inner block */
+ }
+ PAL_ENDTRY;
+
+}
+
+void NestedFunc2 (void)
+{
+ NestedFunc1();
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /*
+ ** test to make sure we get into the second exception block only based
+ ** on the return codes of the filters
+ */
+
+ PAL_TRY
+ {
+ if (bExcept1 || bExcept2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER was hit before PAL_TRY.\n");
+ }
+ bTry1 = TRUE; /* indicate we hit the outer PAL_TRY block */
+
+ NestedFunc2();
+
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " We executed beyond the trapping code.\n");
+ }
+ PAL_EXCEPT_FILTER(ExecExeptionFilter, (LPVOID)&nValidator)
+ {
+ if (!bTry1)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER's handler was hit without PAL_TRY's code "
+ "being hit.\n");
+ }
+ if (!bTry2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER's handler was hit without PAL_TRY's code "
+ "being hit.\n");
+ }
+ if (!bFilterCS)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER's handler was hit without the inner filter "
+ "being hit.\n");
+ }
+ if (!bFilterEE)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER's handler was hit without the outer filter "
+ "being hit.\n");
+ }
+ bExcept1 = TRUE; /* indicate we hit the outer block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry1)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the outer"
+ " PAL_TRY block was not executed.\n");
+ }
+
+ if (bExcept2)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the "
+ "inner PAL_EXCEPT_FILTER block was executed.\n");
+ }
+ if (!bExcept1)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the "
+ "outer PAL_EXCEPT_FILTER block was not executed.\n");
+ }
+
+ if (!bFilterCS)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the "
+ "search continuing filter"
+ " function was not executed.\n");
+ }
+ if (!bFilterEE)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the "
+ "execute handler filter"
+ " function was not executed.\n");
+ }
+
+
+ /* did we hit all the code blocks? */
+ if(!bTry1 || !bTry2 || !bExcept1 || bExcept2 || !bFilterEE || !bFilterCS )
+ {
+ Fail("");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/testinfo.dat b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/testinfo.dat
new file mode 100644
index 0000000000..d2df399392
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/testinfo.dat
@@ -0,0 +1,19 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = exception_handling
+Function = PAL_EXCEPT_FILTER_EX
+Name = Test for nested PAL_EXCEPT_FILTER functions & EXCEPTION_CONTINUE_SEARCH
+Type = DEFAULT
+EXE1 = pal_except_filter
+LANG = cpp
+Description
+= Tests the PAL implementation of the PAL_EXCEPT_FILTER with nested
+= functions to build a call stack. An
+= exception is forced and passed to two nested exception filters for
+= consideration. The first filter returns EXCEPTION_CONTINUE_SEARCH
+= so the second can run and return EXCEPTION_EXECUTE_HANDLER. The
+= initial exception handler should be skipped, and the second
+= executed
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/CMakeLists.txt
new file mode 100644
index 0000000000..1962ade358
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/CMakeLists.txt
new file mode 100644
index 0000000000..21c3b5d33c
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ PAL_EXCEPT_FILTER_EX.c
+)
+
+add_executable(paltest_pal_except_filter_ex_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_except_filter_ex_test1 coreclrpal)
+
+target_link_libraries(paltest_pal_except_filter_ex_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/PAL_EXCEPT_FILTER_EX.c b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/PAL_EXCEPT_FILTER_EX.c
new file mode 100644
index 0000000000..91f392d8d7
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/PAL_EXCEPT_FILTER_EX.c
@@ -0,0 +1,197 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: PAL_EXCEPT_FILTER_EX.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the PAL_EXCEPT_FILTER_EX.
+** There are two try blocks in this test. The first forces an
+** exception error to force hitting the first filter. The second
+** doesn't to make sure we don't hit the filter. A value is also
+** passed into the filter program and it is validated to make sure
+** it was passed correctly.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+BOOL bFilter = FALSE;
+BOOL bTry = FALSE;
+const int nValidator = 12321;
+
+
+/**
+**
+** Filter function for the first try block
+**
+**/
+
+LONG Filter_01(EXCEPTION_POINTERS* ep, VOID *pnTestInt)
+{
+ int nTestInt = *(int *)pnTestInt;
+
+ /* let the main know we've hit the filter function */
+ bFilter = TRUE;
+
+ if (!bTry)
+ {
+ Fail("PAL_EXCEPT_FILTER_EX: ERROR -> Something weird is going on."
+ " The filter was hit without PAL_TRY being hit.\n");
+ }
+
+ /* was the correct value passed? */
+ if (nValidator != nTestInt)
+ {
+ Fail("PAL_EXCEPT_FILTER_EX: ERROR -> Parameter passed to filter"
+ " function should have been \"%d\" but was \"%d\".\n",
+ nValidator,
+ nTestInt);
+ }
+
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+
+/**
+**
+** Filter function for the second try block. We shouldn't
+** hit this function.
+**
+**/
+
+LONG Filter_02(EXCEPTION_POINTERS* ep, VOID *pnTestInt)
+{
+ /* let the main know we've hit the filter function */
+ bFilter = TRUE;
+
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int* p = 0x00000000;
+ BOOL bExcept = FALSE;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /*
+ ** test to make sure we get into the exception block
+ */
+
+ PAL_TRY
+ {
+ if (bExcept)
+ {
+ Fail("PAL_EXCEPT_FILTER_EX: ERROR -> Something weird is going on."
+ " The first PAL_EXCEPT_FILTER_EX was hit before PAL_TRY.\n");
+ }
+
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+ *p = 13; /* causes an access violation exception */
+
+ Fail("PAL_EXCEPT_FILTER_EX: ERROR -> code was executed after the "
+ "access violation.\n");
+ }
+ PAL_EXCEPT_FILTER(Filter_01, (LPVOID)&nValidator)
+ {
+ if (!bTry)
+ {
+ Fail("PAL_EXCEPT_FILTER_EX: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER_EX was hit without PAL_TRY being hit.\n");
+ }
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT_FILTER_EX block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("PAL_EXCEPT_FILTER_EX: ERROR -> It appears the code in the "
+ "first PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("PAL_EXCEPT_FILTER_EX: ERROR -> It appears the code in the "
+ "first PAL_EXCEPT_FILTER_EX block was not executed.\n");
+ }
+
+ if (!bFilter)
+ {
+ Trace("PAL_EXCEPT_FILTER_EX: ERROR -> It appears the code in the first"
+ " filter function was not executed.\n");
+ }
+
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept || !bFilter)
+ {
+ Fail("");
+ }
+
+ bTry = bExcept = bFilter = FALSE;
+
+
+ /*
+ ** test to make sure we skip the exception block
+ */
+
+ PAL_TRY
+ {
+ if (bExcept)
+ {
+ Fail("PAL_EXCEPT_FILTER_EX: ERROR -> Something weird is going on."
+ " Second PAL_EXCEPT_FILTER_EX was hit before PAL_TRY.\n");
+ }
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+ }
+ PAL_EXCEPT_FILTER(Filter_02, (LPVOID)&nValidator)
+ {
+ if (!bTry)
+ {
+ Fail("PAL_EXCEPT_FILTER_EX: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER_EX was hit without PAL_TRY being hit.\n");
+ }
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT_FILTER_EX block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("PAL_EXCEPT_FILTER_EX: ERROR -> It appears the code in the "
+ "second PAL_TRY block was not executed.\n");
+ }
+
+ if (bExcept)
+ {
+ Trace("PAL_EXCEPT_FILTER_EX: ERROR -> It appears the code in the "
+ "second PAL_EXCEPT_FILTER_EX block was executed even though an"
+ " exception was not triggered.\n");
+ }
+
+ if (bFilter)
+ {
+ Trace("PAL_EXCEPT_FILTER_EX: ERROR -> It appears the code in the second"
+ " filter function was executed even though an exception was"
+ " not triggered.\n");
+ }
+
+
+ /* did we hit all the correct code blocks? */
+ if(!bTry || bExcept || bFilter)
+ {
+ Fail("");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/testinfo.dat b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/testinfo.dat
new file mode 100644
index 0000000000..1d8f8f600e
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/testinfo.dat
@@ -0,0 +1,18 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = exception_handling
+Function = PAL_EXCEPT_FILTER_EX
+Name = Test for PAL_EXCEPT_FILTER_EX
+Type = DEFAULT
+EXE1 = pal_except_filter_ex
+LANG = cpp
+Description
+= Tests the PAL implementation of the PAL_EXCEPT_FILTER_EX.
+= There are two try blocks in this test. The first forces an
+= exception error to force hitting the first filter. The second
+= doesn't to make sure we don't hit the filter. A value is also
+= passed into the filter program and it is validated to make sure
+= it was passed correctly.
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/CMakeLists.txt
new file mode 100644
index 0000000000..350acff036
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ pal_except_filter_ex.c
+)
+
+add_executable(paltest_pal_except_filter_ex_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_except_filter_ex_test2 coreclrpal)
+
+target_link_libraries(paltest_pal_except_filter_ex_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/pal_except_filter_ex.c b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/pal_except_filter_ex.c
new file mode 100644
index 0000000000..ab25c49733
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/pal_except_filter_ex.c
@@ -0,0 +1,142 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: PAL_EXCEPT_FILTER_EX.c (test 2)
+**
+** Purpose: Tests the PAL implementation of the PAL_EXCEPT_FILTER_EX.
+** There is a nested try blocks in this test. The nested
+** PAL_TRY creates an exception and the FILTER creates another.
+** This test makes sure that this case does not end in a
+** infinite loop.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+BOOL bFilter = FALSE;
+BOOL bTry = FALSE;
+BOOL bTry2 = FALSE;
+const int nValidator = 12321;
+
+/* Filter function for the first try block.
+ */
+LONG Filter_01(EXCEPTION_POINTERS* ep, VOID *pnTestInt)
+{
+ int nTestInt = *(int *)pnTestInt;
+
+ /* Signal main() that filter has been executed. */
+ bFilter = TRUE;
+
+ if (!bTry)
+ {
+ Fail("ERROR: The filter was executed without "
+ "entering the first PAL_TRY.\n");
+ }
+
+ if (!bTry2)
+ {
+ Fail("ERROR: The filter was executed without "
+ "entering the second PAL_TRY.\n");
+ }
+
+ /* Was the correct value passed? */
+ if (nValidator != nTestInt)
+ {
+ Fail("ERROR: Parameter passed to filter function "
+ "should have been \"%d\" but was \"%d\".\n",
+ nValidator,
+ nTestInt);
+ }
+
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ int* p = 0x00000000;
+ BOOL bExcept = FALSE;
+ BOOL bExcept2 = FALSE;
+
+ /* Initalize the PAL.
+ */
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Test a nested PAL_Try block.
+ */
+ PAL_TRY
+ {
+ /* Signal entry into first PAL_TRY block.*/
+ bTry = TRUE;
+
+ PAL_TRY
+ {
+ /* Signal entry into second PAL_TRY block.*/
+ bTry2 = TRUE;
+ /* Cause an exception.*/
+ *p = 13;
+ }
+ PAL_EXCEPT_FILTER(Filter_01, (LPVOID)&nValidator)
+ {
+ /* Signal entry into second PAL_EXCEPT filter.*/
+ bExcept = TRUE;
+ /* Cause another exception.*/
+ *p = 13;
+ }
+ PAL_ENDTRY
+
+ }
+ PAL_EXCEPT_FILTER(Filter_01, (LPVOID)&nValidator)
+ {
+ /* Signal entry into second PAL_EXCEPT filter.*/
+ bExcept2 = TRUE;
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("ERROR: The code in the first "
+ "PAL_TRY block was not executed.\n");
+ }
+
+ if (!bTry2)
+ {
+ Trace("ERROR: The code in the nested "
+ "PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("ERROR: The code in the first "
+ "PAL_EXCEPT_FILTER_EX block was not executed.\n");
+ }
+
+ if (!bExcept2)
+ {
+ Trace("ERROR: The code in the second "
+ "PAL_EXCEPT_FILTER_EX block was not executed.\n");
+ }
+
+ if (!bFilter)
+ {
+ Trace("ERROR: The code in the first "
+ "filter function was not executed.\n");
+ }
+
+ if(!bTry || !bTry2 || !bExcept || !bExcept2 || !bFilter )
+ {
+ Fail("");
+ }
+
+ /* Terminate the PAL.
+ */
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/testinfo.dat b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/testinfo.dat
new file mode 100644
index 0000000000..0343d133e8
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = exception_handling
+Function = PAL_EXCEPT_FILTER_EX
+Name = Test for PAL_EXCEPT_FILTER_EX
+Type = DEFAULT
+EXE1 = pal_except_filter_ex
+LANG = cpp
+Description
+= Tests the PAL implementation of the PAL_EXCEPT_FILTER_EX.
+= There is a nested try blocks in this test. The nested
+= PAL_TRY creates an exception and the FILTER creates another.
+= This test makes sure that this case does not end in a
+= infinite loop.
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/CMakeLists.txt
new file mode 100644
index 0000000000..7f485c8ca4
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ pal_except_filter.c
+)
+
+add_executable(paltest_pal_except_filter_ex_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_except_filter_ex_test3 coreclrpal)
+
+target_link_libraries(paltest_pal_except_filter_ex_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/pal_except_filter.c b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/pal_except_filter.c
new file mode 100644
index 0000000000..a17cb4f6b3
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/pal_except_filter.c
@@ -0,0 +1,208 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: pal_except_filter_ex.c (test 3)
+**
+** Purpose: Tests the PAL implementation of the PAL_EXCEPT_FILTER_EX. An
+** exception is forced and passed to two nested exception filters for
+** consideration. The first filter returns EXCEPTION_CONTINUE_SEARCH
+** so the second can run and return EXCEPTION_EXECUTE_HANDLER. The
+** initial exception handler should be skipped, and the second
+** executed
+**
+**
+**===================================================================*/
+
+
+
+#include <palsuite.h>
+
+BOOL bFilterCS = FALSE;
+BOOL bFilterEE = FALSE;
+BOOL bTry1 = FALSE;
+BOOL bTry2 = FALSE;
+BOOL bContinued = FALSE;
+const int nValidator = 12321;
+
+LONG ContSearchFilter(EXCEPTION_POINTERS* ep, LPVOID pnTestInt)
+{
+
+ /* let the main know we've hit the filter function */
+ bFilterCS = TRUE;
+
+ if (!bTry1 || !bTry2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The ContSearch filter was hit without PAL_TRY being hit.\n");
+ }
+
+ if (bFilterEE)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The ContSearch filter was hit after the ExecuteException "
+ "filter.\n");
+ }
+
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
+LONG ExecExeptionFilter(EXCEPTION_POINTERS* ep, LPVOID pnTestInt)
+{
+ /* let the main know we've hit the filter function */
+ bFilterEE = TRUE;
+
+ if (!bTry1 || !bTry2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The ContSearch filter was hit without PAL_TRY being hit.\n");
+ }
+
+ if (!bFilterCS)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The ExecExeption filter was hit before the ContSearch "
+ "filter.\n");
+ }
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ int* p = 0x00000000; /* pointer to NULL */
+ BOOL bExcept1 = FALSE;
+ BOOL bExcept2 = FALSE;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /*
+ ** test to make sure we get into the second exception block only based
+ ** on the return codes of the filters
+ */
+
+ PAL_TRY
+ {
+ if (bExcept1 || bExcept2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER was hit before PAL_TRY.\n");
+ }
+ bTry1 = TRUE; /* indicate we hit the outer PAL_TRY block */
+
+ PAL_TRY
+ {
+ if (bExcept1 || bExcept2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER was hit before PAL_TRY.\n");
+ }
+ bTry2 = TRUE; /* indicate we hit the inner PAL_TRY block */
+ *p = 13; /* causes an access violation exception */
+
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " We executed beyond the trapping code.\n");
+ }
+
+ PAL_EXCEPT_FILTER(ContSearchFilter, (LPVOID)&nValidator)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The dummy handler was "
+ "being hit.\n");
+ }
+ PAL_ENDTRY;
+
+ bExcept2 = TRUE; /* indicate we hit the inner block */
+ }
+ PAL_EXCEPT_FILTER(ExecExeptionFilter, (LPVOID)&nValidator)
+ {
+ if (!bTry1)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER's handler was hit without PAL_TRY's code "
+ "being hit.\n");
+ }
+ if (!bTry2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER's handler was hit without PAL_TRY's code "
+ "being hit.\n");
+ }
+ if (!bFilterCS)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on. "
+ "PAL_EXCEPT_FILTER's handler was hit without "
+ "the inner filter being hit.\n");
+ }
+ if (!bFilterEE)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on. "
+ "PAL_EXCEPT_FILTER's handler was hit without "
+ "the outer filter being hit.\n");
+ }
+ bExcept1 = TRUE; /* indicate we hit the outer block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry1)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the outer"
+ " PAL_TRY block was not executed.\n");
+ }
+
+ if (!bTry2)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the inner"
+ " PAL_TRY block was not executed.\n");
+ }
+
+ if (bExcept2)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the "
+ "inner PAL_EXCEPT_FILTER block was executed.\n");
+ }
+ if (!bExcept1)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the "
+ "outer PAL_EXCEPT_FILTER block was not executed.\n");
+ }
+
+ if (!bFilterCS)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the "
+ "search continuing filter"
+ " function was not executed.\n");
+ }
+ if (!bFilterEE)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the "
+ "execute handler filter"
+ " function was not executed.\n");
+ }
+
+
+ if (!bTry2)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the PAL_TRY "
+ "block after the exception causing statements "
+ "was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry1 || !bTry2 || !bExcept1 || bExcept2 || !bFilterEE || !bFilterCS )
+ {
+ Fail("");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/testinfo.dat b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/testinfo.dat
new file mode 100644
index 0000000000..568296c399
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/testinfo.dat
@@ -0,0 +1,18 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = exception_handling
+Function = PAL_EXCEPT_FILTER_EX
+Name = Test for nested PAL_EXCEPT_FILTER_EX & EXCEPTION_CONTINUE_SEARCH
+Type = DEFAULT
+EXE1 = pal_except_filter
+LANG = cpp
+Description
+= Tests the PAL implementation of the PAL_EXCEPT_FILTER_EX. An
+= exception is forced and passed to two nested exception filters for
+= consideration. The first filter returns EXCEPTION_CONTINUE_SEARCH
+= so the second can run and return EXCEPTION_EXECUTE_HANDLER. The
+= initial exception handler should be skipped, and the second
+= executed
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/CMakeLists.txt
new file mode 100644
index 0000000000..8a1a832361
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ PAL_TRY_EXCEPT.c
+)
+
+add_executable(paltest_pal_try_except_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_try_except_test1 coreclrpal)
+
+target_link_libraries(paltest_pal_try_except_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/PAL_TRY_EXCEPT.c b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/PAL_TRY_EXCEPT.c
new file mode 100644
index 0000000000..4fb09bd276
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/PAL_TRY_EXCEPT.c
@@ -0,0 +1,82 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: PAL_TRY_EXCEPT.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the PAL_TRY and
+** PAL_EXCEPT functions. An exception is forced to ensure
+** the exception block is hit.
+**
+**
+**===================================================================*/
+
+
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int* p = 0x00000000; /* NULL pointer */
+ BOOL bTry = FALSE;
+ BOOL bExcept = FALSE;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /*
+ ** test to make sure we get into the exception block
+ */
+
+ PAL_TRY
+ {
+ if (bExcept)
+ {
+ Fail("PAL_TRY_EXCEPT: ERROR -> Something weird is going on."
+ " PAL_EXCEPT was hit before PAL_TRY.\n");
+ }
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+ *p = 13; /* causes an access violation exception */
+ Fail("PAL_TRY_EXCEPT: ERROR -> code was executed after the "
+ "access violation.\n");
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTry)
+ {
+ Fail("PAL_TRY_EXCEPT: ERROR -> Something weird is going on."
+ " PAL_EXCEPT was hit without PAL_TRY being hit.\n");
+ }
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the PAL_TRY"
+ " block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the PAL_EXCEPT"
+ " block was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept)
+ {
+ Fail("");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/testinfo.dat b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/testinfo.dat
new file mode 100644
index 0000000000..1f663a8bc5
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = exception_handling
+Function = PAL_TRY and PAL_EXCEPT
+Name = Test for PAL_TRY and PAL_EXCEPT
+Type = DEFAULT
+EXE1 = pal_try_except
+LANG = cpp
+Description
+= Since these two are so closely connected, they are tested together.
+= In the PAL_TRY block, an access violation is forced to gain
+= access to the PAL_EXCEPT block. Booleans are used to ensure
+= each of the code blocks are hit.
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/CMakeLists.txt
new file mode 100644
index 0000000000..cdf371926c
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ PAL_TRY_EXCEPT.c
+)
+
+add_executable(paltest_pal_try_except_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_try_except_test2 coreclrpal)
+
+target_link_libraries(paltest_pal_try_except_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/PAL_TRY_EXCEPT.c b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/PAL_TRY_EXCEPT.c
new file mode 100644
index 0000000000..eb7b9d1257
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/PAL_TRY_EXCEPT.c
@@ -0,0 +1,68 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: PAL_TRY_EXCEPT.c (test 2)
+**
+** Purpose: Tests the PAL implementation of the PAL_TRY and
+** PAL_EXCEPT functions. Tests that the EXCEPTION block
+** is missed if no exceptions happen
+**
+**
+**===================================================================*/
+
+
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ BOOL bTry = FALSE;
+ BOOL bExcept = FALSE;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /*
+ ** Test to make sure we skip the exception block.
+ */
+
+ PAL_TRY
+ {
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the PAL_TRY"
+ " block was not executed.\n");
+ }
+
+ if (bExcept)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the PAL_EXCEPT"
+ " block was executed even though no exception was supposed to"
+ " happen.\n");
+ }
+
+ /* did we hit the correct code blocks? */
+ if(!bTry || bExcept)
+ {
+ Fail("");
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/testinfo.dat b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/testinfo.dat
new file mode 100644
index 0000000000..a5815f5722
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = exception_handling
+Function = PAL_TRY and PAL_EXCEPT (test 2)
+Name = Test for PAL_TRY and PAL_EXCEPT
+Type = DEFAULT
+EXE1 = pal_try_except
+LANG = cpp
+Description
+= Since these two are so closely connected, they are tested together.
+= In this test, no exceptions are forced to ensure the EXCEPTION block
+= isn't hit. Booleans are used to ensure the proper code blocks are hit.
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/CMakeLists.txt
new file mode 100644
index 0000000000..1962ade358
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/CMakeLists.txt
new file mode 100644
index 0000000000..c30877f65e
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ PAL_TRY_EXCEPT_EX.c
+)
+
+add_executable(paltest_pal_try_except_ex_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_try_except_ex_test1 coreclrpal)
+
+target_link_libraries(paltest_pal_try_except_ex_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/PAL_TRY_EXCEPT_EX.c b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/PAL_TRY_EXCEPT_EX.c
new file mode 100644
index 0000000000..8b4dd7b430
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/PAL_TRY_EXCEPT_EX.c
@@ -0,0 +1,133 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: PAL_TRY_EXCEPT.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the PAL_TRY and
+** PAL_EXCEPT functions. Exceptions are forced to ensure
+** the exception blocks are hit.
+**
+**
+**===================================================================*/
+
+
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int* p = 0x00000000; /* NULL pointer */
+ BOOL bTry = FALSE;
+ BOOL bExcept = FALSE;
+ BOOL bTestA = TRUE;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /*
+ ** test to make sure we get into the exception block
+ */
+
+ PAL_TRY
+ {
+ if (!bTestA)
+ {
+ Fail("PAL_TRY_EXCEPT: ERROR ->"
+ " It appears the first try block was hit a second time.\n");
+ }
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+ *p = 13; /* causes an access violation exception */
+ Fail("PAL_TRY_EXCEPT: ERROR -> code was executed after the "
+ "access violation.\n");
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTestA)
+ {
+ Fail("PAL_TRY_EXCEPT: ERROR ->"
+ " It appears the first except block was hit a second time.\n");
+ }
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the PAL_TRY"
+ " block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the first"
+ " PAL_EXCEPT block was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept)
+ {
+ Fail("");
+ }
+
+
+ /*
+ ** test to make sure we get into the second exception block
+ */
+
+ bTry = FALSE;
+ bExcept = FALSE;
+ bTestA = FALSE; /* we are now going into the second block test */
+
+
+ PAL_TRY
+ {
+ if (bTestA)
+ {
+ Fail("PAL_TRY_EXCEPT: ERROR -> It appears"
+ " the second try block was hit too early.\n");
+ }
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+ *p = 13; /* causes an access violation exception */
+ Fail("PAL_TRY_EXCEPT: ERROR -> code was executed after the "
+ "access violation.\n");
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (bTestA)
+ {
+ Fail("PAL_TRY_EXCEPT: ERROR -> It appears"
+ " the second except block was hit too early.\n");
+ }
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the second"
+ " PAL_TRY block was not executed.");
+ }
+
+ if (!bExcept)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the PAL_EXCEPT"
+ " block was not executed.");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept)
+ {
+ Fail("\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/testinfo.dat b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/testinfo.dat
new file mode 100644
index 0000000000..b571427935
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = exception_handling
+Function = PAL_TRY and PAL_EXCEPT_EX
+Name = Test for PAL_TRY and PAL_EXCEPT_EX
+Type = DEFAULT
+EXE1 = pal_try_except_ex
+LANG = cpp
+Description
+= Since these two are so closely connected, they are tested together.
+= In the PAL_TRY block, an access violation is forced to gain
+= access to the PAL_EXCEPT block. Booleans are used to ensure
+= each of the code blocks are hit.
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/CMakeLists.txt
new file mode 100644
index 0000000000..0d4c4db240
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ PAL_TRY_EXCEPT_EX.c
+)
+
+add_executable(paltest_pal_try_except_ex_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_try_except_ex_test2 coreclrpal)
+
+target_link_libraries(paltest_pal_try_except_ex_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/PAL_TRY_EXCEPT_EX.c b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/PAL_TRY_EXCEPT_EX.c
new file mode 100644
index 0000000000..5ab4a95ce9
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/PAL_TRY_EXCEPT_EX.c
@@ -0,0 +1,123 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: PAL_TRY_EXCEPT.c (test 2)
+**
+** Purpose: Tests the PAL implementation of the PAL_TRY and
+** PAL_EXCEPT functions. Exceptions are not forced to ensure
+** the proper blocks are hit.
+**
+**
+**===================================================================*/
+
+
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ BOOL bTry = FALSE;
+ BOOL bExcept = FALSE;
+ BOOL bTestA = TRUE;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /*
+ ** test to make sure we get into the exception block
+ */
+
+ PAL_TRY
+ {
+ if (!bTestA)
+ {
+ Fail("PAL_TRY_EXCEPT: ERROR ->"
+ " It appears the first try block was hit a second time.\n");
+ }
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the PAL_TRY"
+ " block was not executed.\n");
+ }
+
+ if (bExcept)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the first"
+ " PAL_EXCEPT block was executed even though no exceptions were "
+ "encountered.\n");
+ }
+
+ /* did we hit all the proper code blocks? */
+ if(!bTry || bExcept)
+ {
+ Fail("");
+ }
+
+
+ /*
+ ** test to make sure we skip the second exception block
+ */
+
+ bTry = FALSE;
+ bExcept = FALSE;
+ bTestA = FALSE; /* we are now going into the second block test */
+
+
+ PAL_TRY
+ {
+ if (bTestA)
+ {
+ Fail("PAL_TRY_EXCEPT: ERROR -> It appears"
+ " the second try block was hit too early.\n");
+ }
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (bTestA)
+ {
+ Fail("PAL_TRY_EXCEPT: ERROR -> It appears"
+ " the second except block was hit too early.\n");
+ }
+ bExcept = TRUE; /* indicate we hit the PAL_TRY block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the second"
+ " PAL_TRY block was not executed.\n");
+ }
+
+ if (bExcept)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the second"
+ " PAL_EXCEPT block was executed even though no exceptions were "
+ "encountered.\n");
+ }
+
+ /* did we hit all the proper code blocks? */
+ if(!bTry || bExcept)
+ {
+ Fail("\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/testinfo.dat b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/testinfo.dat
new file mode 100644
index 0000000000..f71964da1c
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = exception_handling
+Function = PAL_TRY and PAL_EXCEPT_EX (test 2)
+Name = Test for PAL_TRY and PAL_EXCEPT_EX
+Type = DEFAULT
+EXE1 = pal_try_except_ex
+LANG = cpp
+Description
+= Since these two are so closely connected, they are tested together.
+= In this test, no exceptions are forced to ensure the EXCEPTION block
+= isn't hit. Booleans are used to ensure the proper code blocks are hit.
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/CMakeLists.txt
new file mode 100644
index 0000000000..dc797f2f09
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ PAL_TRY_EXCEPT_EX.c
+)
+
+add_executable(paltest_pal_try_except_ex_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_try_except_ex_test3 coreclrpal)
+
+target_link_libraries(paltest_pal_try_except_ex_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/PAL_TRY_EXCEPT_EX.c b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/PAL_TRY_EXCEPT_EX.c
new file mode 100644
index 0000000000..d6a948926b
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/PAL_TRY_EXCEPT_EX.c
@@ -0,0 +1,130 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: PAL_TRY_EXCEPT.c (test 3)
+**
+** Purpose: Tests the PAL implementation of the PAL_TRY and
+** PAL_EXCEPT functions. Force an exception in only one block
+** to ensure the proper exception block is hit.
+**
+**
+**===================================================================*/
+
+
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int* p = 0x00000000; /* NULL pointer */
+ BOOL bTry = FALSE;
+ BOOL bExcept = FALSE;
+ BOOL bTestA = TRUE;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /*
+ ** test to make sure we get into the exception block
+ */
+
+ PAL_TRY
+ {
+ if (!bTestA)
+ {
+ Fail("PAL_TRY_EXCEPT: ERROR ->"
+ " It appears the first try block was hit a second time.\n");
+ }
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+ *p = 13; /* causes an access violation exception */
+ Fail("PAL_TRY_EXCEPT: ERROR -> code was executed after the "
+ "access violation.\n");
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTestA)
+ {
+ Fail("PAL_TRY_EXCEPT: ERROR ->"
+ " It appears the first except block was hit a second time.\n");
+ }
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the PAL_TRY"
+ " block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the first"
+ " PAL_EXCEPT block was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept)
+ {
+ Fail("\n");
+ }
+
+
+ /*
+ ** test to make sure we get into the second exception block
+ */
+
+ bTry = FALSE;
+ bExcept = FALSE;
+ bTestA = FALSE; /* we are now going into the second block test */
+
+
+ PAL_TRY
+ {
+ if (bTestA)
+ {
+ Fail("PAL_TRY_EXCEPT: ERROR -> It appears"
+ " the second try block was hit too early.\n");
+ }
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (bTestA)
+ {
+ Fail("PAL_TRY_EXCEPT: ERROR -> It appears"
+ " the second except block was hit too early.\n");
+ }
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the second"
+ " PAL_TRY block was not executed.\n");
+ }
+
+ if (bExcept)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the second "
+ " PAL_EXCEPT block was executed for some reason.\n");
+ }
+
+ /* did we hit all the correct code blocks? */
+ if(!bTry || bExcept)
+ {
+ Fail("\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/testinfo.dat b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/testinfo.dat
new file mode 100644
index 0000000000..a245447088
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = exception_handling
+Function = PAL_TRY and PAL_EXCEPT_EX (test3)
+Name = Test for PAL_TRY and PAL_EXCEPT_EX
+Type = DEFAULT
+EXE1 = pal_try_except_ex
+LANG = cpp
+Description
+= Since these two are so closely connected, they are tested together.
+= Only one of the PAL_TRY blocks will force and exception to ensure the
+= correct PAL_EXCEPT_EX block is hit. Booleans are used to ensure
+= the correct code blocks are hit.
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/CMakeLists.txt
new file mode 100644
index 0000000000..a5fdd26924
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ PAL_TRY_LEAVE_FINALLY.c
+)
+
+add_executable(paltest_pal_try_leave_finally_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_try_leave_finally_test1 coreclrpal)
+
+target_link_libraries(paltest_pal_try_leave_finally_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/PAL_TRY_LEAVE_FINALLY.c b/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/PAL_TRY_LEAVE_FINALLY.c
new file mode 100644
index 0000000000..675c2a5947
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/PAL_TRY_LEAVE_FINALLY.c
@@ -0,0 +1,77 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: pal_try_leave_finally.c
+**
+** Purpose: Tests the PAL implementation of the PAL_TRY, PAL_LEAVE
+** and PAL_FINALLY functions.
+**
+**
+**===================================================================*/
+
+
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ BOOL bTry = FALSE;
+ BOOL bFinally = FALSE;
+ BOOL bLeave = TRUE;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ PAL_TRY
+ {
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+
+ goto Done;
+
+ bLeave = FALSE; /* indicate we stuck around */
+ Done: ;
+ }
+ PAL_FINALLY
+ {
+ bFinally = TRUE; /* indicate we hit the PAL_FINALLY block */
+ }
+ PAL_ENDTRY;
+
+ /* did we go where we were meant to go */
+ if (!bTry)
+ {
+ Trace("PAL_TRY_FINALLY: ERROR -> It appears the code in the PAL_TRY"
+ " block was not executed.\n");
+ }
+
+ if (!bLeave)
+ {
+ Trace("PAL_TRY_FINALLY: ERROR -> It appears code was executed after "
+ "PAL_LEAVE was called. It should have jumped directly to the "
+ "PAL_FINALLY block.\n");
+ }
+
+ if (!bFinally)
+ {
+ Trace("PAL_TRY_FINALLY: ERROR -> It appears the code in the PAL_FINALLY"
+ " block was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bLeave || !bFinally)
+ {
+ Fail("");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/testinfo.dat b/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/testinfo.dat
new file mode 100644
index 0000000000..8a90ef392c
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = PAL_TRY, PAL_LEAVE and PAL_FINALLY
+Name = Test for PAL_TRY, PAL_LEAVE and PAL_EXCEPT
+Type = DEFAULT
+EXE1 = pal_try_leave_finally
+LANG = cpp
+Description
+= Since these three are so closely connected, they are tested together.
+= The PAL_TRY block contains a PAL_LEAVE which kicks execution to
+= the PAL_FINALLY block. Booleans are used to ensure each of the
+= code blocks are properly hit.
+
diff --git a/src/pal/tests/palsuite/exception_handling/RaiseException/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/RaiseException/CMakeLists.txt
new file mode 100644
index 0000000000..1962ade358
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/RaiseException/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+
diff --git a/src/pal/tests/palsuite/exception_handling/RaiseException/test1/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/RaiseException/test1/CMakeLists.txt
new file mode 100644
index 0000000000..2fba7dd9b3
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/RaiseException/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.cpp
+)
+
+add_executable(paltest_raiseexception_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_raiseexception_test1 coreclrpal)
+
+target_link_libraries(paltest_raiseexception_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/RaiseException/test1/test1.cpp b/src/pal/tests/palsuite/exception_handling/RaiseException/test1/test1.cpp
new file mode 100644
index 0000000000..9130bc362d
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/RaiseException/test1/test1.cpp
@@ -0,0 +1,130 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests that RaiseException throws a catchable exception
+** and Tests the behaviour of RaiseException with
+** PAL_FINALLY
+**
+**
+**============================================================*/
+
+
+#include <palsuite.h>
+
+BOOL bExcept = FALSE;
+BOOL bTry = FALSE;
+BOOL bFinally = FALSE;
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /*********************************************************
+ * Tests that RaiseException throws a catchable exception
+ */
+ PAL_TRY(VOID*, unused, NULL)
+ {
+ bTry = TRUE;
+ RaiseException(0,0,0,0);
+
+ Fail("RaiseException: ERROR -> code was executed after the "
+ "exception was raised.\n");
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ bExcept = TRUE;
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("RaiseException: ERROR -> It appears the code in the "
+ "PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("RaiseException: ERROR -> It appears the code in the "
+ "PAL_EXCEPT_FILTER_EX block was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept)
+ {
+ Fail("");
+ }
+
+ /* Reinit flags */
+ bTry = bExcept = FALSE;
+
+
+ /*********************************************************
+ * Tests the behaviour of RaiseException with
+ * PAL_FINALLY
+ * (bFinally should be set before bExcept)
+ */
+ PAL_TRY(VOID*, unused, NULL)
+ {
+ PAL_TRY(VOID*, unused, NULL)
+ {
+ bTry = TRUE;
+ RaiseException(0,0,0,0);
+
+ Fail("RaiseException: ERROR -> code was executed after the "
+ "exception was raised.\n");
+ }
+ PAL_FINALLY
+ {
+ bFinally = TRUE;
+ }
+ PAL_ENDTRY;
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if( bFinally == FALSE )
+ {
+ Fail("RaiseException: ERROR -> It appears the code in the "
+ "PAL_EXCEPT executed before the code in PAL_FINALLY.\n");
+ }
+
+ bExcept = TRUE;
+ }
+
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("RaiseException: ERROR -> It appears the code in the "
+ "PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("RaiseException: ERROR -> It appears the code in the "
+ "PAL_EXCEPT block was not executed.\n");
+ }
+
+ if (!bFinally)
+ {
+ Trace("RaiseException: ERROR -> It appears the code in the "
+ "PAL_FINALLY block was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept || !bFinally)
+ {
+ Fail("");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/exception_handling/RaiseException/test1/testinfo.dat b/src/pal/tests/palsuite/exception_handling/RaiseException/test1/testinfo.dat
new file mode 100644
index 0000000000..890b5efec7
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/RaiseException/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = exception_handling
+Function = RaiseException
+Name = RaiseException test #1
+TYPE = DEFAULT
+EXE1 = test1
+LANG = cpp
+Description
+=Tests that RaiseException throws a catchable exception
diff --git a/src/pal/tests/palsuite/exception_handling/RaiseException/test2/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/RaiseException/test2/CMakeLists.txt
new file mode 100644
index 0000000000..7fc9f5f12c
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/RaiseException/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.cpp
+)
+
+add_executable(paltest_raiseexception_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_raiseexception_test2 coreclrpal)
+
+target_link_libraries(paltest_raiseexception_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/RaiseException/test2/test2.cpp b/src/pal/tests/palsuite/exception_handling/RaiseException/test2/test2.cpp
new file mode 100644
index 0000000000..f8db573ac0
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/RaiseException/test2/test2.cpp
@@ -0,0 +1,224 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test2.c (exception_handling\raiseexception\test2)
+**
+** Purpose: Tests that the correct arguments are passed
+** to the filter by RaiseException and tests that
+** the number of arguments never exceeds
+** EXCEPTION_MAXIMUM_PARAMETERS, even though we
+** pass a greater number of arguments
+**
+**
+**============================================================*/
+
+
+#include <palsuite.h>
+
+BOOL bFilter;
+BOOL bTry;
+BOOL bExcept;
+
+ULONG_PTR lpArguments_test1[EXCEPTION_MAXIMUM_PARAMETERS];
+DWORD nArguments_test1 = EXCEPTION_MAXIMUM_PARAMETERS;
+
+ULONG_PTR lpArguments_test2[EXCEPTION_MAXIMUM_PARAMETERS+1];
+DWORD nArguments_test2 = EXCEPTION_MAXIMUM_PARAMETERS+1;
+
+
+/**
+**
+** Filter function that checks for the parameters
+**
+**/
+LONG Filter_test1(EXCEPTION_POINTERS* ep, VOID *unused)
+{
+ int i;
+
+ /* let the main know we've hit the filter function */
+ bFilter = TRUE;
+
+ if (!bTry)
+ {
+ Fail("PAL_EXCEPT_FILTER_EX: ERROR -> Something weird is going on."
+ " The filter was hit without PAL_TRY being hit.\n");
+ }
+
+
+ /* was the correct number of arguments passed */
+ if (ep->ExceptionRecord->NumberParameters != (DWORD) nArguments_test1)
+ {
+ Fail("RaiseException: ERROR -> Number of arguments passed to filter"
+ " was %d when it should have been %d",
+ ep->ExceptionRecord->NumberParameters,
+ nArguments_test1);
+
+ }
+
+ /* were the correct arguments passed */
+ for( i=0; ((DWORD)i)<nArguments_test1; i++ )
+ {
+ if( ep->ExceptionRecord->ExceptionInformation[i]
+ != lpArguments_test1[i])
+ {
+ Fail("RaiseException: ERROR -> Argument %d passed to filter"
+ " was %d when it should have been %d",
+ i,
+ ep->ExceptionRecord->ExceptionInformation[i],
+ lpArguments_test1[i]);
+ }
+ }
+
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+/**
+**
+** Filter function that checks for the maximum parameters
+**
+**/
+LONG Filter_test2(EXCEPTION_POINTERS* ep, VOID* unused)
+{
+ /* let the main know we've hit the filter function */
+ bFilter = TRUE;
+
+ if (ep->ExceptionRecord->NumberParameters > EXCEPTION_MAXIMUM_PARAMETERS)
+ {
+ Fail("RaiseException: ERROR -> Number of arguments passed to filter"
+ " was %d which is greater than the maximum allowed of %d\n",
+ ep->ExceptionRecord->NumberParameters,
+ EXCEPTION_MAXIMUM_PARAMETERS);
+ }
+
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ bExcept = FALSE;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /********************************************************
+ * Test that the correct arguments are passed
+ * to the filter by RaiseException
+ */
+ PAL_TRY(VOID*, unused, NULL)
+ {
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+
+ /* Initialize arguments to pass to filter */
+ for(int i = 0; ((DWORD)i) < nArguments_test1; i++ )
+ {
+ lpArguments_test1[i] = i;
+ }
+
+ RaiseException(0,0,nArguments_test1,lpArguments_test1);
+
+ Fail("RaiseException: ERROR -> code was executed after the "
+ "exception was raised.\n");
+ }
+ PAL_EXCEPT_FILTER(Filter_test1)
+ {
+ if (!bTry)
+ {
+ Fail("RaiseException: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER was hit without PAL_TRY being hit.\n");
+ }
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT_FILTER_EX block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("RaiseException: ERROR -> It appears the code in the "
+ "PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("RaiseException: ERROR -> It appears the code in the "
+ "PAL_EXCEPT_FILTER_EX block was not executed.\n");
+ }
+
+ if (!bFilter)
+ {
+ Trace("RaiseException: ERROR -> It appears the code in the"
+ " filter function was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept || !bFilter)
+ {
+ Fail("");
+ }
+
+
+ /* Reinit flags */
+ bTry = bExcept = bFilter = FALSE;
+
+ /********************************************************
+ * Test that the number of arguments never
+ * exceeds EXCEPTION_MAXIMUM_PARAMETERS, even though we
+ * pass a greater number of arguments
+ */
+ PAL_TRY(VOID*, unused, NULL)
+ {
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+
+ /* Initialize arguments to pass to filter */
+ for(int i = 0; ((DWORD)i) < nArguments_test2; i++ )
+ {
+ lpArguments_test2[i] = i;
+ }
+
+ RaiseException(0,0,nArguments_test2,lpArguments_test2);
+
+ Fail("RaiseException: ERROR -> code was executed after the "
+ "exception was raised.\n");
+ }
+ PAL_EXCEPT_FILTER(Filter_test2)
+ {
+ if (!bTry)
+ {
+ Fail("RaiseException: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER was hit without PAL_TRY being hit.\n");
+ }
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT_FILTER_EX block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("RaiseException: ERROR -> It appears the code in the "
+ "PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("RaiseException: ERROR -> It appears the code in the "
+ "PAL_EXCEPT_FILTER_EX block was not executed.\n");
+ }
+
+ if (!bFilter)
+ {
+ Trace("RaiseException: ERROR -> It appears the code in the"
+ " filter function was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept || !bFilter)
+ {
+ Fail("");
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/RaiseException/test2/testinfo.dat b/src/pal/tests/palsuite/exception_handling/RaiseException/test2/testinfo.dat
new file mode 100644
index 0000000000..ce85e67ace
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/RaiseException/test2/testinfo.dat
@@ -0,0 +1,28 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+
+Section = exception_handling
+
+Function = RaiseException
+
+Name = RaiseException test #2
+
+TYPE = DEFAULT
+
+EXE1 = test2
+LANG = cpp
+
+Description
+
+=Tests that the correct arguments are passed
+
+=to the filter by RaiseException and tests that
+
+=the number of arguments never exceeds
+
+=EXCEPTION_MAXIMUM_PARAMETERS, even though we
+
+=pass a greater number of arguments
diff --git a/src/pal/tests/palsuite/exception_handling/RaiseException/test3/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/RaiseException/test3/CMakeLists.txt
new file mode 100644
index 0000000000..72e5427b69
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/RaiseException/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.cpp
+)
+
+add_executable(paltest_raiseexception_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_raiseexception_test3 coreclrpal)
+
+target_link_libraries(paltest_raiseexception_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/RaiseException/test3/test.cpp b/src/pal/tests/palsuite/exception_handling/RaiseException/test3/test.cpp
new file mode 100644
index 0000000000..5278ad1772
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/RaiseException/test3/test.cpp
@@ -0,0 +1,115 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test.c (exception_handling\raiseexception\test3)
+**
+** Purpose: Tests that the correct ExceptionCode is passed
+** to the filter by RaiseException
+**
+**
+**============================================================*/
+
+
+#include <palsuite.h>
+
+BOOL bFilter = FALSE;
+BOOL bTry = FALSE;
+BOOL bExcept = FALSE;
+
+/**
+**
+** Filter function that checks for the parameters
+**
+**/
+LONG Filter_test1(EXCEPTION_POINTERS* ep, VOID* unused)
+{
+ /* let the main know we've hit the filter function */
+ bFilter = TRUE;
+
+ if (!bTry)
+ {
+ Fail("PAL_EXCEPT_FILTER_EX: ERROR -> Something weird is going on."
+ " The filter was hit without PAL_TRY being hit.\n");
+ }
+
+
+ /* was the correct exception code passed? */
+ if (ep->ExceptionRecord->ExceptionCode != EXCEPTION_ARRAY_BOUNDS_EXCEEDED)
+ {
+ Fail("RaiseException: ERROR -> ep->ExceptionRecord->ExceptionCode"
+ " was %x when it was expected to be %x\n",
+ ep->ExceptionRecord->ExceptionCode,
+ EXCEPTION_ARRAY_BOUNDS_EXCEEDED);
+
+ }
+
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ bExcept = FALSE;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /********************************************************
+ * Test that the correct arguments are passed
+ * to the filter by RaiseException
+ */
+ PAL_TRY(VOID*, unused, NULL)
+ {
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+
+ RaiseException(EXCEPTION_ARRAY_BOUNDS_EXCEEDED,
+ 0,
+ 0,NULL);
+
+ Fail("RaiseException: ERROR -> code was executed after the "
+ "exception was raised.\n");
+ }
+ PAL_EXCEPT_FILTER(Filter_test1)
+ {
+ if (!bTry)
+ {
+ Fail("RaiseException: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER was hit without PAL_TRY being hit.\n");
+ }
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT_FILTER_EX block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("RaiseException: ERROR -> It appears the code in the "
+ "PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("RaiseException: ERROR -> It appears the code in the "
+ "PAL_EXCEPT_FILTER_EX block was not executed.\n");
+ }
+
+ if (!bFilter)
+ {
+ Trace("RaiseException: ERROR -> It appears the code in the"
+ " filter function was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept || !bFilter)
+ {
+ Fail("");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/RaiseException/test3/testinfo.dat b/src/pal/tests/palsuite/exception_handling/RaiseException/test3/testinfo.dat
new file mode 100644
index 0000000000..12a56f0efe
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/RaiseException/test3/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = exception_handling
+Function = RaiseException
+Name = RaiseException test #3
+TYPE = DEFAULT
+EXE1 = test
+LANG = cpp
+Description
+= Tests that the exception code passed to
+= RaiseException makes it to the filter.
diff --git a/src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/CMakeLists.txt
new file mode 100644
index 0000000000..e526029bee
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_setunhandledexceptionfilter_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setunhandledexceptionfilter_test1 coreclrpal)
+
+target_link_libraries(paltest_setunhandledexceptionfilter_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/test1.c b/src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/test1.c
new file mode 100644
index 0000000000..5a067f9354
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/test1.c
@@ -0,0 +1,82 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test1.c
+**
+** Purpose: Sets up a new unhandled exception filter, and makes sure it
+** returns the previous filter. Raises an unhandled exception and
+** makes sure this reaches the filter.
+**
+**
+**============================================================*/
+
+
+#include <palsuite.h>
+
+/* This isn't defined in the pal, so copied from win32 */
+#define EXCEPTION_EXECUTE_HANDLER 1
+#define EXCEPTION_CONTINUE_EXECUTION -1
+
+
+int InFilter = FALSE;
+
+LONG PALAPI FirstFilter(LPEXCEPTION_POINTERS p)
+{
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+LONG PALAPI ContinueFilter(LPEXCEPTION_POINTERS p)
+{
+ InFilter = TRUE;
+
+ Trace("This test has succeeded as far at the automated checks can "
+ "tell. Manual verification is now required to be completely sure.\n");
+ Trace("Now the PAL's handling of application errors will be tested "
+ "with an exception code of %u.\n",
+ p->ExceptionRecord->ExceptionCode);
+ Trace("Please verify that the actions that the PAL now takes are "
+ "as specified for it.\n");
+
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ LPTOP_LEVEL_EXCEPTION_FILTER OldFilter;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+
+ SetUnhandledExceptionFilter(FirstFilter);
+
+ OldFilter = SetUnhandledExceptionFilter(ContinueFilter);
+ if (OldFilter != FirstFilter)
+ {
+ Fail("SetUnhandledExceptionFilter did not return a pointer to the "
+ "previous filter!\n");
+ }
+
+ /*
+ * Raise an unhandled exception. This should cause our filter to be
+ * excecuted and the program to exit with a code the same as the
+ * exception code.
+ */
+ RaiseException(3,0,0,0);
+
+
+ /*
+ * This code should not be executed because the toplevelhandler is
+ * expected to "just" set the exit code and abend the program
+ */
+ Fail("An unhandled exception did not cause the program to abend with"
+ "the exit code == the ExceptionCode!\n");
+
+ PAL_Terminate();
+ return FAIL;
+}
diff --git a/src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/testinfo.dat b/src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/testinfo.dat
new file mode 100644
index 0000000000..2af29a299a
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = exception_handling
+Function = SetUnhandledExceptionFilter
+Name = SetUnhandledExceptionFilter test #1
+TYPE = DEFAULT
+EXE1 = test1
+LANG = cpp
+Description
+=Sets up a new unhandled exception filter, and makes sure it
+=returns the previous filter. Raises an unhandled exception and
+=makes sure this reaches the filter.
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/pal_except/CMakeLists.txt
new file mode 100644
index 0000000000..19ee487a6a
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/CMakeLists.txt
@@ -0,0 +1,10 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+add_subdirectory(test7)
+
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test1/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/pal_except/test1/CMakeLists.txt
new file mode 100644
index 0000000000..635e35d635
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_pal_except_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_except_test1 coreclrpal)
+
+target_link_libraries(paltest_pal_except_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test1/test1.c b/src/pal/tests/palsuite/exception_handling/pal_except/test1/test1.c
new file mode 100644
index 0000000000..0fe48e7fc3
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test1/test1.c
@@ -0,0 +1,67 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c (exception_handling\pal_except\test1)
+**
+** Purpose: Test to make sure the PAL_EXCEPT block is executed
+** after an exception occurs in the PAL_TRY block
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+/* Execution flags */
+BOOL bTry = FALSE;
+BOOL bExcept = FALSE;
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ PAL_TRY
+ {
+ int* p = 0x00000000; /* NULL pointer */
+
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+ *p = 13; /* causes an access violation exception */
+
+ Fail("ERROR: code was executed after the access violation.\n");
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTry)
+ {
+ Fail("ERROR: PAL_EXCEPT was hit without PAL_TRY being hit.\n");
+ }
+
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("ERROR: the code in the PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("ERROR: the code in the PAL_EXCEPT block was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept)
+ {
+ Fail("");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test1/testinfo.dat b/src/pal/tests/palsuite/exception_handling/pal_except/test1/testinfo.dat
new file mode 100644
index 0000000000..246553a9cb
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test1/testinfo.dat
@@ -0,0 +1,23 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+
+Section = exception_handling
+
+Function = PAL_TRY and PAL_EXCEPT
+
+Name = Test for PAL_TRY and PAL_EXCEPT
+
+Type = DEFAULT
+
+EXE1 = test1
+
+LANG = cpp
+
+Description
+
+= Test to make sure the PAL_EXCEPT block is executed
+
+= after an exception occurs in the PAL_TRY block
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test2/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/pal_except/test2/CMakeLists.txt
new file mode 100644
index 0000000000..813b0e66a1
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_pal_except_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_except_test2 coreclrpal)
+
+target_link_libraries(paltest_pal_except_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test2/test2.c b/src/pal/tests/palsuite/exception_handling/pal_except/test2/test2.c
new file mode 100644
index 0000000000..bc0d4e300a
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test2/test2.c
@@ -0,0 +1,111 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test2.c (exception_handling\pal_except\test2)
+**
+** Purpose: Test to make sure the PAL_EXCEPT block is executed
+** after an exception occurs in the PAL_TRY block
+** that contains another PAL_TRY-PAL_EXCEPT block
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+/* Execution flags */
+BOOL bTry = FALSE;
+BOOL bExcept = FALSE;
+BOOL bTry_nested = FALSE;
+BOOL bExcept_nested = FALSE;
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ PAL_TRY
+ {
+ int* p = 0x00000000; /* NULL pointer */
+
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+
+
+ /* Nested PAL_TRY */
+ PAL_TRY
+ {
+ bTry_nested = TRUE;
+
+ *p = 13; /* causes an access violation exception */
+
+ Fail("ERROR: code was executed after the nested access violation.\n");
+
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTry)
+ {
+ Fail("ERROR: Nested PAL_EXCEPT was hit without "
+ "nested PAL_TRY being hit.\n");
+ }
+ bExcept_nested = TRUE;
+ }
+ PAL_ENDTRY;
+
+ *p = 13; /* causes an access violation exception */
+
+ Fail("ERROR: code was executed after the access violation.\n");
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTry)
+ {
+ Fail("ERROR: PAL_EXCEPT was hit without PAL_TRY being hit.\n");
+ }
+ if (!bExcept_nested)
+ {
+ Fail("ERROR: PAL_EXCEPT was hit without "
+ "nested PAL_EXCEPT being hit.\n");
+ }
+
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("ERROR: the code in the PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("ERROR: the code in the PAL_EXCEPT block was not executed.\n");
+ }
+
+ if (!bTry_nested)
+ {
+ Trace("ERROR: the code in the "
+ "nested PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept_nested)
+ {
+ Trace("ERROR: the code in the "
+ "nested PAL_EXCEPT block was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept ||
+ !bTry_nested || !bExcept_nested)
+ {
+ Fail("");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test2/testinfo.dat b/src/pal/tests/palsuite/exception_handling/pal_except/test2/testinfo.dat
new file mode 100644
index 0000000000..39a628b16c
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test2/testinfo.dat
@@ -0,0 +1,25 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+
+Section = exception_handling
+
+Function = PAL_TRY and PAL_EXCEPT_EX
+
+Name = Test for PAL_TRY and PAL_EXCEPT_EX
+
+Type = DEFAULT
+
+EXE1 = test2
+
+LANG = cpp
+
+Description
+
+= Test to make sure the PAL_EXCEPT_EX block is executed
+
+= after an exception occurs in the PAL_TRY block
+
+= that contains another PAL_TRY-PAL_EXCEPT_EX block
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test3/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/pal_except/test3/CMakeLists.txt
new file mode 100644
index 0000000000..5fc3b096af
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_pal_except_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_except_test3 coreclrpal)
+
+target_link_libraries(paltest_pal_except_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test3/test3.c b/src/pal/tests/palsuite/exception_handling/pal_except/test3/test3.c
new file mode 100644
index 0000000000..0137697774
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test3/test3.c
@@ -0,0 +1,120 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test3.c (exception_handling\pal_except\test3)
+**
+** Purpose: Test to make sure the PAL_EXCEPT block is executed
+** after an exception occurs in the PAL_TRY block
+** that calls a function that contains
+** another PAL_TRY-PAL_EXCEPT block
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+/* Execution flags */
+BOOL bTry = FALSE;
+BOOL bExcept = FALSE;
+BOOL bTry_function = FALSE;
+BOOL bExcept_function = FALSE;
+
+/*
+ * Helper function that contains a PAL_TRY-PAL_EXCEPT block
+ */
+void Helper()
+{
+ /* Nested PAL_TRY */
+ PAL_TRY
+ {
+ int *lp = 0x00000000;
+
+ bTry_function = TRUE;
+
+ *lp = 13; /* causes an access violation exception */
+
+ Fail("ERROR: code was executed after the function's access violation.\n");
+
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTry)
+ {
+ Fail("ERROR: Nested PAL_EXCEPT was hit without "
+ "the function's PAL_TRY being hit.\n");
+ }
+ bExcept_function = TRUE;
+ }
+ PAL_ENDTRY;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ PAL_TRY
+ {
+ int* p = 0x00000000; /* NULL pointer */
+
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+
+ Helper();
+
+ *p = 13; /* causes an access violation exception */
+
+ Fail("ERROR: code was executed after the access violation.\n");
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTry)
+ {
+ Fail("ERROR: PAL_EXCEPT was hit without PAL_TRY being hit.\n");
+ }
+ if (!bExcept_function)
+ {
+ Fail("ERROR: PAL_EXCEPT was hit without "
+ "function's PAL_EXCEPT being hit.\n");
+ }
+
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("ERROR: the code in the PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("ERROR: the code in the PAL_EXCEPT block was not executed.\n");
+ }
+
+ if (!bTry_function)
+ {
+ Trace("ERROR: the code in the "
+ "function's PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept_function)
+ {
+ Trace("ERROR: the code in the "
+ "function's PAL_EXCEPT block was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept ||
+ !bTry_function || !bExcept_function)
+ {
+ Fail("");
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test3/testinfo.dat b/src/pal/tests/palsuite/exception_handling/pal_except/test3/testinfo.dat
new file mode 100644
index 0000000000..07da444a5a
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test3/testinfo.dat
@@ -0,0 +1,27 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+
+Section = exception_handling
+
+Function = PAL_TRY and PAL_EXCEPT
+
+Name = Test for PAL_TRY and PAL_EXCEPT
+
+Type = DEFAULT
+
+EXE1 = test3
+
+LANG = cpp
+
+Description
+
+= Test to make sure the PAL_EXCEPT block is executed
+
+= after an exception occurs in the PAL_TRY block
+
+= that calls a function that contains
+
+= another PAL_TRY-PAL_EXCEPT block
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test4/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/pal_except/test4/CMakeLists.txt
new file mode 100644
index 0000000000..cc054d15dd
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_pal_except_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_except_test4 coreclrpal)
+
+target_link_libraries(paltest_pal_except_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test4/test4.c b/src/pal/tests/palsuite/exception_handling/pal_except/test4/test4.c
new file mode 100644
index 0000000000..87844973b0
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test4/test4.c
@@ -0,0 +1,105 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test4.c (exception_handling\pal_except\test4)
+**
+** Purpose: Test to make sure the PAL_EXCEPT block is executed
+** after an exception occurs in the PAL_TRY block
+** if the PAL_EXCEPT block contains a nested
+** PAL_TRY-PAL_EXCEPT block
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+/* Execution flags */
+BOOL bTry = FALSE;
+BOOL bExcept = FALSE;
+BOOL bTry_nested = FALSE;
+BOOL bExcept_nested = FALSE;
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ PAL_TRY
+ {
+ int* p = 0x00000000; /* NULL pointer */
+
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+ *p = 13; /* causes an access violation exception */
+
+ Fail("ERROR: code was executed after the access violation.\n");
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTry)
+ {
+ Fail("ERROR: PAL_EXCEPT was hit without PAL_TRY being hit.\n");
+ }
+
+ PAL_TRY
+ {
+ int *lp = 0x00000000;
+
+ bTry_nested = TRUE;
+ *lp = 13; /* causes an access violation exception */
+
+ Fail("ERROR: code was executed after the "
+ "nested access violation.\n");
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTry_nested)
+ {
+ Fail("ERROR: PAL_EXCEPT was hit without PAL_TRY being hit "
+ "in the nested block.\n");
+ }
+ bExcept_nested = TRUE;
+ }
+ PAL_ENDTRY;
+
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("ERROR: the code in the PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("ERROR: the code in the PAL_EXCEPT block was not executed.\n");
+ }
+
+ if (!bTry_nested)
+ {
+ Trace("ERROR: the code in the nested "
+ "PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept_nested)
+ {
+ Trace("ERROR: the code in the nested "
+ "PAL_EXCEPT block was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept ||
+ !bTry_nested || !bExcept_nested)
+ {
+ Fail("");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test4/testinfo.dat b/src/pal/tests/palsuite/exception_handling/pal_except/test4/testinfo.dat
new file mode 100644
index 0000000000..d658cc85fa
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test4/testinfo.dat
@@ -0,0 +1,27 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+
+Section = exception_handling
+
+Function = PAL_TRY and PAL_EXCEPT
+
+Name = Test for PAL_TRY and PAL_EXCEPT
+
+Type = DEFAULT
+
+EXE1 = test4
+
+LANG = cpp
+
+Description
+
+= Test to make sure the PAL_EXCEPT block is executed
+
+= after an exception occurs in the PAL_TRY block
+
+= if the PAL_EXCEPT block contains a nested
+
+= PAL_TRY-PAL_EXCEPT block
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test5/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/pal_except/test5/CMakeLists.txt
new file mode 100644
index 0000000000..7b8f1d0361
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test5.c
+)
+
+add_executable(paltest_pal_except_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_except_test5 coreclrpal)
+
+target_link_libraries(paltest_pal_except_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test5/test5.c b/src/pal/tests/palsuite/exception_handling/pal_except/test5/test5.c
new file mode 100644
index 0000000000..f9faf4440e
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test5/test5.c
@@ -0,0 +1,112 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test5.c (exception_handling\pal_except\test5)
+**
+** Purpose: Test to make sure the PAL_EXCEPT block is executed
+** after an exception occurs in the PAL_TRY block
+** if the PAL_EXCEPT block calls a function that contains
+** another PAL_TRY-PAL_EXCEPT block
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+/* Execution flags */
+BOOL bTry = FALSE;
+BOOL bExcept = FALSE;
+BOOL bTry_nested = FALSE;
+BOOL bExcept_nested = FALSE;
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ PAL_TRY
+ {
+ int* p = 0x00000000; /* NULL pointer */
+
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+
+
+ /* Nested PAL_TRY */
+ PAL_TRY
+ {
+ bTry_nested = TRUE;
+
+ *p = 13; /* causes an access violation exception */
+
+ Fail("ERROR: code was executed after the nested access violation.\n");
+
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTry)
+ {
+ Fail("ERROR: Nested PAL_EXCEPT was hit without "
+ "nested PAL_TRY being hit.\n");
+ }
+ bExcept_nested = TRUE;
+ }
+ PAL_ENDTRY;
+
+ *p = 13; /* causes an access violation exception */
+
+ Fail("ERROR: code was executed after the access violation.\n");
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTry)
+ {
+ Fail("ERROR: PAL_EXCEPT was hit without PAL_TRY being hit.\n");
+ }
+ if (!bExcept_nested)
+ {
+ Fail("ERROR: PAL_EXCEPT was hit without "
+ "nested PAL_EXCEPT being hit.\n");
+ }
+
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("ERROR: the code in the PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("ERROR: the code in the PAL_EXCEPT block was not executed.\n");
+ }
+
+ if (!bTry_nested)
+ {
+ Trace("ERROR: the code in the "
+ "nested PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept_nested)
+ {
+ Trace("ERROR: the code in the "
+ "nested PAL_EXCEPT block was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept ||
+ !bTry_nested || !bExcept_nested)
+ {
+ Fail("");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test5/testinfo.dat b/src/pal/tests/palsuite/exception_handling/pal_except/test5/testinfo.dat
new file mode 100644
index 0000000000..2e12d0c64b
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test5/testinfo.dat
@@ -0,0 +1,27 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+
+Section = exception_handling
+
+Function = PAL_TRY and PAL_EXCEPT
+
+Name = Test for PAL_TRY and PAL_EXCEPT
+
+Type = DEFAULT
+
+EXE1 = test5
+
+LANG = cpp
+
+Description
+
+= Test to make sure the PAL_EXCEPT block is executed
+
+= after an exception occurs in the PAL_TRY block
+
+= if the PAL_EXCEPT block calls a function that contains
+
+= another PAL_TRY-PAL_EXCEPT block
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test6/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/pal_except/test6/CMakeLists.txt
new file mode 100644
index 0000000000..7f943bf126
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test6.c
+)
+
+add_executable(paltest_pal_except_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_except_test6 coreclrpal)
+
+target_link_libraries(paltest_pal_except_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test6/test6.c b/src/pal/tests/palsuite/exception_handling/pal_except/test6/test6.c
new file mode 100644
index 0000000000..44b0ba1bc9
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test6/test6.c
@@ -0,0 +1,160 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test6.c (exception_handling\pal_except\test6)
+**
+** Purpose: Test to make sure the PAL_EXCEPT block is executed
+** after an exception occurs in the PAL_TRY block
+** that contains multiple PAL_TRY-PAL_EXCEPT blocks
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+/* Execution flags */
+BOOL bTry = FALSE;
+BOOL bExcept = FALSE;
+BOOL bTry_nested = FALSE;
+BOOL bExcept_nested = FALSE;
+BOOL bTry_nested2 = FALSE;
+BOOL bExcept_nested2 = FALSE;
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* First block */
+ PAL_TRY
+ {
+ int* p = 0x00000000; /* NULL pointer */
+
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+
+ /* Second PAL_TRY block */
+ PAL_TRY
+ {
+ bTry_nested = TRUE;
+
+ /* Third PAL_TRY block*/
+ PAL_TRY
+ {
+ bTry_nested2 = TRUE;
+
+ *p = 13; /* causes an access violation exception */
+
+ Fail("ERROR: code was executed after the nested access violation.\n");
+
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTry_nested2)
+ {
+ Fail("ERROR: Third PAL_EXCEPT was hit without "
+ "third PAL_TRY being hit.\n");
+ }
+ bExcept_nested2 = TRUE;
+ }
+ PAL_ENDTRY;
+
+ *p = 13; /* causes an access violation exception */
+
+ Fail("ERROR: code was executed after the nested access violation.\n");
+
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTry_nested)
+ {
+ Fail("ERROR: Second PAL_EXCEPT was hit without "
+ "second PAL_TRY being hit.\n");
+ }
+ if (!bExcept_nested2)
+ {
+ Fail("ERROR: second PAL_EXCEPT was hit without "
+ "third PAL_EXCEPT being hit.\n");
+ }
+ bExcept_nested = TRUE;
+ }
+ PAL_ENDTRY;
+
+ *p = 13; /* causes an access violation exception */
+
+ Fail("ERROR: code was executed after the access violation.\n");
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTry)
+ {
+ Fail("ERROR: PAL_EXCEPT was hit without PAL_TRY being hit.\n");
+ }
+ if (!bExcept_nested)
+ {
+ Fail("ERROR: first PAL_EXCEPT was hit without "
+ "second PAL_EXCEPT being hit.\n");
+ }
+ if (!bExcept_nested2)
+ {
+ Fail("ERROR: first PAL_EXCEPT was hit without "
+ "third PAL_EXCEPT being hit.\n");
+ }
+
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("ERROR: the code in the "
+ "first PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("ERROR: the code in the "
+ "first PAL_EXCEPT block was not executed.\n");
+ }
+
+ if (!bTry_nested)
+ {
+ Trace("ERROR: the code in the "
+ "second PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept_nested)
+ {
+ Trace("ERROR: the code in the "
+ "second PAL_EXCEPT block was not executed.\n");
+ }
+
+ if (!bTry_nested2)
+ {
+ Trace("ERROR: the code in the "
+ "third PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept_nested2)
+ {
+ Trace("ERROR: the code in the "
+ "third PAL_EXCEPT block was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept ||
+ !bTry_nested || !bExcept_nested ||
+ !bTry_nested2 || !bExcept_nested2)
+ {
+ Fail("");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test6/testinfo.dat b/src/pal/tests/palsuite/exception_handling/pal_except/test6/testinfo.dat
new file mode 100644
index 0000000000..f8901a7f50
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test6/testinfo.dat
@@ -0,0 +1,25 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+
+Section = exception_handling
+
+Function = PAL_TRY and PAL_EXCEPT_EX
+
+Name = Test for PAL_TRY and PAL_EXCEPT_EX
+
+Type = DEFAULT
+
+EXE1 = test6
+
+LANG = cpp
+
+Description
+
+= Test to make sure the PAL_EXCEPT_EX block is executed
+
+= after an exception occurs in the PAL_TRY block
+
+= that contains multiple PAL_TRY-PAL_EXCEPT_EX blocks
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test7/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/pal_except/test7/CMakeLists.txt
new file mode 100644
index 0000000000..09399c8f6b
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test7/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test7.c
+)
+
+add_executable(paltest_pal_except_test7
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_except_test7 coreclrpal)
+
+target_link_libraries(paltest_pal_except_test7
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test7/test7.c b/src/pal/tests/palsuite/exception_handling/pal_except/test7/test7.c
new file mode 100644
index 0000000000..a8dc8331c2
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test7/test7.c
@@ -0,0 +1,67 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test7.c (exception_handling\pal_except\test7)
+**
+** Purpose: Tests the PAL implementation of the PAL_TRY and
+** PAL_EXCEPT functions. Tests that the EXCEPTION block
+** is missed if no exceptions happen
+**
+**
+**===================================================================*/
+
+
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ BOOL bTry = FALSE;
+ BOOL bExcept = FALSE;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /*
+ ** Test to make sure we skip the exception block.
+ */
+
+ PAL_TRY
+ {
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the PAL_TRY"
+ " block was not executed.\n");
+ }
+
+ if (bExcept)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the PAL_EXCEPT"
+ " block was executed even though no exception was supposed to"
+ " happen.\n");
+ }
+
+ /* did we hit the correct code blocks? */
+ if(!bTry || bExcept)
+ {
+ Fail("");
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test7/testinfo.dat b/src/pal/tests/palsuite/exception_handling/pal_except/test7/testinfo.dat
new file mode 100644
index 0000000000..546d64cdec
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test7/testinfo.dat
@@ -0,0 +1,24 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+
+Section = exception_handling
+
+Function = PAL_TRY and PAL_EXCEPT
+
+Name = Test for PAL_TRY and PAL_EXCEPT
+
+Type = DEFAULT
+
+EXE1 = test7
+
+LANG = cpp
+
+Description
+
+= In this test, no exceptions are forced to ensure the EXCEPTION block
+
+= isn't hit.
+
diff --git a/src/pal/tests/palsuite/exception_handling/pal_finally/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/pal_finally/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_finally/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/exception_handling/pal_finally/test1/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/pal_finally/test1/CMakeLists.txt
new file mode 100644
index 0000000000..5d947ad7db
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_finally/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ pal_finally.c
+)
+
+add_executable(paltest_pal_finally_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_finally_test1 coreclrpal)
+
+target_link_libraries(paltest_pal_finally_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/pal_finally/test1/pal_finally.c b/src/pal/tests/palsuite/exception_handling/pal_finally/test1/pal_finally.c
new file mode 100644
index 0000000000..f278f98956
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_finally/test1/pal_finally.c
@@ -0,0 +1,302 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: pal_finally.c (test 3)
+**
+** Purpose: Tests the PAL implementation of the PAL_FINALLY in the
+** presence of a call stack. An exception is forced and
+** passed to two nested exception filters for consideration.
+** The first filter returns EXCEPTION_CONTINUE_SEARCH so the
+** second can run and return EXCEPTION_EXECUTE_HANDLER. The
+** initial exception handler should be skipped, and the
+** second executed, and all the PAL_FINALLY blocks handled
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+BOOL bFilterCS = FALSE;
+BOOL bFilterEE = FALSE;
+BOOL bFinally1 = FALSE;
+BOOL bFinally2 = FALSE;
+BOOL bFinally3 = FALSE;
+BOOL bFinally4 = FALSE;
+BOOL bTry1 = FALSE;
+BOOL bTry2 = FALSE;
+BOOL bExcept1 = FALSE;
+BOOL bExcept2 = FALSE;
+BOOL bContinued = FALSE;
+const int nValidator = 12321;
+
+LONG ContSearchFilter(EXCEPTION_POINTERS* ep, LPVOID pnTestInt)
+{
+
+ /* let the main know we've hit the filter function */
+ bFilterCS = TRUE;
+
+ if (!bTry1 || !bTry2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The ContSearch filter was hit without PAL_TRY being hit.\n");
+ }
+
+ if (bFilterEE)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The ContSearch filter was hit after the ExecuteException "
+ "filter.\n");
+ }
+
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
+LONG ExecExeptionFilter(EXCEPTION_POINTERS* ep, LPVOID pnTestInt)
+{
+ /* let the main know we've hit the filter function */
+ bFilterEE = TRUE;
+
+ if (!bTry1 || !bTry2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The ContSearch filter was hit without PAL_TRY being hit.\n");
+ }
+
+ if (!bFilterCS)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The ExecExeption filter was hit before the ContSearch "
+ "filter.\n");
+ }
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+void NestedFunc1 (void)
+{
+ int* p = 0x00000000; /* pointer to NULL */
+
+ PAL_TRY
+ {
+ PAL_TRY
+ {
+
+ if (bExcept1 || bExcept2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER was hit before PAL_TRY.\n");
+ }
+ bTry2 = TRUE; /* indicate we hit the inner PAL_TRY block */
+ *p = 13; /* causes an access violation exception */
+
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " We executed beyond the trapping code.\n");
+ }
+ PAL_FINALLY
+ {
+ if (!bTry1)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The first finally handler was hit without the outer "
+ "PAL_TRY's code being hit.\n");
+ }
+ if (!bTry2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The first finally handler was hit without the inner "
+ "PAL_TRY's code being hit.\n");
+ }
+ if (!bFilterCS)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The first finally handler was hit without the inner "
+ "filter being hit.\n");
+ }
+ if (!bFilterEE)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The first finally handler handler was hit without the "
+ "outer filter being hit.\n");
+ }
+ bFinally1 = TRUE; /* indicate we hit the first finally block */
+ }
+ PAL_ENDTRY;
+ }
+ PAL_EXCEPT_FILTER(ContSearchFilter, (LPVOID)&nValidator)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The dummy handler was "
+ "being hit.\n");
+ bExcept2 = TRUE; /* indicate we hit the inner block */
+ }
+ PAL_ENDTRY;
+
+}
+
+void NestedFunc2 (void)
+{
+ PAL_TRY
+ {
+ NestedFunc1();
+ }
+ PAL_FINALLY
+ {
+ if (!bFinally1)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The second finally handler handler was hit without the "
+ " top level one being hit.\n");
+ }
+ bFinally2 = TRUE;
+ }
+ PAL_ENDTRY ;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /*
+ ** test to make sure we get into the second exception block only based
+ ** on the return codes of the filters
+ */
+
+ PAL_TRY
+ {
+ PAL_TRY
+ {
+ PAL_TRY
+ {
+ if (bExcept1 || bExcept2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going"
+ " on. PAL_EXCEPT_FILTER was hit before PAL_TRY.\n");
+ }
+ bTry1 = TRUE; /* indicate we hit the outer PAL_TRY block */
+
+ NestedFunc2();
+
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " We executed beyond the trapping code.\n");
+ }
+ PAL_FINALLY
+ {
+ if (!bFinally2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going"
+ " on. Finally handlers hit out of order (2->3)\n");
+ }
+ bFinally3 = TRUE;
+ }
+ PAL_ENDTRY;
+ }
+ PAL_EXCEPT_FILTER(ExecExeptionFilter, (LPVOID)&nValidator)
+ {
+ if (!bTry1)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER's handler was hit without the outer "
+ "PAL_TRY's code being hit.\n");
+ }
+ if (!bTry2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER's handler was hit without the inner "
+ "PAL_TRY's code being hit.\n");
+ }
+ if (!bFilterCS)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER's handler was hit without the inner "
+ "filter being hit.\n");
+ }
+ if (!bFilterEE)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER's handler was hit without the outer "
+ "filter being hit.\n");
+ }
+ bExcept1 = TRUE; /* indicate we hit the outer block */
+ }
+ PAL_ENDTRY;
+
+ if (bFinally4)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " Finally handler # 4 executed before it should be \n");
+ }
+ }
+ PAL_FINALLY
+ {
+ if (!bExcept1 || bExcept2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " Exceptions handlers hit in wierd ways\n");
+ }
+ if (!bFinally3)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " Finally handlers hit out of order 3->4)\n");
+ }
+
+ bFinally4 = TRUE;
+ }
+ PAL_ENDTRY;
+
+ if (!bTry1)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the outer"
+ " PAL_TRY block was not executed.\n");
+ }
+
+ if (!bTry2)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the inner"
+ " PAL_TRY block was not executed.\n");
+ }
+
+ if (bExcept2)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the "
+ "inner PAL_EXCEPT_FILTER block was executed.\n");
+ }
+ if (!bExcept1)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the "
+ "outer PAL_EXCEPT_FILTER block was not executed.\n");
+ }
+
+ if (!bFilterCS)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the "
+ "search continuing filter"
+ " function was not executed.\n");
+ }
+ if (!bFilterEE)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the "
+ "execute handler filter"
+ " function was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if (!bFinally1 || !bFinally2 || !bFinally3 || !bFinally4)
+ {
+ Fail("");
+ }
+ if(!bTry1 || !bTry2 || !bExcept1 || bExcept2 || !bFilterEE || !bFilterCS )
+ {
+ Fail("");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
diff --git a/src/pal/tests/palsuite/exception_handling/pal_finally/test1/testinfo.dat b/src/pal/tests/palsuite/exception_handling/pal_finally/test1/testinfo.dat
new file mode 100644
index 0000000000..5c26243438
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_finally/test1/testinfo.dat
@@ -0,0 +1,19 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = exception_handling
+Function = PAL_FINALLY
+Name = Test for nested PAL_FINALLY
+Type = DEFAULT
+EXE1 = pal_finally
+LANG = cpp
+Description
+= Tests the PAL implementation of the PAL_FINALLY in the presence
+= of a call stack. An exception is forced and passed to two nested
+= exception filters for consideration. The first filter returns
+= EXCEPTION_CONTINUE_SEARCH so the second can run and return
+= EXCEPTION_EXECUTE_HANDLER. The initial exception handler should
+= be skipped, and the second executed, and all the PAL_FINALLY
+= blocks handled.
diff --git a/src/pal/tests/palsuite/exception_handling/pal_sxs/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/pal_sxs/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_sxs/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/CMakeLists.txt
new file mode 100644
index 0000000000..b0458db998
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/CMakeLists.txt
@@ -0,0 +1,97 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+if(CLR_CMAKE_PLATFORM_UNIX)
+ add_compile_options(-fPIC)
+ add_definitions(-DFEATURE_ENABLE_HARDWARE_EXCEPTIONS)
+endif(CLR_CMAKE_PLATFORM_UNIX)
+
+# Set the RPATH of paltest_pal_sxs_test1 so that it can find dependencies without needing to set LD_LIBRARY
+# For more information: http://www.cmake.org/Wiki/CMake_RPATH_handling.
+if(CORECLR_SET_RPATH)
+ if(CLR_CMAKE_PLATFORM_LINUX)
+ set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
+ set(CMAKE_INSTALL_RPATH "\$ORIGIN")
+ endif(CLR_CMAKE_PLATFORM_LINUX)
+endif(CORECLR_SET_RPATH)
+
+# Test DLL1
+
+set(DEF_SOURCES1 dlltest1.src)
+convert_to_absolute_path(DEF_SOURCES1 ${DEF_SOURCES1})
+set(EXPORTS_FILE1 ${CMAKE_CURRENT_BINARY_DIR}/dlltest1.exports)
+generate_exports_file(${DEF_SOURCES1} ${EXPORTS_FILE1})
+
+if(CMAKE_SYSTEM_NAME STREQUAL Linux OR CMAKE_SYSTEM_NAME STREQUAL FreeBSD OR CMAKE_SYSTEM_NAME STREQUAL NetBSD)
+ set(EXPORTS_LINKER_OPTION1 -Wl,--version-script=${EXPORTS_FILE1})
+endif(CMAKE_SYSTEM_NAME STREQUAL Linux OR CMAKE_SYSTEM_NAME STREQUAL FreeBSD OR CMAKE_SYSTEM_NAME STREQUAL NetBSD)
+
+if(CMAKE_SYSTEM_NAME STREQUAL Darwin)
+ set(EXPORTS_LINKER_OPTION1 -Wl,-exported_symbols_list,${EXPORTS_FILE1})
+endif(CMAKE_SYSTEM_NAME STREQUAL Darwin)
+
+set(DLL1SOURCES dlltest1.cpp)
+add_library(paltest_pal_sxs_test1_dll1 SHARED ${DLL1SOURCES})
+add_custom_target(dlltest1_exports DEPENDS ${EXPORTS_FILE1})
+set_property(TARGET paltest_pal_sxs_test1_dll1 APPEND_STRING PROPERTY LINK_FLAGS ${EXPORTS_LINKER_OPTION1})
+set_property(TARGET paltest_pal_sxs_test1_dll1 APPEND_STRING PROPERTY LINK_DEPENDS ${EXPORTS_FILE1})
+
+add_dependencies(paltest_pal_sxs_test1_dll1
+ dlltest1_exports
+ coreclrpal
+)
+
+target_link_libraries(paltest_pal_sxs_test1_dll1
+ pthread
+ m
+ coreclrpal
+)
+
+# Test DLL2
+
+set(DEF_SOURCES2 dlltest2.src)
+convert_to_absolute_path(DEF_SOURCES2 ${DEF_SOURCES2})
+set(EXPORTS_FILE2 ${CMAKE_CURRENT_BINARY_DIR}/dlltest2.exports)
+generate_exports_file(${DEF_SOURCES2} ${EXPORTS_FILE2})
+
+if(CMAKE_SYSTEM_NAME STREQUAL Linux OR CMAKE_SYSTEM_NAME STREQUAL FreeBSD OR CMAKE_SYSTEM_NAME STREQUAL NetBSD)
+ set(EXPORTS_LINKER_OPTION2 -Wl,--version-script=${EXPORTS_FILE2})
+endif(CMAKE_SYSTEM_NAME STREQUAL Linux OR CMAKE_SYSTEM_NAME STREQUAL FreeBSD OR CMAKE_SYSTEM_NAME STREQUAL NetBSD)
+
+if(CMAKE_SYSTEM_NAME STREQUAL Darwin)
+ set(EXPORTS_LINKER_OPTION2 -Wl,-exported_symbols_list,${EXPORTS_FILE2})
+endif(CMAKE_SYSTEM_NAME STREQUAL Darwin)
+
+set(DLL2SOURCES dlltest2.cpp)
+add_library(paltest_pal_sxs_test1_dll2 SHARED ${DLL2SOURCES})
+add_custom_target(dlltest2_exports DEPENDS ${EXPORTS_FILE2})
+set_property(TARGET paltest_pal_sxs_test1_dll2 APPEND_STRING PROPERTY LINK_FLAGS ${EXPORTS_LINKER_OPTION2})
+set_property(TARGET paltest_pal_sxs_test1_dll2 APPEND_STRING PROPERTY LINK_DEPENDS ${EXPORTS_FILE2})
+
+add_dependencies(paltest_pal_sxs_test1_dll2
+ dlltest2_exports
+ coreclrpal
+)
+
+target_link_libraries(paltest_pal_sxs_test1_dll2
+ pthread
+ m
+ coreclrpal
+)
+
+# Main program
+
+set(TESTSOURCES exceptionsxs.cpp)
+
+add_executable(paltest_pal_sxs_test1 ${TESTSOURCES})
+
+add_dependencies(paltest_pal_sxs_test1
+ paltest_pal_sxs_test1_dll1
+ paltest_pal_sxs_test1_dll2
+)
+
+target_link_libraries(paltest_pal_sxs_test1
+ paltest_pal_sxs_test1_dll1
+ paltest_pal_sxs_test1_dll2
+)
diff --git a/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest1.cpp b/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest1.cpp
new file mode 100644
index 0000000000..614690897a
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest1.cpp
@@ -0,0 +1,75 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: dlltest1.c (exception_handling\pal_sxs\test1)
+**
+** Purpose: Test to make sure the PAL_EXCEPT block is executed
+** after an exception occurs in the PAL_TRY block with
+** multiple PALs in the process.
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+extern "C"
+int InitializeDllTest1()
+{
+ return PAL_InitializeDLL();
+}
+
+BOOL bTry = FALSE;
+BOOL bExcept = FALSE;
+
+extern "C"
+int DllTest1()
+{
+ Trace("Starting pal_sxs test1 DllTest1\n");
+
+ PAL_TRY(VOID*, unused, NULL)
+ {
+ volatile int* p = (volatile int *)0x11; // Invalid pointer
+
+ bTry = TRUE; // Indicate we hit the PAL_TRY block
+ *p = 1; // Causes an access violation exception
+
+ Fail("ERROR: code was executed after the access violation.\n");
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTry)
+ {
+ Fail("ERROR: PAL_EXCEPT was hit without PAL_TRY being hit.\n");
+ }
+
+ // Validate that the faulting address is correct; the contents of "p" (0x11).
+ if (ex.GetExceptionRecord()->ExceptionInformation[1] != 0x11)
+ {
+ Fail("ERROR: PAL_EXCEPT ExceptionInformation[1] != 0x11\n");
+ }
+
+ bExcept = TRUE; // Indicate we hit the PAL_EXCEPT block
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("ERROR: the code in the PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("ERROR: the code in the PAL_EXCEPT block was not executed.\n");
+ }
+
+ // Did we hit all the code blocks?
+ if(!bTry || !bExcept)
+ {
+ Fail("DllTest1 FAILED\n");
+ }
+
+ Trace("DLLTest1 PASSED\n");
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest1.src b/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest1.src
new file mode 100644
index 0000000000..0a0a6ee44a
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest1.src
@@ -0,0 +1,3 @@
+InitializeDllTest1
+DllTest1
+
diff --git a/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest2.cpp b/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest2.cpp
new file mode 100644
index 0000000000..1e85821422
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest2.cpp
@@ -0,0 +1,75 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: dlltest2.c (exception_handling\pal_sxs\test1)
+**
+** Purpose: Test to make sure the PAL_EXCEPT block is executed
+** after an exception occurs in the PAL_TRY block with
+** multiple PALs in the process.
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+extern "C"
+int InitializeDllTest2()
+{
+ return PAL_InitializeDLL();
+}
+
+BOOL bTry = FALSE;
+BOOL bExcept = FALSE;
+
+extern "C"
+int DllTest2()
+{
+ Trace("Starting pal_sxs test1 DllTest2\n");
+
+ PAL_TRY(VOID*, unused, NULL)
+ {
+ volatile int* p = (volatile int *)0x22; // Invalid pointer
+
+ bTry = TRUE; // Indicate we hit the PAL_TRY block
+ *p = 2; // Causes an access violation exception
+
+ Fail("ERROR: code was executed after the access violation.\n");
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTry)
+ {
+ Fail("ERROR: PAL_EXCEPT was hit without PAL_TRY being hit.\n");
+ }
+
+ // Validate that the faulting address is correct; the contents of "p" (0x22).
+ if (ex.GetExceptionRecord()->ExceptionInformation[1] != 0x22)
+ {
+ Fail("ERROR: PAL_EXCEPT ExceptionInformation[1] != 0x22\n");
+ }
+
+ bExcept = TRUE; // Indicate we hit the PAL_EXCEPT block
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("ERROR: the code in the PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("ERROR: the code in the PAL_EXCEPT block was not executed.\n");
+ }
+
+ // Did we hit all the code blocks?
+ if(!bTry || !bExcept)
+ {
+ Fail("DllTest2 FAILED\n");
+ }
+
+ Trace("DLLTest2 PASSED\n");
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest2.src b/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest2.src
new file mode 100644
index 0000000000..433419bc5b
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest2.src
@@ -0,0 +1,3 @@
+InitializeDllTest2
+DllTest2
+
diff --git a/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/exceptionsxs.cpp b/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/exceptionsxs.cpp
new file mode 100644
index 0000000000..97a963c120
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/exceptionsxs.cpp
@@ -0,0 +1,117 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: exceptionsxs.c (exception_handling\pal_sxs\test1)
+**
+** Purpose: Test to make sure the PAL_EXCEPT block is executed
+** after an exception occurs in the PAL_TRY block with
+** multiple PALs in the process.
+**
+**
+**===================================================================*/
+
+#include <stdio.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/ucontext.h>
+#include <sys/utsname.h>
+#include <unistd.h>
+
+enum
+{
+ PASS = 0,
+ FAIL = 1
+};
+
+extern "C" int InitializeDllTest1();
+extern "C" int InitializeDllTest2();
+extern "C" int DllTest1();
+extern "C" int DllTest2();
+
+bool bSignal = false;
+bool bCatch = false;
+bool bHandler = false;
+
+void sigsegv_handler(int code, siginfo_t *siginfo, void *context)
+{
+ printf("pal_sxs test1: signal handler called\n");
+ bHandler = true; // Mark that the signal handler was executed
+
+ if (!bSignal)
+ {
+ printf("ERROR: executed signal handler NOT from try/catch\n");
+ _exit(FAIL);
+ }
+
+ // Validate that the faulting address is correct; the contents of "p" (0x22).
+ if (siginfo->si_addr != (void *)0x33)
+ {
+ printf("ERROR: signal handler faulting address != 0x33\n");
+ _exit(FAIL);
+ }
+
+ // Unmask signal so we can receive it again
+ sigset_t signal_set;
+ sigemptyset(&signal_set);
+ sigaddset(&signal_set, SIGSEGV);
+ if (-1 == sigprocmask(SIG_UNBLOCK, &signal_set, NULL))
+ {
+ printf("ERROR: sigprocmask failed; error is %d\n", errno);
+ _exit(FAIL);
+ }
+
+ printf("Signal chaining PASSED\n");
+ _exit(PASS);
+}
+
+int main(int argc, char *argv[])
+{
+ struct sigaction newAction;
+ struct sigaction oldAction;
+ newAction.sa_flags = SA_SIGINFO | SA_RESTART;
+ newAction.sa_handler = NULL;
+ newAction.sa_sigaction = sigsegv_handler;
+ sigemptyset(&newAction.sa_mask);
+
+ if (-1 == sigaction(SIGSEGV, &newAction, &oldAction))
+ {
+ printf("ERROR: sigaction failed; error is %d\n", errno);
+ return FAIL;
+ }
+
+ printf("PAL_SXS test1 SIGSEGV handler %p\n", oldAction.sa_sigaction);
+
+ if (0 != InitializeDllTest1())
+ {
+ return FAIL;
+ }
+
+ if (0 != InitializeDllTest2())
+ {
+ return FAIL;
+ }
+
+ // Test catching exceptions in other PAL instances
+ DllTest2();
+ DllTest1();
+ DllTest2();
+
+ if (bHandler)
+ {
+ printf("ERROR: signal handler called by PAL sxs tests\n");
+ return FAIL;
+ }
+
+ printf("Starting PAL_SXS test1 signal chaining\n");
+
+ bSignal = true;
+
+ volatile int* p = (volatile int *)0x33; // Invalid pointer
+ *p = 3; // Causes an access violation exception
+
+ printf("ERROR: code was executed after the access violation.\n");
+ return FAIL;
+}
diff --git a/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/testinfo.dat b/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/testinfo.dat
new file mode 100644
index 0000000000..c0cf1ddfcb
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = exception_handling
+Function = test1
+Name = pal_sxs test #1
+TYPE = DEFAULT
+EXE1 = test1
+LANG = cpp
+Description
+=Tests that exceptions across multiples pals work correctly
diff --git a/src/pal/tests/palsuite/file_io/AreFileApisANSI/CMakeLists.txt b/src/pal/tests/palsuite/file_io/AreFileApisANSI/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/AreFileApisANSI/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/file_io/AreFileApisANSI/test1/AreFileApisANSI.c b/src/pal/tests/palsuite/file_io/AreFileApisANSI/test1/AreFileApisANSI.c
new file mode 100644
index 0000000000..ec61f0cb7d
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/AreFileApisANSI/test1/AreFileApisANSI.c
@@ -0,0 +1,40 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: AreFileApisANSI.c
+**
+** Purpose: Tests the PAL implementation of the AreFileApisANSI function.
+** The only possible return is TRUE.
+**
+**
+**===================================================================*/
+
+
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ BOOL bRc = FALSE;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ bRc = AreFileApisANSI();
+
+
+ if (bRc == FALSE)
+ {
+ Fail("AreFileApisANSI: ERROR: Function returned FALSE whereas only TRUE "
+ "is acceptable.\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/AreFileApisANSI/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/AreFileApisANSI/test1/CMakeLists.txt
new file mode 100644
index 0000000000..4f50127cb9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/AreFileApisANSI/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ AreFileApisANSI.c
+)
+
+add_executable(paltest_arefileapisansi_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_arefileapisansi_test1 coreclrpal)
+
+target_link_libraries(paltest_arefileapisansi_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/AreFileApisANSI/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/AreFileApisANSI/test1/testinfo.dat
new file mode 100644
index 0000000000..5e6b422ae4
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/AreFileApisANSI/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = AreFileApisANSI
+Name = Positive Test for AreFileApisANSI
+Type = DEFAULT
+EXE1 = arefileapisansi
+Description
+=Ensure the return is TRUE because FALSE is not an option in FreeBSD
+
diff --git a/src/pal/tests/palsuite/file_io/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CMakeLists.txt
new file mode 100644
index 0000000000..3d6eff1379
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CMakeLists.txt
@@ -0,0 +1,61 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(AreFileApisANSI)
+add_subdirectory(CompareFileTime)
+add_subdirectory(CopyFileA)
+add_subdirectory(CopyFileW)
+add_subdirectory(CreateDirectoryA)
+add_subdirectory(CreateDirectoryW)
+add_subdirectory(CreateFileA)
+add_subdirectory(CreateFileW)
+add_subdirectory(DeleteFileA)
+add_subdirectory(DeleteFileW)
+add_subdirectory(errorpathnotfound)
+add_subdirectory(FILECanonicalizePath)
+add_subdirectory(FileTimeToDosDateTime)
+add_subdirectory(FindClose)
+add_subdirectory(FindFirstFileA)
+add_subdirectory(FindFirstFileW)
+add_subdirectory(FindNextFileA)
+add_subdirectory(FindNextFileW)
+add_subdirectory(FlushFileBuffers)
+add_subdirectory(GetConsoleCP)
+add_subdirectory(GetConsoleOutputCP)
+add_subdirectory(GetCurrentDirectoryA)
+add_subdirectory(GetCurrentDirectoryW)
+add_subdirectory(GetDiskFreeSpaceW)
+add_subdirectory(GetFileAttributesA)
+add_subdirectory(GetFileAttributesExW)
+add_subdirectory(GetFileAttributesW)
+add_subdirectory(GetFileSize)
+add_subdirectory(GetFileSizeEx)
+add_subdirectory(GetFileTime)
+add_subdirectory(GetFileType)
+add_subdirectory(GetFullPathNameA)
+add_subdirectory(GetFullPathNameW)
+add_subdirectory(GetLongPathNameW)
+add_subdirectory(GetStdHandle)
+add_subdirectory(GetSystemTime)
+add_subdirectory(GetSystemTimeAsFileTime)
+add_subdirectory(GetTempFileNameA)
+add_subdirectory(GetTempFileNameW)
+add_subdirectory(gettemppatha)
+add_subdirectory(GetTempPathW)
+add_subdirectory(MoveFileA)
+add_subdirectory(MoveFileExA)
+add_subdirectory(MoveFileExW)
+add_subdirectory(MoveFileW)
+add_subdirectory(ReadFile)
+add_subdirectory(RemoveDirectoryA)
+add_subdirectory(RemoveDirectoryW)
+add_subdirectory(SearchPathA)
+add_subdirectory(SearchPathW)
+add_subdirectory(SetCurrentDirectoryA)
+add_subdirectory(SetCurrentDirectoryW)
+add_subdirectory(SetEndOfFile)
+add_subdirectory(SetFileAttributesA)
+add_subdirectory(SetFileAttributesW)
+add_subdirectory(SetFilePointer)
+add_subdirectory(SetFileTime)
+add_subdirectory(WriteFile)
+
diff --git a/src/pal/tests/palsuite/file_io/CompareFileTime/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CompareFileTime/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CompareFileTime/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/file_io/CompareFileTime/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CompareFileTime/test1/CMakeLists.txt
new file mode 100644
index 0000000000..fdcb6559b3
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CompareFileTime/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ CompareFileTime.c
+)
+
+add_executable(paltest_comparefiletime_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_comparefiletime_test1 coreclrpal)
+
+target_link_libraries(paltest_comparefiletime_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/CompareFileTime/test1/CompareFileTime.c b/src/pal/tests/palsuite/file_io/CompareFileTime/test1/CompareFileTime.c
new file mode 100644
index 0000000000..3758f7e4eb
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CompareFileTime/test1/CompareFileTime.c
@@ -0,0 +1,68 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: CompareFileTime.c
+**
+** Purpose: Tests the PAL implementation of the CompareFileTime function.
+** Defines a large and small file time, and compares them in all fashions
+** to ensure proper return values.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+
+int __cdecl main(int argc, char **argv)
+{
+
+ FILETIME SmallTime, BigTime;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* Set a Big and Small time. These were generated using
+ GetFileTime on a file, with a recent creation time and an old
+ modify time, to get a bigger and smaller value.
+ */
+
+ BigTime.dwLowDateTime = -755748832;
+ BigTime.dwHighDateTime = 29436941;
+
+ SmallTime.dwLowDateTime = -459754240;
+ SmallTime.dwHighDateTime = 29436314;
+
+ /* Check to see that SmallTime is less than Big Time */
+
+ if(CompareFileTime(&SmallTime,&BigTime) != -1)
+ {
+ Fail("ERROR: The first time is less than the second time, so "
+ "-1 should have been returned to indicate this.");
+ }
+
+ /* Check that BigTime is greater than SmallTime */
+
+ if(CompareFileTime(&BigTime,&SmallTime) != 1)
+ {
+ Fail("ERROR: The first time is greater than the second time, so "
+ "1 should have been returned to indicate this.");
+ }
+
+ /* Check that BigTime is equal to BigTime */
+
+ if(CompareFileTime(&BigTime,&BigTime) != 0)
+ {
+ Fail("ERROR: The first time is equal to the second time, so "
+ "0 should have been returned to indicate this.");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/file_io/CompareFileTime/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/CompareFileTime/test1/testinfo.dat
new file mode 100644
index 0000000000..4ff1b4c980
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CompareFileTime/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = CompareFileTime
+Name = Positive Test for CompareFileTime
+TYPE = DEFAULT
+EXE1 = comparefiletime
+Description
+= Test the CompareFileTime function.
+= Defines a large and small file time, and compares them in all fashions
+= to ensure proper return values.
diff --git a/src/pal/tests/palsuite/file_io/CopyFileA/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CopyFileA/CMakeLists.txt
new file mode 100644
index 0000000000..a3847f8ca9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CopyFileA/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+
diff --git a/src/pal/tests/palsuite/file_io/CopyFileA/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CopyFileA/test1/CMakeLists.txt
new file mode 100644
index 0000000000..b52e5076fa
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CopyFileA/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ CopyFileA.c
+)
+
+add_executable(paltest_copyfilea_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_copyfilea_test1 coreclrpal)
+
+target_link_libraries(paltest_copyfilea_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/CopyFileA/test1/CopyFileA.c b/src/pal/tests/palsuite/file_io/CopyFileA/test1/CopyFileA.c
new file mode 100644
index 0000000000..bfea85b7cb
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CopyFileA/test1/CopyFileA.c
@@ -0,0 +1,159 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: CopyFileA.c
+**
+** Purpose: Tests the PAL implementation of the CopyFileA function
+**
+**
+**===================================================================*/
+
+/*
+ 1. copy an existing file to existing with overwrite true
+ 2. copy an existing file to existing with overwrite false
+ 3. copy an existing file to non-existant with overwrite true
+ 4. copy an existing file to non-existant with overwrite false
+ 5. copy non-existant file to existing with overwrite true
+ 6. copy non-existant file to existing with overwrite false
+ 7. copy non-existant file to non-existant with overwrite true
+ 8. copy non-existant file to non-existant with overwrite false
+*/
+
+#include <palsuite.h>
+
+struct TESTS{
+ char* lpSource;
+ char* lpDestination;
+ BOOL bFailIfExists;
+ int nResult;
+ };
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ char szSrcExisting[] = {"src_existing.tmp"};
+ char szSrcNonExistant[] = {"src_non-existant.tmp"};
+ char szDstExisting[] = {"dst_existing.tmp"};
+ char szDstNonExistant[] = {"dst_non-existant.tmp"};
+ BOOL bRc = TRUE;
+ BOOL bSuccess = TRUE;
+ FILE* tempFile = NULL;
+ int i;
+ struct TESTS testCase[] =
+ {
+ {szSrcExisting, szDstExisting, FALSE, 1},
+ {szSrcExisting, szDstExisting, TRUE, 0},
+ {szSrcExisting, szDstNonExistant, FALSE, 1},
+ {szSrcExisting, szDstNonExistant, TRUE, 1},
+ {szSrcNonExistant, szDstExisting, FALSE, 0},
+ {szSrcNonExistant, szDstExisting, TRUE, 0},
+ {szSrcNonExistant, szDstNonExistant, FALSE, 0},
+ {szSrcNonExistant, szDstNonExistant, TRUE, 0}
+ };
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* create the src_existing file */
+ tempFile = fopen(szSrcExisting, "w");
+ if (tempFile != NULL)
+ {
+ fprintf(tempFile, "CopyFileA test file: src_existing.tmp\n");
+ fclose(tempFile);
+ }
+ else
+ {
+ Fail("CopyFileA: ERROR-> Couldn't create \"src_existing.tmp\" with "
+ "error %ld\n",
+ GetLastError());
+ }
+
+ /* create the dst_existing file */
+ tempFile = fopen(szDstExisting, "w");
+ if (tempFile != NULL)
+ {
+ fprintf(tempFile, "CopyFileA test file: dst_existing.tmp\n");
+ fclose(tempFile);
+ }
+ else
+ {
+ Fail("CopyFileA: ERROR-> Couldn't create \"dst_existing.tmp\" with "
+ "error %ld\n",
+ GetLastError());
+ }
+
+
+
+ for (i = 0; i < (sizeof(testCase) / sizeof(struct TESTS)); i++)
+ {
+ bRc = CopyFileA(testCase[i].lpSource,
+ testCase[i].lpDestination,
+ testCase[i].bFailIfExists);
+ if (!bRc)
+ {
+ if (testCase[i].nResult == 1)
+ {
+ Trace("CopyFileA: FAILED: %s -> %s with bFailIfExists = %d "
+ "with error %ld\n",
+ testCase[i].lpSource,
+ testCase[i].lpDestination,
+ testCase[i].bFailIfExists,
+ GetLastError());
+ bSuccess = FALSE;
+ }
+ }
+ else
+ {
+ if (testCase[i].nResult == 0)
+ {
+ Trace("CopyFileA: FAILED: %s -> %s with bFailIfExists = %d\n",
+ testCase[i].lpSource,
+ testCase[i].lpDestination,
+ testCase[i].bFailIfExists);
+ bSuccess = FALSE;
+ }
+ else
+ {
+ /* verify the file was moved */
+ if (GetFileAttributesA(testCase[i].lpDestination) == -1)
+ {
+ Trace("CopyFileA: GetFileAttributes of destination file "
+ "failed with error code %ld. \n",
+ GetLastError());
+ bSuccess = FALSE;
+ }
+ else if (GetFileAttributesA(testCase[i].lpSource) == -1)
+ {
+ Trace("CopyFileA: GetFileAttributes of source file "
+ "failed with error code %ld. \n",
+ GetLastError());
+ bSuccess = FALSE;
+ }
+ else
+ {
+ /* verify attributes of destination file to source file*/
+ if(GetFileAttributes(testCase[i].lpSource) !=
+ GetFileAttributes(testCase[i].lpDestination))
+ {
+ Trace("CopyFileA : The file attributes of the "
+ "destination file do not match the file "
+ "attributes of the source file.\n");
+ bSuccess = FALSE;
+ }
+ }
+ }
+ }
+ /* delete file file but don't worry if it fails */
+ DeleteFileA(szDstNonExistant);
+ }
+
+ int exitCode = bSuccess ? PASS : FAIL;
+ PAL_TerminateEx(exitCode);
+ return exitCode;
+}
diff --git a/src/pal/tests/palsuite/file_io/CopyFileA/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/CopyFileA/test1/testinfo.dat
new file mode 100644
index 0000000000..88b9c73cb4
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CopyFileA/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = CopyFileA
+Name = Test for CopyFileA (test 1)
+Type = DEFAULT
+EXE1 = copyfilea
+Description
+= Test the CopyFileA function
diff --git a/src/pal/tests/palsuite/file_io/CopyFileA/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CopyFileA/test2/CMakeLists.txt
new file mode 100644
index 0000000000..7454f32f51
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CopyFileA/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_copyfilea_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_copyfilea_test2 coreclrpal)
+
+target_link_libraries(paltest_copyfilea_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/CopyFileA/test2/test2.c b/src/pal/tests/palsuite/file_io/CopyFileA/test2/test2.c
new file mode 100644
index 0000000000..56618d0a58
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CopyFileA/test2/test2.c
@@ -0,0 +1,120 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test2.c
+**
+** Purpose: Tests the PAL implementation of the CopyFileA function
+** to see if a file can be copied to itself
+**
+**
+**===================================================================*/
+
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ BOOL bRc = TRUE;
+ char* szSrcExisting = "src_existing.tmp";
+ FILE* tempFile = NULL;
+ DWORD temp;
+ int retCode;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* create the src_existing file */
+ tempFile = fopen(szSrcExisting, "w");
+ if (tempFile != NULL)
+ {
+ retCode = fputs("CopyFileA test file: src_existing.tmp ", tempFile);
+ if(retCode < 0)
+ {
+ Fail("CopyFileA: ERROR-> Couldn't write to %s with error "
+ "%u.\n", szSrcExisting, GetLastError());
+ }
+ retCode = fclose(tempFile);
+ if(retCode != 0)
+ {
+ Fail("CopyFileA: ERROR-> Couldn't close file: %s with error "
+ "%u.\n", szSrcExisting, GetLastError());
+ }
+
+ }
+ else
+ {
+ Fail("CopyFileA: ERROR-> Couldn't create %s with "
+ "error %ld\n",szSrcExisting,GetLastError());
+ }
+
+ /* Get file attributes of source */
+ temp = GetFileAttributes(szSrcExisting);
+ if (temp == -1)
+ {
+ Fail("CopyFileA: GetFileAttributes of source file "
+ "failed with error code %ld. \n",
+ GetLastError());
+ }
+
+ /* make sure a file can't copy to itself
+ first testing with IfFileExists flag set to true */
+ bRc = CopyFileA(szSrcExisting,szSrcExisting,TRUE);
+ if(bRc)
+ {
+ Fail("ERROR: Cannot copy a file to itself, %u",GetLastError());
+ }
+
+ /* try to get file attributes of desitnation */
+ if (GetFileAttributesA(szSrcExisting) == -1)
+ {
+ Fail("CopyFileA: GetFileAttributes of destination file "
+ "failed with error code %ld. \n",
+ GetLastError());
+ }
+ else
+ {
+ /* verify attributes of destination file to source file*/
+
+ if(temp != GetFileAttributes(szSrcExisting))
+ {
+ Fail("CopyFileA : The file attributes of the "
+ "destination file do not match the file "
+ "attributes of the source file.\n");
+ }
+ }
+
+ /* testing with IfFileExists flags set to false
+ should fail in Windows and pass in UNIX */
+ bRc = CopyFileA(szSrcExisting,szSrcExisting,FALSE);
+ if(bRc && (GetLastError() != ERROR_ALREADY_EXISTS))
+ {
+ Fail("ERROR: Cannot copy a file to itself, %u",GetLastError());
+ }
+
+ if (GetFileAttributesA(szSrcExisting) == -1)
+ {
+ Fail("CopyFileA: GetFileAttributes of destination file "
+ "failed with error code %ld. \n",
+ GetLastError());
+ }
+ else
+ {
+ /* verify attributes of destination file to source file*/
+
+ if(temp != GetFileAttributes(szSrcExisting))
+ {
+ Fail("CopyFileA : The file attributes of the "
+ "destination file do not match the file "
+ "attributes of the source file.\n");
+ }
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/CopyFileA/test2/testinfo.dat b/src/pal/tests/palsuite/file_io/CopyFileA/test2/testinfo.dat
new file mode 100644
index 0000000000..31143842e6
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CopyFileA/test2/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = CopyFileA
+Name = CopyFileA - checking copying to itself (test2)
+Type = DEFAULT
+EXE1 = test2
+Description
+= Test the CopyFileA function's behaviour
+= for copying a file to itself.
+
diff --git a/src/pal/tests/palsuite/file_io/CopyFileA/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CopyFileA/test3/CMakeLists.txt
new file mode 100644
index 0000000000..986be9fd22
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CopyFileA/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_copyfilea_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_copyfilea_test3 coreclrpal)
+
+target_link_libraries(paltest_copyfilea_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/CopyFileA/test3/test3.c b/src/pal/tests/palsuite/file_io/CopyFileA/test3/test3.c
new file mode 100644
index 0000000000..18c8ce80dc
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CopyFileA/test3/test3.c
@@ -0,0 +1,141 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test3.c
+**
+** Purpose: Tests the PAL implementation of the CopyFileA function
+** to see if a file can be copied to itself
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ BOOL bRc = TRUE;
+ char* szSrcExisting = "src_existing.tmp";
+ char* szDest = "src_dest.tmp";
+ FILE* tempFile = NULL;
+ int retCode;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* create the src_existing file */
+ tempFile = fopen(szSrcExisting, "w");
+ if (tempFile != NULL)
+ {
+ retCode = fputs("CopyFileA test file: src_existing.tmp ", tempFile);
+ if(retCode < 0)
+ {
+ retCode = fclose(tempFile);
+ if(retCode != 0)
+ {
+ Trace("CopyFileA: ERROR-> Couldn't close file: %s with error "
+ "%u.\n", szSrcExisting, GetLastError());
+ }
+
+ Fail("CopyFileA: ERROR-> Couldn't write to %s with error "
+ "%u.\n", szSrcExisting, GetLastError());
+ }
+ retCode = fclose(tempFile);
+ if(retCode != 0)
+ {
+ Fail("CopyFileA: ERROR-> Couldn't close file: %s with error "
+ "%u.\n", szSrcExisting, GetLastError());
+ }
+
+ }
+ else
+ {
+ Fail("CopyFileA: ERROR-> Couldn't create %s with "
+ "error %ld\n",szSrcExisting,GetLastError());
+ }
+
+ /* set the file attributes of the source file to readonly */
+ bRc = SetFileAttributes(szSrcExisting, FILE_ATTRIBUTE_READONLY);
+ if(!bRc)
+ {
+ Fail("CopyFileA: ERROR-> Couldn't set file attributes for "
+ "file %s with error %u\n", szSrcExisting, GetLastError());
+ }
+
+ // Check the file attributes to make sure SetFileAttributes() above actually succeeded
+ DWORD fileAttributes = GetFileAttributesA(szSrcExisting);
+ if (fileAttributes == INVALID_FILE_ATTRIBUTES)
+ {
+ Fail("CopyFileA: Failed to get file attributes for source file, %u\n", GetLastError());
+ }
+ if ((fileAttributes & FILE_ATTRIBUTE_READONLY) == 0)
+ {
+ Fail("CopyFileA: SetFileAttributes(read-only) on source file returned success but did not make it read-only.\n");
+ }
+
+ /* copy the file */
+ bRc = CopyFileA(szSrcExisting,szDest,TRUE);
+ if(!bRc)
+ {
+ Fail("CopyFileA: Cannot copy a file with error, %u",GetLastError());
+ }
+
+
+ /* try to get file attributes of destination file */
+ fileAttributes = GetFileAttributesA(szDest);
+ if (fileAttributes == INVALID_FILE_ATTRIBUTES)
+ {
+ Fail("CopyFileA: GetFileAttributes of destination file "
+ "failed with error code %ld. \n",
+ GetLastError());
+ }
+
+ /* verify attributes of destination file to source file*/
+ if((fileAttributes & FILE_ATTRIBUTE_READONLY) != FILE_ATTRIBUTE_READONLY)
+ {
+ Fail("CopyFileA : The file attributes of the "
+ "destination file do not match the file "
+ "attributes of the source file.\n");
+ }
+
+ /* set the attributes of the destination file to normal again */
+ bRc = SetFileAttributesA(szDest, FILE_ATTRIBUTE_NORMAL);
+ if(!bRc)
+ {
+ Fail("CopyFileA: ERROR-> Couldn't set file attributes for "
+ "file %s with error %u\n", szDest, GetLastError());
+ }
+
+ /* delete the newly copied file */
+ bRc = DeleteFile(szDest);
+ if(!bRc)
+ {
+ Fail("CopyFileA: DeleteFile failed to delete the"
+ "file correctly with error,%u.\n",GetLastError());
+ }
+
+ /* set the attributes of the source file to normal again */
+ bRc = SetFileAttributesA(szSrcExisting, FILE_ATTRIBUTE_NORMAL);
+ if(!bRc)
+ {
+ Fail("CopyFileA: ERROR-> Couldn't set file attributes for "
+ "file %s with error %u\n", szSrcExisting, GetLastError());
+ }
+
+ /* delete the original file */
+ bRc = DeleteFile(szSrcExisting);
+ if(!bRc)
+ {
+ Fail("CopyFileA: DeleteFile failed to delete the"
+ "file correctly with error,%u.\n",GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/file_io/CopyFileA/test3/testinfo.dat b/src/pal/tests/palsuite/file_io/CopyFileA/test3/testinfo.dat
new file mode 100644
index 0000000000..5a9775d14f
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CopyFileA/test3/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = CopyFileA
+Name = CopyFileA - checking file attributes maintained (test2)
+Type = DEFAULT
+EXE1 = test3
+Description
+= Test the CopyFileA function's behaviour
+= for copying a file and verifying that
+= the copied file has the same file attributes
+= as the original.
+
diff --git a/src/pal/tests/palsuite/file_io/CopyFileA/test4/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CopyFileA/test4/CMakeLists.txt
new file mode 100644
index 0000000000..fb48c83741
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CopyFileA/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_copyfilea_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_copyfilea_test4 coreclrpal)
+
+target_link_libraries(paltest_copyfilea_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/CopyFileA/test4/test4.c b/src/pal/tests/palsuite/file_io/CopyFileA/test4/test4.c
new file mode 100644
index 0000000000..1ae69f5e1f
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CopyFileA/test4/test4.c
@@ -0,0 +1,180 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test4.c
+**
+** Purpose: Tests the PAL implementation of the CopyFileA function
+** to see if a file can through different users belonging to
+** different groups.
+**
+
+=====================================================================*/
+
+/* USECASE
+ Copy a file from a different user, belonging to a different group to
+ the the current user, who is a member of the current group. Then check
+ to see that the current user has the basic access rights to the copied
+ file.
+
+ Thie original file used is the passwd file in the etc directory of a
+ BSD machine. This file should exist on all machines.
+*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+#if WIN32
+ return PASS;
+
+#else
+
+ BOOL bRc = TRUE;
+ char* szSrcExisting = "/etc/passwd";
+ char* szDest = "temp.tmp";
+ char* szStringTest = "Marry had a little lamb";
+ char szStringRead[30]; /* large enough for string szStringTest */
+
+ HANDLE hFile = NULL;
+ DWORD dwBytesWritten=0;
+ DWORD dwBytesRead=0;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* copy the file */
+ bRc = CopyFileA(szSrcExisting,szDest,TRUE);
+ if(!bRc)
+ {
+ Fail("CopyFileA: Cannot copy a file with error, %u",GetLastError());
+ }
+
+ /* try to get file attributes of destination file */
+ if (GetFileAttributesA(szDest) == -1)
+ {
+ Fail("CopyFileA: GetFileAttributes of destination file "
+ "failed with error code %u. \n",
+ GetLastError());
+ }
+
+ /* set the attributes of the destination file to normal again */
+ bRc = SetFileAttributes(szDest, FILE_ATTRIBUTE_NORMAL);
+ if(!bRc)
+ {
+ Fail("CopyFileA: ERROR-> Couldn't set file attributes for "
+ "file %s with error %u\n", szDest, GetLastError());
+ }
+
+ /* open the file for write purposes */
+ hFile = CreateFile(szDest,
+ GENERIC_WRITE,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("CopyFileA: ERROR -> Unable to create file \"%s\".\n",
+ szDest);
+ }
+
+ /* Attempt to write to the file */
+ bRc = WriteFile(hFile, szStringTest, strlen(szStringTest), &dwBytesWritten, NULL);
+ if (!bRc)
+ {
+ Trace("CopyFileA: ERROR -> Unable to write to copied file with error "
+ "%u.\n", GetLastError());
+ bRc = CloseHandle(hFile);
+ if (!bRc)
+ {
+ Fail("CopyFileA: ERROR -> Unable to close file \"%s\" with "
+ "error %u.\n",szDest, GetLastError());
+ }
+ Fail("");
+
+ }
+
+ /* Close the file handle */
+ bRc = CloseHandle(hFile);
+ if (!bRc)
+ {
+ Fail("CopyFileA: ERROR -> Unable to close file \"%s\" with error %u "
+ ".\n",szDest,GetLastError());
+ }
+
+
+ /* open the file for read purposes */
+ hFile = CreateFile(szDest,
+ GENERIC_READ,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("CopyFileA: ERROR -> Unable to create file \"%s\".\n",
+ szDest);
+ }
+
+ /* Attempt to read from the file */
+ bRc = ReadFile(hFile, szStringRead, strlen(szStringTest), &dwBytesRead, NULL);
+ if (!bRc)
+ {
+ Trace("CopyFileA: ERROR -> Unable to read from copied file with "
+ "error %u.\n",GetLastError());
+ bRc = CloseHandle(hFile);
+ if (!bRc)
+ {
+ Fail("CopyFileA: ERROR -> Unable to close file \"%s\" with "
+ "error %u.\n",szDest, GetLastError());
+ }
+ Fail("");
+
+ }
+
+ if(strncmp(szStringTest,szStringRead, strlen(szStringTest)) != 0)
+ {
+ Trace("CopyFileA: ERROR -> The string which was written '%s' does not "
+ "match the string '%s' which was read from the copied file.\n",
+ szStringTest,szStringRead);
+ bRc = CloseHandle(hFile);
+ if (!bRc)
+ {
+ Fail("CopyFileA: ERROR -> Unable to close file \"%s\" with "
+ "error %u.\n",szDest, GetLastError());
+ }
+ Fail("");
+ }
+
+ /* Close the file handle */
+ bRc = CloseHandle(hFile);
+ if (!bRc)
+ {
+ Fail("CopyFileA: ERROR -> Unable to close file \"%s\" with error %u "
+ ".\n",szDest,GetLastError());
+ }
+
+ /* Remove the temporary file */
+ bRc = DeleteFile(szDest);
+ if(!bRc)
+ {
+ Fail("CopyFileA: Could not remove copied file with error %u\n",
+ GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+#endif
+
+}
diff --git a/src/pal/tests/palsuite/file_io/CopyFileA/test4/testinfo.dat b/src/pal/tests/palsuite/file_io/CopyFileA/test4/testinfo.dat
new file mode 100644
index 0000000000..42187b760f
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CopyFileA/test4/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = CopyFileA
+Name = CopyFileA - checking file attributes maintained (test4)
+Type = DEFAULT
+EXE1 = test4
+Description
+= Copy a file from a different user, belonging to a different group to
+= the the current user, who is a member of the current group. Then check
+= to see that the current user has the basic access rights to the copied
+= file.
+
diff --git a/src/pal/tests/palsuite/file_io/CopyFileW/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CopyFileW/CMakeLists.txt
new file mode 100644
index 0000000000..1962ade358
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CopyFileW/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+
diff --git a/src/pal/tests/palsuite/file_io/CopyFileW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CopyFileW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..766b120035
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CopyFileW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ CopyFileW.c
+)
+
+add_executable(paltest_copyfilew_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_copyfilew_test1 coreclrpal)
+
+target_link_libraries(paltest_copyfilew_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/CopyFileW/test1/CopyFileW.c b/src/pal/tests/palsuite/file_io/CopyFileW/test1/CopyFileW.c
new file mode 100644
index 0000000000..6127cc21bd
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CopyFileW/test1/CopyFileW.c
@@ -0,0 +1,155 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: CopyFileW.c
+**
+** Purpose: Tests the PAL implementation of the CopyFileW function
+**
+**
+**===================================================================*/
+
+/*
+1. copy an existing file to non-existant with overwrite true
+2. copy an existing file to non-existant with overwrite false
+3. copy an existing file to existing with overwrite true
+4. copy an existing file to existing with overwrite false
+5. copy non-existant file to non-existant with overwrite true
+6. copy non-existant file to non-existant with overwrite false
+7. copy non-existant file to existing with overwrite true
+8. copy non-existant file to existing with overwrite false
+*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ LPSTR lpSource[2] = {"src_existing.tmp", "src_non-existant.tmp"};
+ LPSTR lpDestination[2] = {"dst_existing.tmp", "dst_non-existant.tmp"};
+ WCHAR* wcSource;
+ WCHAR* wcDest;
+ BOOL bFailIfExists[3] = {FALSE, TRUE};
+ BOOL bRc = TRUE;
+ BOOL bSuccess = TRUE;
+ char results[20];
+ FILE* resultsFile = NULL;
+ FILE* tempFile = NULL;
+ int nCounter = 0;
+ int i, j, k;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* load the expected results */
+ resultsFile = fopen("expectedresults.txt", "r");
+ memset (results, 0, 20);
+ fgets(results, 20, resultsFile);
+ fclose(resultsFile);
+
+ nCounter = 0;
+
+ /* create the src_existing file */
+ tempFile = fopen(lpSource[0], "w");
+ if (tempFile != NULL)
+ {
+ fprintf(tempFile, "CopyFileW test file: src_existing.tmp\n");
+ fclose(tempFile);
+ }
+ else
+ {
+ Fail("CopyFileW: ERROR-> Couldn't create \"src_existing.tmp\"\n");
+ }
+
+ /* create the dst_existing file */
+ tempFile = fopen(lpDestination[0], "w");
+ if (tempFile != NULL)
+ {
+ fprintf(tempFile, "CopyFileW test file: dst_existing.tmp\n");
+ fclose(tempFile);
+ }
+ else
+ {
+ Fail("CopyFileW: ERROR-> Couldn't create \"dst_existing.tmp\"\n");
+ }
+
+
+ /* lpSource loop */
+ for (i = 0; i < 2; i++)
+ {
+ /* lpDestination loop */
+ for (j = 0; j < 2; j++)
+ {
+ /* bFailIfExists loop */
+ for (k = 0; k < 2; k++)
+ {
+ wcSource = convert(lpSource[i]);
+ wcDest = convert(lpDestination[j]);
+ bRc = CopyFileW(wcSource,
+ wcDest,
+ bFailIfExists[k]);
+ free(wcSource);
+ free(wcDest);
+ if (!bRc)
+ {
+ if (results[nCounter] == '1')
+ {
+ Trace("CopyFileW: FAILED: test[%d][%d][%d]\n", i, j, k);
+ bSuccess = FALSE;
+ }
+ }
+ else
+ {
+ if (results[nCounter] == '0')
+ {
+ Trace("CopyFileW: FAILED: test[%d][%d][%d]\n", i, j, k);
+ bSuccess = FALSE;
+ }
+ else
+ {
+ /* verify the file was moved */
+ if (GetFileAttributesA(lpDestination[j]) == -1)
+ {
+ Trace("CopyFileW: GetFileAttributes of destination"
+ "file failed on test[%d][%d][%d] with error "
+ "code %ld. \n",i,j,k,GetLastError());
+ bSuccess = FALSE;
+ }
+ else if (GetFileAttributesA(lpSource[i]) == -1)
+ {
+ Trace("CopyFileW: GetFileAttributes of source file "
+ "file failed on test[%d][%d][%d] with error "
+ "code %ld. \n",i,j,k,GetLastError());
+ bSuccess = FALSE;
+ }
+ else
+ {
+ /* verify attributes of destination file to
+ source file*/
+ if(GetFileAttributes(lpSource[i]) !=
+ GetFileAttributes(lpDestination[j]))
+ {
+ Trace("CopyFileW : The file attributes of the "
+ "destination file do not match the file "
+ "attributes of the source file on test "
+ "[%d][%d][%d].\n",i,j,k);
+ bSuccess = FALSE;
+ }
+ }
+ }
+
+ }
+ nCounter++;
+ /* delete file file but don't worry if it fails */
+ DeleteFileA(lpDestination[1]);
+ }
+ }
+ }
+
+ int exitCode = bSuccess ? PASS : FAIL;
+ PAL_TerminateEx(exitCode);
+ return exitCode;
+}
diff --git a/src/pal/tests/palsuite/file_io/CopyFileW/test1/ExpectedResults.txt b/src/pal/tests/palsuite/file_io/CopyFileW/test1/ExpectedResults.txt
new file mode 100644
index 0000000000..535a89fe50
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CopyFileW/test1/ExpectedResults.txt
@@ -0,0 +1 @@
+10110000 \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/CopyFileW/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/CopyFileW/test1/testinfo.dat
new file mode 100644
index 0000000000..b7ff6de2fd
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CopyFileW/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = CopyFileW
+Name = Tests CopyFileW functionality.
+Type = DEFAULT
+EXE1 = copyfilew
+Description
+= Test the CopyFileW function
+
diff --git a/src/pal/tests/palsuite/file_io/CopyFileW/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CopyFileW/test2/CMakeLists.txt
new file mode 100644
index 0000000000..5c0030bc8d
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CopyFileW/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_copyfilew_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_copyfilew_test2 coreclrpal)
+
+target_link_libraries(paltest_copyfilew_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/CopyFileW/test2/test2.c b/src/pal/tests/palsuite/file_io/CopyFileW/test2/test2.c
new file mode 100644
index 0000000000..5380a181ca
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CopyFileW/test2/test2.c
@@ -0,0 +1,124 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test2.c
+**
+** Purpose: Tests the PAL implementation of the CopyFileW function
+** Attempt to copy a file to itself
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ LPSTR szSrcExisting = "src_existing.tmp";
+ WCHAR* wcSource;
+ BOOL bRc = TRUE;
+ FILE* tempFile = NULL;
+ DWORD temp;
+ int retCode;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* create the src_existing file */
+ tempFile = fopen(szSrcExisting, "w");
+ if (tempFile != NULL)
+ {
+ retCode = fputs("CopyFileA test file: src_existing.tmp ", tempFile);
+ if(retCode < 0)
+ {
+ Fail("CopyFileW: ERROR-> Couldn't write to %s with error "
+ "%u.\n", szSrcExisting, GetLastError());
+ }
+ retCode = fclose(tempFile);
+ if(retCode != 0)
+ {
+ Fail("CopyFileW: ERROR-> Couldn't close file: %s with error "
+ "%u.\n", szSrcExisting, GetLastError());
+ }
+ }
+ else
+ {
+ Fail("CopyFileW: ERROR-> Couldn't create %s.\n", szSrcExisting);
+ }
+
+ /* convert source string to wide character */
+ wcSource = convert(szSrcExisting);
+
+ /* Get file attributes of source */
+ temp = GetFileAttributes(szSrcExisting);
+ if (temp == -1)
+ {
+ free(wcSource);
+ Fail("CopyFileW: GetFileAttributes of source file "
+ "failed with error code %ld. \n",
+ GetLastError());
+ }
+
+ /* make sure a file can't copy to itself
+ first testing with IfFileExists flag set to true */
+ bRc = CopyFileW(wcSource,wcSource,TRUE);
+ if(bRc)
+ {
+ free(wcSource);
+ Fail("ERROR: Cannot copy a file to itself, %u",GetLastError());
+ }
+
+ /* try to get file attributes of desitnation */
+ if (GetFileAttributesA(szSrcExisting) == -1)
+ {
+ free(wcSource);
+ Fail("CopyFileW: GetFileAttributes of destination file "
+ "failed with error code %ld. \n",
+ GetLastError());
+ }
+ else
+ {
+ /* verify attributes of destination file to source file*/
+ if(temp != GetFileAttributes(szSrcExisting))
+ {
+ free(wcSource);
+ Fail("CopyFileW : The file attributes of the "
+ "destination file do not match the file "
+ "attributes of the source file.\n");
+ }
+ }
+
+ /* testing with IfFileExists flags set to false
+ should fail in Windows and pass in UNIX */
+ bRc = CopyFileW(wcSource,wcSource,FALSE);
+ free(wcSource);
+ if(bRc && (GetLastError() != ERROR_ALREADY_EXISTS))
+ {
+ Fail("ERROR: Cannot copy a file to itself, %u",GetLastError());
+ }
+
+ if (GetFileAttributesA(szSrcExisting) == -1)
+ {
+ Fail("CopyFileW: GetFileAttributes of destination file "
+ "failed with error code %ld. \n",
+ GetLastError());
+ }
+ else
+ {
+ /* verify attributes of destination file to source file*/
+
+ if(temp != GetFileAttributes(szSrcExisting))
+ {
+ Fail("CopyFileW : The file attributes of the "
+ "destination file do not match the file "
+ "attributes of the source file.\n");
+ }
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/CopyFileW/test2/testinfo.dat b/src/pal/tests/palsuite/file_io/CopyFileW/test2/testinfo.dat
new file mode 100644
index 0000000000..7e1591dd72
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CopyFileW/test2/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = CopyFileW
+Name = Tests CopyFileW to check if file can be copied to itself. (test2)
+Type = DEFAULT
+EXE1 = test2
+Description
+= Test the CopyFileW function
+= to see the effect of copying a
+= file to itself.
+
diff --git a/src/pal/tests/palsuite/file_io/CopyFileW/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CopyFileW/test3/CMakeLists.txt
new file mode 100644
index 0000000000..52d9aad1c0
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CopyFileW/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_copyfilew_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_copyfilew_test3 coreclrpal)
+
+target_link_libraries(paltest_copyfilew_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/CopyFileW/test3/test3.c b/src/pal/tests/palsuite/file_io/CopyFileW/test3/test3.c
new file mode 100644
index 0000000000..a2eb04c443
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CopyFileW/test3/test3.c
@@ -0,0 +1,196 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test4.c
+**
+** Purpose: Tests the PAL implementation of the CopyFileW function
+** to see if a file can through different users belonging to
+** different groups.
+**
+
+=====================================================================*/
+
+/* USECASE
+ Copy a file from a different user, belonging to a different group to
+ the the current user, who is a member of the current group. Then check
+ to see that the current user has the basic access rights to the copied
+ file.
+
+ Thie original file used is the passwd file in the etc directory of a
+ BSD machine. This file should exist on all machines.
+*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+#if WIN32
+ return PASS;
+
+#else
+
+ BOOL bRc = TRUE;
+ WCHAR szSrcExisting[] = {'/','e','t','c','/','p','a','s','s','w','d','\0'};
+ WCHAR szDest[] = {'t','e','m','p','.','t','m','p','\0'};
+ WCHAR szStringTest[] = {'M','a','r','r','y',' ','h','a','d',' ','a',' ',
+ 'l','i','t','t','l','e',' ','l','a','m','b','\0'};
+ WCHAR szStringRead[30]; /* large enough for string szStringTest */
+
+ HANDLE hFile = NULL;
+ DWORD dwBytesWritten=0;
+ DWORD dwBytesRead=0;
+ int size=0;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* copy the file */
+ bRc = CopyFileW(szSrcExisting,szDest,TRUE);
+ if(!bRc)
+ {
+ Fail("CopyFileW: Cannot copy a file with error, %u",GetLastError());
+ }
+
+ /* try to get file attributes of destination file */
+ if (GetFileAttributesW(szDest) == -1)
+ {
+ Fail("CopyFileW: GetFileAttributes of destination file "
+ "failed with error code %u. \n",
+ GetLastError());
+ }
+
+ /* set the attributes of the destination file to normal again */
+ bRc = SetFileAttributesW(szDest, FILE_ATTRIBUTE_NORMAL);
+ if(!bRc)
+ {
+ Fail("CopyFileW: ERROR-> Couldn't set file attributes for "
+ "file %S with error %u\n", szDest, GetLastError());
+ }
+
+ /* open the file for write purposes */
+ hFile = CreateFileW((WCHAR *)szDest,
+ GENERIC_WRITE,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("CopyFileW: ERROR -> Unable to create file \"%S\".\n",
+ szDest);
+ }
+
+ /* To account for the size of a WCHAR is twice that of a char */
+ size = wcslen(szStringTest);
+ size = size*sizeof(WCHAR);
+
+ /* Attempt to write to the file */
+ bRc = WriteFile(hFile,
+ szStringTest,
+ size,
+ &dwBytesWritten,
+ NULL);
+
+ if (!bRc)
+ {
+ Trace("CopyFileW: ERROR -> Unable to write to copied file with error "
+ "%u.\n", GetLastError());
+ bRc = CloseHandle(hFile);
+ if (!bRc)
+ {
+ Fail("CopyFileW: ERROR -> Unable to close file \"%S\" with "
+ "error %u.\n",szDest, GetLastError());
+ }
+ Fail("");
+
+ }
+
+ /* Close the file handle */
+ bRc = CloseHandle(hFile);
+ if (!bRc)
+ {
+ Fail("CopyFileW: ERROR -> Unable to close file \"%S\" with error %u "
+ ".\n",szDest,GetLastError());
+ }
+
+
+ /* open the file for read purposes */
+ hFile = CreateFileW((WCHAR *)szDest,
+ GENERIC_READ,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("CopyFileW: ERROR -> Unable to create file \"%S\".\n",
+ szDest);
+ }
+
+ /* Attempt to read from the file */
+ bRc = ReadFile(hFile,
+ szStringRead,
+ size,
+ &dwBytesRead,
+ NULL);
+
+ if (!bRc)
+ {
+ Trace("CopyFileW: ERROR -> Unable to read from copied file with "
+ "error %u.\n",GetLastError());
+ bRc = CloseHandle(hFile);
+ if (!bRc)
+ {
+ Fail("CopyFileW: ERROR -> Unable to close file \"%S\" with "
+ "error %u.\n",szDest, GetLastError());
+ }
+ Fail("");
+
+ }
+
+ if(wcsncmp(szStringTest,szStringRead, wcslen(szStringTest)) != 0)
+ {
+ Trace("CopyFileW: ERROR -> The string which was written '%S' does not "
+ "match the string '%S' which was read from the copied file.\n",
+ szStringTest,szStringRead);
+ bRc = CloseHandle(hFile);
+ if (!bRc)
+ {
+ Fail("CopyFileW: ERROR -> Unable to close file \"%S\" with "
+ "error %u.\n",szDest, GetLastError());
+ }
+ Fail("");
+ }
+
+ /* Close the file handle */
+ bRc = CloseHandle(hFile);
+ if (!bRc)
+ {
+ Fail("CopyFileW: ERROR -> Unable to close file \"%S\" with error %u "
+ ".\n",szDest,GetLastError());
+ }
+
+ /* Remove the temporary file */
+ bRc = DeleteFileW(szDest);
+ if(!bRc)
+ {
+ Fail("CopyFileW: Could not remove copied file with error %u.\n",
+ GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+#endif
+
+}
diff --git a/src/pal/tests/palsuite/file_io/CopyFileW/test3/testinfo.dat b/src/pal/tests/palsuite/file_io/CopyFileW/test3/testinfo.dat
new file mode 100644
index 0000000000..9fd185dad0
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CopyFileW/test3/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = CopyFileW
+Name = CopyFileW - checking file attributes maintained (test3)
+Type = DEFAULT
+EXE1 = test3
+Description
+= Copy a file from a different user, belonging to a different group to
+= the the current user, who is a member of the current group. Then check
+= to see that the current user has the basic access rights to the copied
+= file.
+
diff --git a/src/pal/tests/palsuite/file_io/CreateDirectoryA/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CreateDirectoryA/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CreateDirectoryA/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/file_io/CreateDirectoryA/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CreateDirectoryA/test1/CMakeLists.txt
new file mode 100644
index 0000000000..f8cdf19933
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CreateDirectoryA/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ CreateDirectoryA.c
+)
+
+add_executable(paltest_createdirectorya_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createdirectorya_test1 coreclrpal)
+
+target_link_libraries(paltest_createdirectorya_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/CreateDirectoryA/test1/CreateDirectoryA.c b/src/pal/tests/palsuite/file_io/CreateDirectoryA/test1/CreateDirectoryA.c
new file mode 100644
index 0000000000..2bb441e732
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CreateDirectoryA/test1/CreateDirectoryA.c
@@ -0,0 +1,296 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: CreateDirectoryA.c
+**
+** Purpose: Tests the PAL implementation of the CreateDirectoryA function.
+**
+** Depends on:
+** RemoveDirectoryW (since RemoveDirectoryA is unavailable)
+** GetCurrentDirectoryA
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+/* apparently, under WIN32 the max path size is 248 but under
+ BSD it is _MAX_PATH */
+#if WIN32
+#define CREATE_MAX_PATH_SIZE 248
+#else
+#define CREATE_MAX_PATH_SIZE _MAX_PATH
+#endif
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ const char* szTestDir = {"test_directory"};
+ const char* szDotDir = {".dotDirectory"};
+ BOOL bRc = FALSE;
+ BOOL bSuccess = FALSE;
+ const int buf_size = CREATE_MAX_PATH_SIZE + 10;
+ char szDirName[CREATE_MAX_PATH_SIZE + 10];
+ char buffer[CREATE_MAX_PATH_SIZE + 10];
+ WCHAR* pTemp = NULL;
+ DWORD curDirLen;
+ DWORD curDirectory = 1024;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+
+ /* directory does not exist */
+ bRc = CreateDirectoryA(szTestDir, NULL);
+ if (bRc == FALSE)
+ {
+ Fail("CreateDirectoryA: Failed to create \"%s\" with error code %ld\n",
+ szTestDir,
+ GetLastError());
+ }
+
+
+ /* directory exists should fail */
+ bRc = CreateDirectoryA(szTestDir, NULL);
+ if (bRc == TRUE)
+ {
+ pTemp = convert((LPSTR)szTestDir);
+ bRc = RemoveDirectoryW(pTemp);
+ free(pTemp);
+ if (!bRc)
+ {
+ Trace("CreateDirectoryA: RemoveDirectoryW failed to remove "
+ "\"%s\" with the error code %ld.\n",
+ szTestDir,
+ GetLastError());
+ }
+ Fail("CreateDirectoryA: Succeeded creating the directory"
+ "\"%s\" when it exists already.\n",
+ szTestDir);
+ }
+ else
+ {
+ pTemp = convert((LPSTR)szTestDir);
+ bRc = RemoveDirectoryW(pTemp);
+ free(pTemp);
+ if (!bRc)
+ {
+ Fail("CreateDirectoryA: RemoveDirectoryW failed to remove "
+ "\"%s\" with the error code %ld.\n",
+ szTestDir,
+ GetLastError());
+ }
+ }
+
+
+ /* long directory names (CREATE_MAX_PATH_SIZE - 1, CREATE_MAX_PATH_SIZE
+ and CREATE_MAX_PATH_SIZE + 1 characters
+ including terminating null char) */
+
+ curDirLen = GetCurrentDirectoryA(0, NULL);
+
+ memset(szDirName, 0, buf_size);
+ memset(szDirName, 'a', CREATE_MAX_PATH_SIZE - 2 - curDirLen);
+ bRc = CreateDirectoryA(szDirName, NULL);
+ if (bRc == FALSE)
+ {
+ Fail("CreateDirectoryA: Failed to create a directory"
+ " name %d chars long with the error code %ld\n",
+ strlen(szDirName),
+ GetLastError());
+ }
+ else
+ {
+ /* Check to see if it's possible to navigate to directory */
+ GetCurrentDirectoryA(curDirectory, buffer);
+ bSuccess = SetCurrentDirectoryA(szDirName);
+ if(!bSuccess)
+ {
+ Fail("CreateDirectoryA: SetCurrentDirectoryA failed to "
+ "navigate to the newly created directory with error "
+ "code %u.\n", GetLastError());
+ }
+
+ /* Set directory back to initial directory */
+ SetCurrentDirectoryA(buffer);
+
+ pTemp = convert((LPSTR)szDirName);
+ bRc = RemoveDirectoryW(pTemp);
+ free(pTemp);
+ if (!bRc)
+ {
+ Fail("CreateDirectoryA: RemoveDirectoryW failed to remove "
+ "\"%s\" with the error code %ld.\n",
+ szDirName,
+ GetLastError());
+ }
+ }
+
+
+ memset(szDirName, 0, buf_size);
+ memset(szDirName, 'a', CREATE_MAX_PATH_SIZE - 1 - curDirLen);
+ bRc = CreateDirectoryA(szDirName, NULL);
+ if (bRc == FALSE)
+ {
+ Fail("CreateDirectoryA: Failed to create a directory"
+ " name %d chars long with error code %ld\n",
+ strlen(szDirName),
+ GetLastError());
+ }
+ else
+ {
+ /* Check to see if it's possible to navigate to directory */
+ GetCurrentDirectoryA(curDirectory, buffer);
+ bSuccess = SetCurrentDirectoryA(szDirName);
+ if(!bSuccess)
+ {
+ Fail("CreateDirectoryA: SetCurrentDirectoryA failed to "
+ "navigate to the newly created directory with error "
+ "code %u.\n", GetLastError());
+ }
+
+ /* Set Directroy back to initial directory */
+ SetCurrentDirectoryA(buffer);
+
+ pTemp = convert(szDirName);
+ bRc = RemoveDirectoryW(pTemp);
+ free(pTemp);
+ if (!bRc)
+ {
+ Fail("CreateDirectoryA: RemoveDirectoryW failed to remove "
+ "\"%s\" with the error code %ld.\n",
+ szDirName,
+ GetLastError());
+ }
+ }
+
+ memset(szDirName, 0, buf_size);
+ memset(szDirName, 'a', CREATE_MAX_PATH_SIZE - curDirLen);
+ bRc = CreateDirectoryA(szDirName, NULL);
+ if (bRc != FALSE)
+ {
+ /* Check to see if it's possible to navigate to directory */
+ GetCurrentDirectoryA(curDirectory, buffer);
+ bSuccess = SetCurrentDirectoryA(szDirName);
+ if(!bSuccess)
+ {
+ Fail("CreateDirectoryA: SetCurrentDirectoryA failed to "
+ "navigate to the newly created directory with error "
+ "code %u.\n", GetLastError());
+ }
+
+ /* set directory back to initial directory */
+ SetCurrentDirectoryA(buffer);
+
+ pTemp = convert(szDirName);
+ bRc = RemoveDirectoryW(pTemp);
+ free(pTemp);
+ if (!bRc)
+ {
+ Trace("CreateDirectoryA: RemoveDirectoryW failed to remove "
+ "\"%s\" with the error code %ld.\n",
+ szDirName,
+ GetLastError());
+ }
+ if (strlen(szDirName) > CREATE_MAX_PATH_SIZE)
+ {
+ Fail("CreateDirectoryA: Failed because it created a directory"
+ " name 1 character longer (%d chars) than the max dir size "
+ "allowed\n",
+ strlen(szDirName));
+ }
+ }
+
+
+ /* long directory name CREATE_MAX_PATH_SIZE + 3 chars including "..\"
+ (real path length <= CREATE_MAX_PATH_SIZE) */
+ memset(szDirName, 0, buf_size);
+ memset(szDirName, 'a', CREATE_MAX_PATH_SIZE + 3 - 1 - curDirLen);
+ szDirName[0] = '.';
+ szDirName[1] = '.';
+ szDirName[2] = '\\';
+ bRc = CreateDirectoryA(szDirName, NULL);
+ if (bRc == FALSE)
+ {
+ Fail("CreateDirectoryA: Failed to create a directory name more "
+ "than %d chars long and its real path name is less "
+ "than %d chars, error %u\n",
+ CREATE_MAX_PATH_SIZE,
+ CREATE_MAX_PATH_SIZE, GetLastError());
+ }
+ else
+ {
+ /* Check to see if it's possible to navigate to directory */
+ GetCurrentDirectoryA(curDirectory, buffer);
+ bSuccess = SetCurrentDirectoryA(szDirName);
+ if(!bSuccess)
+ {
+ Fail("CreateDirectoryA: SetCurrentDirectoryA failed to "
+ "navigate to the newly created directory with error "
+ "code %u.\n", GetLastError());
+ }
+
+ /* set directory back to initial directory */
+ SetCurrentDirectoryA(buffer);
+
+ pTemp = convert(szDirName);
+ bRc = RemoveDirectoryW(pTemp);
+ free(pTemp);
+ if (!bRc)
+ {
+ Fail("CreateDirectoryA: RemoveDirectoryW failed to remove "
+ " \"%s\" with the error code %ld.\n",
+ szDirName,
+ GetLastError());
+ }
+ }
+
+
+ /* directories with dots */
+ memset(szDirName, 0, buf_size);
+ sprintf(szDirName, szDotDir);
+ bRc = CreateDirectoryA(szDirName, NULL);
+ if (bRc == FALSE)
+ {
+ Fail("CreateDirectoryA: Failed to create \"%s\" with error code %ld\n",
+ szDotDir,
+ GetLastError());
+ }
+ else
+ {
+
+ /* Check to see if it's possible to navigate to directory */
+ GetCurrentDirectoryA(curDirectory, buffer);
+ bSuccess = SetCurrentDirectoryA(szDirName);
+ if(!bSuccess)
+ {
+ Fail("CreateDirectoryA: SetCurrentDirectoryA failed to "
+ "navigate to the newly created directory with error "
+ "code %u.\n", GetLastError());
+ }
+
+ /* set directory back to initial directory */
+ SetCurrentDirectoryA(buffer);
+
+ pTemp = convert((LPSTR)szDotDir);
+ bRc = RemoveDirectoryW(pTemp);
+ free(pTemp);
+ if (!bRc)
+ {
+ Fail("CreateDirectoryA: RemoveDirectoryW failed to remove "
+ " \"%s\" with the error code %ld.\n",
+ szDotDir,
+ GetLastError());
+ }
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/CreateDirectoryA/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/CreateDirectoryA/test1/testinfo.dat
new file mode 100644
index 0000000000..562d76d7be
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CreateDirectoryA/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = CreateDirectoryA
+Name = Test for CreateDirectoryA
+Type = DEFAULT
+EXE1 = createdirectorya
+Description
+= Create a directory that exists (should fail) and create
+= a directory that doesn't exist and verify results.
diff --git a/src/pal/tests/palsuite/file_io/CreateDirectoryA/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CreateDirectoryA/test2/CMakeLists.txt
new file mode 100644
index 0000000000..a50a986d1a
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CreateDirectoryA/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ createdirectorya.c
+)
+
+add_executable(paltest_createdirectorya_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createdirectorya_test2 coreclrpal)
+
+target_link_libraries(paltest_createdirectorya_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/CreateDirectoryA/test2/createdirectorya.c b/src/pal/tests/palsuite/file_io/CreateDirectoryA/test2/createdirectorya.c
new file mode 100644
index 0000000000..fc1bc967b7
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CreateDirectoryA/test2/createdirectorya.c
@@ -0,0 +1,335 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: createdirectorya.c
+**
+** Purpose: Tests the PAL implementation of the CreateDirectoryA function.
+** Test creating a directory in a directory path that does not exist.
+** Test creating directory with trailing slashes.
+**
+** Depends on:
+** RemoveDirectoryW (since RemoveDirectoryA is unavailable)
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+
+int main(int argc, char *argv[])
+{
+
+#if WIN32
+ const char* szTestRootDir = {"/at_root_directory_PALTEST"};
+#endif
+
+ const char* szTestDir = {"test_ directory"};
+ const char* szTestSubDir =
+ {".\\./././../test2/./../../////////createdirectorya"
+ "\\\\/test2/test_ directory\\sub"};
+ const char* szTest2SubDir = {"test_ directory/sub\\sub_sub"};
+ const char* szTest2SubDirWinSlash =
+ {"test_ directory/sub\\sub_sub\\"};
+ const char* szTest2SubDirUnixSlash =
+ {"test_ directory/sub\\sub_sub/////"};
+ BOOL bRc = FALSE;
+ BOOL clean = TRUE;
+ WCHAR* pTemp = NULL;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* platform dependent cases */
+ /* test for WIN32, create directory at the root."
+ * using '/directory_name ' format */
+#if WIN32
+
+ bRc = CreateDirectoryA(szTestRootDir, NULL);
+
+ if (bRc != TRUE)
+ {
+ Fail("CreateDirectoryA: Failed creating the directory "
+ "\"%s\" with the error code %ld.\n",
+ szTestRootDir,GetLastError());
+ }
+
+ /* clean szTestRootDir */
+ pTemp = convert((LPSTR) szTestRootDir);
+ bRc = RemoveDirectoryW(pTemp);
+ free(pTemp);
+
+ if (! bRc)
+ {
+ clean=bRc;
+ Trace("CreateDirectoryA: RemoveDirectoryW failed to remove "
+ "\"%s\" with the error code %ld.\n",
+ szTestRootDir,
+ GetLastError());
+ }
+
+#endif
+
+
+ /*
+ * create subdirectory "test_directory//sub//sub_sub"
+ * while parent directory does not exist.
+ */
+ bRc = CreateDirectoryA(szTest2SubDir, NULL);
+ if (bRc == TRUE)
+ {
+ pTemp = convert((LPSTR)szTest2SubDir);
+ bRc = RemoveDirectoryW(pTemp);
+ free(pTemp);
+ if (!bRc)
+ {
+ Trace("CreateDirectoryA: RemoveDirectoryW failed to remove "
+ "\"%s\" with the error code %ld.\n",
+ szTest2SubDir,
+ GetLastError());
+ }
+ Fail("CreateDirectoryA: Succeeded creating the directory\"%s\" while"
+ " its parent directory does not exists. It should fail.\n",
+ szTest2SubDir);
+
+ }
+
+
+ /* create directory tree one by one
+ * first create "test_dir"
+ */
+ bRc = CreateDirectoryA(szTestDir, NULL);
+
+ if (bRc != TRUE)/*failed creating the path*/
+ {
+ Fail("CreateDirectoryA: Failed creating the directory "
+ "\"%s\" with the error code %ld.\n", szTestDir,GetLastError());
+ }
+
+ /* create the sub directory test_directory//sub */
+ bRc = CreateDirectoryA(szTestSubDir, NULL);
+
+ if (bRc != TRUE)/*failed creating the path*/
+ {
+ Trace("CreateDirectoryA: Failed creating the directory "
+ "\"%s\" with the error code %ld.\n",
+ szTestSubDir , GetLastError());
+
+ /* cleaning... remove parent directory */
+ pTemp = convert((LPSTR)szTestDir);
+ bRc = RemoveDirectoryW(pTemp);
+ free(pTemp);
+ if (!bRc)
+ {
+ Trace("CreateDirectoryA: RemoveDirectoryW failed to remove "
+ "\"%s\" with an error code %ld.\n",
+ szTestDir,
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ /*
+ * the director structure is test_directory//sub
+ * test creating directory " test_directory//sub//sub_sub"
+ */
+ bRc = CreateDirectoryA(szTest2SubDir, NULL);
+ if (bRc != TRUE)
+ {
+ Trace("CreateDirectoryA: Failed creating the directory "
+ "\"%s\" with the error code %ld.\n",
+ szTest2SubDir , GetLastError());
+
+ /* remove parent directory test_directory//sub */
+ pTemp = convert((LPSTR)szTestSubDir);
+ bRc = RemoveDirectoryW(pTemp);
+ free(pTemp);
+ if (!bRc)
+ {
+ Trace("CreateDirectoryA: RemoveDirectoryW failed to remove "
+ "\"%s\" with the error code %ld.\n",
+ szTestSubDir,
+ GetLastError());
+ }
+
+ /* remove parent directory test_directory */
+ pTemp = convert((LPSTR)szTestDir);
+ bRc = RemoveDirectoryW(pTemp);
+ free(pTemp);
+ if (! bRc)
+ {
+ Trace("CreateDirectoryA: RemoveDirectoryW failed to remove "
+ "\"%s\" with the error code %ld.\n",
+ szTestDir,
+ GetLastError());
+ }
+ Fail("");
+
+ }
+
+ /* RemoveDirectiryW szTest2SubDir */
+ pTemp = convert((LPSTR)szTest2SubDir);
+ bRc = RemoveDirectoryW(pTemp);
+ free(pTemp);
+
+ if (! bRc)
+ {
+ clean=bRc;
+ Trace("CreateDirectoryA: RemoveDirectoryW failed to remove "
+ "\"%s\" with the error code %ld.\n",
+ szTest2SubDir,
+ GetLastError());
+ }
+
+
+ /*
+ * the director structure is test_directory//sub
+ * test creating directory " test_directory//sub//sub_sub\\"
+ */
+ bRc = CreateDirectoryA(szTest2SubDirWinSlash, NULL);
+ if (bRc != TRUE)
+ {
+ Trace("CreateDirectoryA: Failed creating the directory "
+ "\"%s\" with the error code %ld.\n",
+ szTest2SubDirWinSlash , GetLastError());
+
+ /* remove parent directory test_directory//sub */
+ pTemp = convert((LPSTR)szTestSubDir);
+ bRc = RemoveDirectoryW(pTemp);
+ free(pTemp);
+ if (! bRc)
+ {
+ Trace("CreateDirectoryA: RemoveDirectoryW failed to remove "
+ "\"%s\" with the error code %ld.\n",
+ szTestSubDir,
+ GetLastError());
+ }
+
+ /* remove parent directory test_directory */
+ pTemp = convert((LPSTR)szTestDir);
+ bRc = RemoveDirectoryW(pTemp);
+ free(pTemp);
+ if (! bRc)
+ {
+ Trace("CreateDirectoryA: RemoveDirectoryW failed to remove "
+ "\"%s\" with the error code %ld.\n",
+ szTestDir,
+ GetLastError());
+ }
+ Fail("");
+
+ }
+
+ /* RemoveDirectiryW szTest2SubDirWinSlash */
+ pTemp = convert((LPSTR)szTest2SubDirWinSlash);
+ bRc = RemoveDirectoryW(pTemp);
+ free(pTemp);
+
+ if (! bRc)
+ {
+ clean=bRc;
+ Trace("CreateDirectoryA: RemoveDirectoryW failed to remove "
+ "\"%s\" with the error code %ld.\n",
+ szTest2SubDirWinSlash,
+ GetLastError());
+ }
+
+ /*
+ * the director structure is test_directory//sub
+ * test creating directory " test_directory//sub//sub_sub/////"
+ */
+ bRc = CreateDirectoryA(szTest2SubDirUnixSlash, NULL);
+ if (bRc != TRUE)
+ {
+ Trace("CreateDirectoryA: Failed creating the directory "
+ "\"%s\" with the error code %ld.\n",
+ szTest2SubDirUnixSlash , GetLastError());
+
+ /* remove parent directory test_directory//sub */
+ pTemp = convert((LPSTR)szTestSubDir);
+ bRc = RemoveDirectoryW(pTemp);
+ free(pTemp);
+ if (! bRc)
+ {
+ Trace("CreateDirectoryA: RemoveDirectoryW failed to remove "
+ "\"%s\" with the error code %ld.\n",
+ szTestSubDir,
+ GetLastError());
+ }
+
+ /* remove parent directory test_directory */
+ pTemp = convert((LPSTR)szTestDir);
+ bRc = RemoveDirectoryW(pTemp);
+ free(pTemp);
+ if (! bRc)
+ {
+ Trace("CreateDirectoryA: RemoveDirectoryW failed to remove "
+ "\"%s\" with the error code %ld.\n",
+ szTestDir,
+ GetLastError());
+ }
+ Fail("");
+
+ }
+
+ /* RemoveDirectiryW will return false if directory does not exist.
+ * if it returns true then test is completed and the directory path
+ * is clean for running the test again.
+ */
+ pTemp = convert((LPSTR)szTest2SubDirUnixSlash);
+ bRc = RemoveDirectoryW(pTemp);
+ free(pTemp);
+
+ if (! bRc)
+ {
+ clean=bRc;
+ Trace("CreateDirectoryA: RemoveDirectoryW failed to remove "
+ "\"%s\" with the error code %ld.\n",
+ szTest2SubDirUnixSlash,
+ GetLastError());
+ }
+
+
+
+
+ /*clean parent szTestSubDir */
+ pTemp = convert((LPSTR)szTestSubDir);
+ bRc = RemoveDirectoryW(pTemp);
+ free(pTemp);
+
+ if (! bRc)
+ {
+ clean = bRc;
+ Trace("CreateDirectoryA: RemoveDirectoryW failed to remove "
+ "\"%s\" with the error code %ld.\n",
+ szTestSubDir,
+ GetLastError());
+ }
+
+ /*clean parent szTestDir */
+ pTemp = convert((LPSTR)szTestDir);
+ bRc = RemoveDirectoryW(pTemp);
+ free(pTemp);
+
+ if (! bRc)
+ {
+ clean = bRc;
+ Trace("CreateDirectoryA: RemoveDirectoryW failed to remove "
+ "\"%s\" with the error code %ld.\n",
+ szTestDir,
+ GetLastError());
+ }
+
+ if(! clean)
+ {
+ Fail("");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/CreateDirectoryA/test2/testinfo.dat b/src/pal/tests/palsuite/file_io/CreateDirectoryA/test2/testinfo.dat
new file mode 100644
index 0000000000..1e2ae774da
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CreateDirectoryA/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = CreateDirectoryA
+Name = Test for CreateDirectoryA
+Type = DEFAULT
+EXE1 = createdirectorya
+Description
+= Call CreateDirectoryA with a path in which more than just
+= the last component doesn't exist.
diff --git a/src/pal/tests/palsuite/file_io/CreateDirectoryW/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CreateDirectoryW/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CreateDirectoryW/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/file_io/CreateDirectoryW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CreateDirectoryW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..1981e37082
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CreateDirectoryW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ CreateDirectoryW.c
+)
+
+add_executable(paltest_createdirectoryw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createdirectoryw_test1 coreclrpal)
+
+target_link_libraries(paltest_createdirectoryw_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/CreateDirectoryW/test1/CreateDirectoryW.c b/src/pal/tests/palsuite/file_io/CreateDirectoryW/test1/CreateDirectoryW.c
new file mode 100644
index 0000000000..9b020cc19c
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CreateDirectoryW/test1/CreateDirectoryW.c
@@ -0,0 +1,347 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: CreateDirectoryW.c
+**
+** Purpose: Tests the PAL implementation of the CreateDirectoryW function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+/* apparently, under WIN32 the max path size is 248 but under
+ BSD it is _MAX_PATH */
+#if WIN32
+#define CREATE_MAX_PATH_SIZE 248
+#else
+#define CREATE_MAX_PATH_SIZE _MAX_PATH
+#endif
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ BOOL bRc = FALSE;
+ BOOL bSuccess = FALSE;
+ const int buf_size = CREATE_MAX_PATH_SIZE + 10;
+ char szDirName[CREATE_MAX_PATH_SIZE + 10];
+ char buffer[CREATE_MAX_PATH_SIZE + 10];
+ WCHAR* pTemp = NULL;
+ DWORD curDirLen;
+ DWORD curDirectory = 1024;
+
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* directory does not exist */
+ pTemp = convert("test_directory");
+ bRc = CreateDirectoryW(pTemp, NULL);
+ free(pTemp);
+ if (bRc == FALSE)
+ {
+ Fail("CreateDirectoryW: Failed to create \"test_directory\"\n");
+ }
+
+ /* directory exists */
+ pTemp = convert("test_directory");
+ bRc = CreateDirectoryW(pTemp, NULL);
+ if (bRc == TRUE)
+ {
+ bRc = RemoveDirectoryW(pTemp);
+ if(!bRc)
+ {
+ free(pTemp);
+ Fail("CreateDirectoryW: RemoveDirectoryW failed to "
+ "delete the directory with error %u.\n",
+ GetLastError());
+ }
+ free(pTemp);
+ Fail("CreateDirectoryW: Succeeded creating the directory"
+ " \"test_directory\" when it exists already.\n");
+ }
+
+ bRc = RemoveDirectoryW(pTemp);
+ if(!bRc)
+ {
+ free(pTemp);
+ Fail("CreateDirectoryW: RemoveDirectoryW failed to "
+ "delete the directory with error %u.\n",
+ GetLastError());
+ }
+ free(pTemp);
+
+ /* long directory names (CREATE_MAX_PATH_SIZE - 1, CREATE_MAX_PATH_SIZE
+ and CREATE_MAX_PATH_SIZE + 1 characters
+ including terminating null char) */
+
+ curDirLen = GetCurrentDirectoryA(0, NULL);
+
+ memset(szDirName, 0, buf_size);
+ memset(szDirName, 'a', CREATE_MAX_PATH_SIZE - 2 - curDirLen);
+ pTemp = convert((LPSTR)szDirName);
+ bRc = CreateDirectoryW(pTemp, NULL);
+ if (bRc == FALSE)
+ {
+ free(pTemp);
+ Fail("CreateDirectoryW: Failed to create a directory"
+ " name (%d) chars long with the error code %ld\n",
+ CREATE_MAX_PATH_SIZE - 1,
+ GetLastError());
+ }
+ else
+ {
+
+ /* Check to see if it's possible to navigate to directory */
+ GetCurrentDirectoryA(curDirectory, buffer);
+ bSuccess = SetCurrentDirectoryA(szDirName);
+ if(!bSuccess)
+ {
+ Trace("CreateDirectoryW: SetCurrentDirectoryA failed to "
+ "navigate to the newly created directory with error "
+ "code %u.\n", GetLastError());
+ bRc = RemoveDirectoryW(pTemp);
+ if(!bRc)
+ {
+ free(pTemp);
+ Fail("CreateDirectoryW: RemoveDirectoryW failed to "
+ "delete the directory with error %u.\n",
+ GetLastError());
+ }
+ free(pTemp);
+ Fail("");
+
+ }
+
+ /* Set directory back to initial directory */
+ bRc = SetCurrentDirectoryA(buffer);
+ if(!bRc)
+ {
+ free(pTemp);
+ Fail("CreateDirectoryW: SetCurrentDirectoryA failed to "
+ "change the directory with error %u.\n",
+ GetLastError());
+ }
+
+ bRc = RemoveDirectoryW(pTemp);
+ if(!bRc)
+ {
+ free(pTemp);
+ Fail("CreateDirectoryW: RemoveDirectoryW failed to "
+ "delete the directory with error %u.\n",
+ GetLastError());
+ }
+ free(pTemp);
+ }
+
+
+ memset(szDirName, 0, buf_size);
+ memset(szDirName, 'a', CREATE_MAX_PATH_SIZE - 1 - curDirLen);
+ pTemp = convert(szDirName);
+ bRc = CreateDirectoryW(pTemp, NULL);
+ if (bRc == FALSE)
+ {
+ free(pTemp);
+ Fail("CreateDirectoryW: Failed to create a directory"
+ " name %d chars long with error code %ld\n",
+ strlen(szDirName),
+ GetLastError());
+ }
+ else
+ {
+ /* Check to see if it's possible to navigate to directory */
+ GetCurrentDirectoryA(curDirectory, buffer);
+ bSuccess = SetCurrentDirectoryA(szDirName);
+ if(!bSuccess)
+ {
+ Trace("CreateDirectoryW: SetCurrentDirectoryA failed to "
+ "navigate to the newly created directory with error "
+ "code %u.\n", GetLastError());
+
+ bRc = RemoveDirectoryW(pTemp);
+ if(!bRc)
+ {
+ free(pTemp);
+ Fail("CreateDirectoryW: RemoveDirectoryW failed to "
+ "delete the directory with error %u.\n",
+ GetLastError());
+ }
+ free(pTemp);
+ Fail("");
+ }
+
+ /* Set directory back to initial directory */
+ bRc = SetCurrentDirectoryA(buffer);
+ if(!bRc)
+ {
+ free(pTemp);
+ Fail("CreateDirectoryW: SetCurrentDirectoryA failed to "
+ "change the directory with error %u.\n",
+ GetLastError());
+ }
+
+
+ bRc = RemoveDirectoryW(pTemp);
+ if(!bRc)
+ {
+ free(pTemp);
+ Fail("CreateDirectoryW: RemoveDirectoryW failed to "
+ "delete the directory with error %u.\n",
+ GetLastError());
+ }
+ free(pTemp);
+ }
+
+ memset(szDirName, 0, buf_size);
+ memset(szDirName, 'a', CREATE_MAX_PATH_SIZE - curDirLen);
+ pTemp = convert(szDirName);
+ bRc = CreateDirectoryW(pTemp, NULL);
+
+ if (bRc != FALSE)
+ {
+ RemoveDirectoryW(pTemp);
+ if(!bRc)
+ {
+ free(pTemp);
+ Fail("CreateDirectoryW: RemoveDirectoryW failed to "
+ "delete the directory with error %u.\n",
+ GetLastError());
+ }
+ if (strlen(szDirName) > CREATE_MAX_PATH_SIZE)
+ {
+ free(pTemp);
+ Fail("CreateDirectoryW: Failed because it created a directory"
+ " name 1 character longer (%d chars) than the max dir size"
+ " allowed\n",
+ strlen(szDirName));
+ }
+ }
+
+ free(pTemp);
+
+ /* long directory name CREATE_MAX_PATH_SIZE + 3 chars including "..\"
+ (real path length <= CREATE_MAX_PATH_SIZE) */
+ memset(szDirName, 0, buf_size);
+ memset(szDirName, 'a', CREATE_MAX_PATH_SIZE + 3 - 1 - curDirLen);
+ szDirName[0] = '.';
+ szDirName[1] = '.';
+ szDirName[2] = '\\';
+ pTemp = convert(szDirName);
+ bRc = CreateDirectoryW(pTemp, NULL);
+ if (bRc == FALSE)
+ {
+ free(pTemp);
+ Fail("CreateDirectoryW: Failed to create a directory name more "
+ "than %d chars long and its real path name is less "
+ "than %d chars\n",
+ CREATE_MAX_PATH_SIZE,
+ CREATE_MAX_PATH_SIZE);
+ }
+ else
+ {
+ /* Check to see if it's possible to navigate to directory */
+ GetCurrentDirectoryA(curDirectory, buffer);
+ bSuccess = SetCurrentDirectoryA(szDirName);
+ if(!bSuccess)
+ {
+ Trace("CreateDirectoryW: SetCurrentDirectoryA failed to "
+ "navigate to the newly created directory with error "
+ "code %u.\n", GetLastError());
+ bRc = RemoveDirectoryW(pTemp);
+ if(!bRc)
+ {
+ free(pTemp);
+ Fail("CreateDirectoryW: RemoveDirectoryW failed to "
+ "delete the directory with error %u.\n",
+ GetLastError());
+ }
+ free(pTemp);
+ Fail("");
+ }
+
+ /* Set directory back to initial directory */
+ bRc = SetCurrentDirectoryA(buffer);
+ if(!bRc)
+ {
+ free(pTemp);
+ Fail("CreateDirectoryW: SetCurrentDirectoryA failed to "
+ "change the directory with error %u.\n",
+ GetLastError());
+ }
+
+ bRc = RemoveDirectoryW(pTemp);
+ if(!bRc)
+ {
+ free(pTemp);
+ Fail("CreateDirectoryW: RemoveDirectoryW failed to "
+ "delete the directory with error %u.\n",
+ GetLastError());
+ }
+ free(pTemp);
+ }
+
+ /* directories with dots */
+ memset(szDirName, 0, 252);
+ sprintf(szDirName, ".dotDirectory");
+ pTemp = convert(szDirName);
+ bRc = CreateDirectoryW(pTemp, NULL);
+ if (bRc == FALSE)
+ {
+ free(pTemp);
+ Fail("CreateDirectoryW: Failed to create a dot directory\n");
+ }
+ else
+ {
+ /* Check to see if it's possible to navigate to directory */
+ GetCurrentDirectoryA(curDirectory, buffer);
+ bSuccess = SetCurrentDirectoryA(szDirName);
+ if(!bSuccess)
+ {
+ Trace("CreateDirectoryW: SetCurrentDirectoryA failed to "
+ "navigate to the newly created directory with error "
+ "code %u.\n", GetLastError());
+
+ bRc = RemoveDirectoryW(pTemp);
+ if(!bRc)
+ {
+ free(pTemp);
+ Fail("CreateDirectoryW: RemoveDirectoryW failed to "
+ "delete the directory with error %u.\n",
+ GetLastError());
+ }
+ free(pTemp);
+ Fail("");
+ }
+
+ /* Set directory back to initial directory */
+ bRc = SetCurrentDirectoryA(buffer);
+ if(!bRc)
+ {
+ free(pTemp);
+ Fail("CreateDirectoryW: SetCurrentDirectoryA failed to "
+ "change the directory with error %u.\n",
+ GetLastError());
+ }
+
+ bRc = RemoveDirectoryW(pTemp);
+ if(!bRc)
+ {
+ free(pTemp);
+ Fail("CreateDirectoryW: RemoveDirectoryW failed to "
+ "delete the directory with error %u.\n",
+ GetLastError());
+ }
+ free(pTemp);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/file_io/CreateDirectoryW/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/CreateDirectoryW/test1/testinfo.dat
new file mode 100644
index 0000000000..bc664892b4
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CreateDirectoryW/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = CreateDirectoryW
+Name = Positive Test for CreateDirectoryW
+Type = DEFAULT
+EXE1 = createdirectoryw
+Description
+= Test the CreateDirctoryW function
diff --git a/src/pal/tests/palsuite/file_io/CreateDirectoryW/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CreateDirectoryW/test2/CMakeLists.txt
new file mode 100644
index 0000000000..aae4e7dc54
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CreateDirectoryW/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ createdirectoryw.c
+)
+
+add_executable(paltest_createdirectoryw_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createdirectoryw_test2 coreclrpal)
+
+target_link_libraries(paltest_createdirectoryw_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/CreateDirectoryW/test2/createdirectoryw.c b/src/pal/tests/palsuite/file_io/CreateDirectoryW/test2/createdirectoryw.c
new file mode 100644
index 0000000000..20fac5a879
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CreateDirectoryW/test2/createdirectoryw.c
@@ -0,0 +1,345 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: createdirectoryw.c
+**
+** Purpose: Tests the PAL implementation of the CreateDirectoryW function.
+** Test creating a directory in a directory path that does not exist.
+** Test creating directory with trailing slashes.
+**
+** Depends on:
+** RemoveDirectoryW.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+#if WIN32
+WCHAR* szTestRootDir = NULL;
+#endif
+
+WCHAR* szTestDir = NULL;
+WCHAR* szTestSubDir = NULL;
+WCHAR* szTest2SubDir = NULL;
+WCHAR* szTest2SubDirWinSlash = NULL;
+WCHAR* szTest2SubDirUnixSlash = NULL;
+
+
+/* Free the memory allocated by convert(...) function*/
+static void CleanMemory(){
+
+#if WIN32
+ free(szTestRootDir);
+#endif
+
+ free( szTestDir);
+ free( szTestSubDir);
+ free( szTest2SubDir);
+ free( szTest2SubDirWinSlash);
+ free( szTest2SubDirUnixSlash);
+
+}
+
+
+int main(int argc, char *argv[])
+{
+ BOOL bRc = FALSE;
+ BOOL clean = TRUE;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* initialize strings */
+
+#if WIN32
+ szTestRootDir = convert("/at_root_directory_PALTEST");
+#endif
+
+ szTestDir = convert("test_ directory");
+ szTestSubDir = convert(
+ ".\\./././../test2/./../../////////createdirectoryw"
+ "\\\\/test2/test_ directory\\sub");
+ szTest2SubDir = convert("test_ directory/sub\\sub_sub");
+ szTest2SubDirWinSlash = convert("test_ directory/sub\\sub_sub\\\\");
+ szTest2SubDirUnixSlash = convert("test_ directory/sub\\sub_sub///");
+
+
+ /* Platform dependent cases:-
+ * test for WIN32, create directory at the root.
+ * using /directory_name format
+ */
+#if WIN32
+
+ bRc = CreateDirectoryW(szTestRootDir, NULL);
+
+ if (bRc != TRUE)
+ {
+
+ Trace("CreateDirectoryW: Failed creating the directory "
+ "\"%S\" with the error code %ld.\n",
+ szTestRootDir,GetLastError());
+ CleanMemory();
+ Fail("");
+ }
+
+ /*clean szTestRootDir */
+ bRc = RemoveDirectoryW(szTestRootDir);
+
+ if (! bRc)
+ {
+ clean = bRc;
+ Trace("CreateDirectoryW: RemoveDirectoryW failed to remove "
+ "\"%S\" with the error code %ld.\n",
+ szTestRootDir,
+ GetLastError());
+ }
+
+#endif
+
+
+ /*
+ * create subdirectory "test_directory//sub//sub_sub"
+ * while parent directory does not exist.
+ */
+ bRc = CreateDirectoryW(szTest2SubDir, NULL);
+ if (bRc == TRUE)
+ {
+ bRc = RemoveDirectoryW(szTest2SubDir);
+
+ if (! bRc )
+ {
+ Trace("CreateDirectoryW: RemoveDirectoryW failed to remove "
+ "\"%S\" with the error code %ld.\n",
+ szTest2SubDir,
+ GetLastError());
+ }
+
+ Trace("CreateDirectoryW: Succeeded creating the directory\"%S\" while"
+ " its parent directory does not exists. It should fail.\n",
+ szTest2SubDir);
+ CleanMemory();
+ Fail("");
+
+ }
+
+
+ /* create directory tree one by one
+ * first create "test_dir"
+ */
+ bRc = CreateDirectoryW(szTestDir, NULL);
+
+
+ if (bRc != TRUE)/*failed creating the path*/
+ {
+
+ Trace("CreateDirectoryW: Failed creating the directory "
+ "\"%S\" with the error code %ld.\n", szTestDir,GetLastError());
+ CleanMemory();
+ Fail("");
+ }
+
+ /* create the sub directory test_directory//sub */
+ bRc = CreateDirectoryW(szTestSubDir, NULL);
+
+ if (bRc != TRUE)/*failed creating the path*/
+ {
+ Trace("CreateDirectoryW: Failed creating the directory "
+ "\"%S\" with the error code %ld.\n",
+ szTestSubDir , GetLastError());
+
+ /* cleaning... remove parent directory */
+ bRc = RemoveDirectoryW(szTestDir);
+ if (! bRc)
+ {
+ Trace("CreateDirectoryW: RemoveDirectoryW failed to remove "
+ "\"%S\" with an error code %ld.\n",
+ szTestDir,
+ GetLastError());
+ }
+ CleanMemory();
+ Fail("");
+ }
+
+ /*
+ * the director structure is test_directory//sub
+ * test creating directory " test_directory//sub//sub_sub"
+ */
+ bRc = CreateDirectoryW(szTest2SubDir, NULL);
+ if (bRc != TRUE)
+ {
+ Trace("CreateDirectoryW: Failed creating the directory "
+ "\"%S\" with the error code %ld.\n",
+ szTest2SubDir , GetLastError());
+
+ /* remove parent directory test_directory//sub */
+ bRc = RemoveDirectoryW(szTestSubDir);
+ if (! bRc)
+ {
+ Trace("CreateDirectoryW: RemoveDirectoryW failed to remove "
+ "\"%S\" with the error code %ld.\n",
+ szTestSubDir,
+ GetLastError());
+ }
+
+ /* remove parent directory test_directory */
+ bRc = RemoveDirectoryW(szTestDir);
+ if (! bRc)
+ {
+ Trace("CreateDirectoryW: RemoveDirectoryW failed to remove "
+ "\"%S\" with the error code %ld.\n",
+ szTestDir,
+ GetLastError());
+ }
+ CleanMemory();
+ Fail("");
+
+ }
+
+ /* Remove Directiry szTest2SubDir*/
+ bRc = RemoveDirectoryW(szTest2SubDir);
+
+ if (! bRc)
+ {
+ clean = bRc;
+ Trace("CreateDirectoryW: RemoveDirectoryW failed to remove "
+ "\"%S\" with the error code %ld.\n",
+ szTest2SubDir,
+ GetLastError());
+ }
+
+ /*
+ * the director structure is test_directory//sub
+ * test creating directory " test_directory//sub//sub_sub\\\\"
+ */
+ bRc = CreateDirectoryW(szTest2SubDirWinSlash, NULL);
+ if (bRc != TRUE)
+ {
+ Trace("CreateDirectoryW: Failed creating the directory "
+ "\"%S\" with the error code %ld.\n",
+ szTest2SubDirWinSlash , GetLastError());
+
+ /* remove parent directory test_directory//sub */
+ bRc = RemoveDirectoryW(szTestSubDir);
+ if (! bRc)
+ {
+ Trace("CreateDirectoryW: RemoveDirectoryW failed to remove "
+ "\"%S\" with the error code %ld.\n",
+ szTestSubDir,
+ GetLastError());
+ }
+
+ /* remove parent directory test_directory */
+ bRc = RemoveDirectoryW(szTestDir);
+ if (! bRc)
+ {
+ Trace("CreateDirectoryW: RemoveDirectoryW failed to remove "
+ "\"%S\" with the error code %ld.\n",
+ szTestDir,
+ GetLastError());
+ }
+ CleanMemory();
+ Fail("");
+
+ }
+
+ /* Remove Directiry szTest2SubDirWinSlash */
+ bRc = RemoveDirectoryW(szTest2SubDirWinSlash);
+
+ if (! bRc)
+ {
+ clean = bRc;
+ Trace("CreateDirectoryW: RemoveDirectoryW failed to remove "
+ "\"%S\" with the error code %ld.\n",
+ szTest2SubDirWinSlash,
+ GetLastError());
+ }
+
+ /*
+ * the director structure is test_directory//sub
+ * test creating directory " test_directory//sub//sub_sub///"
+ */
+ bRc = CreateDirectoryW(szTest2SubDirUnixSlash, NULL);
+ if (bRc != TRUE)
+ {
+ Trace("CreateDirectoryW: Failed creating the directory "
+ "\"%S\" with the error code %ld.\n",
+ szTest2SubDirUnixSlash , GetLastError());
+
+ /* remove parent directory test_directory//sub */
+ bRc = RemoveDirectoryW(szTestSubDir);
+ if (! bRc)
+ {
+ Trace("CreateDirectoryW: RemoveDirectoryW failed to remove "
+ "\"%S\" with the error code %ld.\n",
+ szTestSubDir,
+ GetLastError());
+ }
+
+ /* remove parent directory test_directory */
+ bRc = RemoveDirectoryW(szTestDir);
+ if (! bRc)
+ {
+ Trace("CreateDirectoryW: RemoveDirectoryW failed to remove "
+ "\"%S\" with the error code %ld.\n",
+ szTestDir,
+ GetLastError());
+ }
+ CleanMemory();
+ Fail("");
+
+ }
+
+ /* Remove Directiry szTest2SubDirUnixSlash.*/
+ bRc = RemoveDirectoryW(szTest2SubDirUnixSlash);
+
+ if (! bRc)
+ {
+ clean = bRc;
+ Trace("CreateDirectoryW: RemoveDirectoryW failed to remove "
+ "\"%S\" with the error code %ld.\n",
+ szTest2SubDirUnixSlash,
+ GetLastError());
+ }
+
+ /*clean parent szTestSubDir */
+ bRc = RemoveDirectoryW(szTestSubDir);
+
+ if (! bRc)
+ {
+ clean = bRc;
+ Trace("CreateDirectoryW: RemoveDirectoryW failed to remove "
+ "\"%S\" with the error code %ld.\n",
+ szTestSubDir,
+ GetLastError());
+ }
+
+ /*clean parent szTestDir */
+ bRc = RemoveDirectoryW(szTestDir);
+
+
+ if (! bRc)
+ {
+ clean = bRc;
+ Trace("CreateDirectoryW: RemoveDirectoryW failed to remove "
+ "\"%S\" with the error code %ld.\n",
+ szTestDir,
+ GetLastError());
+ }
+
+ if(! clean)
+ {
+ CleanMemory();
+ Fail("");
+ }
+
+ CleanMemory();
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/CreateDirectoryW/test2/testinfo.dat b/src/pal/tests/palsuite/file_io/CreateDirectoryW/test2/testinfo.dat
new file mode 100644
index 0000000000..0d98a5f3b6
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CreateDirectoryW/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = CreateDirectoryW
+Name = Test for CreateDirectoryW
+Type = DEFAULT
+EXE1 = createdirectoryW
+Description
+= Call CreateDirectoryW with a path in which more than just
+= the last component doesn't exist.
diff --git a/src/pal/tests/palsuite/file_io/CreateFileA/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CreateFileA/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CreateFileA/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/file_io/CreateFileA/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CreateFileA/test1/CMakeLists.txt
new file mode 100644
index 0000000000..8814b2281b
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CreateFileA/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ CreateFileA.c
+)
+
+add_executable(paltest_createfilea_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createfilea_test1 coreclrpal)
+
+target_link_libraries(paltest_createfilea_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/CreateFileA/test1/CreateFileA.c b/src/pal/tests/palsuite/file_io/CreateFileA/test1/CreateFileA.c
new file mode 100644
index 0000000000..a70867a5c8
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CreateFileA/test1/CreateFileA.c
@@ -0,0 +1,145 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: CreateFileA.c
+**
+** Purpose: Test the PAL implementation of the CreateFileA function
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+BOOL Cleanup(void)
+{
+ char FileName[20];
+ int i;
+ BOOL bRet = TRUE; // assume success
+
+ // loop through all accesses, modes, dispositions and flags
+ for (i=0; i<4*8*4*5; ++i) {
+ sprintf(FileName, "test%03d.txt", i);
+ if (DeleteFileA(FileName) == FALSE) {
+ if (GetLastError() != ERROR_FILE_NOT_FOUND) {
+ bRet = FALSE;
+ }
+ }
+ }
+ return bRet;
+}
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ BOOL bSuccess = TRUE;
+ int nCounter = 0;
+ HANDLE hFile;
+ char lpFileName[20];
+ FILE *outFile = NULL;
+ char results[1024];
+ int i, j, k, l;
+ DWORD dwDesiredAccess[4] = {0, // 0
+ GENERIC_READ, // 1
+ GENERIC_WRITE, // 2
+ GENERIC_READ | GENERIC_WRITE}; // 3
+ DWORD dwShareMode[8] = {0, // 0
+ FILE_SHARE_READ, // 1
+ FILE_SHARE_WRITE, // 2
+ FILE_SHARE_DELETE, // 3
+ FILE_SHARE_READ | FILE_SHARE_WRITE, // 4
+ FILE_SHARE_READ | FILE_SHARE_DELETE, // 5
+ FILE_SHARE_WRITE | FILE_SHARE_DELETE, // 6
+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE}; // 7
+ LPSECURITY_ATTRIBUTES lpAttr = NULL;
+ DWORD dwCreationDisp[4] = {CREATE_NEW, // 0
+ CREATE_ALWAYS, // 1
+ OPEN_EXISTING, // 2
+ OPEN_ALWAYS}; // 3
+ DWORD dwFlagsAttrib[5] = {FILE_ATTRIBUTE_NORMAL, // 0
+ FILE_FLAG_SEQUENTIAL_SCAN, // 1
+ FILE_FLAG_WRITE_THROUGH, // 2
+ FILE_FLAG_NO_BUFFERING, // 3
+ FILE_FLAG_RANDOM_ACCESS}; // 4
+ HANDLE hTemplate = NULL;
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ if (!Cleanup()) {
+ Trace("Pre-test Cleanup() failed. LastError=%d\n", GetLastError());
+ return FAIL;
+ }
+
+ /* open the file to read the expected results */
+ outFile = fopen("winoutput", "r");
+ memset (results, 0, 1024);
+
+ fgets(results, 1024, outFile);
+ nCounter = (int)strlen(results);
+ fclose(outFile);
+
+ nCounter = 0;
+
+ // desired access loop
+ for (i = 0; i < 4; i++)
+ {
+ // share mode loop
+ for (j = 0; j < 8; j++)
+ {
+ // security attributes loop
+ for (k = 0; k < 4; k++)
+ {
+ // creation disp loop
+ for (l = 0; l < 5; l++)
+ {
+ sprintf(lpFileName, "test%03d.txt", nCounter);
+ hFile = CreateFile(lpFileName,
+ dwDesiredAccess[i],
+ dwShareMode[j],
+ lpAttr,
+ dwCreationDisp[k],
+ dwFlagsAttrib[l],
+ hTemplate);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ if (results[nCounter] == '1')
+ {
+ Trace("CreateFile: ERROR: Failed when expected "
+ "to pass %s [%d][%d][%d][%d]\n",
+ lpFileName, i, j, k, l);
+ bSuccess = FALSE;
+ }
+ }
+ else
+ {
+ CloseHandle(hFile);
+ if (results[nCounter] == '0')
+ {
+ Trace("CreateFile: ERROR: Passed when expected "
+ "to fail %s [%d][%d][%d][%d]\n",
+ lpFileName, i, j, k, l);
+ bSuccess = FALSE;
+ }
+ }
+ nCounter ++;
+ }
+ }
+ }
+ }
+
+ if (!Cleanup())
+ {
+ Trace("Post-test Cleanup() failed. LastError=%d\n", GetLastError());
+ return FAIL;
+ }
+
+ int exitCode = bSuccess ? PASS : FAIL;
+ PAL_TerminateEx(exitCode);
+ return exitCode;
+}
diff --git a/src/pal/tests/palsuite/file_io/CreateFileA/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/CreateFileA/test1/testinfo.dat
new file mode 100644
index 0000000000..bb872806eb
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CreateFileA/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = CreateFileA
+Name = test for CreateFileA
+Type = DEFAULT
+EXE1 = createfilea
+Description
+= Attempts to create files based on all combinations of
+= options of CreateFileA
diff --git a/src/pal/tests/palsuite/file_io/CreateFileA/test1/winoutput b/src/pal/tests/palsuite/file_io/CreateFileA/test1/winoutput
new file mode 100644
index 0000000000..3913b99427
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CreateFileA/test1/winoutput
@@ -0,0 +1 @@
+1111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111 \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/CreateFileW/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CreateFileW/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CreateFileW/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/file_io/CreateFileW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CreateFileW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..1ff0b8062f
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CreateFileW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ CreateFileW.c
+)
+
+add_executable(paltest_createfilew_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createfilew_test1 coreclrpal)
+
+target_link_libraries(paltest_createfilew_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/CreateFileW/test1/CreateFileW.c b/src/pal/tests/palsuite/file_io/CreateFileW/test1/CreateFileW.c
new file mode 100644
index 0000000000..4d7d20af29
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CreateFileW/test1/CreateFileW.c
@@ -0,0 +1,152 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: CreateFileW.c
+**
+** Purpose: Test the PAL implementation of the CreateFileW function
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+BOOL Cleanup(void)
+{
+ char FileName[20];
+ int i;
+ BOOL bRet = TRUE; // assume success
+
+ // loop through all accesses, modes, dispositions and flags
+ for (i=0; i<4*8*4*5; ++i) {
+ sprintf(FileName, "test%03d.txt", i);
+ if (DeleteFileA(FileName) == FALSE) {
+ if (GetLastError() != ERROR_FILE_NOT_FOUND) {
+ bRet = FALSE;
+ }
+ }
+ }
+ return bRet;
+}
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ BOOL bSuccess = TRUE;
+ int nCounter = 0;
+ HANDLE hFile = NULL;
+ WCHAR *lpFileName = NULL;
+ char* pTemp = NULL;
+ char string[40];
+ FILE *outFile = NULL;
+ char results[1024];
+ int i, j, k, l;
+ DWORD dwDesiredAccess[4] = {0, // 0
+ GENERIC_READ, // 1
+ GENERIC_WRITE, // 2
+ GENERIC_READ | GENERIC_WRITE}; // 3
+ DWORD dwShareMode[8] = {0, // 0
+ FILE_SHARE_READ, // 1
+ FILE_SHARE_WRITE, // 2
+ FILE_SHARE_DELETE, // 3
+ FILE_SHARE_READ | FILE_SHARE_WRITE, // 4
+ FILE_SHARE_READ | FILE_SHARE_DELETE, // 5
+ FILE_SHARE_WRITE | FILE_SHARE_DELETE, // 6
+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE}; // 7
+ LPSECURITY_ATTRIBUTES lpAttr = NULL;
+ DWORD dwCreationDisp[4] = {CREATE_NEW, // 0
+ CREATE_ALWAYS, // 1
+ OPEN_EXISTING, // 2
+ OPEN_ALWAYS}; // 3
+ DWORD dwFlagsAttrib[5] = {FILE_ATTRIBUTE_NORMAL, // 0
+ FILE_FLAG_SEQUENTIAL_SCAN, // 1
+ FILE_FLAG_WRITE_THROUGH, // 2
+ FILE_FLAG_NO_BUFFERING, // 3
+ FILE_FLAG_RANDOM_ACCESS}; // 4
+ HANDLE hTemplate = NULL;
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ if (!Cleanup()) {
+ Trace("Pre-test Cleanup() failed. LastError=%d\n", GetLastError());
+ return FAIL;
+ }
+
+ /* open the file to read the expected results */
+ outFile = fopen("winoutput", "r");
+ memset (results, 0, 1024);
+
+ fgets(results, 1024, outFile);
+ fclose(outFile);
+
+ nCounter = 0;
+
+ // desired access loop
+ for (i = 0; i < 4; i++)
+ {
+ // share mode loop
+ for (j = 0; j < 8; j++)
+ {
+ // security attributes loop
+ for (k = 0; k < 4; k++)
+ {
+ // creation disp loop
+ for (l = 0; l < 5; l++)
+ {
+ sprintf(string, "test%03d.txt", nCounter);
+ lpFileName = convert(string);
+ hFile = CreateFileW(lpFileName,
+ dwDesiredAccess[i],
+ dwShareMode[j],
+ lpAttr,
+ dwCreationDisp[k],
+ dwFlagsAttrib[l],
+ hTemplate);
+ free(lpFileName);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ if (results[nCounter] == '1')
+ {
+ pTemp = convertC(lpFileName);
+ Trace("CreateFile: ERROR: Failed when expected "
+ "to pass %s [%d][%d][%d][%d]\n",
+ pTemp, i, j, k, l);
+ free(pTemp);
+ bSuccess = FALSE;
+ }
+ }
+ else
+ {
+ CloseHandle(hFile);
+ if (results[nCounter] == '0')
+ {
+ pTemp = convertC(lpFileName);
+ Trace("CreateFile: ERROR: Passed when expected "
+ "to fail %s [%d][%d][%d][%d]\n",
+ pTemp, i, j, k, l);
+ free(pTemp);
+ bSuccess = FALSE;
+ }
+ }
+ nCounter ++;
+ }
+ }
+ }
+ }
+
+ if (!Cleanup())
+ {
+ Trace("Post-test Cleanup() failed. LastError=%d\n", GetLastError());
+ return FAIL;
+ }
+
+ int exitCode = bSuccess ? PASS : FAIL;
+ PAL_TerminateEx(exitCode);
+ return exitCode;
+}
diff --git a/src/pal/tests/palsuite/file_io/CreateFileW/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/CreateFileW/test1/testinfo.dat
new file mode 100644
index 0000000000..2dbf159996
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CreateFileW/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = CreateFileW
+Name = test for CreateFileW
+Type = DEFAULT
+EXE1 = createfilew
+Description
+= Attempts to create files based on all combinations of
+= options of CreateFileW
diff --git a/src/pal/tests/palsuite/file_io/CreateFileW/test1/winoutput b/src/pal/tests/palsuite/file_io/CreateFileW/test1/winoutput
new file mode 100644
index 0000000000..3913b99427
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/CreateFileW/test1/winoutput
@@ -0,0 +1 @@
+1111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111111111111100000111111111111111000001111111111111110000011111 \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/DeleteFileA/CMakeLists.txt b/src/pal/tests/palsuite/file_io/DeleteFileA/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/DeleteFileA/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/file_io/DeleteFileA/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/DeleteFileA/test1/CMakeLists.txt
new file mode 100644
index 0000000000..b979c206b2
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/DeleteFileA/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ DeleteFileA.cpp
+)
+
+add_executable(paltest_deletefilea_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_deletefilea_test1 coreclrpal)
+
+target_link_libraries(paltest_deletefilea_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/DeleteFileA/test1/DeleteFileA.cpp b/src/pal/tests/palsuite/file_io/DeleteFileA/test1/DeleteFileA.cpp
new file mode 100644
index 0000000000..a8eb71decb
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/DeleteFileA/test1/DeleteFileA.cpp
@@ -0,0 +1,182 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: DeleteFileA.c
+**
+** Purpose: Tests the PAL implementation of the DeleteFileA function.
+**
+**
+**===================================================================*/
+
+// delete an existing file
+// delete a non-existant file
+// delete an open file
+// delete files using wild cards
+// delete a hidden file
+// delete a file without proper permissions
+//
+
+#define PAL_STDCPP_COMPAT
+#include <palsuite.h>
+#undef PAL_STDCPP_COMPAT
+
+#include <unistd.h>
+#include <sys/stat.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ FILE *tempFile = NULL;
+ BOOL bRc = FALSE;
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ //
+ // create a test file
+ //
+ tempFile = fopen("testFile01.txt", "w");
+ if (tempFile == NULL)
+ {
+ Fail ("DeleteFileA: ERROR: Couldn't create \"DeleteFileA's"
+ " testFile01.txt\"\n");
+ }
+
+ fprintf(tempFile, "DeleteFileA test file.\n");
+ if (fclose(tempFile) != 0)
+ {
+ Fail ("DeleteFileA: ERROR: Couldn't close \"DeleteFileA's"
+ " testFile01.txt\"\n");
+ }
+
+ //
+ // delete a symlink to an existing file
+ //
+ if (symlink("testFile01.txt", "testFile01_symlink") != 0)
+ {
+ Fail("DeleteFileA: ERROR: Failed to create a symlink to testFile01.txt.\n");
+ }
+
+ bRc = DeleteFileA("testFile01_symlink");
+ if (bRc != TRUE)
+ {
+ Fail ("DeleteFileA: ERROR: Couldn't delete symlink!\n Error is %d\n", GetLastError());
+ }
+
+ struct stat statBuffer;
+ if (lstat("testFile01.txt", &statBuffer) != 0)
+ {
+ Fail("DeleteFileA: ERROR: Deleting a symlink deleted the file it was pointing to.\n");
+ }
+
+ if (lstat("testFile01_symlink", &statBuffer) == 0)
+ {
+ Fail("DeleteFileA: ERROR: Failed to delete a symlink.\n");
+ }
+
+ //
+ // deleting an existing file
+ //
+ bRc = DeleteFileA("testFile01.txt");
+ if (bRc != TRUE)
+ {
+ Fail ("DeleteFileA: ERROR: Couldn't delete DeleteFileA's"
+ " \"testFile01.txt\"\n"
+ " Error is %d\n", GetLastError());
+ }
+
+
+ //
+ // deleting a non-existant file : should fail
+ //
+
+ bRc = DeleteFileA("testFile02.txt");
+ if (bRc != FALSE)
+ {
+ Fail ("DeleteFileA: ERROR: Was able to delete the non-existant"
+ " file \"testFile02.txt\"\n");
+ }
+
+
+
+
+ //
+ // deleting an open file
+ //
+ tempFile = fopen("testFile03.txt", "w");
+ if (tempFile == NULL)
+ {
+ Fail("DeleteFileA: ERROR: Couldn't create \"DeleteFileA's"
+ " testFile03.txt\"\n");
+ }
+
+ fprintf(tempFile, "DeleteFileA test file.\n");
+ if (fclose(tempFile) != 0)
+ {
+ Fail ("DeleteFileA: ERROR: Couldn't close \"DeleteFileA's"
+ " testFile03.txt\"\n");
+ }
+
+ bRc = DeleteFileA("testFile03.txt");
+ if (bRc != TRUE)
+ {
+ Fail("DeleteFileA: ERROR: Couldn't delete DeleteFileA's"
+ " \"testFile03.txt\"\n"
+ " Error is %d\n", GetLastError());
+ }
+ bRc = DeleteFileA("testFile03.txt");
+
+
+
+
+ //
+ // delete using wild cards
+ //
+
+ // create the test file
+ tempFile = fopen("testFile04.txt", "w");
+ if (tempFile == NULL)
+ {
+ Fail("DeleteFileA: ERROR: Couldn't create DeleteFileA's"
+ " \"testFile04.txt\"\n");
+ }
+ fprintf(tempFile, "DeleteFileA test file.\n");
+ if (fclose(tempFile) != 0)
+ {
+ Fail ("DeleteFileA: ERROR: Couldn't close \"DeleteFileA's"
+ " testFile04.txt\"\n");
+ }
+
+ // delete using '?'
+ bRc = DeleteFileA("testFile0?.txt");
+ if (bRc == TRUE)
+ {
+ Fail("DeleteFileA: ERROR: Was able to delete using the"
+ " \'?\' wildcard\n");
+ }
+
+ // delete using '*'
+ bRc = DeleteFileA("testFile*.txt");
+ if (bRc == TRUE)
+ {
+ Fail("DeleteFileA: ERROR: Was able to delete using the"
+ " \'*\' wildcard\n");
+ }
+
+ bRc = DeleteFileA("testFile04.txt");
+ if (bRc != TRUE)
+ {
+ Fail ("DeleteFileA: ERROR: Couldn't delete DeleteFileA's"
+ " \"testFile04.txt\"\n"
+ " Error is %d\n", GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/DeleteFileA/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/DeleteFileA/test1/testinfo.dat
new file mode 100644
index 0000000000..24283ed932
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/DeleteFileA/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = DeleteFileA
+Name = Test for DeleteFileA (test 1)
+Type = DEFAULT
+EXE1 = deletefilea
+Description
+= Attempt to delete various files.
+
diff --git a/src/pal/tests/palsuite/file_io/DeleteFileW/CMakeLists.txt b/src/pal/tests/palsuite/file_io/DeleteFileW/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/DeleteFileW/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/file_io/DeleteFileW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/DeleteFileW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..046fd35148
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/DeleteFileW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ DeleteFileW.c
+)
+
+add_executable(paltest_deletefilew_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_deletefilew_test1 coreclrpal)
+
+target_link_libraries(paltest_deletefilew_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/DeleteFileW/test1/DeleteFileW.c b/src/pal/tests/palsuite/file_io/DeleteFileW/test1/DeleteFileW.c
new file mode 100644
index 0000000000..fca96d1e00
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/DeleteFileW/test1/DeleteFileW.c
@@ -0,0 +1,164 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: DeleteFileW.c
+**
+** Purpose: Tests the PAL implementation of the DeleteFileW function.
+**
+**
+**===================================================================*/
+
+// delete an existing file
+// delete a non-existant file
+// delete an open file
+// delete files using wild cards
+// delete a hidden file
+// delete a file without proper permissions
+//
+
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ FILE *tempFile = NULL;
+ BOOL bRc = FALSE;
+ WCHAR* pTemp = NULL;
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ //
+ // deleting an existing file
+ //
+ tempFile = fopen("testFile01.tmp", "w");
+ if (tempFile == NULL)
+ {
+ Fail ("DeleteFileW: ERROR: Couldn't create \"DeleteFileW's"
+ " testFile01.tmp\"\n");
+ }
+
+ fprintf(tempFile, "DeleteFileW test file.\n");
+ if (fclose(tempFile) != 0)
+ {
+ Fail ("DeleteFileA: ERROR: Couldn't close \"DeleteFileW's"
+ " testFile01.tmp\"\n");
+ }
+
+ pTemp = convert("testFile01.tmp");
+ bRc = DeleteFileW(pTemp);
+ free(pTemp);
+ if (bRc != TRUE)
+ {
+ Fail ("DeleteFileW: ERROR: Couldn't delete DeleteFileW's"
+ " \"testFile01.tmp\"\n"
+ " Error is %d\n", GetLastError());
+ }
+
+
+ //
+ // deleting a non-existant file : should fail
+ //
+
+ pTemp = convert("testFile02.tmp");
+ bRc = DeleteFileW(pTemp);
+ free(pTemp);
+ if (bRc != FALSE)
+ {
+ Fail ("DeleteFileW: ERROR: Was able to delete the non-existant"
+ " file \"testFile02.tmp\"\n");
+ }
+
+
+
+
+ //
+ // deleting an open file
+ //
+ tempFile = fopen("testFile03.tmp", "w");
+ if (tempFile == NULL)
+ {
+ Fail("DeleteFileW: ERROR: Couldn't create \"DeleteFileW's"
+ " testFile03.tmp\"\n");
+ }
+
+ fprintf(tempFile, "DeleteFileW test file.\n");
+ if (fclose(tempFile) != 0)
+ {
+ Fail ("DeleteFileA: ERROR: Couldn't close \"DeleteFileW's"
+ " testFile03.tmp\"\n");
+ }
+
+ pTemp = convert("testFile03.tmp");
+ bRc = DeleteFileW(pTemp);
+ if (bRc != TRUE)
+ {
+ Fail("DeleteFileW: ERROR: Couldn't delete DeleteFileW's"
+ " \"testFile03.tmp\"\n"
+ " Error is %d\n", GetLastError());
+ free(pTemp);
+ }
+ bRc = DeleteFileW(pTemp);
+ free(pTemp);
+
+
+
+
+ //
+ // delete using wild cards
+ //
+
+ // create the test file
+ tempFile = fopen("testFile04.tmp", "w");
+ if (tempFile == NULL)
+ {
+ Fail("DeleteFileW: ERROR: Couldn't create DeleteFileW's"
+ " \"testFile04.tmp\"\n");
+ }
+ fprintf(tempFile, "DeleteFileW test file.\n");
+ if (fclose(tempFile) != 0)
+ {
+ Fail ("DeleteFileA: ERROR: Couldn't close \"DeleteFileW's"
+ " testFile04.tmp\"\n");
+ }
+
+ // delete using '?'
+ pTemp = convert("testFile0?.tmp");
+ bRc = DeleteFileW(pTemp);
+ free(pTemp);
+ if (bRc == TRUE)
+ {
+ Fail("DeleteFileW: ERROR: Was able to delete using the"
+ " \'?\' wildcard\n");
+ }
+
+ // delete using '*'
+ pTemp = convert("testFile*.tmp");
+ bRc = DeleteFileW(pTemp);
+ free(pTemp);
+ if (bRc == TRUE)
+ {
+ Fail("DeleteFileW: ERROR: Was able to delete using the"
+ " \'*\' wildcard\n");
+ }
+
+ pTemp = convert("testFile04.tmp");
+ bRc = DeleteFileW(pTemp);
+ free(pTemp);
+ if (bRc != TRUE)
+ {
+ Fail ("DeleteFileW: ERROR: Couldn't delete DeleteFileW's"
+ " \"testFile04.tmp\"\n"
+ " Error is %d\n", GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/DeleteFileW/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/DeleteFileW/test1/testinfo.dat
new file mode 100644
index 0000000000..db44f998fc
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/DeleteFileW/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = DeleteFileW
+Name = Test for DeleteFileW (test 1)
+Type = DEFAULT
+EXE1 = deletefilew
+Description
+= Tests DeleteFileW on various file names
+
diff --git a/src/pal/tests/palsuite/file_io/FILECanonicalizePath/CMakeLists.txt b/src/pal/tests/palsuite/file_io/FILECanonicalizePath/CMakeLists.txt
new file mode 100644
index 0000000000..0c02c98f15
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FILECanonicalizePath/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ FILECanonicalizePath.c
+)
+
+add_executable(paltest_filecanonicalizepath_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_filecanonicalizepath_test1 coreclrpal)
+
+target_link_libraries(paltest_filecanonicalizepath_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/FILECanonicalizePath/FILECanonicalizePath.c b/src/pal/tests/palsuite/file_io/FILECanonicalizePath/FILECanonicalizePath.c
new file mode 100644
index 0000000000..91bac1f3cb
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FILECanonicalizePath/FILECanonicalizePath.c
@@ -0,0 +1,83 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: FILECanonicalizePath.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the FILECanonicalizePath function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+extern void FILECanonicalizePath(LPSTR lpUnixPath);
+
+void TestCase(LPSTR input, LPSTR expectedOutput);
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (PAL_Initialize(argc,argv) != 0)
+ {
+ return FAIL;
+ }
+
+ // Case 01: /<name> should not change
+ TestCase("/Test", "/Test");
+
+ // Case 02: /<name>/<name2> should not change
+ TestCase("/Test/Foo", "/Test/Foo");
+
+ // Case 03: // transforms to /
+ TestCase("//", "/");
+
+ // Case 04: /./ transforms to /
+ TestCase("/./", "/");
+
+ // Case 05: /<name>/../ transforms to /
+ TestCase("/Test/../", "/");
+
+ // Case 06: /Test/Foo/.. transforms to /Test
+ TestCase("/Test/Foo/..", "/Test");
+
+ // Case 07: /Test/.. transforms to /
+ TestCase("/Test/..", "/");
+
+ // Case 08: /. transforms to /
+ TestCase("/.", "/");
+
+ // Case 09: /<name/. transforms to /<name>
+ TestCase("/Test/.", "/Test");
+
+ // Case 10: /<name>/../. transforms to /
+ TestCase("/Test/../.", "/");
+
+ // Case 11: /.. transforms to /
+ TestCase("/..", "/");
+
+ PAL_Terminate();
+ return PASS;
+}
+
+void TestCase(LPSTR input, LPSTR expectedOutput)
+{
+ // Save the input for debug logging since the input is edited in-place
+ char* pOriginalInput = (char*)malloc(strlen(input) * sizeof(char) + 1);
+ strcpy(pOriginalInput, input);
+
+ char* pInput = (char*)malloc(strlen(input) * sizeof(char) + 1);
+ strcpy(pInput, pOriginalInput);
+
+ FILECanonicalizePath(pInput);
+ if (strcmp(pInput, expectedOutput) != 0)
+ {
+ free(pOriginalInput);
+ free(pInput);
+ Fail("FILECanonicalizePath error: input %s did not match expected output %s; got %s instead", pOriginalInput, expectedOutput, pInput);
+ }
+
+ free(pOriginalInput);
+ free(pInput);
+}
diff --git a/src/pal/tests/palsuite/file_io/FILECanonicalizePath/testinfo.dat b/src/pal/tests/palsuite/file_io/FILECanonicalizePath/testinfo.dat
new file mode 100644
index 0000000000..033ad78b47
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FILECanonicalizePath/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = FILECanonicalizePath
+Name = Test for FILECanonicalizePath (test 1)
+Type = DEFAULT
+EXE1 = filecanonicalizepath
+Description
+= Canonicalizes paths and verifies the results
diff --git a/src/pal/tests/palsuite/file_io/FileTimeToDosDateTime/CMakeLists.txt b/src/pal/tests/palsuite/file_io/FileTimeToDosDateTime/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FileTimeToDosDateTime/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/file_io/FileTimeToDosDateTime/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/FileTimeToDosDateTime/test1/CMakeLists.txt
new file mode 100644
index 0000000000..131054266b
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FileTimeToDosDateTime/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_filetimetodosdatetime_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_filetimetodosdatetime_test1 coreclrpal)
+
+target_link_libraries(paltest_filetimetodosdatetime_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/FileTimeToDosDateTime/test1/test1.c b/src/pal/tests/palsuite/file_io/FileTimeToDosDateTime/test1/test1.c
new file mode 100644
index 0000000000..5f2c81ff98
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FileTimeToDosDateTime/test1/test1.c
@@ -0,0 +1,116 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests that FileTimeToDosDateTime successfully converts values.
+** Makes sure values are rounded up, and the limits of the function
+** pass. Also tests that values outside the valid range fail.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+typedef struct
+{
+ DWORD FileTimeLow;
+ DWORD FileTimeHigh;
+ WORD FatDate;
+ WORD FatTime;
+} testCase;
+
+int __cdecl main(int argc, char **argv)
+{
+ FILETIME FileTime;
+ WORD ResultDate;
+ WORD ResultTime;
+ BOOL ret;
+ int i;
+
+ testCase testCases[] =
+ {
+ /* Test a normal time */
+ {0x9BE00100, 0x1B4A02C, 0x14CF, 0x55AF}, /* 12/15/2000, 10:45:30 AM*/
+ /* Test that 12/15/2000, 10:45:29 Gets rounded up */
+ {0x9B476A80, 0x1B4A02C, 0x14CF, 0x55AF}, /* 12/15/2000, 10:45:30 AM*/
+ /* Test that 12/15/2000, 10:45:31 Gets rounded up */
+ {0x9C789780, 0x1B4A02C, 0x14CF, 0x55B0}, /* 12/15/2000, 10:45:32 AM*/
+
+ /* Test the upper and lower limits of the function */
+ {0xE1D58000, 0x1A8E79F, 0x0021, 0x0000}, /* 1/1/1980, 12:00:00 AM*/
+ {0xb9de1300, 0x1e9eede, 0x739f, 0xbf7d}, /* 12/31/2037, 11:59:58 PM*/
+
+ /* Tests that should fail */
+ {0, 0, 0, 0},
+ {0xE0A45300, 0x1A8E79F, 0, 0},
+ {0x66D29301, 0x23868B8, 0, 0}
+
+ /* All this accomplishes is for the date to overflow.
+ Likely the only reason it fails in Windows is bacause the
+ resulting date falls outside of the legal range. Under BSD,
+ it falls into a legal range. This being that BSD calculates time
+ from 1900 to 2037, not 1980 to 2107.
+ {0xFFFFFFFF, 0xFFFFFFF, 0, 0}
+ */
+ };
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ for (i=0; i<sizeof(testCases) / sizeof(testCase); i++)
+ {
+ ResultDate = 0xFFFF;
+ ResultTime = 0xFFFF;
+
+ FileTime.dwLowDateTime = testCases[i].FileTimeLow;
+ FileTime.dwHighDateTime = testCases[i].FileTimeHigh;
+
+
+ ret = FileTimeToDosDateTime(&FileTime, &ResultDate, &ResultTime);
+ if (testCases[i].FatDate != 0 || testCases[i].FatTime != 0)
+ {
+ /* Expected it to pass */
+ if (!ret)
+ {
+ Fail("FileTimeToDosDateTime failed for %X,%X!\n",
+ testCases[i].FileTimeLow, testCases[i].FileTimeHigh);
+ }
+
+ if (ResultDate != testCases[i].FatDate ||
+ ResultTime != testCases[i].FatTime)
+ {
+ Fail("FileTimeToDosDateTime did not convert %X,%X "
+ "successfully:\nExpected date to be %hX, time %hx.\n"
+ "Got %hX, %hX\n", testCases[i].FileTimeLow,
+ testCases[i].FileTimeHigh, testCases[i].FatDate,
+ testCases[i].FatTime, ResultDate, ResultTime);
+ }
+ }
+ else
+ {
+ /* Expected it to fail. */
+ if (ret)
+ {
+ Fail("FileTimeToDosDateTime passed for %X,%X!\n",
+ testCases[i].FileTimeLow, testCases[i].FileTimeHigh);
+ }
+
+ if (ResultDate != 0xFFFF || ResultTime != 0xFFFF)
+ {
+ Fail("FileTimeToDosDateTime failed, but modified output "
+ "parameters: %X %X\n", ResultDate, ResultTime);
+ }
+ }
+
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/file_io/FileTimeToDosDateTime/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/FileTimeToDosDateTime/test1/testinfo.dat
new file mode 100644
index 0000000000..b5c7e1ae52
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FileTimeToDosDateTime/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = FileTimeToDosDateTime
+Name = Positive Test #1 for FileTimeToDosDateTime
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Tests that FileTimeToDosDateTime successfully converts values.
+=Makes sure values are rounded up, and the limits of the function
+=pass. Also tests that values outside the valid range fail.
+
diff --git a/src/pal/tests/palsuite/file_io/FindClose/CMakeLists.txt b/src/pal/tests/palsuite/file_io/FindClose/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FindClose/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/file_io/FindClose/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/FindClose/test1/CMakeLists.txt
new file mode 100644
index 0000000000..732c9f58d3
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FindClose/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ FindClose.c
+)
+
+add_executable(paltest_findclose_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_findclose_test1 coreclrpal)
+
+target_link_libraries(paltest_findclose_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/FindClose/test1/FindClose.c b/src/pal/tests/palsuite/file_io/FindClose/test1/FindClose.c
new file mode 100644
index 0000000000..3d53806e48
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FindClose/test1/FindClose.c
@@ -0,0 +1,275 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: FindClose.c
+**
+** Purpose: Tests the PAL implementation of the FindClose function.
+**
+**
+**===================================================================*/
+
+
+#include <palsuite.h>
+
+
+
+const WCHAR szFindName[] = {'t','e', 's', 't', '0', '1', '.', 't', 'x', 't', '\0'};
+const WCHAR szFindName_02[] = {'t','e', 's', 't', '0', '2', '.', 't', 'x', 't', '\0'};
+const WCHAR szFindName_03[] = {'t','e', 's', 't', '0', '3', '.', 't', 'x', 't', '\0'};
+const WCHAR szFindNameWldCard_01[] = {'t','e', 's', 't', '0', '?', '.', 't', 'x', 't', '\0'};
+const WCHAR szFindNameWldCard_02[] = {'*', '.', 't', 'x', 't', '\0'};
+const WCHAR szDirName[] = {'t','e', 's', 't', '_', 'd', 'i', 'r', '\0'};
+const WCHAR szDirName_02[] = {'t','e', 's', 't', '_', 'd', 'i', 'r', '0', '2', '\0'};
+const WCHAR szDirNameWldCard[] = {'t','e', 's', 't', '_', '*', '\0'};
+
+
+
+BOOL createTestFile(const WCHAR* szName)
+{
+ FILE *pFile = NULL;
+ char* pTemp = NULL;
+
+ pTemp = convertC((WCHAR*)szName);
+ pFile = fopen(pTemp, "w");
+ if (pFile == NULL)
+ {
+ Trace("FindClose: ERROR -> Unable to create file \"%s\".\n", pTemp);
+ free(pTemp);
+ return FALSE;
+ }
+ else
+ {
+ fprintf(pFile, "FindClose test file, \"%s\".\n", pTemp);
+ free(pTemp);
+ fclose(pFile);
+ }
+ return TRUE;
+}
+
+
+void removeAll()
+{
+ RemoveDirectoryW(szDirName);
+ RemoveDirectoryW(szDirName_02);
+
+ DeleteFileW(szFindName);
+ DeleteFileW(szFindName_02);
+ DeleteFileW(szFindName_03);
+}
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ WIN32_FIND_DATAW findFileData;
+ WIN32_FIND_DATAW findFileData_02;
+ HANDLE hFind = NULL;
+ BOOL bRc = FALSE;
+ char* pTemp = NULL;
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* do some clean up just to be sure */
+ removeAll();
+
+ /* FindClose a null handle */
+ if(FindClose(NULL)!=0)
+ {
+ Fail("FindClose: ERROR -> Closing a NULL handle succeeded.\n");
+ }
+
+ /* find a file that exists */
+ if(createTestFile(szFindName) == FALSE)
+ {
+ removeAll();
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ if(createTestFile(szFindName_02) == FALSE)
+ {
+ removeAll();
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ if(createTestFile(szFindName_03) == FALSE)
+ {
+ removeAll();
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ // close a FindFirstFileW handle
+ hFind = FindFirstFileW(szFindName, &findFileData);
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ pTemp = convertC((WCHAR*)szFindName);
+ Trace("FindClose: ERROR -> Unable to find \"%s\"\n", pTemp);
+ free(pTemp);
+ removeAll();
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ else
+ {
+ bRc = FindClose(hFind);
+ if (bRc == FALSE)
+ {
+ removeAll();
+ Fail("FindClose: ERROR -> Unable to close a valid"
+ " FindFirstFileW handle.\n");
+ }
+ }
+ hFind = FindFirstFileW(szFindName, &findFileData);
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ pTemp = convertC((WCHAR*)szFindName);
+ Trace("FindClose: ERROR -> Unable to find \"%s\"\n", pTemp);
+ free(pTemp);
+ removeAll();
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ else
+ {
+ bRc = FindNextFileW(hFind, &findFileData);
+ if (bRc != FALSE)
+ {
+ removeAll();
+ Fail("FindClose: ERROR -> Found a file that doesn't exist.\n");
+ }
+ else
+ {
+ bRc = FindClose(hFind);
+ if (bRc == FALSE)
+ {
+ removeAll();
+ Fail("FindClose: ERROR -> Unable to close a valid "
+ "FindNextFileW handle.\n");
+ }
+ }
+ }
+
+ /* find a directory that exists */
+ bRc = CreateDirectoryW(szDirName, NULL);
+ if (bRc == FALSE)
+ {
+ pTemp = convertC((WCHAR*)szDirName);
+ Trace("FindClose: ERROR -> Failed to create the directory \"%s\"\n",
+ pTemp);
+ free(pTemp);
+ removeAll();
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ bRc = CreateDirectoryW(szDirName_02, NULL);
+ if (bRc == FALSE)
+ {
+ pTemp = convertC((WCHAR*)szDirName_02);
+ Trace("FindClose: ERROR -> Failed to create the directory \"%s\"\n",
+ pTemp);
+ free(pTemp);
+ removeAll();
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ hFind = FindFirstFileW(szDirName, &findFileData);
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ pTemp = convertC((WCHAR*)szDirName);
+ Trace("FindClose: ERROR. FindFirstFileW was unable to find \"%s\"\n",
+ pTemp);
+ free(pTemp);
+ removeAll();
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ else
+ {
+ bRc = FindClose(hFind);
+ if (bRc == FALSE)
+ {
+ removeAll();
+ Fail("FindClose: ERROR -> Unable to close a valid"
+ " FindFirstFileW handle of a directory.\n");
+ }
+ }
+
+ /* find a file using wild cards */
+ hFind = FindFirstFileW(szFindNameWldCard_01, &findFileData);
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ pTemp = convertC((WCHAR*)szFindNameWldCard_01);
+ Trace("FindClose: ERROR -> FindFirstFileW was unable to find \"%s\"\n",
+ pTemp);
+ free(pTemp);
+ removeAll();
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ else
+ {
+ bRc = FindNextFileW(hFind, &findFileData_02);
+ if (bRc == FALSE)
+ {
+ removeAll();
+ Fail("FindClose: ERROR -> Unable to find another file.\n");
+ }
+ else
+ {
+ bRc = FindClose(hFind);
+ if (bRc == FALSE)
+ {
+ removeAll();
+ Fail("FindClose: ERROR -> Unable to close a valid"
+ " FindNextFileW handle.\n");
+ }
+ }
+ }
+
+ /* find a directory using wild cards */
+ hFind = FindFirstFileW(szDirNameWldCard, &findFileData);
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ pTemp = convertC((WCHAR*)szDirNameWldCard);
+ Trace("FindClose: ERROR -> Unable to find \"%s\"\n",
+ pTemp);
+ free(pTemp);
+ removeAll();
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ else
+ {
+ bRc = FindNextFileW(hFind, &findFileData_02);
+ if (bRc == FALSE)
+ {
+ removeAll();
+ Fail("FindClose: ERROR -> Unable to find another directory.\n");
+ }
+ else
+ {
+ bRc = FindClose(hFind);
+ if (bRc == FALSE)
+ {
+ removeAll();
+ Fail("FindClose: ERROR -> Unable to close a valid"
+ " FindNextFileW handle of a directory.\n");
+ }
+ }
+ }
+
+
+ removeAll();
+ PAL_Terminate();
+
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/file_io/FindClose/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/FindClose/test1/testinfo.dat
new file mode 100644
index 0000000000..b59bcbf578
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FindClose/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = FindClose
+Name = Test for FindClose (test 1)
+Type = DEFAULT
+EXE1 = findclose
+Description
+= Test the FindClose on handles opened using the Find functions
+
diff --git a/src/pal/tests/palsuite/file_io/FindFirstFileA/CMakeLists.txt b/src/pal/tests/palsuite/file_io/FindFirstFileA/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FindFirstFileA/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/file_io/FindFirstFileA/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/FindFirstFileA/test1/CMakeLists.txt
new file mode 100644
index 0000000000..6613c4d444
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FindFirstFileA/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ FindFirstFileA.c
+)
+
+add_executable(paltest_findfirstfilea_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_findfirstfilea_test1 coreclrpal)
+
+target_link_libraries(paltest_findfirstfilea_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/FindFirstFileA/test1/FindFirstFileA.c b/src/pal/tests/palsuite/file_io/FindFirstFileA/test1/FindFirstFileA.c
new file mode 100644
index 0000000000..6ceb6a9747
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FindFirstFileA/test1/FindFirstFileA.c
@@ -0,0 +1,206 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: FindFirstFileA.c
+**
+** Purpose: Tests the PAL implementation of the FindFirstFileA function.
+**
+**
+**===================================================================*/
+
+
+#include <palsuite.h>
+
+
+const char* szNoFileName = "333asdf.x77t";
+const char* szFindName = "test01.txt";
+const char* szFindNameWldCard_01 = "test0?.txt";
+const char* szFindNameWldCard_02 = "*.txt";
+const char* szDirName = "test_dir";
+const char* szDirNameSlash = "test_dir\\";
+const char* szDirNameWldCard_01 = "?est_dir";
+const char* szDirNameWldCard_02 = "test_*";
+/* Longer than MAX_LONGPATH characters */
+char szLongFindName[MAX_LONGPATH+1];
+
+BOOL CleanUp()
+{
+ DWORD dwAtt;
+ BOOL result = TRUE;
+
+ dwAtt = GetFileAttributesA(szFindName);
+ if( dwAtt != INVALID_FILE_ATTRIBUTES )
+ {
+ if(!SetFileAttributesA (szFindName, FILE_ATTRIBUTE_NORMAL))
+ {
+ result = FALSE;
+ Trace("ERROR:%d: Error setting attributes [%s][%d]\n", szFindName, FILE_ATTRIBUTE_NORMAL);
+ }
+ if(!DeleteFileA (szFindName))
+ {
+ result = FALSE;
+ Trace("ERROR:%d: Error deleting file [%s][%d]\n", GetLastError(), szFindName, dwAtt);
+ }
+ }
+
+ dwAtt = GetFileAttributesA(szDirName);
+ if( dwAtt != INVALID_FILE_ATTRIBUTES )
+ {
+ if(!RemoveDirectoryA (szDirName))
+ {
+ result = FALSE;
+ Trace("ERROR:%d: Error deleting file [%s][%d]\n", GetLastError(), szDirName, dwAtt);
+ }
+ }
+
+ return result;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ WIN32_FIND_DATA findFileData;
+ HANDLE hFind = NULL;
+ FILE *pFile = NULL;
+ BOOL bRc = FALSE;
+ WCHAR* szwTemp = NULL;
+
+ memset(szLongFindName, 'a', MAX_LONGPATH+1);
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+
+ if(!CleanUp())
+ {
+ Fail("FindFirstFileW: ERROR : Initial Clean Up failed\n");
+ }
+
+ //
+ // find a file with a NULL pointer
+ //
+ hFind = FindFirstFileA(NULL, &findFileData);
+ if (hFind != INVALID_HANDLE_VALUE)
+ {
+ Fail ("FindFirstFileA: ERROR -> Found invalid NULL file");
+ }
+
+
+ //
+ // find a file that doesn't exist
+ //
+ hFind = FindFirstFileA(szNoFileName, &findFileData);
+ if (hFind != INVALID_HANDLE_VALUE)
+ {
+ Fail ("FindFirstFileA: ERROR -> Found invalid NULL file");
+ }
+
+
+ //
+ // find a file that exists
+ //
+ pFile = fopen(szFindName, "w");
+ if (pFile == NULL)
+ {
+ Fail("FindFirstFileA: ERROR -> Unable to create a test file\n");
+ }
+ else
+ {
+ fclose(pFile);
+ }
+ hFind = FindFirstFileA(szFindName, &findFileData);
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ Fail ("FindFirstFileA: ERROR -> Unable to find \"%s\"\n", szFindName);
+ }
+ else
+ {
+ // validate we found the correct file
+ if (strcmp(szFindName, findFileData.cFileName) != 0)
+ {
+ Fail ("FindFirstFileA: ERROR -> Found the wrong file\n");
+ }
+ }
+
+
+ //
+ // find a directory that exists
+ //
+ szwTemp = convert((LPSTR)szDirName);
+ bRc = CreateDirectoryW(szwTemp, NULL);
+ free(szwTemp);
+ if (bRc == FALSE)
+ {
+ Fail("FindFirstFileA: ERROR -> Failed to create the directory "
+ "\"%s\"\n",
+ szDirName);
+ }
+
+ hFind = FindFirstFileA(szDirName, &findFileData);
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ Fail ("FindFirstFileA: ERROR. Unable to find \"%s\"\n", szDirName);
+ }
+ else
+ {
+ // validate we found the correct directory
+ if (strcmp(szDirName, findFileData.cFileName) != 0)
+ {
+ Fail ("FindFirstFileA: ERROR -> Found the wrong directory\n");
+ }
+ }
+
+
+ //
+ // find a directory using a trailing '\' on the directory name: should fail
+ //
+ hFind = FindFirstFileA(szDirNameSlash, &findFileData);
+ if (hFind != INVALID_HANDLE_VALUE)
+ {
+ Fail ("FindFirstFileA: ERROR -> Able to find \"%s\": trailing "
+ "slash should have failed.\n",
+ szDirNameSlash);
+ }
+
+ // find a file using wild cards
+ hFind = FindFirstFileA(szFindNameWldCard_01, &findFileData);
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ Fail ("FindFirstFileA: ERROR -> Unable to find \"%s\"\n",
+ szFindNameWldCard_01);
+ }
+
+ hFind = FindFirstFileA(szFindNameWldCard_02, &findFileData);
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ Fail ("FindFirstFileA: ERROR -> Unable to find \"%s\"\n", szFindNameWldCard_02);
+ }
+
+
+ //
+ // find a directory using wild cards
+ //
+ hFind = FindFirstFileA(szDirNameWldCard_01, &findFileData);
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ Fail ("FindFirstFileA: ERROR -> Unable to find \"%s\"\n", szDirNameWldCard_01);
+ }
+
+ hFind = FindFirstFileA(szDirNameWldCard_02, &findFileData);
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ Fail ("FindFirstFileA: ERROR -> Unable to find \"%s\"\n", szDirNameWldCard_02);
+ }
+
+ if(!CleanUp())
+ {
+ Fail("FindFirstFileW: ERROR : Final Clean Up failed\n");
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/FindFirstFileA/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/FindFirstFileA/test1/testinfo.dat
new file mode 100644
index 0000000000..5b92f8c642
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FindFirstFileA/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = FindFirstFileA
+Name = Test for FindFirstFileA (test 1)
+Type = DEFAULT
+EXE1 = findfirstfilea
+Description
+= Create a number of files and try to find them
+
diff --git a/src/pal/tests/palsuite/file_io/FindFirstFileW/CMakeLists.txt b/src/pal/tests/palsuite/file_io/FindFirstFileW/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FindFirstFileW/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/file_io/FindFirstFileW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/FindFirstFileW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..23e95c7dad
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FindFirstFileW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ FindFirstFileW.c
+)
+
+add_executable(paltest_findfirstfilew_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_findfirstfilew_test1 coreclrpal)
+
+target_link_libraries(paltest_findfirstfilew_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/FindFirstFileW/test1/FindFirstFileW.c b/src/pal/tests/palsuite/file_io/FindFirstFileW/test1/FindFirstFileW.c
new file mode 100644
index 0000000000..f69a625976
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FindFirstFileW/test1/FindFirstFileW.c
@@ -0,0 +1,212 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: FindFirstFileW.c
+**
+** Purpose: Tests the PAL implementation of the FindFirstFileW function.
+**
+**
+**===================================================================*/
+
+
+#include <palsuite.h>
+
+
+const char* szNoFileName = "333asdf.x77t";
+const char* szFindName = "test01.txt";
+const char* szFindNameWldCard_01 = "test0?.txt";
+const char* szFindNameWldCard_02 = "*.txt";
+const char* szDirName = "test_dir";
+const char* szDirNameSlash = "test_dir\\";
+const char* szDirNameWldCard_01 = "?est_dir";
+const char* szDirNameWldCard_02 = "test_*";
+
+
+BOOL CleanUp()
+{
+ DWORD dwAtt;
+ BOOL result = TRUE;
+
+ dwAtt = GetFileAttributesA(szFindName);
+ if( dwAtt != INVALID_FILE_ATTRIBUTES )
+ {
+ if(!SetFileAttributesA (szFindName, FILE_ATTRIBUTE_NORMAL))
+ {
+ result = FALSE;
+ Trace("ERROR:%d: Error setting attributes [%s][%d]\n", szFindName, FILE_ATTRIBUTE_NORMAL);
+ }
+ if(!DeleteFileA (szFindName))
+ {
+ result = FALSE;
+ Trace("ERROR:%d: Error deleting file [%s][%d]\n", GetLastError(), szFindName, dwAtt);
+ }
+ }
+
+ dwAtt = GetFileAttributesA(szDirName);
+ if( dwAtt != INVALID_FILE_ATTRIBUTES )
+ {
+ if(!RemoveDirectoryA (szDirName))
+ {
+ result = FALSE;
+ Trace("ERROR:%d: Error deleting file [%s][%d]\n", GetLastError(), szDirName, dwAtt);
+ }
+ }
+
+ return result;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ WIN32_FIND_DATAW findFileData;
+ HANDLE hFind = NULL;
+ FILE *pFile = NULL;
+ BOOL bRc = FALSE;
+ WCHAR* pTemp = NULL;
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ if(!CleanUp())
+ {
+ Fail("FindFirstFileW: ERROR : Initial Clean Up failed\n");
+ }
+
+ //
+ // find a file that doesn't exist
+ //
+ pTemp = convert((LPSTR)szNoFileName);
+ hFind = FindFirstFileW(pTemp, &findFileData);
+ free(pTemp);
+ if (hFind != INVALID_HANDLE_VALUE)
+ {
+ Fail ("FindFirstFileW: ERROR -> Found invalid NULL file\n");
+ }
+
+
+ //
+ // find a file that exists
+ //
+ pFile = fopen(szFindName, "w");
+ if (pFile == NULL)
+ {
+ Fail("FindFirstFileW: ERROR -> Unable to create a test file\n");
+ }
+ else
+ {
+ fclose(pFile);
+ }
+ pTemp = convert((LPSTR)szFindName);
+ hFind = FindFirstFileW(pTemp, &findFileData);
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ free(pTemp);
+ Fail ("FindFirstFileW: ERROR -> Unable to find \"%s\"\n", szFindName);
+ }
+ else
+ {
+ // validate we found the correct file
+ if (wcscmp(pTemp, findFileData.cFileName) != 0)
+ {
+ free(pTemp);
+ Fail ("FindFirstFileW: ERROR -> Found the wrong file\n");
+ }
+ }
+ free(pTemp);
+
+ //
+ // find a directory that exists
+ //
+ pTemp = convert((LPSTR)szDirName);
+ bRc = CreateDirectoryW(pTemp, NULL);
+ if (bRc == FALSE)
+ {
+ Fail("FindFirstFileW: ERROR[%u] -> Failed to create the directory \"%s\"\n",
+ GetLastError(), szDirName);
+ }
+
+ hFind = FindFirstFileW(pTemp, &findFileData);
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ free(pTemp);
+ Fail("FindFirstFileW: ERROR. Unable to find \"%s\"\n", szDirName);
+ }
+ else
+ {
+ // validate we found the correct directory
+ if (wcscmp(pTemp, findFileData.cFileName) != 0)
+ {
+ free(pTemp);
+ Fail("FindFirstFileW: ERROR -> Found the wrong directory\n");
+ }
+ }
+ free(pTemp);
+
+ //
+ // find a directory using a trailing '\' on the directory name: should fail
+ //
+ pTemp = convert((LPSTR)szDirNameSlash);
+ hFind = FindFirstFileW(pTemp, &findFileData);
+ free(pTemp);
+ if (hFind != INVALID_HANDLE_VALUE)
+ {
+ Fail("FindFirstFileW: ERROR -> Able to find \"%s\": trailing "
+ "slash should have failed.\n",
+ szDirNameSlash);
+ }
+
+ // find a file using wild cards
+ pTemp = convert((LPSTR)szFindNameWldCard_01);
+ hFind = FindFirstFileW(pTemp, &findFileData);
+ free(pTemp);
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ Fail("FindFirstFileW: ERROR -> Unable to find \"%s\"\n",
+ szFindNameWldCard_01);
+ }
+
+ pTemp = convert((LPSTR)szFindNameWldCard_02);
+ hFind = FindFirstFileW(pTemp, &findFileData);
+ free(pTemp);
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ Fail("FindFirstFileW: ERROR -> Unable to find \"%s\"\n",
+ szFindNameWldCard_02);
+ }
+
+
+ //
+ // find a directory using wild cards
+ //
+
+ pTemp = convert((LPSTR)szDirNameWldCard_01);
+ hFind = FindFirstFileW(pTemp, &findFileData);
+ free(pTemp);
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ Fail("FindFirstFileW: ERROR -> Unable to find \"%s\"\n",
+ szDirNameWldCard_01);
+ }
+
+ pTemp = convert((LPSTR)szDirNameWldCard_02);
+ hFind = FindFirstFileW(pTemp, &findFileData);
+ free(pTemp);
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ Fail("FindFirstFileW: ERROR -> Unable to find \"%s\"\n",
+ szDirNameWldCard_02);
+ }
+
+ if(!CleanUp())
+ {
+ Fail("FindFirstFileW: ERROR : Final Clean Up failed\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/FindFirstFileW/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/FindFirstFileW/test1/testinfo.dat
new file mode 100644
index 0000000000..c088c04cbd
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FindFirstFileW/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = FindFirstFileW
+Name = Test for FindFirstFileW (test 1)
+Type = DEFAULT
+EXE1 = findfirstfilew
+Description
+= Create a number of files and try to find them
+
diff --git a/src/pal/tests/palsuite/file_io/FindNextFileA/CMakeLists.txt b/src/pal/tests/palsuite/file_io/FindNextFileA/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FindNextFileA/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/file_io/FindNextFileA/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/FindNextFileA/test1/CMakeLists.txt
new file mode 100644
index 0000000000..efb1655d95
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FindNextFileA/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ FindNextFileA.c
+)
+
+add_executable(paltest_findnextfilea_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_findnextfilea_test1 coreclrpal)
+
+target_link_libraries(paltest_findnextfilea_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/FindNextFileA/test1/FindNextFileA.c b/src/pal/tests/palsuite/file_io/FindNextFileA/test1/FindNextFileA.c
new file mode 100644
index 0000000000..578fa00542
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FindNextFileA/test1/FindNextFileA.c
@@ -0,0 +1,243 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: FindNextFileA.c
+**
+** Purpose: Tests the PAL implementation of the FindNextFileA function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+const char* szFindName = "test01.txt";
+const char* szFindName_02 = "test02.txt";
+const char* szFindNameWldCard_01 = "test0?.txt";
+const char* szFindNameWldCard_02 = "*.txt";
+const char* szDirName = "test_dir";
+const char* szDirName_02 = "test_dir_02";
+const char* szDirNameWldCard = "test_*";
+
+
+
+void removeAll()
+{
+ WCHAR* wTempPtr = NULL;
+
+ wTempPtr = convert((LPSTR)szDirName);
+ RemoveDirectoryW(wTempPtr);
+ free (wTempPtr);
+ wTempPtr = convert((LPSTR)szDirName_02);
+ RemoveDirectoryW(wTempPtr);
+ free (wTempPtr);
+ DeleteFile(szFindName);
+ DeleteFile(szFindName_02);
+}
+
+
+
+BOOL createTestFile(const char* szName)
+{
+ FILE *pFile = NULL;
+
+ pFile = fopen(szName, "w");
+ if (pFile == NULL)
+ {
+ Trace("FindNextFile: ERROR -> Unable to create file \"%s\".\n",
+ szName);
+ removeAll();
+ return FALSE;
+ }
+ else
+ {
+ fprintf(pFile, "FindNextFile test file, \"%s\".\n", szFindName);
+ fclose(pFile);
+ }
+ return TRUE;
+}
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ WIN32_FIND_DATA findFileData;
+ WIN32_FIND_DATA findFileData_02;
+ HANDLE hFind = NULL;
+ BOOL bRc = FALSE;
+ DWORD dwBytesWritten;
+ WCHAR* wTempPtr = NULL;
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+ removeAll();
+
+
+ //
+ // find a file with a NULL pointer
+ //
+ hFind = FindFirstFileA(NULL, &findFileData);
+ if (hFind != INVALID_HANDLE_VALUE)
+ {
+ Fail("FindNextFile: ERROR -> Found invalid NULL file");
+ }
+
+ bRc = FindNextFile(hFind, &findFileData);
+ if (bRc == TRUE)
+ {
+ Fail("FindNextFile: ERROR -> Found a file based on an invalid handle");
+ }
+
+
+ //
+ // find a file that exists
+ //
+ if(createTestFile(szFindName) == FALSE)
+ {
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ if(createTestFile(szFindName_02) == FALSE)
+ {
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ hFind = FindFirstFileA(szFindName, &findFileData);
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ removeAll();
+ Fail("FindNextFile: ERROR -> Unable to find \"%s\"\n", szFindName);
+ }
+ else
+ {
+ bRc = FindNextFile(hFind, &findFileData);
+ if (bRc != FALSE)
+ {
+ removeAll();
+ Fail("FindNextFile: ERROR -> Found a file that doesn't exist.\n");
+ }
+ }
+
+
+ //
+ // find a directory that exists
+ //
+ wTempPtr = convert((LPSTR)szDirName);
+ bRc = CreateDirectoryW(wTempPtr, NULL);
+ free (wTempPtr);
+ if (bRc == FALSE)
+ {
+ removeAll();
+ Fail("FindNextFile: ERROR -> Failed to create the directory \"%s\"\n",
+ szDirName);
+ }
+ wTempPtr = convert((LPSTR)szDirName_02);
+ bRc = CreateDirectoryW(wTempPtr, NULL);
+ free (wTempPtr);
+ if (bRc == FALSE)
+ {
+ removeAll();
+ Fail("FindNextFile: ERROR -> Failed to create the directory \"%s\"\n",
+ szDirName_02);
+ }
+
+ hFind = FindFirstFileA(szDirName, &findFileData);
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ removeAll();
+ Fail("FindNextFile: ERROR. FindFirstFileA was unable to find \"%s\"\n",
+ szDirName);
+ }
+ else
+ {
+ bRc = FindNextFile(hFind, &findFileData);
+ if (bRc != FALSE)
+ {
+ removeAll();
+ Fail("FindNextFile: ERROR -> Found a directory that doesn't exist.\n");
+ }
+ }
+
+
+ //
+ // find a file using wild cards
+ //
+ hFind = FindFirstFileA(szFindNameWldCard_01, &findFileData);
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ removeAll();
+ Fail("FindNextFile: ERROR -> FindFirstFileA was unable to find \"%s\"\n",
+ szFindNameWldCard_01);
+ }
+ else
+ {
+ bRc = FindNextFile(hFind, &findFileData_02);
+ if (bRc == FALSE)
+ {
+ removeAll();
+ Fail("FindNextFile: ERROR -> Unable to find another file.\n");
+ }
+ else
+ {
+ // validate we found the correct file
+ if (strcmp(findFileData_02.cFileName, findFileData.cFileName) == 0)
+ {
+ removeAll();
+ Fail("FindNextFile: ERROR -> Found the same file \"%s\".\n",
+ findFileData.cFileName);
+ }
+ }
+ }
+
+
+ //
+ // find a directory using wild cards
+ //
+ hFind = FindFirstFileA(szDirNameWldCard, &findFileData);
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ removeAll();
+ Fail("FindNextFile: ERROR -> Unable to find \"%s\"\n",
+ szDirNameWldCard);
+ }
+ else
+ {
+ bRc = FindNextFile(hFind, &findFileData_02);
+ if (bRc == FALSE)
+ {
+ removeAll();
+ Fail("FindNextFile: ERROR -> Unable to find another directory.\n");
+ }
+ else
+ {
+ // validate we found the correct directory
+ if (strcmp(findFileData_02.cFileName, findFileData.cFileName) == 0)
+ {
+ removeAll();
+ Fail("FindNextFile: ERROR -> Found the same directory \"%s\".\n",
+ findFileData.cFileName);
+ }
+ }
+ }
+
+ //
+ // attempt to write to the hFind handle (which should fail)
+ //
+ bRc = WriteFile(hFind, "this is a test", 10, &dwBytesWritten, NULL);
+ removeAll();
+ if (bRc == TRUE)
+ {
+ Fail("FindNextFile: ERROR -> Able to write to a FindNextFile handle.\n");
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/FindNextFileA/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/FindNextFileA/test1/testinfo.dat
new file mode 100644
index 0000000000..e1027eff32
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FindNextFileA/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = FindNextFileA
+Name = Test for FindNextFileA (test 1)
+Type = DEFAULT
+EXE1 = findnextfilea
+Description
+= Create test files and directories to verify FindNextFileA
+
diff --git a/src/pal/tests/palsuite/file_io/FindNextFileA/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/FindNextFileA/test2/CMakeLists.txt
new file mode 100644
index 0000000000..96821bdaaa
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FindNextFileA/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ findnextfilea.c
+)
+
+add_executable(paltest_findnextfilea_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_findnextfilea_test2 coreclrpal)
+
+target_link_libraries(paltest_findnextfilea_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/FindNextFileA/test2/findnextfilea.c b/src/pal/tests/palsuite/file_io/FindNextFileA/test2/findnextfilea.c
new file mode 100644
index 0000000000..c841a4d498
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FindNextFileA/test2/findnextfilea.c
@@ -0,0 +1,107 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: findnextfilea.c
+**
+** Purpose: Tests the PAL implementation of the FindNextFileA function.
+** Tests '*' and '*.*' to ensure that '.' and '..' are
+** returned in the expected order
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+const char* szDot = ".";
+const char* szDotDot = "..";
+const char* szStar = "*";
+const char* szStarDotStar = "*.*";
+
+
+static void DoTest(const char* szDir,
+ const char* szResult1,
+ const char* szResult2)
+{
+ HANDLE hFind;
+ WIN32_FIND_DATA findFileData;
+
+ /*
+ ** find the first
+ */
+ if ((hFind = FindFirstFileA(szDir, &findFileData)) == INVALID_HANDLE_VALUE)
+ {
+ Fail("FindNextFileA: ERROR -> FindFirstFileA(\"%s\") failed. "
+ "GetLastError returned %u.\n",
+ szStar,
+ GetLastError());
+ }
+
+ /* did we find the expected */
+ if (strcmp(szResult1, findFileData.cFileName) != 0)
+ {
+ if (!FindClose(hFind))
+ {
+ Trace("FindNextFileA: ERROR -> Failed to close the find handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("FindNextFileA: ERROR -> FindFirstFile(\"%s\") didn't find"
+ " the expected \"%s\" but found \"%s\" instead.\n",
+ szDir,
+ szResult1,
+ findFileData.cFileName);
+ }
+
+ /* we found the first expected, let's see if we find the next expected*/
+ if (!FindNextFileA(hFind, &findFileData))
+ {
+ Trace("FindNextFileA: ERROR -> FindNextFileA should have found \"%s\""
+ " but failed. GetLastError returned %u.\n",
+ szResult2,
+ GetLastError());
+ if (!FindClose(hFind))
+ {
+ Trace("FindNextFileA: ERROR -> Failed to close the find handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ /* we found something, but was it '.' */
+ if (strcmp(szResult2, findFileData.cFileName) != 0)
+ {
+ if (!FindClose(hFind))
+ {
+ Trace("FindNextFileA: ERROR -> Failed to close the find handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("FindNextFileA: ERROR -> FindNextFileA based on \"%s\" didn't find"
+ " the expected \"%s\" but found \"%s\" instead.\n",
+ szDir,
+ szResult2,
+ findFileData.cFileName);
+ }
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ DoTest(szStar, szDot, szDotDot);
+ DoTest(szStarDotStar, szDot, szDotDot);
+
+
+ PAL_Terminate();
+
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/FindNextFileA/test2/testinfo.dat b/src/pal/tests/palsuite/file_io/FindNextFileA/test2/testinfo.dat
new file mode 100644
index 0000000000..dd6c1e48b3
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FindNextFileA/test2/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = FindNextFileA
+Name = Test for FindNextFileA (test 2)
+Type = DEFAULT
+EXE1 = findnextfilea
+Description
+= Tests the PAL implementation of the FindNextFileA function.
+= Tests '*' and '*.*' to ensure that '.' and '..' are
+= returned in the expected order
diff --git a/src/pal/tests/palsuite/file_io/FindNextFileW/CMakeLists.txt b/src/pal/tests/palsuite/file_io/FindNextFileW/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FindNextFileW/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/file_io/FindNextFileW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/FindNextFileW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..4a283dd3a5
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FindNextFileW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ FindNextFileW.c
+)
+
+add_executable(paltest_findnextfilew_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_findnextfilew_test1 coreclrpal)
+
+target_link_libraries(paltest_findnextfilew_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/FindNextFileW/test1/FindNextFileW.c b/src/pal/tests/palsuite/file_io/FindNextFileW/test1/FindNextFileW.c
new file mode 100644
index 0000000000..42e2e55805
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FindNextFileW/test1/FindNextFileW.c
@@ -0,0 +1,249 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: FindNextFileW.c
+**
+** Purpose: Tests the PAL implementation of the FindNextFileW function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+const char* szFindName = "test01.txt";
+const char* szFindName_02 = "test02.txt";
+const char* szFindNameWldCard_01 = "test0?.txt";
+const char* szFindNameWldCard_02 = "*.txt";
+const char* szDirName = "test_dir";
+const char* szDirName_02 = "test_dir_02";
+const char* szDirNameWldCard = "test_*";
+
+
+
+void removeAll()
+{
+ WCHAR* wTempPtr = NULL;
+
+ wTempPtr = convert((LPSTR)szDirName);
+ RemoveDirectoryW(wTempPtr);
+ free(wTempPtr);
+
+ wTempPtr = convert((LPSTR)szDirName_02);
+ RemoveDirectoryW(wTempPtr);
+ free(wTempPtr);
+
+ wTempPtr = convert((LPSTR)szFindName);
+ DeleteFileW(wTempPtr);
+ free(wTempPtr);
+
+ wTempPtr = convert((LPSTR)szFindName_02);
+ DeleteFileW(wTempPtr);
+ free(wTempPtr);
+}
+
+
+
+BOOL createTestFile(const char* szName)
+{
+ FILE *pFile = NULL;
+
+ pFile = fopen(szName, "w");
+ if (pFile == NULL)
+ {
+ Trace("FindNextFileW: ERROR -> Unable to create file \"%s\".\n", szName);
+ removeAll();
+ return FALSE;
+ }
+ else
+ {
+ fprintf(pFile, "FindNextFileW test file, \"%s\".\n", szFindName);
+ fclose(pFile);
+ }
+
+ return TRUE;
+}
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ WIN32_FIND_DATAW findFileData;
+ WIN32_FIND_DATAW findFileData_02;
+ HANDLE hFind = NULL;
+ BOOL bRc = FALSE;
+ DWORD dwBytesWritten;
+ WCHAR* wTempPtr = NULL;
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+ removeAll();
+
+
+ //
+ // find a file that exists
+ //
+ if(createTestFile(szFindName) == FALSE)
+ {
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ if(createTestFile(szFindName_02) == FALSE)
+ {
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ wTempPtr = convert((LPSTR)szFindName);
+ hFind = FindFirstFileW(wTempPtr, &findFileData);
+ free(wTempPtr);
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ removeAll();
+ Fail("FindNextFileW: ERROR -> Unable to find \"%s\"\n", szFindName);
+ }
+ else
+ {
+ bRc = FindNextFileW(hFind, &findFileData);
+ if (bRc != FALSE)
+ {
+ removeAll();
+ Fail("FindNextFileW: ERROR -> Found a file that doesn't exist.\n");
+ }
+ }
+
+
+ //
+ // find a directory that exists
+ //
+ wTempPtr = convert((LPSTR)szDirName);
+ bRc = CreateDirectoryW(wTempPtr, NULL);
+ free (wTempPtr);
+ if (bRc == FALSE)
+ {
+ removeAll();
+ Fail("FindNextFileW: ERROR -> Failed to create the directory \"%s\"\n",
+ szDirName);
+ }
+ wTempPtr = convert((LPSTR)szDirName_02);
+ bRc = CreateDirectoryW(wTempPtr, NULL);
+ free (wTempPtr);
+ if (bRc == FALSE)
+ {
+ removeAll();
+ Fail("FindNextFileW: ERROR -> Failed to create the directory "
+ "\"%s\"\n",
+ szDirName_02);
+ }
+
+ wTempPtr = convert((LPSTR)szDirName);
+ hFind = FindFirstFileW(wTempPtr, &findFileData);
+ free (wTempPtr);
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ removeAll();
+ Fail("FindNextFileW: ERROR. FindFirstFileW was unable "
+ "to find \"%s\"\n",
+ szDirName);
+ }
+ else
+ {
+ bRc = FindNextFileW(hFind, &findFileData);
+ if (bRc != FALSE)
+ {
+ removeAll();
+ Fail("FindNextFileW: ERROR -> Found a directory that "
+ "doesn't exist.\n");
+ }
+ }
+
+
+ //
+ // find a file using wild cards
+ //
+ wTempPtr = convert((LPSTR)szFindNameWldCard_01);
+ hFind = FindFirstFileW(wTempPtr, &findFileData);
+ free(wTempPtr);
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ removeAll();
+ Fail("FindNextFileW: ERROR -> FindFirstFileW was unable to "
+ "find \"%s\"\n",
+ szFindNameWldCard_01);
+ }
+ else
+ {
+ bRc = FindNextFileW(hFind, &findFileData_02);
+ if (bRc == FALSE)
+ {
+ removeAll();
+ Fail("FindNextFileW: ERROR -> Unable to find another file.\n");
+ }
+ else
+ {
+ // validate we found the correct file
+ if (wcscmp(findFileData_02.cFileName, findFileData.cFileName) == 0)
+ {
+ removeAll();
+ Fail("FindNextFileW: ERROR -> Found the same file \"%S\".\n",
+ findFileData.cFileName);
+ }
+ }
+ }
+
+
+ //
+ // find a directory using wild cards
+ //
+ wTempPtr = convert((LPSTR)szDirNameWldCard);
+ hFind = FindFirstFileW(wTempPtr, &findFileData);
+ free(wTempPtr);
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ removeAll();
+ Fail("FindNextFileW: ERROR -> Unable to find \"%s\"\n",
+ szDirNameWldCard);
+ }
+ else
+ {
+ bRc = FindNextFileW(hFind, &findFileData_02);
+ if (bRc == FALSE)
+ {
+ removeAll();
+ Fail("FindNextFileW: ERROR -> Unable to find another directory.\n");
+ }
+ else
+ {
+ // validate we found the correct directory
+ if (wcscmp(findFileData_02.cFileName, findFileData.cFileName) == 0)
+ {
+ removeAll();
+ Fail("FindNextFileW: ERROR -> Found the same directory "
+ "\"%S\".\n",
+ findFileData.cFileName);
+ }
+ }
+ }
+
+ //
+ // attempt to write to the hFind handle (which should fail)
+ //
+ bRc = WriteFile(hFind, "this is a test", 10, &dwBytesWritten, NULL);
+ if (bRc == TRUE)
+ {
+ removeAll();
+ Fail("FindNextFileW: ERROR -> Able to write to a FindNextFileW "
+ "handle.\n");
+ }
+
+ removeAll();
+ PAL_Terminate();
+
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/FindNextFileW/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/FindNextFileW/test1/testinfo.dat
new file mode 100644
index 0000000000..3eaebef43e
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FindNextFileW/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = FindNextFileW
+Name = Test for FindNextFileW (test 1)
+Type = DEFAULT
+EXE1 = findnextfilew
+Description
+= Create test files and directories to verify FindNextFileW
+
diff --git a/src/pal/tests/palsuite/file_io/FindNextFileW/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/FindNextFileW/test2/CMakeLists.txt
new file mode 100644
index 0000000000..2938afb888
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FindNextFileW/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ findnextfilew.c
+)
+
+add_executable(paltest_findnextfilew_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_findnextfilew_test2 coreclrpal)
+
+target_link_libraries(paltest_findnextfilew_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/FindNextFileW/test2/findnextfilew.c b/src/pal/tests/palsuite/file_io/FindNextFileW/test2/findnextfilew.c
new file mode 100644
index 0000000000..3e806c2576
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FindNextFileW/test2/findnextfilew.c
@@ -0,0 +1,107 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: FindNextFileW.c
+**
+** Purpose: Tests the PAL implementation of the FindNextFileW function.
+** Tests '*' and '*.*' to ensure that '.' and '..' are
+** returned in the expected order
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+const WCHAR szwDot[] = {'.','\0'};
+const WCHAR szwDotDot[] = {'.','.','\0'};
+const WCHAR szwStar[] = {'*','\0'};
+const WCHAR szwStarDotStar[] = {'*','.','*','\0'};
+
+
+static void DoTest(const WCHAR* szwDir,
+ const WCHAR* szwResult1,
+ const WCHAR* szwResult2)
+{
+ HANDLE hFind;
+ WIN32_FIND_DATAW findFileData;
+
+ /*
+ ** find the first
+ */
+ if ((hFind = FindFirstFileW(szwDir, &findFileData)) == INVALID_HANDLE_VALUE)
+ {
+ Fail("FindNextFileW: ERROR -> FindFirstFileW(\"%S\") failed. "
+ "GetLastError returned %u.\n",
+ szwStar,
+ GetLastError());
+ }
+
+ /* did we find the expected */
+ if (wcscmp(szwResult1, findFileData.cFileName) != 0)
+ {
+ if (!FindClose(hFind))
+ {
+ Trace("FindNextFileW: ERROR -> Failed to close the find handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("FindNextFileW: ERROR -> FindFirstFile(\"%S\") didn't find"
+ " the expected \"%S\" but found \"%S\" instead.\n",
+ szwDir,
+ szwResult1,
+ findFileData.cFileName);
+ }
+
+ /* we found the first expected, let's see if we find the next expected*/
+ if (!FindNextFileW(hFind, &findFileData))
+ {
+ Trace("FindNextFileW: ERROR -> FindNextFileW should have found \"%S\""
+ " but failed. GetLastError returned %u.\n",
+ szwResult2,
+ GetLastError());
+ if (!FindClose(hFind))
+ {
+ Trace("FindNextFileW: ERROR -> Failed to close the find handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ /* we found something, but was it '.' */
+ if (wcscmp(szwResult2, findFileData.cFileName) != 0)
+ {
+ if (!FindClose(hFind))
+ {
+ Trace("FindNextFileW: ERROR -> Failed to close the find handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("FindNextFileW: ERROR -> FindNextFileW based on \"%S\" didn't find"
+ " the expected \"%S\" but found \"%S\" instead.\n",
+ szwDir,
+ szwResult2,
+ findFileData.cFileName);
+ }
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ DoTest(szwStar, szwDot, szwDotDot);
+ DoTest(szwStarDotStar, szwDot, szwDotDot);
+
+
+ PAL_Terminate();
+
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/FindNextFileW/test2/testinfo.dat b/src/pal/tests/palsuite/file_io/FindNextFileW/test2/testinfo.dat
new file mode 100644
index 0000000000..98bd5e7793
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FindNextFileW/test2/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = FindNextFileW
+Name = Test for FindNextFileW (test 2)
+Type = DEFAULT
+EXE1 = findnextfilew
+Description
+= Tests the PAL implementation of the FindNextFileW function.
+= Tests '*' and '*.*' to ensure that '.' and '..' are
+= returned in the expected order
diff --git a/src/pal/tests/palsuite/file_io/FlushFileBuffers/CMakeLists.txt b/src/pal/tests/palsuite/file_io/FlushFileBuffers/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FlushFileBuffers/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/CMakeLists.txt
new file mode 100644
index 0000000000..e3fbccd2ae
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ FlushFileBuffers.c
+)
+
+add_executable(paltest_flushfilebuffers_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_flushfilebuffers_test1 coreclrpal)
+
+target_link_libraries(paltest_flushfilebuffers_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/FlushFileBuffers.c b/src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/FlushFileBuffers.c
new file mode 100644
index 0000000000..246be64847
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/FlushFileBuffers.c
@@ -0,0 +1,130 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: FlushFileBuffers.c
+**
+** Purpose: Tests the PAL implementation of the FlushFileBuffers function
+** This tests checks the return values of FlushFileBuffers -- once on an
+** open handle and once on a closed handle.
+**
+** Depends:
+** CreateFile
+** WriteFile
+** CloseHandle
+** DeleteFileA
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char **argv)
+{
+
+ int TheReturn;
+ HANDLE TheFileHandle;
+ DWORD temp;
+ DWORD originalSize=10000;
+ DWORD finalSize=10000;
+ const char* fileName="the_file";
+
+ /* 1 2 3 4*/
+ char * SomeText = "1234567890123456789012345678901234567890";
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+
+ /* Open the file to get a HANDLE */
+ TheFileHandle =
+ CreateFile(
+ fileName,
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(TheFileHandle == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: CreateFile failed. Test depends on this function.");
+ }
+
+ /* get the file size */
+ originalSize = GetFileSize (TheFileHandle, NULL) ;
+ if(originalSize == INVALID_FILE_SIZE)
+ {
+ Fail("ERROR: call to GetFileSize faild with error "
+ "The GetLastError is %d.",GetLastError());
+ }
+
+ /* Write something too the HANDLE. Should be buffered */
+ TheReturn = WriteFile(TheFileHandle,
+ SomeText,
+ strlen(SomeText),
+ &temp,
+ NULL);
+
+ if(TheReturn == 0)
+ {
+ Fail("ERROR: WriteFile failed. Test depends on this function.");
+ }
+
+ /* Test to see that FlushFileBuffers returns a success value */
+ TheReturn = FlushFileBuffers(TheFileHandle);
+ if(TheReturn == 0)
+ {
+ Fail("ERROR: The FlushFileBuffers function returned 0, which "
+ "indicates failure, when trying to flush a valid HANDLE. "
+ "The GetLastError is %d.",GetLastError());
+ }
+
+ /* test if flush modified the file */
+ finalSize = GetFileSize (TheFileHandle, NULL) ;
+ if(finalSize==INVALID_FILE_SIZE)
+ {
+ Fail("ERROR: call to GetFileSize faild with error "
+ "The GetLastError is %d.",GetLastError());
+ }
+ if(finalSize!=(originalSize+strlen(SomeText)))
+ {
+ Fail("ERROR: FlushFileBuffers failed. data was not written to the file");
+ }
+
+
+ /* Close the Handle */
+ TheReturn = CloseHandle(TheFileHandle);
+ if(TheReturn == 0)
+ {
+ Fail("ERROR: CloseHandle failed. This function depends "
+ "upon it.");
+ }
+
+
+ /* Test to see that FlushFileBuffers returns a failure value */
+ TheReturn = FlushFileBuffers(TheFileHandle);
+ if(TheReturn != 0)
+ {
+ Fail("ERROR: The FlushFileBuffers function returned non-zero, "
+ "which indicates success, when trying to flush an invalid "
+ "HANDLE.");
+ }
+
+ /* make sure file does not exist */
+ if(DeleteFileA(fileName)== 0 )
+ {
+ Fail("ERROR: call to DeleteFileA faild with error "
+ "The GetLastError is %d.",GetLastError());
+ }
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/testinfo.dat
new file mode 100644
index 0000000000..3a0da6918d
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = FlushFileBuffers
+Name = Positive Test for FlushFileBuffers
+TYPE = DEFAULT
+EXE1 = flushfilebuffers
+Description
+= Test the FlushFileBuffers
+= Test the return values -- ensure that the correct values are
+= returned for success and failure.
+= This test does not prove that flush worked,
+= there is no way of stopping the OS from flushing
+= the file by itself.
diff --git a/src/pal/tests/palsuite/file_io/GetConsoleCP/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetConsoleCP/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetConsoleCP/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/file_io/GetConsoleCP/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetConsoleCP/test1/CMakeLists.txt
new file mode 100644
index 0000000000..131f4a5fb7
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetConsoleCP/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetConsoleCP.c
+)
+
+add_executable(paltest_getconsolecp_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getconsolecp_test1 coreclrpal)
+
+target_link_libraries(paltest_getconsolecp_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetConsoleCP/test1/GetConsoleCP.c b/src/pal/tests/palsuite/file_io/GetConsoleCP/test1/GetConsoleCP.c
new file mode 100644
index 0000000000..ba17d6c64d
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetConsoleCP/test1/GetConsoleCP.c
@@ -0,0 +1,35 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: GetConsoleCP.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the GetConsoleCP function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ UINT uiCP = 0;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ uiCP = GetConsoleCP();
+ if ((uiCP != CP_ACP) && (uiCP != GetACP()) && (uiCP != 437)) /*437 for MSDOS*/
+ {
+ Fail("GetConsoleCP: ERROR -> The invalid code page %d was returned.\n",
+ uiCP);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/GetConsoleCP/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/GetConsoleCP/test1/testinfo.dat
new file mode 100644
index 0000000000..608a01b2ef
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetConsoleCP/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetConsoleCP
+Name = Positive Test for GetConsoleCP (test 1)
+Type = DEFAULT
+EXE1 = getconsolecp
+Description
+= Test GetConsoleCP. Apparently there are only two possible
+= return values: CP_ACP or 1252
diff --git a/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/CMakeLists.txt
new file mode 100644
index 0000000000..d19ab95a37
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetConsoleOutputCP.c
+)
+
+add_executable(paltest_getconsoleoutputcp_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getconsoleoutputcp_test1 coreclrpal)
+
+target_link_libraries(paltest_getconsoleoutputcp_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/GetConsoleOutputCP.c b/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/GetConsoleOutputCP.c
new file mode 100644
index 0000000000..3deaebf68f
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/GetConsoleOutputCP.c
@@ -0,0 +1,35 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: GetConsoleOutputCP.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the GetConsoleOutputCP function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ UINT uiCP = 0;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ uiCP = GetConsoleOutputCP();
+ if ((uiCP != CP_ACP) && (uiCP != GetACP()) && (uiCP != 437)) /*437 for MSDOS*/
+ {
+ Fail("GetConsoleOutputCP: ERROR -> The invalid code page %d was returned.\n",
+ uiCP);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/testinfo.dat
new file mode 100644
index 0000000000..9ad624eaf2
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetConsoleOutputCP
+Name = Positive Test for GetConsoleOutputCP (test 1)
+Type = DEFAULT
+EXE1 = getconsoleoutputcp
+Description
+= Test GetConsoleOutputCP. Apparently there are only two possible
+= return values: CP_ACP or 1252
diff --git a/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/CMakeLists.txt
new file mode 100644
index 0000000000..f7382b047d
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetCurrentDirectoryA.c
+)
+
+add_executable(paltest_getcurrentdirectorya_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getcurrentdirectorya_test1 coreclrpal)
+
+target_link_libraries(paltest_getcurrentdirectorya_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/GetCurrentDirectoryA.c b/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/GetCurrentDirectoryA.c
new file mode 100644
index 0000000000..b09e8a104d
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/GetCurrentDirectoryA.c
@@ -0,0 +1,97 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: GetCurrentDirectoryA.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the GetCurrentDirectoryA function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+const char* szFileName = "blah";
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ DWORD dwRc = 0;
+ DWORD dwRc2 = 0;
+ char szReturnedPath[_MAX_PATH+1];
+ char szCurrentDir[_MAX_PATH+1];
+ LPSTR pPathPtr;
+ size_t nCount = 0;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ // use GetFullPathName to to get the current path by stripping
+ // the file name off the end
+ memset(szReturnedPath, 0, sizeof(char)*(_MAX_PATH+1));
+ dwRc = GetFullPathNameA(szFileName, _MAX_PATH, szReturnedPath, &pPathPtr);
+ if (dwRc == 0)
+ {
+ // GetFullPathName failed
+ Fail("GetCurrentDirectoryA: ERROR -> GetFullPathNameA failed "
+ "with error code: %ld.\n", GetLastError());
+ }
+ else if(dwRc > _MAX_PATH)
+ {
+ Fail("GetCurrentDirectoryA: ERROR -> The path name GetFullPathNameA "
+ "returned is longer than _MAX_PATH characters.\n");
+ }
+
+
+ // strip the file name from the full path to get the current path
+ nCount = strlen(szReturnedPath) - strlen(szFileName) - 1;
+ memset(szCurrentDir, 0, sizeof(char)*(_MAX_PATH+1));
+ strncpy(szCurrentDir, szReturnedPath, nCount);
+
+ // compare the results of GetCurrentDirectoryA with the above
+ memset(szReturnedPath, 0, sizeof(char)*(_MAX_PATH+1));
+ dwRc = GetCurrentDirectoryA((sizeof(char)*(_MAX_PATH+1)), szReturnedPath);
+ if (dwRc == 0)
+ {
+ Fail("GetCurrentDirectoryA: ERROR -> GetCurrentDirectoryA failed "
+ "with error code: %ld.\n", GetLastError());
+ }
+ else if(dwRc > _MAX_PATH)
+ {
+ Fail("GetCurrentDirectoryA: ERROR -> The path name "
+ "returned is longer than _MAX_PATH characters.\n");
+ }
+
+
+ /* test case the passed buffer size is not big enough
+ * function should return the size required + 1 a terminating null character
+ */
+
+ /* good buffer size */
+ dwRc = GetCurrentDirectoryA((sizeof(CHAR)*(_MAX_PATH+1)), szReturnedPath);
+
+ /* small buffer (0 size)*/
+ dwRc2 = GetCurrentDirectoryA(0, szReturnedPath);
+ if (dwRc2 != (dwRc+1) )
+ {
+ Fail("GetCurrentDirectoryA: ERROR -> failed to give the correct "
+ "return value when passed a buffer not big enough. "
+ "Expected %u while result is %u \n",(dwRc+1),dwRc2);
+
+ }
+
+ if (strcmp(szReturnedPath, szCurrentDir) != 0)
+ {
+ Fail("GetCurrentDirectoryA: ERROR -> The computed and returned "
+ "directories do not compare.\n");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/testinfo.dat
new file mode 100644
index 0000000000..c14eb42b22
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetCurrentDirectoryA
+Name = Test for GetCurrentDirectoryA (test 1)
+Type = DEFAULT
+EXE1 = getcurrentdirectorya
+Description
+= Calculate the current directory name and compare to that
+= returned by GetCurrentDirectoryA
+
diff --git a/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..ed8419926c
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetCurrentDirectoryW.c
+)
+
+add_executable(paltest_getcurrentdirectoryw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getcurrentdirectoryw_test1 coreclrpal)
+
+target_link_libraries(paltest_getcurrentdirectoryw_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/GetCurrentDirectoryW.c b/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/GetCurrentDirectoryW.c
new file mode 100644
index 0000000000..4f4697b0a2
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/GetCurrentDirectoryW.c
@@ -0,0 +1,106 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: GetCurrentDirectoryW.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the GetCurrentDirectoryW function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ DWORD dwRc = 0;
+ DWORD dwRc2 = 0;
+ WCHAR szwReturnedPath[_MAX_PATH+1];
+ WCHAR szwCurrentDir[_MAX_PATH+1];
+ WCHAR szwFileName[_MAX_PATH] = {'b','l','a','h','\0'};
+ LPWSTR pPathPtr;
+ size_t nCount = 0;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* use GetFullPathName to to get the current path by stripping
+ * the file name off the end */
+ memset(szwReturnedPath, 0, sizeof(WCHAR)*(_MAX_PATH+1));
+ dwRc = GetFullPathNameW(szwFileName, _MAX_PATH, szwReturnedPath, &pPathPtr);
+ if (dwRc == 0)
+ {
+ /* GetFullPathName failed */
+ Fail("GetCurrentDirectoryW: ERROR -> GetFullPathNameW failed "
+ "with error code: %ld.\n", GetLastError());
+ }
+ else if(dwRc >_MAX_PATH)
+ {
+ Fail("GetCurrentDirectoryW: ERROR -> The path name GetFullPathNameW "
+ "returned is longer than _MAX_PATH characters.\n");
+ }
+
+ /* strip the file name from the full path to get the current path */
+ nCount = wcslen(szwReturnedPath) - wcslen(szwFileName) - 1;
+ memset(szwCurrentDir, 0, sizeof(WCHAR)*(_MAX_PATH+1));
+ memcpy(szwCurrentDir, szwReturnedPath, nCount*sizeof(WCHAR));
+
+ /* compare the results of GetCurrentDirectoryW with the above */
+ memset(szwReturnedPath, 0, sizeof(WCHAR)*(_MAX_PATH+1));
+ dwRc = GetCurrentDirectoryW((sizeof(WCHAR)*(_MAX_PATH+1)), szwReturnedPath);
+ if (dwRc == 0)
+ {
+ Fail("GetCurrentDirectoryW: ERROR -> GetCurrentDirectoryW failed "
+ "with error code: %ld.\n", GetLastError());
+ }
+ else if(dwRc >_MAX_PATH)
+ {
+ Fail("GetCurrentDirectoryW: ERROR -> The path name "
+ "returned is longer than _MAX_PATH characters.\n");
+ }
+
+ /* check to see whether the length of the returned string is equal to
+ * the DWORD returned by GetCurrentDirectoryW.
+ */
+ if(wcslen(szwReturnedPath) != dwRc)
+ {
+ Fail("GetCurrentDirectoryW: ERROR -> The Length of the path name "
+ "returned \"%u\" is not equal to the return value of the "
+ "function \"%u\".\n" , wcslen(szwReturnedPath), dwRc);
+ }
+
+
+
+ /* test case the passed buffer size is not big enough
+ * function should return the size required + 1 for a terminating null character
+ */
+
+ /* good buffer size */
+ dwRc = GetCurrentDirectoryW((sizeof(WCHAR)*(_MAX_PATH+1)), szwReturnedPath);
+
+ /* small buffer (0 size)*/
+ dwRc2 = GetCurrentDirectoryW(0, szwReturnedPath);
+ if (dwRc2 != (dwRc+1) )
+ {
+ Fail("GetCurrentDirectoryW: ERROR -> failed to give the correct "
+ "return value when passed a buffer not big enough. "
+ "Expected %u while result is %u ",(dwRc+1),dwRc2);
+
+ }
+
+ if (wcsncmp(szwReturnedPath, szwCurrentDir, wcslen(szwReturnedPath)) != 0)
+ {
+ Fail("GetCurrentDirectoryW: ERROR -> The computed and returned "
+ "directories do not compare.\n");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/testinfo.dat
new file mode 100644
index 0000000000..4443a79833
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetCurrentDirectoryW
+Name = Test for GetCurrentDirectoryW (test 1)
+Type = DEFAULT
+EXE1 = getcurrentdirectoryw
+Description
+= Compute the current directory and compare with the results
+= from GetCurrentDirectoryW
+
diff --git a/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..6b06376233
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetDiskFreeSpaceW.c
+)
+
+add_executable(paltest_getdiskfreespacew_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getdiskfreespacew_test1 coreclrpal)
+
+target_link_libraries(paltest_getdiskfreespacew_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test1/GetDiskFreeSpaceW.c b/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test1/GetDiskFreeSpaceW.c
new file mode 100644
index 0000000000..c1445f654f
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test1/GetDiskFreeSpaceW.c
@@ -0,0 +1,94 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: GetDiskFreeSpaceW.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the GetDiskFreeSpaceW function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ DWORD dwSectorsPerCluster; /* sectors per cluster */
+ DWORD dwBytesPerSector; /* bytes per sector */
+ DWORD dwSectorsPerCluster_02; /* sectors per cluster */
+ DWORD dwBytesPerSector_02; /* bytes per sector */
+ DWORD dwNumberOfFreeClusters; /* free clusters */
+ DWORD dwTotalNumberOfClusters; /* total clusters */
+ BOOL bRc = FALSE;
+ WCHAR szwRootPath[10] = {'/','\0'};
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* test the NULL option which translates to the current drive */
+ bRc = GetDiskFreeSpaceW(NULL,
+ &dwSectorsPerCluster,
+ &dwBytesPerSector,
+ &dwNumberOfFreeClusters,
+ &dwTotalNumberOfClusters);
+ if (bRc != TRUE)
+ {
+ Fail("GetDiskFreeSpaceW: ERROR -> Failed with error code: %ld\n",
+ GetLastError());
+ }
+ else if (dwSectorsPerCluster == 0)
+ {
+ Fail("GetDiskFreeSpaceW: ERROR -> dwSectorsPerCluster returned 0\n");
+ }
+ else if (dwBytesPerSector == 0)
+ {
+ Fail("GetDiskFreeSpaceW: ERROR -> dwBytesPerSector returned 0\n");
+ }
+
+ /* test the root directory to the current drive */
+ bRc = GetDiskFreeSpaceW(szwRootPath,
+ &dwSectorsPerCluster_02,
+ &dwBytesPerSector_02,
+ &dwNumberOfFreeClusters,
+ &dwTotalNumberOfClusters);
+ if (bRc != TRUE)
+ {
+ Fail("GetDiskFreeSpaceW: ERROR -> Failed with error code: %ld\n",
+ GetLastError());
+ }
+ else if (dwSectorsPerCluster == 0)
+ {
+ Fail("GetDiskFreeSpaceW: ERROR -> dwSectorsPerCluster returned 0\n");
+ }
+ else if (dwBytesPerSector == 0)
+ {
+ Fail("GetDiskFreeSpaceW: ERROR -> dwBytesPerSector returned 0\n");
+ }
+ /*
+ ** make sure the values returned for NULL path and root path
+ ** are the same
+ */
+ else if (dwSectorsPerCluster_02 != dwSectorsPerCluster)
+ {
+ Fail("GetDiskFreeSpaceW: ERROR -> dwSectorsPerCluster for NULL path "
+ "(%u) should have been the same as the root path (%u).\n",
+ dwSectorsPerCluster,
+ dwSectorsPerCluster_02);
+ }
+ else if (dwBytesPerSector_02 != dwBytesPerSector)
+ {
+ Fail("GetDiskFreeSpaceW: ERROR -> dwBytesPerSector for NULL path "
+ "(%u) should have been the same as the root path (%u).\n",
+ dwBytesPerSector,
+ dwBytesPerSector_02);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test1/testinfo.dat
new file mode 100644
index 0000000000..61b0e55fae
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetDiskFreeSpaceW
+Name = Positive Test for GetDiskFreeSpaceW (test 1)
+Type = DEFAULT
+EXE1 = getdiskfreespacew
+Description
+= Test GetDiskFreeSpaceW. lpNumberOfFreeClusters and
+= lpTotalNumberOfClusters are to be ignored
diff --git a/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test2/CMakeLists.txt
new file mode 100644
index 0000000000..5660b39e1a
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ getdiskfreespacew.c
+)
+
+add_executable(paltest_getdiskfreespacew_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getdiskfreespacew_test2 coreclrpal)
+
+target_link_libraries(paltest_getdiskfreespacew_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test2/getdiskfreespacew.c b/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test2/getdiskfreespacew.c
new file mode 100644
index 0000000000..83dcb54b51
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test2/getdiskfreespacew.c
@@ -0,0 +1,65 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: GetDiskFreeSpaceW.c (test 2)
+**
+** Purpose: Tests the PAL implementation of the GetDiskFreeSpaceW
+** function on valid non-root paths.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ DWORD dwSectorsPerCluster; /* sectors per cluster */
+ DWORD dwBytesPerSector; /* bytes per sector */
+ DWORD dwNumberOfFreeClusters; /* free clusters */
+ DWORD dwTotalNumberOfClusters; /* total clusters */
+ BOOL bRc = FALSE;
+ WCHAR szwCurrentPath[MAX_LONGPATH];
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* get the current directory so we are sure to have a valid path */
+ if (!GetCurrentDirectoryW(MAX_LONGPATH, szwCurrentPath))
+ {
+ Fail("GetDiskFreeSpaceW: ERROR -> GetCurrentDirectoryW failed with "
+ "error code: %u.\n",
+ GetLastError());
+ }
+
+ /* test the current path*/
+ bRc = GetDiskFreeSpaceW(szwCurrentPath,
+ &dwSectorsPerCluster,
+ &dwBytesPerSector,
+ &dwNumberOfFreeClusters,
+ &dwTotalNumberOfClusters);
+ if (bRc != TRUE)
+ {
+ Fail("GetDiskFreeSpaceW: ERROR -> Failed with error code: %u for "
+ "the path \"%S\".\n",
+ GetLastError(),
+ szwCurrentPath);
+ }
+ else if (dwSectorsPerCluster == 0)
+ {
+ Fail("GetDiskFreeSpaceW: ERROR -> dwSectorsPerCluster returned 0\n");
+ }
+ else if (dwBytesPerSector == 0)
+ {
+ Fail("GetDiskFreeSpaceW: ERROR -> dwBytesPerSector returned 0\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test2/testinfo.dat b/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test2/testinfo.dat
new file mode 100644
index 0000000000..0a687240ea
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test2/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetDiskFreeSpaceW
+Name = Positive Test for GetDiskFreeSpaceW (test 2)
+Type = DEFAULT
+EXE1 = getdiskfreespacew
+Description
+= Test GetDiskFreeSpaceW with valid non-root paths
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesA/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileAttributesA/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesA/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_directory/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_directory/CMakeLists.txt
new file mode 100644
index 0000000000..a8fd227402
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_directory/CMakeLists.txt
@@ -0,0 +1,2 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_directory/keepme b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_directory/keepme
new file mode 100644
index 0000000000..31eade7217
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_directory/keepme
@@ -0,0 +1 @@
+Make CVS checkout this directory even with -p option. \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_file b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_file
new file mode 100644
index 0000000000..0d1ac31cfa
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_file
@@ -0,0 +1 @@
+Hidden file \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_ro_directory/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_ro_directory/CMakeLists.txt
new file mode 100644
index 0000000000..a8fd227402
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_ro_directory/CMakeLists.txt
@@ -0,0 +1,2 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_ro_directory/keepme b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_ro_directory/keepme
new file mode 100644
index 0000000000..31eade7217
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_ro_directory/keepme
@@ -0,0 +1 @@
+Make CVS checkout this directory even with -p option. \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_ro_file b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_ro_file
new file mode 100644
index 0000000000..8f78fcb436
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/.hidden_ro_file
@@ -0,0 +1 @@
+.hidden_ro_file
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/CMakeLists.txt
new file mode 100644
index 0000000000..6bf9818e86
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/CMakeLists.txt
@@ -0,0 +1,26 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetFileAttributesA.c
+)
+
+add_executable(paltest_getfileattributesa_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getfileattributesa_test1 coreclrpal)
+
+target_link_libraries(paltest_getfileattributesa_test1
+ pthread
+ m
+ coreclrpal
+)
+add_subdirectory(.hidden_directory)
+add_subdirectory(.hidden_ro_directory)
+add_subdirectory(normal_test_directory)
+add_subdirectory(no_directory)
+add_subdirectory(ro_test_directory)
+add_subdirectory(rw_directory)
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/GetFileAttributesA.c b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/GetFileAttributesA.c
new file mode 100644
index 0000000000..ff6bd0b8e0
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/GetFileAttributesA.c
@@ -0,0 +1,340 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: GetFileAttributesA.c
+**
+** Purpose: Tests the PAL implementation of the GetFileAttributesA function by
+** checking the attributes of:
+** - a normal directory and file
+** - a read only directory and file
+** - a read write directory and file
+** - a hidden directory and file
+** - a read only hidden directory and file
+** - a directory and a file with no attributes
+** - an invalid file name
+**
+**
+**===========================================================================*/
+#include <palsuite.h>
+
+const int TYPE_DIR = 0;
+const int TYPE_FILE = 1;
+/* Structure defining a test case */
+typedef struct
+{
+ char *name; /* name of the file/directory */
+ DWORD expectedAttribs; /* expected attributes */
+ HANDLE hFile; /* Handle to the file */
+ int isFile; /* is file (1) or dir (0) */
+}TestCaseFile;
+
+typedef struct
+{
+ char *name; /* name of the file/directory */
+ DWORD expectedAttribs; /* expected attributes */
+ HANDLE hFile; /* Handle to the file */
+ int isFile; /* is file (1) or dir (0) */
+}TestCaseDir;
+
+DWORD desiredAccessFile = GENERIC_READ | GENERIC_WRITE;
+DWORD shareModeFile = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
+LPSECURITY_ATTRIBUTES lpAttrFile = NULL;
+DWORD dwCreationDispFile = CREATE_NEW;
+DWORD dwFlagsAttribFile = FILE_ATTRIBUTE_NORMAL;
+HANDLE hTemplateFile = NULL;
+
+int numFileTests = 6;
+TestCaseFile gfaTestsFile[6]; /* GetFileAttributes tests list */
+
+int numDirTests = 6;
+TestCaseDir gfaTestsDir[6]; /* GetFileAttributes tests list */
+
+BOOL CleanUpFiles()
+{
+ DWORD dwAtt;
+ int i;
+ BOOL result = TRUE;
+ for (i = 0; i < numFileTests -1 ; i++ )
+ {
+ dwAtt = GetFileAttributesA(gfaTestsFile[i].name);
+
+ if( dwAtt != INVALID_FILE_ATTRIBUTES )
+ {
+ //Trace("Files iteration %d\n", i);
+ if(!SetFileAttributesA (gfaTestsFile[i].name, FILE_ATTRIBUTE_NORMAL))
+ {
+ result = FALSE;
+ Trace("ERROR:%d: Error setting attributes [%s][%d]\n", GetLastError(), gfaTestsFile[i].name, FILE_ATTRIBUTE_NORMAL);
+ }
+
+ if(!DeleteFileA (gfaTestsFile[i].name))
+ {
+ result = FALSE;
+ Trace("ERROR:%d: Error deleting file [%s][%d]\n", GetLastError(), gfaTestsFile[i].name, dwAtt);
+ }
+
+ }
+ }
+// Trace("Value of result is %d\n", result);
+ return result;
+}
+BOOL SetUpFiles()
+{
+ int i = 0;
+ BOOL result = TRUE;
+ for (i = 0; i < numFileTests -1; i++ )
+ {
+ gfaTestsFile[i].hFile = CreateFile(gfaTestsFile[i].name,
+ desiredAccessFile,
+ shareModeFile,
+ lpAttrFile,
+ dwCreationDispFile,
+ dwFlagsAttribFile,
+ hTemplateFile);
+
+ if( gfaTestsFile[i].hFile == NULL )
+ {
+ Fail("Error while creating files for iteration %d\n", i);
+ }
+
+ if(!SetFileAttributesA (gfaTestsFile[i].name, gfaTestsFile[i].expectedAttribs))
+ {
+ result = FALSE;
+ Trace("ERROR:%d: Error setting attributes [%s][%d]\n", GetLastError(), gfaTestsFile[i].name, gfaTestsFile[i].expectedAttribs);
+ }
+ }
+
+ return result;
+}
+
+BOOL CleanUpDirs()
+{
+ DWORD dwAtt;
+ int i;
+ BOOL result = TRUE;
+ for (i = 0; i < numDirTests -1 ; i++ )
+ {
+ dwAtt = GetFileAttributesA(gfaTestsDir[i].name);
+
+ if( dwAtt != INVALID_FILE_ATTRIBUTES )
+ {
+
+ if(!SetFileAttributesA (gfaTestsDir[i].name, FILE_ATTRIBUTE_DIRECTORY))
+ {
+ result = FALSE;
+ Trace("ERROR:%d: Error setting attributes [%s][%d]\n", GetLastError(), gfaTestsDir[i].name, (FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY));
+ }
+
+ if(!RemoveDirectoryA (gfaTestsDir[i].name))
+ {
+ result = FALSE;
+ Trace("ERROR:%d: Error deleting file [%s][%d]\n", GetLastError(), gfaTestsDir[i].name, dwAtt);
+ }
+
+ }
+ }
+
+ return result;
+}
+
+BOOL SetUpDirs()
+{
+ int i = 0;
+ BOOL result = TRUE;
+ DWORD ret = 0;
+ for (i = 0; i < numDirTests - 1 ; i++ )
+ {
+ result = CreateDirectory(gfaTestsDir[i].name,
+ NULL);
+
+ if(!result )
+ {
+ result = FALSE;
+ Fail("Error while creating directory for iteration %d\n", i);
+ }
+
+ if(!SetFileAttributesA (gfaTestsDir[i].name, gfaTestsDir[i].expectedAttribs))
+ {
+ result = FALSE;
+ Trace("ERROR:%d: Error setting attributes [%s][%d]\n", GetLastError(), gfaTestsDir[i].name, gfaTestsDir[i].expectedAttribs);
+ }
+
+ ret = GetFileAttributesA (gfaTestsDir[i].name);
+ if(ret != gfaTestsDir[i].expectedAttribs)
+ {
+ result = FALSE;
+ Trace("ERROR: Error setting attributes [%s][%d]\n", gfaTestsDir[i].name, gfaTestsDir[i].expectedAttribs);
+ }
+ //Trace("Setup Dir setting attr [%d], returned [%d]\n", gfaTestsDir[i].expectedAttribs, ret);
+
+ }
+ //Trace("Setup dirs returning %d\n", result);
+ return result;
+}
+int __cdecl main(int argc, char **argv)
+{
+ int i;
+ BOOL bFailed = FALSE;
+ DWORD result;
+
+ char * NormalDirectoryName = "normal_test_directory";
+ char * ReadOnlyDirectoryName = "ro_test_directory";
+ char * ReadWriteDirectoryName = "rw_directory";
+ char * HiddenDirectoryName = ".hidden_directory";
+ char * HiddenReadOnlyDirectoryName = ".hidden_ro_directory";
+ char * NoDirectoryName = "no_directory";
+
+ char * NormalFileName = "normal_test_file";
+ char * ReadOnlyFileName = "ro_test_file";
+ char * ReadWriteFileName = "rw_file";
+ char * HiddenFileName = ".hidden_file";
+ char * HiddenReadOnlyFileName = ".hidden_ro_file";
+ char * NotReallyAFileName = "not_really_a_file";
+
+ /* Tests on directory */
+ gfaTestsDir[0].name = NormalDirectoryName;
+ gfaTestsDir[0].expectedAttribs = FILE_ATTRIBUTE_DIRECTORY;
+ gfaTestsDir[0].isFile = TYPE_DIR;
+
+ gfaTestsDir[1].name = ReadOnlyDirectoryName;
+ gfaTestsDir[1].expectedAttribs = FILE_ATTRIBUTE_DIRECTORY |
+ FILE_ATTRIBUTE_READONLY;
+ gfaTestsDir[1].isFile = TYPE_DIR;
+
+ gfaTestsDir[2].name = ReadWriteDirectoryName;
+ gfaTestsDir[2].expectedAttribs = FILE_ATTRIBUTE_DIRECTORY;
+ gfaTestsDir[2].isFile = TYPE_DIR;
+
+ gfaTestsDir[3].name = HiddenDirectoryName;
+ gfaTestsDir[3].expectedAttribs = FILE_ATTRIBUTE_DIRECTORY; //|
+ //FILE_ATTRIBUTE_HIDDEN;
+ gfaTestsDir[3].isFile = TYPE_DIR;
+
+ gfaTestsDir[4].name = HiddenReadOnlyDirectoryName;
+ gfaTestsDir[4].expectedAttribs = FILE_ATTRIBUTE_DIRECTORY |
+ FILE_ATTRIBUTE_READONLY; //|
+ //FILE_ATTRIBUTE_HIDDEN;
+ gfaTestsDir[4].isFile = TYPE_DIR;
+
+ gfaTestsDir[5].name = NoDirectoryName;
+ gfaTestsDir[5].expectedAttribs = INVALID_FILE_ATTRIBUTES;
+ gfaTestsDir[5].isFile = TYPE_DIR;
+
+ /* Tests on file */
+ gfaTestsFile[0].name = NormalFileName;
+ gfaTestsFile[0].expectedAttribs = FILE_ATTRIBUTE_NORMAL;
+ gfaTestsFile[0].isFile = TYPE_FILE;
+
+
+ gfaTestsFile[1].name = ReadOnlyFileName;
+ gfaTestsFile[1].expectedAttribs = FILE_ATTRIBUTE_READONLY;
+ gfaTestsFile[1].isFile = TYPE_FILE;
+
+ gfaTestsFile[2].name = ReadWriteFileName;
+ gfaTestsFile[2].expectedAttribs = FILE_ATTRIBUTE_NORMAL;
+ gfaTestsFile[2].isFile = TYPE_FILE;
+
+ gfaTestsFile[3].name = HiddenFileName;
+ gfaTestsFile[3].expectedAttribs = FILE_ATTRIBUTE_NORMAL; //FILE_ATTRIBUTE_HIDDEN;
+ gfaTestsFile[3].isFile = TYPE_FILE;
+
+ gfaTestsFile[4].name = HiddenReadOnlyFileName;
+ gfaTestsFile[4].expectedAttribs = FILE_ATTRIBUTE_READONLY; //|
+ //FILE_ATTRIBUTE_HIDDEN;
+ gfaTestsFile[4].isFile = TYPE_FILE;
+
+
+ gfaTestsFile[5].name = NotReallyAFileName;
+ gfaTestsFile[5].expectedAttribs = INVALID_FILE_ATTRIBUTES;
+ gfaTestsFile[5].isFile = TYPE_FILE;
+
+ /* Initialize PAL environment */
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ if(!CleanUpFiles())
+ {
+ Fail("GetFileAttributesA: Pre-Clean Up Files Failed\n");
+ }
+
+ if(0 == SetUpFiles())
+ {
+ Fail("GetFileAttributesA: SetUp Files Failed\n");
+ }
+
+ if(!CleanUpDirs())
+ {
+ Fail("GetFileAttributesA: Pre-Clean Up Directories Failed\n");
+ }
+
+ if(!SetUpDirs())
+ {
+ Fail("GetFileAttributesA: SetUp Directories Failed\n");
+ }
+
+ /*
+ * Go through all the test cases above,
+ * call GetFileAttributesA on the name and
+ * make sure the return value is the one expected
+ */
+ for( i = 0; i < numFileTests; i++ )
+ {
+ result = GetFileAttributesA(gfaTestsFile[i].name);
+
+ if( result != gfaTestsFile[i].expectedAttribs )
+ {
+ bFailed = TRUE;
+
+ Trace("ERROR: GetFileAttributesA Test#%u on %s "
+ "returned %u instead of %u. \n",
+ i,
+ gfaTestsFile[i].name,
+ result,
+ gfaTestsFile[i].expectedAttribs);
+
+ }
+ }
+
+
+ for( i = 0; i < numDirTests; i++ )
+ {
+ result = GetFileAttributesA(gfaTestsDir[i].name);
+
+ if( result != gfaTestsDir[i].expectedAttribs )
+ {
+ bFailed = TRUE;
+
+ Trace("ERROR: GetFileAttributesA on Directories Test#%u on %s "
+ "returned %u instead of %u. \n",
+ i,
+ gfaTestsDir[i].name,
+ result,
+ gfaTestsDir[i].expectedAttribs);
+
+ }
+ }
+
+ if(!CleanUpFiles())
+ {
+ Fail("GetFileAttributesA: Post-Clean Up Files Failed\n");
+ }
+
+ if(!CleanUpDirs())
+ {
+ Fail("GetFileAttributesA: Post-Clean Up Directories Failed\n");
+ }
+
+ /* If any errors, just call Fail() */
+ if( bFailed )
+ {
+ Fail("");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/no_directory/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/no_directory/CMakeLists.txt
new file mode 100644
index 0000000000..a8fd227402
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/no_directory/CMakeLists.txt
@@ -0,0 +1,2 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/no_directory/keepme b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/no_directory/keepme
new file mode 100644
index 0000000000..31eade7217
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/no_directory/keepme
@@ -0,0 +1 @@
+Make CVS checkout this directory even with -p option. \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/no_file b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/no_file
new file mode 100644
index 0000000000..3d631e8103
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/no_file
@@ -0,0 +1 @@
+No attribs file \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/normal_test_directory/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/normal_test_directory/CMakeLists.txt
new file mode 100644
index 0000000000..a8fd227402
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/normal_test_directory/CMakeLists.txt
@@ -0,0 +1,2 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/normal_test_directory/keepme b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/normal_test_directory/keepme
new file mode 100644
index 0000000000..31eade7217
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/normal_test_directory/keepme
@@ -0,0 +1 @@
+Make CVS checkout this directory even with -p option. \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/normal_test_file b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/normal_test_file
new file mode 100644
index 0000000000..a6e1e627a8
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/normal_test_file
@@ -0,0 +1,6 @@
+file_io
+CopyFileW
+Positive Test for CopyFileW
+test the CopyFileW function
+DEFAULT
+CopyFileW \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/ro_test_directory/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/ro_test_directory/CMakeLists.txt
new file mode 100644
index 0000000000..a8fd227402
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/ro_test_directory/CMakeLists.txt
@@ -0,0 +1,2 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/ro_test_directory/keepme b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/ro_test_directory/keepme
new file mode 100644
index 0000000000..31eade7217
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/ro_test_directory/keepme
@@ -0,0 +1 @@
+Make CVS checkout this directory even with -p option. \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/ro_test_file b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/ro_test_file
new file mode 100644
index 0000000000..a6e1e627a8
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/ro_test_file
@@ -0,0 +1,6 @@
+file_io
+CopyFileW
+Positive Test for CopyFileW
+test the CopyFileW function
+DEFAULT
+CopyFileW \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/rw_directory/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/rw_directory/CMakeLists.txt
new file mode 100644
index 0000000000..a8fd227402
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/rw_directory/CMakeLists.txt
@@ -0,0 +1,2 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/rw_directory/keepme b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/rw_directory/keepme
new file mode 100644
index 0000000000..31eade7217
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/rw_directory/keepme
@@ -0,0 +1 @@
+Make CVS checkout this directory even with -p option. \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/rw_file b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/rw_file
new file mode 100644
index 0000000000..39d66f0365
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/rw_file
@@ -0,0 +1 @@
+Read Write file \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/testinfo.dat
new file mode 100644
index 0000000000..2053220bf3
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/testinfo.dat
@@ -0,0 +1,20 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+
+Section = file_io
+
+Function = GetFileAttributesA
+
+Name = Positive Test for GetFileAttributesA
+
+TYPE = DEFAULT
+
+EXE1 = getfileattributesa
+
+Description
+
+= Test the GetFileAttributesA function
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesExW/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/.hidden_directory/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/.hidden_directory/CMakeLists.txt
new file mode 100644
index 0000000000..a8fd227402
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/.hidden_directory/CMakeLists.txt
@@ -0,0 +1,2 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/.hidden_directory/anchor.txt b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/.hidden_directory/anchor.txt
new file mode 100644
index 0000000000..9a277fa04e
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/.hidden_directory/anchor.txt
@@ -0,0 +1,2 @@
+This file is here so this directory gets checked out even with the -P
+option. \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/.hidden_file b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/.hidden_file
new file mode 100644
index 0000000000..0d1ac31cfa
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/.hidden_file
@@ -0,0 +1 @@
+Hidden file \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..2d299d82e5
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/CMakeLists.txt
@@ -0,0 +1,23 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_getfileattributesexw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getfileattributesexw_test1 coreclrpal)
+
+target_link_libraries(paltest_getfileattributesexw_test1
+ pthread
+ m
+ coreclrpal
+)
+add_subdirectory(.hidden_directory)
+add_subdirectory(normal_test_directory)
+add_subdirectory(ro_test_directory)
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/normal_test_directory/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/normal_test_directory/CMakeLists.txt
new file mode 100644
index 0000000000..a8fd227402
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/normal_test_directory/CMakeLists.txt
@@ -0,0 +1,2 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/normal_test_directory/keepme b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/normal_test_directory/keepme
new file mode 100644
index 0000000000..31eade7217
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/normal_test_directory/keepme
@@ -0,0 +1 @@
+Make CVS checkout this directory even with -p option. \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/normal_test_file b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/normal_test_file
new file mode 100644
index 0000000000..ab7622ffb1
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/normal_test_file
@@ -0,0 +1,6 @@
+file_io
+CopyFileW
+Positive Test for CopyFileW
+test the CopyFileW function
+DEFAULT
+CopyFileW \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/ro_test_directory/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/ro_test_directory/CMakeLists.txt
new file mode 100644
index 0000000000..a8fd227402
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/ro_test_directory/CMakeLists.txt
@@ -0,0 +1,2 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/ro_test_directory/keepme b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/ro_test_directory/keepme
new file mode 100644
index 0000000000..31eade7217
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/ro_test_directory/keepme
@@ -0,0 +1 @@
+Make CVS checkout this directory even with -p option. \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/ro_test_file b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/ro_test_file
new file mode 100644
index 0000000000..ab7622ffb1
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/ro_test_file
@@ -0,0 +1,6 @@
+file_io
+CopyFileW
+Positive Test for CopyFileW
+test the CopyFileW function
+DEFAULT
+CopyFileW \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/test1.c b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/test1.c
new file mode 100644
index 0000000000..7a622b628c
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/test1.c
@@ -0,0 +1,227 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests the PAL implementation of the GetFileAttributesExW function.
+** Call the function on a normal directory and file and a read-only directory
+** and file and a hidden file and directory.
+** Ensure that the attributes returned are correct, and the
+** file times and file sizes.
+**
+**
+**===================================================================*/
+
+#define UNICODE
+#include <palsuite.h>
+
+typedef enum Item
+{
+ IS_DIR,
+ IS_FILE
+}ItemType;
+
+/*
+ This is a helper function which takes two FILETIME structures and
+ checks to see if they contain the exact same time.
+*/
+int IsEqualFileTime(FILETIME FirstTime, FILETIME SecondTime)
+{
+
+ ULONG64 TimeOne, TimeTwo;
+
+ TimeOne = ((((ULONG64)FirstTime.dwHighDateTime)<<32) |
+ ((ULONG64)FirstTime.dwLowDateTime));
+
+ TimeTwo = ((((ULONG64)SecondTime.dwHighDateTime)<<32) |
+ ((ULONG64)SecondTime.dwLowDateTime));
+
+ return(TimeOne == TimeTwo);
+}
+
+/* This function takes a structure and checks that the information
+ within the structure is correct. The 'Attribs' are the expected
+ file attributes, 'TheType' is IS_DIR or IS_FILE and the 'Name' is the
+ name of the file/directory in question.
+*/
+void VerifyInfo(WIN32_FILE_ATTRIBUTE_DATA InfoStruct,
+ DWORD Attribs, ItemType TheType, WCHAR* Name)
+{
+ HANDLE hFile;
+ FILETIME CorrectCreation, CorrectAccess, CorrectModify;
+ WCHAR CopyName[64];
+
+ wcscpy(CopyName,Name);
+ free(Name);
+
+ /* Check to see that the file attributes were recorded */
+ if(InfoStruct.dwFileAttributes != Attribs)
+ {
+ Fail("ERROR: The file attributes on the file/directory were "
+ "recorded as being %d instead of %d.\n",
+ InfoStruct.dwFileAttributes,
+ Attribs);
+ }
+
+ /* Note: We can't open a handle to a directory in windows. This
+ block of tests will only be run on files.
+ */
+ if(TheType == IS_FILE)
+ {
+
+ /* Get a handle to the file */
+ hFile = CreateFile(CopyName,
+ 0,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Could not open a handle to the file "
+ "'%S'. GetLastError() returned %d.",CopyName,
+ GetLastError());
+ }
+
+
+
+ /* Get the FileTime of the file in question */
+ if(GetFileTime(hFile, &CorrectCreation,
+ &CorrectAccess, &CorrectModify) == 0)
+ {
+ Fail("ERROR: GetFileTime failed to get the filetime of the "
+ "file. GetLastError() returned %d.",
+ GetLastError());
+ }
+
+ /* Check that the Creation, Access and Last Modified times are all
+ the same in the structure as what GetFileTime just returned.
+ */
+ if(!IsEqualFileTime(CorrectCreation, InfoStruct.ftCreationTime))
+ {
+ Fail("ERROR: The creation time of the file "
+ "does not match the creation time given from "
+ "GetFileTime.\n");
+ }
+ if(!IsEqualFileTime(CorrectAccess, InfoStruct.ftLastAccessTime))
+ {
+ Fail("ERROR: The access time of the file "
+ "does not match the access time given from "
+ "GetFileTime.\n");
+ }
+ if(!IsEqualFileTime(CorrectModify, InfoStruct.ftLastWriteTime))
+ {
+ Fail("ERROR: The write time of the file "
+ "does not match the last write time given from "
+ "GetFileTime.\n");
+ }
+
+ if(InfoStruct.nFileSizeLow != GetFileSize(hFile,NULL))
+ {
+ Fail("ERROR: The file size reported by GetFileAttributesEx "
+ "did not match the file size given by GetFileSize.\n");
+ }
+
+ if(CloseHandle(hFile) == 0)
+ {
+ Fail("ERROR: Failed to properly close the handle to the "
+ "file we're testing. GetLastError() returned %d.\n",
+ GetLastError());
+
+ }
+
+ }
+
+
+}
+
+/* Given a file/directory name, the expected attribs and whether or not it
+ is a file or directory, call GetFileAttributesEx and verify the
+ results are correct.
+*/
+
+void RunTest(char* Name, DWORD Attribs, ItemType TheType )
+{
+ WCHAR* TheName;
+ WIN32_FILE_ATTRIBUTE_DATA InfoStruct;
+ DWORD TheResult;
+
+ TheName = convert(Name);
+
+ TheResult = GetFileAttributesEx(TheName,
+ GetFileExInfoStandard,
+ &InfoStruct);
+ if(TheResult == 0)
+ {
+ free(TheName);
+ Fail("ERROR: GetFileAttributesEx returned 0, indicating failure. "
+ "GetLastError returned %d.\n",GetLastError());
+ }
+
+ VerifyInfo(InfoStruct, Attribs, TheType, TheName);
+
+}
+
+int __cdecl main(int argc, char **argv)
+{
+ DWORD TheResult;
+ WCHAR* FileName;
+ WIN32_FILE_ATTRIBUTE_DATA InfoStruct;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* Test a Directroy */
+ RunTest("normal_test_directory", FILE_ATTRIBUTE_DIRECTORY, IS_DIR);
+
+
+ /* Test a Normal File */
+
+ RunTest("normal_test_file", FILE_ATTRIBUTE_NORMAL, IS_FILE);
+
+ /* Test a Read-Only Directroy */
+
+ RunTest("ro_test_directory",
+ FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_DIRECTORY, IS_DIR);
+
+ /* Test a Read-Only File */
+
+ RunTest("ro_test_file", FILE_ATTRIBUTE_READONLY, IS_FILE);
+
+ /* Test a Hidden File */
+
+ RunTest(".hidden_file", FILE_ATTRIBUTE_HIDDEN, IS_FILE);
+
+ /* Test a Hidden Directroy */
+
+ RunTest(".hidden_directory",
+ FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_DIRECTORY, IS_DIR);
+
+ /* Test a Non-Existant File */
+
+ FileName = convert("nonexistent_test_file");
+
+ TheResult = GetFileAttributesEx(FileName,
+ GetFileExInfoStandard,
+ &InfoStruct);
+
+ if(TheResult != 0)
+ {
+ free(FileName);
+ Fail("ERROR: GetFileAttributesEx returned non-zero, indicating "
+ "success when it should have failed. It was called on a "
+ "non-existent file.");
+ }
+
+ free(FileName);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/testinfo.dat
new file mode 100644
index 0000000000..fbc397eac0
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetFileAttributesExW
+Name = Test with normal file/dir and readonly file/dir and hidden file/dir
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests the PAL implementation of the GetFileAttributesExW function.
+= Call the function on a normal directory and file and a read-only directory
+= and file and a hidden file and directory.
+= Ensure that the attributes returned are correct, and the
+= file times and file sizes.
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/CMakeLists.txt
new file mode 100644
index 0000000000..70caac2c69
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_getfileattributesexw_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getfileattributesexw_test2 coreclrpal)
+
+target_link_libraries(paltest_getfileattributesexw_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/test2.c b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/test2.c
new file mode 100644
index 0000000000..f244a3bf6a
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/test2.c
@@ -0,0 +1,170 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: getfileattributesexw.c (getfileattributesexw\test2)
+**
+** Purpose: Tests the PAL implementation of GetFileAttributesExW.
+** First get a file's attributes, modify the file,
+** re-get its attributes
+** and compare the two sets of attributes.
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+/**
+ * This is a helper function which takes two FILETIME structures and
+ * checks that the second time isn't before the first.
+ */
+static int IsFileTimeOk(FILETIME FirstTime, FILETIME SecondTime)
+{
+
+ ULONG64 TimeOne, TimeTwo;
+
+ TimeOne = ((((ULONG64)FirstTime.dwHighDateTime)<<32) |
+ ((ULONG64)FirstTime.dwLowDateTime));
+
+ TimeTwo = ((((ULONG64)SecondTime.dwHighDateTime)<<32) |
+ ((ULONG64)SecondTime.dwLowDateTime));
+
+ return(TimeOne <= TimeTwo);
+}
+
+int __cdecl main(int argc, char **argv)
+{
+ DWORD res;
+ char fileName[MAX_PATH] = "test_file";
+ WCHAR *wFileName;
+ WIN32_FILE_ATTRIBUTE_DATA beforeAttribs;
+ WIN32_FILE_ATTRIBUTE_DATA afterAttribs;
+ FILE *testFile;
+ ULONG64 beforeFileSize;
+ ULONG64 afterFileSize;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* Create the file */
+ testFile = fopen(fileName, "w+");
+ if( NULL == testFile )
+ {
+ Fail("Unexpected error: Unable to open file %S "
+ "with fopen. \n",
+ fileName);
+ }
+
+ if( EOF == fputs( "testing", testFile ) )
+ {
+ Fail("Unexpected error: Unable to write to file %S "
+ "with fputs. \n",
+ fileName);
+ }
+
+ if( 0 != fclose(testFile) )
+ {
+ Fail("Unexpected error: Unable to close file %S "
+ "with fclose. \n",
+ fileName);
+ }
+
+ /* Test the Values returned by GetFileAttributesExW
+ * before and after manipulating a file shouldn't be the same.
+ */
+
+ wFileName = convert(fileName);
+
+ res = GetFileAttributesExW(wFileName,
+ GetFileExInfoStandard,
+ &beforeAttribs);
+
+ if(res == 0)
+ {
+ Fail("ERROR: unable to get initial file attributes with "
+ "GetFileAttributesEx that returned 0 with error %d.\n",
+ GetLastError());
+ }
+
+ /* Make sure the time are different */
+ Sleep(500);
+
+ testFile = fopen(fileName, "w+");
+ if( NULL == testFile )
+ {
+ Fail("Unexpected error: Unable to open file %S "
+ "with fopen. \n",
+ fileName);
+ }
+
+ if( EOF == fputs( "testing GetFileAttributesExW", testFile ) )
+ {
+ Fail("Unexpected error: Unable to write to file %S "
+ "with fputs. \n",
+ fileName);
+ }
+
+ if( 0 != fclose(testFile) )
+ {
+ Fail("Unexpected error: Unable to close file %S "
+ "with fclose. \n",
+ fileName);
+ }
+
+ res = GetFileAttributesExW(wFileName,
+ GetFileExInfoStandard,
+ &afterAttribs);
+
+ if(res == 0)
+ {
+ Fail("ERROR: unable to get file attributes after operations with "
+ "GetFileAttributesEx that returned 0 with error %d.\n",
+ GetLastError());
+ }
+
+ /* Check the creation time */
+ if(!IsFileTimeOk(beforeAttribs.ftCreationTime,
+ afterAttribs.ftCreationTime))
+ {
+ Fail("ERROR: Creation time after the fputs operation "
+ "is earlier than the creation time before the fputs.\n");
+ }
+
+ /* Check the last access time */
+ if(!IsFileTimeOk(beforeAttribs.ftLastAccessTime,
+ afterAttribs.ftLastAccessTime))
+ {
+ Fail("ERROR: Last access time after the fputs operation "
+ "is earlier than the last access time before the fputs.\n");
+ }
+
+ /* Check the last write time */
+ if(!IsFileTimeOk(beforeAttribs.ftLastWriteTime,
+ afterAttribs.ftLastWriteTime))
+ {
+ Fail("ERROR: Last write time after the fputs operation "
+ "is earlier than the last write time before the fputs.\n");
+ }
+
+ beforeFileSize = ((ULONG64)beforeAttribs.nFileSizeHigh)<< 32 |
+ ((ULONG64)beforeAttribs.nFileSizeLow);
+
+ afterFileSize = ((ULONG64)afterAttribs.nFileSizeHigh)<< 32 |
+ ((ULONG64)afterAttribs.nFileSizeLow);
+
+ /* Check the file size */
+ if( afterFileSize <= beforeFileSize )
+ {
+ Fail("ERROR: the file should have had a bigger size "
+ "after(%d) the operations than before(%d)\n",
+ afterAttribs.nFileSizeLow,
+ beforeAttribs.nFileSizeLow);
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/testinfo.dat b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/testinfo.dat
new file mode 100644
index 0000000000..560e3f6266
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetFileAttributesExW
+Name = Test for GetFileAttributesExW
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Tests the PAL implementation of the GetFileAttributesExW function.
+= First get a file's attributes, modify the file, re-get its attributes
+= and compare the two sets of attributes
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesW/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileAttributesW/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesW/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_directory/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_directory/CMakeLists.txt
new file mode 100644
index 0000000000..a8fd227402
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_directory/CMakeLists.txt
@@ -0,0 +1,2 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_directory/keepme b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_directory/keepme
new file mode 100644
index 0000000000..31eade7217
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_directory/keepme
@@ -0,0 +1 @@
+Make CVS checkout this directory even with -p option. \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_file b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_file
new file mode 100644
index 0000000000..0d1ac31cfa
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_file
@@ -0,0 +1 @@
+Hidden file \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_ro_directory/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_ro_directory/CMakeLists.txt
new file mode 100644
index 0000000000..a8fd227402
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_ro_directory/CMakeLists.txt
@@ -0,0 +1,2 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_ro_directory/keepme b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_ro_directory/keepme
new file mode 100644
index 0000000000..31eade7217
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_ro_directory/keepme
@@ -0,0 +1 @@
+Make CVS checkout this directory even with -p option. \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_ro_file b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_ro_file
new file mode 100644
index 0000000000..8f78fcb436
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/.hidden_ro_file
@@ -0,0 +1 @@
+.hidden_ro_file
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..7050484607
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/CMakeLists.txt
@@ -0,0 +1,26 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetFileAttributesW.c
+)
+
+add_executable(paltest_getfileattributesw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getfileattributesw_test1 coreclrpal)
+
+target_link_libraries(paltest_getfileattributesw_test1
+ pthread
+ m
+ coreclrpal
+)
+add_subdirectory(.hidden_directory)
+add_subdirectory(.hidden_ro_directory)
+add_subdirectory(normal_test_directory)
+add_subdirectory(no_directory)
+add_subdirectory(ro_test_directory)
+add_subdirectory(rw_test_directory)
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/GetFileAttributesW.c b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/GetFileAttributesW.c
new file mode 100644
index 0000000000..9d00da4bd4
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/GetFileAttributesW.c
@@ -0,0 +1,345 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: GetFileAttributesW.c
+**
+** Purpose: Tests the PAL implementation of the GetFileAttributesW function by
+** checking the attributes of:
+** - a normal directory and file
+** - a read only directory and file
+** - a read write directory and file
+** - a hidden directory and file
+** - a read only hidden directory and file
+** - a directory and a file with no attributes
+** - an invalid file name
+**
+**
+**===========================================================================*/
+#include <palsuite.h>
+
+const int TYPE_DIR = 0;
+const int TYPE_FILE = 1;
+/* Structure defining a test case */
+typedef struct
+{
+ char *name; /* name of the file/directory */
+ DWORD expectedAttribs; /* expected attributes */
+ HANDLE hFile; /* Handle to the file */
+ int isFile; /* is file (1) or dir (0) */
+}TestCaseFile;
+
+typedef struct
+{
+ char *name; /* name of the file/directory */
+ DWORD expectedAttribs; /* expected attributes */
+ HANDLE hFile; /* Handle to the file */
+ int isFile; /* is file (1) or dir (0) */
+}TestCaseDir;
+
+DWORD desiredAccessFile = GENERIC_READ | GENERIC_WRITE;
+DWORD shareModeFile = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
+LPSECURITY_ATTRIBUTES lpAttrFile = NULL;
+DWORD dwCreationDispFile = CREATE_NEW;
+DWORD dwFlagsAttribFile = FILE_ATTRIBUTE_NORMAL;
+HANDLE hTemplateFile = NULL;
+
+int numFileTests = 6;
+TestCaseFile gfaTestsFile[6]; /* GetFileAttributes tests list */
+
+int numDirTests = 6;
+TestCaseDir gfaTestsDir[6]; /* GetFileAttributes tests list */
+
+BOOL CleanUpFiles()
+{
+ DWORD dwAtt;
+ int i;
+ BOOL result = TRUE;
+ for (i = 0; i < numFileTests - 1 ; i++ )
+ {
+ dwAtt = GetFileAttributesA(gfaTestsFile[i].name);
+
+ if( dwAtt != INVALID_FILE_ATTRIBUTES )
+ {
+ //Trace("Files iteration %d\n", i);
+ if(!SetFileAttributesA (gfaTestsFile[i].name, FILE_ATTRIBUTE_NORMAL))
+ {
+ result = FALSE;
+ Trace("ERROR:%d: Error setting attributes [%s][%d]\n", GetLastError(), gfaTestsFile[i].name, FILE_ATTRIBUTE_NORMAL);
+ }
+
+ if(!DeleteFileA (gfaTestsFile[i].name))
+ {
+ result = FALSE;
+ Trace("ERROR:%d: Error deleting file [%s][%d]\n", GetLastError(), gfaTestsFile[i].name, dwAtt);
+ }
+
+ }
+ }
+// Trace("Value of result is %d\n", result);
+ return result;
+}
+BOOL SetUpFiles()
+{
+ int i = 0;
+ BOOL result = TRUE;
+ for (i = 0; i < numFileTests - 1 ; i++ )
+ {
+ gfaTestsFile[i].hFile = CreateFile(gfaTestsFile[i].name,
+ desiredAccessFile,
+ shareModeFile,
+ lpAttrFile,
+ dwCreationDispFile,
+ dwFlagsAttribFile,
+ hTemplateFile);
+
+ if( gfaTestsFile[i].hFile == NULL )
+ {
+ Fail("Error while creating files for iteration %d\n", i);
+ }
+
+ if(!SetFileAttributesA (gfaTestsFile[i].name, gfaTestsFile[i].expectedAttribs))
+ {
+ result = FALSE;
+ Trace("ERROR:%d: Error setting attributes [%s][%d]\n", GetLastError(), gfaTestsFile[i].name, gfaTestsFile[i].expectedAttribs);
+ }
+ }
+
+ return result;
+}
+
+BOOL CleanUpDirs()
+{
+ DWORD dwAtt;
+ int i;
+ BOOL result = TRUE;
+ for (i = 0; i < numDirTests - 1; i++ )
+ {
+ dwAtt = GetFileAttributesA(gfaTestsDir[i].name);
+
+ if( dwAtt != INVALID_FILE_ATTRIBUTES )
+ {
+
+ if(!SetFileAttributesA (gfaTestsDir[i].name, FILE_ATTRIBUTE_DIRECTORY))
+ {
+ result = FALSE;
+ Trace("ERROR:%d: Error setting attributes [%s][%d]\n", GetLastError(), gfaTestsDir[i].name, (FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY));
+ }
+
+ if(!RemoveDirectoryA (gfaTestsDir[i].name))
+ {
+ result = FALSE;
+ Trace("ERROR:%d: Error deleting file [%s][%d]\n", GetLastError(), gfaTestsDir[i].name, dwAtt);
+ }
+
+ }
+ }
+
+ return result;
+}
+
+BOOL SetUpDirs()
+{
+ int i = 0;
+ BOOL result = TRUE;
+ DWORD ret = 0;
+ for (i = 0; i < numDirTests - 1; i++ )
+ {
+ result = CreateDirectory(gfaTestsDir[i].name,
+ NULL);
+
+ if(!result )
+ {
+ result = FALSE;
+ Fail("Error while creating directory for iteration %d\n", i);
+ }
+
+ if(!SetFileAttributesA (gfaTestsDir[i].name, gfaTestsDir[i].expectedAttribs))
+ {
+ result = FALSE;
+ Trace("ERROR:%d: Error setting attributes [%s][%d]\n", GetLastError(), gfaTestsDir[i].name, gfaTestsDir[i].expectedAttribs);
+ }
+
+ ret = GetFileAttributesA (gfaTestsDir[i].name);
+ if(ret != gfaTestsDir[i].expectedAttribs)
+ {
+ result = FALSE;
+ Trace("ERROR: Error setting attributes [%s][%d]\n", gfaTestsDir[i].name, gfaTestsDir[i].expectedAttribs);
+ }
+ // Trace("Setup Dir setting attr [%d], returned [%d]\n", gfaTestsDir[i].expectedAttribs, ret);
+
+ }
+// Trace("Setup dirs returning %d\n", result);
+ return result;
+}
+int __cdecl main(int argc, char **argv)
+{
+ int i;
+ BOOL bFailed = FALSE;
+ DWORD result;
+
+ char * NormalDirectoryName = "normal_test_directory";
+ char * ReadOnlyDirectoryName = "ro_test_directory";
+ char * ReadWriteDirectoryName = "rw_directory";
+ char * HiddenDirectoryName = ".hidden_directory";
+ char * HiddenReadOnlyDirectoryName = ".hidden_ro_directory";
+ char * NoDirectoryName = "no_directory";
+
+ char * NormalFileName = "normal_test_file";
+ char * ReadOnlyFileName = "ro_test_file";
+ char * ReadWriteFileName = "rw_file";
+ char * HiddenFileName = ".hidden_file";
+ char * HiddenReadOnlyFileName = ".hidden_ro_file";
+ char * NotReallyAFileName = "not_really_a_file";
+
+ WCHAR *WStr;
+ /* Tests on directory */
+ gfaTestsDir[0].name = NormalDirectoryName;
+ gfaTestsDir[0].expectedAttribs = FILE_ATTRIBUTE_DIRECTORY;
+ gfaTestsDir[0].isFile = TYPE_DIR;
+
+ gfaTestsDir[1].name = ReadOnlyDirectoryName;
+ gfaTestsDir[1].expectedAttribs = FILE_ATTRIBUTE_DIRECTORY |
+ FILE_ATTRIBUTE_READONLY;
+ gfaTestsDir[1].isFile = TYPE_DIR;
+
+ gfaTestsDir[2].name = ReadWriteDirectoryName;
+ gfaTestsDir[2].expectedAttribs = FILE_ATTRIBUTE_DIRECTORY;
+ gfaTestsDir[2].isFile = TYPE_DIR;
+
+ gfaTestsDir[3].name = HiddenDirectoryName;
+ gfaTestsDir[3].expectedAttribs = FILE_ATTRIBUTE_DIRECTORY; //|
+ //FILE_ATTRIBUTE_HIDDEN;
+ gfaTestsDir[3].isFile = TYPE_DIR;
+
+ gfaTestsDir[4].name = HiddenReadOnlyDirectoryName;
+ gfaTestsDir[4].expectedAttribs = FILE_ATTRIBUTE_DIRECTORY |
+ FILE_ATTRIBUTE_READONLY; //|
+ //FILE_ATTRIBUTE_HIDDEN;
+ gfaTestsDir[4].isFile = TYPE_DIR;
+
+ gfaTestsDir[5].name = NoDirectoryName;
+ gfaTestsDir[5].expectedAttribs = INVALID_FILE_ATTRIBUTES;
+ gfaTestsDir[5].isFile = TYPE_DIR;
+
+ /* Tests on file */
+ gfaTestsFile[0].name = NormalFileName;
+ gfaTestsFile[0].expectedAttribs = FILE_ATTRIBUTE_NORMAL;
+ gfaTestsFile[0].isFile = TYPE_FILE;
+
+
+ gfaTestsFile[1].name = ReadOnlyFileName;
+ gfaTestsFile[1].expectedAttribs = FILE_ATTRIBUTE_READONLY;
+ gfaTestsFile[1].isFile = TYPE_FILE;
+
+ gfaTestsFile[2].name = ReadWriteFileName;
+ gfaTestsFile[2].expectedAttribs = FILE_ATTRIBUTE_NORMAL;
+ gfaTestsFile[2].isFile = TYPE_FILE;
+
+ gfaTestsFile[3].name = HiddenFileName;
+ gfaTestsFile[3].expectedAttribs = FILE_ATTRIBUTE_NORMAL; //FILE_ATTRIBUTE_HIDDEN;
+ gfaTestsFile[3].isFile = TYPE_FILE;
+
+ gfaTestsFile[4].name = HiddenReadOnlyFileName;
+ gfaTestsFile[4].expectedAttribs = FILE_ATTRIBUTE_READONLY; //|
+ //FILE_ATTRIBUTE_HIDDEN;
+ gfaTestsFile[4].isFile = TYPE_FILE;
+
+
+ gfaTestsFile[5].name = NotReallyAFileName;
+ gfaTestsFile[5].expectedAttribs = INVALID_FILE_ATTRIBUTES;
+ gfaTestsFile[5].isFile = TYPE_FILE;
+
+ /* Initialize PAL environment */
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ if(!CleanUpFiles())
+ {
+ Fail("GetFileAttributesW: Pre-Clean Up Files Failed\n");
+ }
+
+ if(0 == SetUpFiles())
+ {
+ Fail("GetFileAttributesW: SetUp Files Failed\n");
+ }
+
+ if(!CleanUpDirs())
+ {
+ Fail("GetFileAttributesW: Pre-Clean Up Directories Failed\n");
+ }
+
+ if(!SetUpDirs())
+ {
+ Fail("GetFileAttributesW: SetUp Directories Failed\n");
+ }
+
+ /*
+ * Go through all the test cases above,
+ * call GetFileAttributesW on the name and
+ * make sure the return value is the one expected
+ */
+ for( i = 0; i < numFileTests; i++ )
+ {
+ WStr = convert(gfaTestsFile[i].name);
+ result = GetFileAttributesW(WStr);
+
+ if( result != gfaTestsFile[i].expectedAttribs )
+ {
+ bFailed = TRUE;
+
+ Trace("ERROR: GetFileAttributesW Test#%u on %s "
+ "returned %u instead of %u. \n",
+ i,
+ gfaTestsFile[i].name,
+ result,
+ gfaTestsFile[i].expectedAttribs);
+
+ }
+ free(WStr);
+ }
+
+
+ for( i = 0; i < numDirTests; i++ )
+ {
+ WStr = convert(gfaTestsDir[i].name);
+ result = GetFileAttributesW(WStr);
+
+ if( result != gfaTestsDir[i].expectedAttribs )
+ {
+ bFailed = TRUE;
+
+ Trace("ERROR: GetFileAttributesW on Directories Test#%u on %s "
+ "returned %u instead of %u. \n",
+ i,
+ gfaTestsDir[i].name,
+ result,
+ gfaTestsDir[i].expectedAttribs);
+
+ }
+ free(WStr);
+ }
+
+ if(!CleanUpFiles())
+ {
+ Fail("GetFileAttributesW: Post-Clean Up Files Failed\n");
+ }
+
+ if(!CleanUpDirs())
+ {
+ Fail("GetFileAttributesW: Post-Clean Up Directories Failed\n");
+ }
+
+ /* If any errors, just call Fail() */
+ if( bFailed )
+ {
+ Fail("");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/no_directory/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/no_directory/CMakeLists.txt
new file mode 100644
index 0000000000..a8fd227402
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/no_directory/CMakeLists.txt
@@ -0,0 +1,2 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/no_directory/keepme b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/no_directory/keepme
new file mode 100644
index 0000000000..31eade7217
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/no_directory/keepme
@@ -0,0 +1 @@
+Make CVS checkout this directory even with -p option. \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/no_file b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/no_file
new file mode 100644
index 0000000000..3d631e8103
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/no_file
@@ -0,0 +1 @@
+No attribs file \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/normal_test_directory/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/normal_test_directory/CMakeLists.txt
new file mode 100644
index 0000000000..a8fd227402
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/normal_test_directory/CMakeLists.txt
@@ -0,0 +1,2 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/normal_test_directory/keepme b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/normal_test_directory/keepme
new file mode 100644
index 0000000000..31eade7217
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/normal_test_directory/keepme
@@ -0,0 +1 @@
+Make CVS checkout this directory even with -p option. \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/normal_test_file b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/normal_test_file
new file mode 100644
index 0000000000..a6e1e627a8
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/normal_test_file
@@ -0,0 +1,6 @@
+file_io
+CopyFileW
+Positive Test for CopyFileW
+test the CopyFileW function
+DEFAULT
+CopyFileW \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/ro_test_directory/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/ro_test_directory/CMakeLists.txt
new file mode 100644
index 0000000000..a8fd227402
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/ro_test_directory/CMakeLists.txt
@@ -0,0 +1,2 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/ro_test_directory/keepme b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/ro_test_directory/keepme
new file mode 100644
index 0000000000..31eade7217
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/ro_test_directory/keepme
@@ -0,0 +1 @@
+Make CVS checkout this directory even with -p option. \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/ro_test_file b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/ro_test_file
new file mode 100644
index 0000000000..a6e1e627a8
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/ro_test_file
@@ -0,0 +1,6 @@
+file_io
+CopyFileW
+Positive Test for CopyFileW
+test the CopyFileW function
+DEFAULT
+CopyFileW \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/rw_file b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/rw_file
new file mode 100644
index 0000000000..39d66f0365
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/rw_file
@@ -0,0 +1 @@
+Read Write file \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/rw_test_directory/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/rw_test_directory/CMakeLists.txt
new file mode 100644
index 0000000000..a8fd227402
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/rw_test_directory/CMakeLists.txt
@@ -0,0 +1,2 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/rw_test_directory/keepme b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/rw_test_directory/keepme
new file mode 100644
index 0000000000..31eade7217
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/rw_test_directory/keepme
@@ -0,0 +1 @@
+Make CVS checkout this directory even with -p option. \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/testinfo.dat
new file mode 100644
index 0000000000..1a8089a0f1
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/testinfo.dat
@@ -0,0 +1,20 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+
+Section = file_io
+
+Function = GetFileAttributesW
+
+Name = Positive Test for GetFileAttributesW
+
+TYPE = DEFAULT
+
+EXE1 = getfileattributesw
+
+Description
+
+= Test the GetFileAttributesW function
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileSize/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileSize/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileSize/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileSize/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileSize/test1/CMakeLists.txt
new file mode 100644
index 0000000000..ff20de5905
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileSize/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetFileSize.c
+)
+
+add_executable(paltest_getfilesize_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getfilesize_test1 coreclrpal)
+
+target_link_libraries(paltest_getfilesize_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetFileSize/test1/GetFileSize.c b/src/pal/tests/palsuite/file_io/GetFileSize/test1/GetFileSize.c
new file mode 100644
index 0000000000..fac01c98c9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileSize/test1/GetFileSize.c
@@ -0,0 +1,173 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: GetFileSize.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the GetFileSize function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+const char* szTextFile = "text.txt";
+
+void CleanUp(HANDLE hFile)
+{
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Fail("GetFileSize: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Fail("GetFileSize: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+}
+
+void CheckFileSize(HANDLE hFile, DWORD dwOffset, DWORD dwHighOrder)
+{
+ DWORD dwRc = 0;
+ DWORD dwReturnedHighOrder = 0;
+ DWORD dwReturnedOffset = 0;
+
+ dwRc = SetFilePointer(hFile, dwOffset, (PLONG)&dwHighOrder, FILE_BEGIN);
+ if (dwRc == INVALID_SET_FILE_POINTER)
+ {
+ Trace("GetFileSize: ERROR -> Call to SetFilePointer failed with %ld.\n",
+ GetLastError());
+ CleanUp(hFile);
+ Fail("");
+ }
+ else
+ {
+ if (!SetEndOfFile(hFile))
+ {
+ Trace("GetFileSize: ERROR -> Call to SetEndOfFile failed with %ld.\n",
+ GetLastError());
+ CleanUp(hFile);
+ Fail("");
+ }
+ dwReturnedOffset = GetFileSize(hFile, &dwReturnedHighOrder);
+ if ((dwReturnedOffset != dwOffset) ||
+ (dwReturnedHighOrder != dwHighOrder))
+ {
+ CleanUp(hFile);
+ Fail("GetFileSize: ERROR -> File sizes do not match up.\n");
+ }
+ }
+}
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE hFile = NULL;
+ DWORD dwRc = 0;
+ DWORD dwRc2 = 0;
+ DWORD dwHighOrder = 0;
+ DWORD lpNumberOfBytesWritten;
+ char * data = "1234567890";
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+
+ /* test on a null file handle */
+ dwRc = GetFileSize(hFile, NULL);
+ if (dwRc != INVALID_FILE_SIZE)
+ {
+ Fail("GetFileSize: ERROR -> A file size was returned for "
+ "a null handle.\n");
+ }
+
+ /* test on a null file handle using the high order option */
+ dwRc = GetFileSize(hFile, &dwHighOrder);
+ if (dwRc != INVALID_FILE_SIZE)
+ {
+ Fail("GetFileSize: ERROR -> A file size was returned for "
+ "a null handle.\n");
+ }
+
+ /* test on an invalid file handle */
+ dwRc = GetFileSize(INVALID_HANDLE_VALUE, NULL);
+ if (dwRc != INVALID_FILE_SIZE)
+ {
+ Fail("GetFileSize: ERROR -> A file size was returned for "
+ "an invalid handle.\n");
+ }
+
+ /* test on an invalid file handle using the high order option */
+ dwRc = GetFileSize(INVALID_HANDLE_VALUE, &dwHighOrder);
+ if (dwRc != INVALID_FILE_SIZE)
+ {
+ Fail("GetFileSize: ERROR -> A file size was returned for "
+ "an invalid handle.\n");
+ }
+
+
+ /* create a test file */
+ hFile = CreateFile(szTextFile,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("GetFileSize: ERROR -> Unable to create file \"%s\".\n",
+ szTextFile);
+ }
+
+ /* give the file a size */
+ CheckFileSize(hFile, 256, 0);
+
+ /* make the file large using the high order option */
+ CheckFileSize(hFile, 256, 1);
+
+
+ /* set the file size to zero */
+ CheckFileSize(hFile, 0, 0);
+
+ /* test if file size changes by writing to it. */
+ /* get file size */
+ dwRc = GetFileSize(hFile, NULL);
+
+ /* test writing to the file */
+ if(WriteFile(hFile, data, strlen(data), &lpNumberOfBytesWritten, NULL)==0)
+ {
+ Trace("GetFileSize: ERROR -> Call to WriteFile failed with %ld.\n",
+ GetLastError());
+ CleanUp(hFile);
+ Fail("");
+ }
+
+ /* make sure the buffer flushed.*/
+ if(FlushFileBuffers(hFile)==0)
+ {
+ Trace("GetFileSize: ERROR -> Call to FlushFileBuffers failed with %ld.\n",
+ GetLastError());
+ CleanUp(hFile);
+ Fail("");
+ }
+
+ /* get file size after writing some chars */
+ dwRc2 = GetFileSize(hFile, NULL);
+ if((dwRc2-dwRc) !=strlen(data))
+ {
+ CleanUp(hFile);
+ Fail("GetFileSize: ERROR -> File size did not increase properly after.\n"
+ "writing %d chars\n", strlen(data));
+ }
+
+ CleanUp(hFile);
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/GetFileSize/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/GetFileSize/test1/testinfo.dat
new file mode 100644
index 0000000000..38258572db
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileSize/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetFileSize
+Name = Positive Test for GetFileSize (test 1)
+Type = DEFAULT
+EXE1 = getfilesize
+Description
+= Test GetFileSize on a NULL handle and valid file handles
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileSizeEx/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileSizeEx/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileSizeEx/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/CMakeLists.txt
new file mode 100644
index 0000000000..1369a5dc5a
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetFileSizeEx.c
+)
+
+add_executable(paltest_getfilesizeex_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getfilesizeex_test1 coreclrpal)
+
+target_link_libraries(paltest_getfilesizeex_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/GetFileSizeEx.c b/src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/GetFileSizeEx.c
new file mode 100644
index 0000000000..ef5afd0e6b
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/GetFileSizeEx.c
@@ -0,0 +1,173 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: GetFileSizeEx.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the GetFileSizeEx function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+const char* szTextFile = "text.txt";
+
+void CleanUp(HANDLE hFile)
+{
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Fail("GetFileSizeEx: ERROR -> Unable to close file \"%s\".\n"
+ " Error is %d\n",
+ szTextFile, GetLastError());
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Fail("GetFileSizeEx: ERROR -> Unable to delete file \"%s\".\n"
+ " Error is %d\n",
+ szTextFile, GetLastError());
+ }
+}
+
+void CheckFileSize(HANDLE hFile, DWORD dwOffset, DWORD dwHighOrder)
+{
+ DWORD dwRc = 0;
+ DWORD dwError = 0;
+ LARGE_INTEGER qwFileSize;
+
+ dwRc = SetFilePointer(hFile, dwOffset, (PLONG)&dwHighOrder, FILE_BEGIN);
+ if (dwRc == INVALID_SET_FILE_POINTER)
+ {
+ Trace("GetFileSizeEx: ERROR -> Call to SetFilePointer failed with %ld.\n",
+ GetLastError());
+ CleanUp(hFile);
+ Fail("");
+ }
+ else
+ {
+ if (!SetEndOfFile(hFile))
+ {
+ dwError = GetLastError();
+ CleanUp(hFile);
+ if (dwError == 112)
+ {
+ Fail("GetFileSizeEx: ERROR -> SetEndOfFile failed due to lack of "
+ "disk space\n");
+ }
+ else
+ {
+ Fail("GetFileSizeEx: ERROR -> SetEndOfFile call failed "
+ "with error %ld\n", dwError);
+ }
+ }
+ else
+ {
+ GetFileSizeEx(hFile, &qwFileSize);
+ if ((qwFileSize.u.LowPart != dwOffset) ||
+ (qwFileSize.u.HighPart != dwHighOrder))
+ {
+ CleanUp(hFile);
+ Fail("GetFileSizeEx: ERROR -> File sizes do not match up.\n");
+ }
+ }
+ }
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE hFile = NULL;
+ BOOL bRc = FALSE;
+ DWORD lpNumberOfBytesWritten;
+ LARGE_INTEGER qwFileSize;
+ LARGE_INTEGER qwFileSize2;
+ char * data = "1234567890";
+
+ qwFileSize.QuadPart = 0;
+ qwFileSize2.QuadPart = 0;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+
+ /* test on a null file */
+ bRc = GetFileSizeEx(NULL, &qwFileSize);
+ if (bRc != FALSE)
+ {
+ Fail("GetFileSizeEx: ERROR -> Returned status as TRUE for "
+ "a null handle.\n");
+ }
+
+
+ /* test on an invalid file */
+ bRc = GetFileSizeEx(INVALID_HANDLE_VALUE, &qwFileSize);
+ if (bRc != FALSE)
+ {
+ Fail("GetFileSizeEx: ERROR -> Returned status as TRUE for "
+ "an invalid handle.\n");
+ }
+
+
+ /* create a test file */
+ hFile = CreateFile(szTextFile,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("GetFileSizeEx: ERROR -> Unable to create file \"%s\".\n",
+ szTextFile);
+ }
+
+ /* give the file a size */
+ CheckFileSize(hFile, 256, 0);
+
+ /* make the file large using the high order option */
+ CheckFileSize(hFile, 256, 1);
+
+
+ /* set the file size to zero */
+ CheckFileSize(hFile, 0, 0);
+
+ /* test if file size changes by writing to it. */
+ /* get file size */
+ GetFileSizeEx(hFile, &qwFileSize);
+
+ /* test writing to the file */
+ if(WriteFile(hFile, data, strlen(data), &lpNumberOfBytesWritten, NULL)==0)
+ {
+ Trace("GetFileSizeEx: ERROR -> Call to WriteFile failed with %ld.\n",
+ GetLastError());
+ CleanUp(hFile);
+ Fail("");
+ }
+
+ /* make sure the buffer flushed.*/
+ if(FlushFileBuffers(hFile)==0)
+ {
+ Trace("GetFileSizeEx: ERROR -> Call to FlushFileBuffers failed with %ld.\n",
+ GetLastError());
+ CleanUp(hFile);
+ Fail("");
+ }
+
+ /* get file size after writing some chars */
+ GetFileSizeEx(hFile, &qwFileSize2);
+ if((qwFileSize2.QuadPart-qwFileSize.QuadPart) !=strlen(data))
+ {
+ CleanUp(hFile);
+ Fail("GetFileSizeEx: ERROR -> File size did not increase properly after.\n"
+ "writing %d chars\n", strlen(data));
+ }
+
+ CleanUp(hFile);
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/testinfo.dat
new file mode 100644
index 0000000000..5968fe7271
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetFileSizeEx
+Name = Positive Test for GetFileSizeEx (test 1)
+Type = DEFAULT
+EXE1 = getfilesizeex
+Description
+= Test GetFileSizeEx on a NULL handle and valid file handles
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileTime/CMakeLists.txt
new file mode 100644
index 0000000000..19ee487a6a
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileTime/CMakeLists.txt
@@ -0,0 +1,10 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+add_subdirectory(test7)
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileTime/test1/CMakeLists.txt
new file mode 100644
index 0000000000..6a89846d21
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileTime/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetFileTime.c
+)
+
+add_executable(paltest_getfiletime_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getfiletime_test1 coreclrpal)
+
+target_link_libraries(paltest_getfiletime_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test1/GetFileTime.c b/src/pal/tests/palsuite/file_io/GetFileTime/test1/GetFileTime.c
new file mode 100644
index 0000000000..fb7bcb8513
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileTime/test1/GetFileTime.c
@@ -0,0 +1,180 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: GetFileTime.c
+**
+** Purpose: Tests the PAL implementation of the GetFileTime function.
+** This test checks the time of a file, writes to it, then checks the
+** time again to ensure that write time has increased. It
+** also checks that creation time is the same under WIN32 and has
+** increased under FreeBSD.
+**
+** Depends:
+** CreateFile
+** WriteFile
+** CloseHandle
+**
+**
+**===================================================================*/
+
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char **argv)
+{
+
+ FILETIME Creation,LastAccess,LastWrite;
+ HANDLE TheFileHandle;
+ ULONG64 FirstWrite, SecondWrite, FirstCreationTime, SecondCreationTime;
+ DWORD temp;
+ BOOL result;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* Open the file to get a HANDLE */
+ TheFileHandle =
+ CreateFile(
+ "the_file", // File Name
+ GENERIC_READ|GENERIC_WRITE, // Access Mode
+ 0, // Share Mode
+ NULL, // SD
+ OPEN_ALWAYS, // Howto Create
+ FILE_ATTRIBUTE_NORMAL, // File Attributes
+ NULL // Template file
+ );
+
+ if(TheFileHandle == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Failed to open the file. The error number "
+ "returned was %d.",GetLastError());
+ }
+
+
+ /* Get the Last Write, Creation and Access File time of that File */
+ if(!GetFileTime(TheFileHandle,&Creation,&LastAccess,&LastWrite))
+ {
+ Fail("ERROR: GetFileTime returned 0, indicating failure.");
+ }
+
+ /* Convert the structure to an ULONG64 */
+
+ FirstCreationTime = ((((ULONG64)Creation.dwHighDateTime)<<32) |
+ ((ULONG64)Creation.dwLowDateTime));
+
+ FirstWrite = ((((ULONG64)LastWrite.dwHighDateTime)<<32) |
+ ((ULONG64)LastWrite.dwLowDateTime));
+
+ /* Sleep for 3 seconds, this will ensure the time changes */
+ Sleep(3000);
+
+ /* Write to the file -- this should change write access and
+ last access
+ */
+
+ result = WriteFile(TheFileHandle, // File handle
+ "something", // String to write
+ 9, // Bytes to write
+ &temp, // Bytes written
+ NULL);
+
+ if(result == 0)
+ {
+ Fail("ERROR: Failed to write to file. The file must be "
+ "written to in order to test that the write time is "
+ "updated.");
+ }
+
+ /* Close the File, so the changes are recorded */
+ result = CloseHandle(TheFileHandle);
+
+ if(result == 0)
+ {
+ Fail("ERROR: Failed to close the file handle.");
+ }
+
+
+ /* Reopen the file */
+ TheFileHandle =
+ CreateFile(
+ "the_file", /* file name */
+ GENERIC_READ|GENERIC_WRITE, /* access mode */
+ 0, /* share mode */
+ NULL, /* SD */
+ OPEN_ALWAYS, /* how to create */
+ FILE_ATTRIBUTE_NORMAL, /* file attributes */
+ NULL /* handle to template file */
+ );
+
+
+ if(TheFileHandle == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Failed to re-open the file. The error number "
+ "returned was %d.",GetLastError());
+ }
+
+
+
+ /* Call GetFileTime again */
+ if(!GetFileTime(TheFileHandle,&Creation,&LastAccess,&LastWrite))
+ {
+ Fail("ERROR: GetFileTime returned 0, indicating failure.");
+ }
+
+ /* Store the results in a ULONG64 */
+
+ SecondCreationTime = ( (((ULONG64)Creation.dwHighDateTime)<<32) |
+ ((ULONG64)Creation.dwLowDateTime));
+
+ SecondWrite = ( (((ULONG64)LastWrite.dwHighDateTime)<<32) |
+ ((ULONG64)LastWrite.dwLowDateTime));
+
+
+ /* Now -- to test. We'll ensure that the Second
+ LastWrite time is larger than the first. It tells us that
+ time is passing, which is good!
+ */
+
+ if(FirstWrite >= SecondWrite)
+ {
+ Fail("ERROR: The last-write-file-time after writing did not "
+ "increase from the original. The second value should be "
+ "larger.");
+ }
+
+#if WIN32
+ /* Then we can check to make sure that the creation time
+ hasn't changed. This should always stay the same.
+ */
+
+ if(FirstCreationTime != SecondCreationTime)
+ {
+ Fail("ERROR: The creation time after writing should not "
+ "not change from the original. The second value should be "
+ "equal.");
+ }
+#else
+ /* Then we can check to make sure that the creation time
+ has changed. Under FreeBSD it changes whenever the file is
+ access or written.
+ */
+
+ if(FirstCreationTime >= SecondCreationTime)
+ {
+ Fail("ERROR: The creation time after writing should be "
+ "greater than the original. The second value should be "
+ "larger.");
+ }
+
+#endif
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/GetFileTime/test1/testinfo.dat
new file mode 100644
index 0000000000..50cd35214d
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileTime/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetFileTime
+Name = Positive Test for GetFileTime
+TYPE = DEFAULT
+EXE1 = getfiletime
+Description
+= Test the GetFileTime function. Open a file and get the time. Then write
+= to that file. This will change the write and under FreeBSD
+= the creation time. Ensure that all of these are increasing.
diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileTime/test2/CMakeLists.txt
new file mode 100644
index 0000000000..3d315e44de
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileTime/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetFileTime.c
+)
+
+add_executable(paltest_getfiletime_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getfiletime_test2 coreclrpal)
+
+target_link_libraries(paltest_getfiletime_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test2/GetFileTime.c b/src/pal/tests/palsuite/file_io/GetFileTime/test2/GetFileTime.c
new file mode 100644
index 0000000000..5b14a1e357
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileTime/test2/GetFileTime.c
@@ -0,0 +1,195 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: GetFileTime.c
+**
+** Purpose: Tests the PAL implementation of the GetFileTime function
+** Test to see that access date either stays the same or increases
+** when a read is performed. Write
+** and creation time should stay unchanged. Note: Under FreeBSD
+** the Creation time should not change with just a read.
+**
+** Depends:
+** FileTimeToDosDateTime
+** CreateFile
+** ReadFile
+** CloseHandle
+**
+**
+**===================================================================*/
+
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char **argv)
+{
+
+ FILETIME Creation,LastAccess,LastWrite;
+ HANDLE TheFileHandle;
+ ULONG64 FirstWrite, SecondWrite,
+ FirstCreationTime, SecondCreationTime;
+ DWORD temp;
+ char ReadBuffer[10];
+ BOOL result;
+ WORD DosDateOne, DosDateTwo, DosTime;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* Open the file to get a HANDLE */
+ TheFileHandle =
+ CreateFile(
+ "the_file",
+ GENERIC_READ,
+ 0,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+
+ if(TheFileHandle == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Failed to open the file. The error number "
+ "returned was %d.",GetLastError());
+ }
+
+
+ /* Get the Last Write, Creation and Access File time of that File */
+ if(GetFileTime(TheFileHandle,&Creation,&LastAccess,&LastWrite)==0)
+ {
+ Fail("ERROR: GetFileTime returned 0, indicating failure.");
+ }
+
+ /* Call FileTimeToDosDateTime so we can aquire just the date
+ portion of the Last Access FILETIME.
+ */
+ if(FileTimeToDosDateTime(&LastAccess, &DosDateOne, &DosTime) == 0)
+ {
+ Fail("ERROR: FiletimeToDosDateTime failed, returning 0. "
+ "GetLastError returned %d.\n",GetLastError());
+ }
+
+ /* Convert the structure to an ULONG64 */
+
+ FirstCreationTime = ( (((ULONG64)Creation.dwHighDateTime)<<32) |
+ ((ULONG64)Creation.dwLowDateTime));
+
+ FirstWrite = ( (((ULONG64)LastWrite.dwHighDateTime)<<32) |
+ ((ULONG64)LastWrite.dwLowDateTime));
+
+ /* Sleep for 3 seconds, this will ensure the time changes */
+ Sleep(3000);
+
+ /* Read from the file -- this should change
+ last access, but we'll only check the date portion, because some file
+ systems have a resolution of a day.
+ */
+
+ result = ReadFile(TheFileHandle, // handle to file
+ &ReadBuffer, // data buffer
+ 2, // number of bytes to read
+ &temp, // number of bytes read
+ NULL);
+
+ if(result == 0)
+ {
+ Fail("ERROR: Failed to read from the file.");
+ }
+
+
+ /* Close the File, so the changes are recorded */
+ result = CloseHandle(TheFileHandle);
+
+ if(result == 0)
+ {
+ Fail("ERROR: Failed to close the file handle.");
+ }
+
+
+ /* Reopen the file */
+ TheFileHandle =
+ CreateFile("the_file", /* file name */
+ GENERIC_READ, /* access mode */
+ 0, /* share mode */
+ NULL, /* SD */
+ OPEN_ALWAYS, /* how to create */
+ FILE_ATTRIBUTE_NORMAL, /* file attributes */
+ NULL /* handle to template file */
+ );
+
+ if(TheFileHandle == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Failed to re-open the file. The error number "
+ "returned was %d.",GetLastError());
+ }
+
+ /* Call GetFileTime again */
+ if(GetFileTime(TheFileHandle,&Creation,&LastAccess,&LastWrite) == 0)
+ {
+ Fail("ERROR: GetFileTime returned 0, indicating failure.");
+ }
+
+ /* Get the Date of the LastAccessTime here again. */
+ if(FileTimeToDosDateTime(&LastAccess, &DosDateTwo, &DosTime) == 0)
+ {
+ Fail("ERROR: FileTimeToDosDateTime failed, returning 0. "
+ "GetLastError returned %d.\n",GetLastError());
+ }
+
+
+ /* Store the results in a ULONG64 */
+
+ SecondCreationTime = ( (((ULONG64)Creation.dwHighDateTime)<<32) |
+ ((ULONG64)Creation.dwLowDateTime));
+
+ SecondWrite = ( (((ULONG64)LastWrite.dwHighDateTime)<<32) |
+ ((ULONG64)LastWrite.dwLowDateTime));
+
+ /* Now -- to test. We'll ensure that the Second
+ LastWrite time is the same as the first. This shouldn't
+ have changed.
+ */
+
+ if(FirstWrite != SecondWrite)
+ {
+ Fail("ERROR: The last-write-file-time after reading "
+ "increased from the original. The second value should be "
+ "equal.");
+ }
+
+
+ /*
+ For LastAccessTime, just check that the date is greater or equal
+ for the second over the first. The time is not conisered on some
+ file systems. (such as fat32)
+ */
+
+ if(DosDateOne > DosDateTwo)
+ {
+ Fail("ERROR: The last-access-time after reading should have "
+ "stayed the same or increased, but it did not.\n");
+ }
+
+
+ /* Check to ensure CreationTime hasn't changed. This should not
+ have changed in either environment.
+ */
+
+ if(FirstCreationTime != SecondCreationTime)
+ {
+ Fail("ERROR: The creation time after reading should not "
+ "not change from the original. The second value should be "
+ "equal.");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test2/testinfo.dat b/src/pal/tests/palsuite/file_io/GetFileTime/test2/testinfo.dat
new file mode 100644
index 0000000000..a60dcf45a4
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileTime/test2/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetFileTime
+Name = Positive Test for GetFileTime
+TYPE = DEFAULT
+EXE1 = getfiletime
+Description
+= Tests the PAL implementation of the GetFileTime function
+= Test to see that access date either stays the same or increases
+= when a read is performed. Write
+= and creation time should stay unchanged. Note: Under FreeBSD
+= the Creation time should not change with just a read.
diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileTime/test3/CMakeLists.txt
new file mode 100644
index 0000000000..34f7310464
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileTime/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetFileTime.c
+)
+
+add_executable(paltest_getfiletime_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getfiletime_test3 coreclrpal)
+
+target_link_libraries(paltest_getfiletime_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test3/GetFileTime.c b/src/pal/tests/palsuite/file_io/GetFileTime/test3/GetFileTime.c
new file mode 100644
index 0000000000..a3f46c2bf8
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileTime/test3/GetFileTime.c
@@ -0,0 +1,142 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: GetFileTime.c
+**
+** Purpose: Tests the PAL implementation of the GetFileTime function
+** Test to see that creation time is changed when two different files
+** are created.
+**
+** Depends:
+** CreateFile
+** ReadFile
+** CloseHandle
+**
+**
+**===================================================================*/
+
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char **argv)
+{
+
+ FILETIME Creation;
+ HANDLE TheFileHandle, SecondFileHandle;
+ ULONG64 FirstCreationTime, SecondCreationTime;
+ BOOL result;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* Open the file to get a HANDLE */
+ TheFileHandle =
+ CreateFile(
+ "the_file",
+ GENERIC_READ,
+ 0,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+
+ if(TheFileHandle == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Failed to open the file. The error number "
+ "returned was %d.",GetLastError());
+ }
+
+
+ /* Get the Creation time of the File */
+ if(GetFileTime(TheFileHandle,&Creation,NULL,NULL)==0)
+ {
+ Fail("ERROR: GetFileTime returned 0, indicating failure. "
+ "Two of the params were NULL in this case, did they "
+ "cause the probleM?");
+ }
+
+ /* Convert the structure to an ULONG64 */
+
+ FirstCreationTime = ( (((ULONG64)Creation.dwHighDateTime)<<32) |
+ ((ULONG64)Creation.dwLowDateTime));
+
+
+ /* Close the File, so the changes are recorded */
+ result = CloseHandle(TheFileHandle);
+
+ if(result == 0)
+ {
+ Fail("ERROR: Failed to close the file handle.");
+ }
+
+
+ /* Sleep for 3 seconds, this will ensure the time changes */
+ Sleep(3000);
+
+
+
+ /* Open another file */
+ SecondFileHandle =
+ CreateFile("the_other_file", /* file name */
+ GENERIC_READ, /* access mode */
+ 0, /* share mode */
+ NULL, /* SD */
+ CREATE_ALWAYS, /* how to create */
+ FILE_ATTRIBUTE_NORMAL, /* file attributes */
+ NULL /* handle to template file */
+ );
+
+ if(SecondFileHandle == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Failed to open the second file. The error number "
+ "returned was %d.",GetLastError());
+ }
+
+
+ /* Call GetFileTime again */
+ if(GetFileTime(SecondFileHandle,&Creation,NULL,NULL) == 0)
+ {
+ Fail("ERROR: GetFileTime returned 0, indicating failure. "
+ "Perhaps the NULLs in the function broke it?");
+ }
+
+ /* Close the File*/
+ result = CloseHandle(SecondFileHandle);
+
+ if(result == 0)
+ {
+ Fail("ERROR: Failed to close the file handle.");
+ }
+
+
+ /* Store the results in a ULONG64 */
+
+ SecondCreationTime = ( (((ULONG64)Creation.dwHighDateTime)<<32) |
+ ((ULONG64)Creation.dwLowDateTime));
+
+
+
+ /* Now -- to test. We ensure that the FirstCreationTime is
+ less than the SecondCreationTime
+ */
+
+
+ if(FirstCreationTime >= SecondCreationTime)
+ {
+ Fail("ERROR: The creation time of the two files should be "
+ "different. The first file should have a creation "
+ "time less than the second.");
+ }
+
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test3/testinfo.dat b/src/pal/tests/palsuite/file_io/GetFileTime/test3/testinfo.dat
new file mode 100644
index 0000000000..6d1eba739d
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileTime/test3/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetFileTime
+Name = Positive Test for GetFileTime
+TYPE = DEFAULT
+EXE1 = getfiletime
+Description
+= Test the GetFileTime function. This test creates two files and compares
+= their creation times. They should be different. It also tries to get the
+= file time of an invalid handle, which should cause the function to tail.
diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test4/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileTime/test4/CMakeLists.txt
new file mode 100644
index 0000000000..0c9dcf7802
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileTime/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetFileTime.c
+)
+
+add_executable(paltest_getfiletime_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getfiletime_test4 coreclrpal)
+
+target_link_libraries(paltest_getfiletime_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test4/GetFileTime.c b/src/pal/tests/palsuite/file_io/GetFileTime/test4/GetFileTime.c
new file mode 100644
index 0000000000..ffba516e35
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileTime/test4/GetFileTime.c
@@ -0,0 +1,98 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: GetFileTime.c
+**
+** Purpose: Tests the PAL implementation of the GetFileTime function
+** Test to see that passing NULL values to GetFileTime works and that
+** calling the function on a bad HANDLE causes the correct failure.
+**
+** Depends:
+** CreateFile
+** CloseHandle
+**
+**
+**===================================================================*/
+
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char **argv)
+{
+
+ FILETIME Creation,LastWrite,LastAccess;
+ HANDLE TheFileHandle;
+ BOOL result;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* Open the file to get a HANDLE */
+ TheFileHandle =
+ CreateFile(
+ "the_file",
+ GENERIC_READ,
+ 0,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+
+ if(TheFileHandle == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Failed to open the file. The error number "
+ "returned was %d.",GetLastError());
+ }
+
+ /* Pass all NULLs, this is useless but should still work. */
+ if(GetFileTime(TheFileHandle,NULL,NULL,NULL)==0)
+ {
+ Fail("ERROR: GetFileTime returned 0, indicating failure. "
+ "Three of the params were NULL in this case, did they "
+ "cause the problem?");
+ }
+
+
+ /* Get the Creation time of the File */
+ if(GetFileTime(TheFileHandle,&Creation,NULL,NULL)==0)
+ {
+ Fail("ERROR: GetFileTime returned 0, indicating failure. "
+ "Two of the params were NULL in this case, did they "
+ "cause the probleM?");
+ }
+
+ /* Get the Creation, LastWrite time of the File */
+ if(GetFileTime(TheFileHandle,&Creation,&LastWrite,NULL)==0)
+ {
+ Fail("ERROR: GetFileTime returned 0, indicating failure. "
+ "One of the params were NULL in this case, did it "
+ "cause the problem?");
+ }
+
+
+ /* Close the File, so the changes are recorded */
+ result = CloseHandle(TheFileHandle);
+
+ if(result == 0)
+ {
+ Fail("ERROR: Failed to close the file handle.");
+ }
+
+ /* Call GetFileTime again */
+ if(GetFileTime(TheFileHandle,&Creation,&LastWrite,&LastAccess) != 0)
+ {
+ Fail("ERROR: GetFileTime returned non zero, indicating success. "
+ "It was passed an invalid file HANDLE and should have "
+ "failed.");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test4/testinfo.dat b/src/pal/tests/palsuite/file_io/GetFileTime/test4/testinfo.dat
new file mode 100644
index 0000000000..af90558cae
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileTime/test4/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetFileTime
+Name = Positive Test for GetFileTime
+TYPE = DEFAULT
+EXE1 = getfiletime
+Description
+= Test the GetFileTime function. This test gets the file time of a given
+= file while passing all the combonations of NULL as parameters. The
+= function should handle these as unneeded times, and still succeed.
diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test5/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileTime/test5/CMakeLists.txt
new file mode 100644
index 0000000000..a82717e657
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileTime/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ getfiletime.c
+)
+
+add_executable(paltest_getfiletime_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getfiletime_test5 coreclrpal)
+
+target_link_libraries(paltest_getfiletime_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test5/getfiletime.c b/src/pal/tests/palsuite/file_io/GetFileTime/test5/getfiletime.c
new file mode 100644
index 0000000000..d8196d84bc
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileTime/test5/getfiletime.c
@@ -0,0 +1,224 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: GetFileTime.c
+**
+** Purpose: Test the PAL implementation of GetFileTime. This test
+** creates a file and compares create and write times between
+** writes, but before the close, and verifies the results are
+** as expected
+**
+** Depends:
+** CreateFile
+** WriteFile
+** CloseHandle
+**
+**
+**===================================================================*/
+
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char **argv)
+{
+ FILETIME Creation;
+ FILETIME LastAccess;
+ FILETIME LastWrite;
+ HANDLE hFile;
+ ULONG64 FirstWrite;
+ ULONG64 SecondWrite;
+ ULONG64 FirstCreationTime;
+ ULONG64 SecondCreationTime;
+ DWORD temp;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* Open the file to get a HANDLE */
+ hFile = CreateFile("test.tmp",
+ GENERIC_READ|GENERIC_WRITE,
+ 0,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Failed to create the file. The error number "
+ "returned was %u.\n",
+ GetLastError());
+ }
+
+ /* Write to the file -- this should change write access and
+ last access
+ */
+ if(!WriteFile(hFile, "something", 9, &temp, NULL))
+ {
+ Trace("ERROR: Failed to write to file. The file must be "
+ "written to in order to test that the write time is "
+ "updated. GetLastError returned %u.\n",
+ GetLastError());
+ /* Close the File */
+ if(!CloseHandle(hFile))
+ {
+ Trace("ERROR: Failed to close the file handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ FlushFileBuffers(hFile);
+
+ /* Get the Last Write, Creation and Access File time of that File */
+ if(!GetFileTime(hFile, &Creation, &LastAccess, &LastWrite))
+ {
+ Trace("ERROR: GetFileTime returned 0, indicating failure."
+ " GetLastError returned %u\n",
+ GetLastError());
+ /* Close the File */
+ if(!CloseHandle(hFile))
+ {
+ Trace("ERROR: Failed to close the file handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ /* Convert the structure to an ULONG64 */
+
+ FirstCreationTime = ((((ULONG64)Creation.dwHighDateTime)<<32) |
+ ((ULONG64)Creation.dwLowDateTime));
+
+ FirstWrite = ((((ULONG64)LastWrite.dwHighDateTime)<<32) |
+ ((ULONG64)LastWrite.dwLowDateTime));
+
+ /* Sleep for 3 seconds, this will ensure the time changes */
+ Sleep(3000);
+
+ /* Write to the file again -- this should change write access and
+ last access
+ */
+ if(!WriteFile(hFile, "something", 9, &temp, NULL))
+ {
+ Trace("ERROR: Failed to write to file. The file must be "
+ "written to in order to test that the write time is "
+ "updated. GetLastError returned %u.\n",
+ GetLastError());
+ /* Close the File */
+ if(!CloseHandle(hFile))
+ {
+ Trace("ERROR: Failed to close the file handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+
+ FlushFileBuffers(hFile);
+
+ /* Call GetFileTime again */
+ if(!GetFileTime(hFile,&Creation,&LastAccess,&LastWrite))
+ {
+ Trace("ERROR: GetFileTime returned 0, indicating failure."
+ "GetLastError returned %u.\n",
+ GetLastError());
+ /* Close the File */
+ if(!CloseHandle(hFile))
+ {
+ Trace("ERROR: Failed to close the file handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ /* Store the results in a ULONG64 */
+
+ SecondCreationTime = ( (((ULONG64)Creation.dwHighDateTime)<<32) |
+ ((ULONG64)Creation.dwLowDateTime));
+
+ SecondWrite = ( (((ULONG64)LastWrite.dwHighDateTime)<<32) |
+ ((ULONG64)LastWrite.dwLowDateTime));
+
+
+ /* Now -- to test. We'll ensure that the Second
+ LastWrite time is larger than the first. It tells us that
+ time is passing, which is good!
+ */
+
+ if(FirstWrite >= SecondWrite)
+ {
+ /* Close the File */
+ if(!CloseHandle(hFile))
+ {
+ Trace("ERROR: Failed to close the file handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("ERROR: The last-write-file-time after writing did not "
+ "increase from the original. The second value should be "
+ "larger.\n");
+ }
+
+#if WIN32
+ /* Then we can check to make sure that the creation time
+ hasn't changed. This should always stay the same.
+ */
+
+ if(FirstCreationTime != SecondCreationTime)
+ {
+ /* Close the File */
+ if(!CloseHandle(hFile))
+ {
+ Trace("ERROR: Failed to close the file handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("ERROR: The creation time after writing should not "
+ "not change from the original. The second value should be "
+ "equal.\n");
+ }
+#else
+ /* Then we can check to make sure that the creation time
+ has changed. Under FreeBSD it changes whenever the file is
+ access or written.
+ */
+
+ if(FirstCreationTime >= SecondCreationTime)
+ {
+ /* Close the File */
+ if(!CloseHandle(hFile))
+ {
+ Trace("ERROR: Failed to close the file handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("ERROR: The creation time after writing should be "
+ "greater than the original. The second value should be "
+ "larger.\n");
+ }
+
+#endif
+
+ /* Close the File */
+ if(!CloseHandle(hFile))
+ {
+ Fail("ERROR: Failed to close the file handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test5/testinfo.dat b/src/pal/tests/palsuite/file_io/GetFileTime/test5/testinfo.dat
new file mode 100644
index 0000000000..fd4112b1fa
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileTime/test5/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetFileTime
+Name = Positive Test for GetFileTime
+TYPE = DEFAULT
+EXE1 = getfiletime
+Description
+= Test the PAL implementation of GetFileTime. This test
+= creates a file and compares create and write times between
+= writes, but before the close, and verifies the results are
+= as expected
diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test6/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileTime/test6/CMakeLists.txt
new file mode 100644
index 0000000000..24992dfa66
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileTime/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ getfiletime.c
+)
+
+add_executable(paltest_getfiletime_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getfiletime_test6 coreclrpal)
+
+target_link_libraries(paltest_getfiletime_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test6/getfiletime.c b/src/pal/tests/palsuite/file_io/GetFileTime/test6/getfiletime.c
new file mode 100644
index 0000000000..3eedddf82d
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileTime/test6/getfiletime.c
@@ -0,0 +1,281 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: GetFileTime.c
+**
+** Purpose: Tests the PAL implementation of the GetFileTime function.
+** Perform two reads from a file without closing until the end
+** of the test and verify that only the access times change.
+** Note: Under Win32, modify time changes as well so we will
+** check that it doesn't go backwards
+**
+** Depends:
+** FileTimeToDosDateTime
+** CreateFile
+** ReadFile
+** WriteFile
+** CloseHandle
+**
+**
+**===================================================================*/
+
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char **argv)
+{
+
+ FILETIME Creation;
+ FILETIME LastAccess;
+ FILETIME LastWrite;
+ HANDLE hFile;
+ ULONG64 FirstWrite = (ULONG64)0;
+ ULONG64 SecondWrite = (ULONG64)0;
+ ULONG64 FirstCreationTime = (ULONG64)0;
+ ULONG64 SecondCreationTime = (ULONG64)0;
+ DWORD temp;
+ char ReadBuffer[10];
+ WORD DosDateOne;
+ WORD DosDateTwo;
+ WORD DosTime;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+ memset(&Creation, 0, sizeof(FILETIME));
+ memset(&LastAccess, 0, sizeof(FILETIME));
+ memset(&LastWrite, 0, sizeof(FILETIME));
+
+ /* Create the file to get a HANDLE */
+ hFile = CreateFile("test.tmp",
+ GENERIC_READ|GENERIC_WRITE,
+ 0,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Failed to create the file. The error number "
+ "returned was %u.\n",
+ GetLastError());
+ }
+
+ /* give us something to read from the file */
+ if(!WriteFile(hFile, "something", 9, &temp, NULL))
+ {
+ Trace("ERROR: Failed to write to file. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ /* Close the File */
+ if(!CloseHandle(hFile))
+ {
+ Trace("ERROR: Failed to close the file handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ /* let's do a read to set the file times for our test */
+ if(!ReadFile(hFile, &ReadBuffer, 2, &temp, NULL))
+ {
+ Trace("ERROR: Failed to read from the file. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ /* Close the File */
+ if(!CloseHandle(hFile))
+ {
+ Trace("ERROR: Failed to close the file handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ /* Get the Last Write, Creation and Access File time of the file */
+ if(GetFileTime(hFile, &Creation, &LastAccess, &LastWrite)==0)
+ {
+ Trace("ERROR: GetFileTime returned 0, indicating failure."
+ " GetLastError returned %u\n",
+ GetLastError());
+ /* Close the File */
+ if(!CloseHandle(hFile))
+ {
+ Trace("ERROR: Failed to close the file handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ /* Call FileTimeToDosDateTime so we can aquire just the date
+ portion of the Last Access FILETIME.
+ */
+ if(FileTimeToDosDateTime(&LastAccess, &DosDateOne, &DosTime) == 0)
+ {
+ Trace("ERROR: FiletimeToDosDateTime failed, returning 0. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ /* Close the File */
+ if(!CloseHandle(hFile))
+ {
+ Trace("ERROR: Failed to close the file handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ /* Convert the structure to an ULONG64 */
+ FirstCreationTime = ( (((ULONG64)Creation.dwHighDateTime)<<32) |
+ ((ULONG64)Creation.dwLowDateTime));
+
+ FirstWrite = ( (((ULONG64)LastWrite.dwHighDateTime)<<32) |
+ ((ULONG64)LastWrite.dwLowDateTime));
+
+ /* Sleep for 3 seconds, this will ensure the time changes */
+ Sleep(3000);
+
+ /* Read from the file -- this should change
+ last access, but we'll only check the date portion, because some file
+ systems have a resolution of a day.
+ */
+ memset(&Creation, 0, sizeof(FILETIME));
+ memset(&LastAccess, 0, sizeof(FILETIME));
+ memset(&LastWrite, 0, sizeof(FILETIME));
+
+ if(!ReadFile(hFile, &ReadBuffer, 2, &temp, NULL))
+ {
+ Trace("ERROR: Failed to read from the file. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ /* Close the File */
+ if(!CloseHandle(hFile))
+ {
+ Trace("ERROR: Failed to close the file handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+
+ /* Call GetFileTime to get the updated time values*/
+ if(GetFileTime(hFile, &Creation, &LastAccess, &LastWrite) == 0)
+ {
+ Trace("ERROR: GetFileTime returned 0, indicating failure. "
+ "GetLastError returned %d.\n",
+ GetLastError());
+ /* Close the File */
+ if(!CloseHandle(hFile))
+ {
+ Trace("ERROR: Failed to close the file handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ /* Get the Date of the LastAccessTime here again. */
+ if(FileTimeToDosDateTime(&LastAccess, &DosDateTwo, &DosTime) == 0)
+ {
+ Trace("ERROR: FileTimeToDosDateTime failed, returning 0. "
+ "GetLastError returned %d.\n",
+ GetLastError());
+ /* Close the File */
+ if(!CloseHandle(hFile))
+ {
+ Trace("ERROR: Failed to close the file handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+
+ /* Store the results in a ULONG64 */
+ SecondCreationTime = ( (((ULONG64)Creation.dwHighDateTime)<<32) |
+ ((ULONG64)Creation.dwLowDateTime));
+
+ SecondWrite = ( (((ULONG64)LastWrite.dwHighDateTime)<<32) |
+ ((ULONG64)LastWrite.dwLowDateTime));
+
+ /* Now -- to test. We'll ensure that the SecondWrite
+ time is not less than the FirstWrite time
+ */
+
+ if(SecondWrite < FirstWrite)
+ {
+ Trace("ERROR: The write-file-time (%I64d) after the first read "
+ "is less than the write-file-time (%I64d) after the second "
+ "read.\n",
+ FirstWrite,
+ LastWrite);
+ /* Close the File */
+ if(!CloseHandle(hFile))
+ {
+ Trace("ERROR: Failed to close the file handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ /*
+ For LastAccessTime, just check that the date is greater or equal
+ for the second over the first. The time is not conisered on some
+ file systems. (such as fat32)
+ */
+
+ if(DosDateOne > DosDateTwo)
+ {
+ Trace("ERROR: The last-access-time after reading should have "
+ "stayed the same or increased, but it did not.\n");
+ /* Close the File */
+ if(!CloseHandle(hFile))
+ {
+ Trace("ERROR: Failed to close the file handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+
+ /* Check to ensure CreationTime hasn't changed. This should not
+ have changed in either environment.
+ */
+
+ if(FirstCreationTime != SecondCreationTime)
+ {
+ Trace("ERROR: The creation time after reading should not "
+ "not change from the original. The second value should be "
+ "equal.\n");
+ /* Close the File */
+ if(!CloseHandle(hFile))
+ {
+ Trace("ERROR: Failed to close the file handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ /* Close the File, so the changes are recorded */
+ if(!CloseHandle(hFile))
+ {
+ Fail("ERROR: Failed to close the file handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test6/testinfo.dat b/src/pal/tests/palsuite/file_io/GetFileTime/test6/testinfo.dat
new file mode 100644
index 0000000000..844043689c
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileTime/test6/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetFileTime
+Name = Positive Test for GetFileTime
+TYPE = DEFAULT
+EXE1 = getfiletime
+Description
+= Tests the PAL implementation of the GetFileTime function.
+= Perform two reads from a file without closing until the end
+= of the test and verify that only the access times change.
diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test7/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileTime/test7/CMakeLists.txt
new file mode 100644
index 0000000000..6646fd9272
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileTime/test7/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ getfiletime.c
+)
+
+add_executable(paltest_getfiletime_test7
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getfiletime_test7 coreclrpal)
+
+target_link_libraries(paltest_getfiletime_test7
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test7/getfiletime.c b/src/pal/tests/palsuite/file_io/GetFileTime/test7/getfiletime.c
new file mode 100644
index 0000000000..d33175b8ec
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileTime/test7/getfiletime.c
@@ -0,0 +1,279 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: GetFileTime.c
+**
+** Purpose: Test the PAL implementation of GetFileTime. This test
+** creates a file and compares create and write times after
+** the buffers are flushed, but before the close, and verifies
+** the results are as expected
+**
+** Depends:
+** CreateFile
+** WriteFile
+** FlushFileBuffers
+** CloseHandle
+**
+**
+**===================================================================*/
+
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char **argv)
+{
+ FILETIME Creation;
+ FILETIME LastAccess;
+ FILETIME LastWrite;
+ HANDLE hFile;
+ ULONG64 FirstWrite;
+ ULONG64 SecondWrite;
+ ULONG64 FirstAccess;
+ ULONG64 SecondAccess;
+ ULONG64 FirstCreationTime;
+ ULONG64 SecondCreationTime;
+ DWORD temp;
+ const char* someText = "1234567890123456789012345678901234567890";
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* Open the file to get a HANDLE */
+ hFile = CreateFile("test.tmp",
+ GENERIC_READ|GENERIC_WRITE,
+ 0,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Failed to create the file. The error number "
+ "returned was %u.\n",
+ GetLastError());
+ }
+
+ /* Write to the file -- this should change write access and
+ last access
+ */
+ if(!WriteFile(hFile, someText, strlen(someText), &temp, NULL))
+ {
+ Trace("ERROR: Failed to write to file. The file must be "
+ "written to in order to test that the write time is "
+ "updated. GetLastError returned %u.\n",
+ GetLastError());
+ /* Close the File */
+ if(!CloseHandle(hFile))
+ {
+ Trace("ERROR: Failed to close the file handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ /* Flush the buffers */
+ if(!FlushFileBuffers(hFile))
+ {
+ Trace("ERROR: The FlushFileBuffers function failed. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ /* Close the File */
+ if(!CloseHandle(hFile))
+ {
+ Trace("ERROR: Failed to close the file handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ /* Get the Last Write, Creation and Access File time of that File */
+ if(!GetFileTime(hFile, &Creation, &LastAccess, &LastWrite))
+ {
+ Trace("ERROR: GetFileTime returned 0, indicating failure."
+ " GetLastError returned %u\n",
+ GetLastError());
+ /* Close the File */
+ if(!CloseHandle(hFile))
+ {
+ Trace("ERROR: Failed to close the file handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ /* Convert the structures to an ULONG64 */
+ FirstCreationTime = ((((ULONG64)Creation.dwHighDateTime)<<32) |
+ ((ULONG64)Creation.dwLowDateTime));
+
+ FirstWrite = ((((ULONG64)LastWrite.dwHighDateTime)<<32) |
+ ((ULONG64)LastWrite.dwLowDateTime));
+
+ FirstAccess = ((((ULONG64)LastAccess.dwHighDateTime)<<32) |
+ ((ULONG64)LastAccess.dwLowDateTime));
+
+ /* Sleep for 3 seconds, this will ensure the time changes */
+ Sleep(3000);
+
+ /* Write to the file again so we have something to flush */
+ if(!WriteFile(hFile, someText, strlen(someText), &temp, NULL))
+ {
+ Trace("ERROR: Failed to write to file. The file must be "
+ "written to in order to test that the write time is "
+ "updated. GetLastError returned %u.\n",
+ GetLastError());
+ /* Close the File */
+ if(!CloseHandle(hFile))
+ {
+ Trace("ERROR: Failed to close the file handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ /* Flush the buffers forcing the access/mod time to change */
+ if(!FlushFileBuffers(hFile))
+ {
+ Trace("ERROR: The FlushFileBuffers function failed. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ /* Close the File */
+ if(!CloseHandle(hFile))
+ {
+ Trace("ERROR: Failed to close the file handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+
+ /* Call GetFileTime again */
+ if(!GetFileTime(hFile,&Creation,&LastAccess,&LastWrite))
+ {
+ Trace("ERROR: GetFileTime returned 0, indicating failure."
+ "GetLastError returned %u.\n",
+ GetLastError());
+ /* Close the File */
+ if(!CloseHandle(hFile))
+ {
+ Trace("ERROR: Failed to close the file handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ /* Store the results in a ULONG64 */
+
+ SecondCreationTime = ( (((ULONG64)Creation.dwHighDateTime)<<32) |
+ ((ULONG64)Creation.dwLowDateTime));
+
+ SecondWrite = ( (((ULONG64)LastWrite.dwHighDateTime)<<32) |
+ ((ULONG64)LastWrite.dwLowDateTime));
+
+ SecondAccess = ((((ULONG64)LastAccess.dwHighDateTime)<<32) |
+ ((ULONG64)LastAccess.dwLowDateTime));
+
+
+ /* Now -- to test. We'll ensure that the Second
+ LastWrite and access times are larger than the first.
+ It tells us that time is passing, which is good!
+ */
+
+ if(FirstWrite >= SecondWrite)
+ {
+ /* Close the File */
+ if(!CloseHandle(hFile))
+ {
+ Trace("ERROR: Failed to close the file handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("ERROR: The write-file-time (%I64d) after the first flush "
+ "should be less than the write-file-time (%I64d) after the second "
+ "flush.\n",
+ FirstWrite,
+ LastWrite);
+
+ }
+
+
+ if(SecondAccess < FirstAccess)
+ {
+ /* Close the File */
+ if(!CloseHandle(hFile))
+ {
+ Trace("ERROR: Failed to close the file handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("ERROR: The access-file-time (%I64d) after the first flush "
+ "should be less than or equal to the access-file-time (%I64d) "
+ "after the second flush.\n",
+ FirstAccess,
+ LastAccess);
+ }
+
+#if WIN32
+ /* Then we can check to make sure that the creation time
+ hasn't changed. This should always stay the same.
+ */
+
+ if(FirstCreationTime != SecondCreationTime)
+ {
+ /* Close the File */
+ if(!CloseHandle(hFile))
+ {
+ Trace("ERROR: Failed to close the file handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("ERROR: The creation time after writing should not "
+ "not change from the original. The second value should be "
+ "equal.\n");
+ }
+#else
+ /* Then we can check to make sure that the creation time
+ has changed. Under FreeBSD it changes whenever the file is
+ access or written.
+ */
+
+ if(FirstCreationTime >= SecondCreationTime)
+ {
+ /* Close the File */
+ if(!CloseHandle(hFile))
+ {
+ Trace("ERROR: Failed to close the file handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+ Fail("ERROR: The creation time after writing should be "
+ "greater than the original. The second value should be "
+ "larger.\n");
+ }
+
+#endif
+
+ /* Close the File */
+ if(!CloseHandle(hFile))
+ {
+ Fail("ERROR: Failed to close the file handle. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test7/testinfo.dat b/src/pal/tests/palsuite/file_io/GetFileTime/test7/testinfo.dat
new file mode 100644
index 0000000000..774f759adc
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileTime/test7/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetFileTime
+Name = Positive Test for GetFileTime
+TYPE = DEFAULT
+EXE1 = getfiletime
+Description
+= Test the PAL implementation of GetFileTime. This test
+= creates a file and compares create and write times after
+= the buffers are flushed, but before the close, and verifies
+= the results are as expected
diff --git a/src/pal/tests/palsuite/file_io/GetFileType/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileType/CMakeLists.txt
new file mode 100644
index 0000000000..1962ade358
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileType/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileType/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileType/test1/CMakeLists.txt
new file mode 100644
index 0000000000..66467e99c5
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileType/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetFileType.c
+)
+
+add_executable(paltest_getfiletype_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getfiletype_test1 coreclrpal)
+
+target_link_libraries(paltest_getfiletype_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetFileType/test1/GetFileType.c b/src/pal/tests/palsuite/file_io/GetFileType/test1/GetFileType.c
new file mode 100644
index 0000000000..6558c00bdd
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileType/test1/GetFileType.c
@@ -0,0 +1,76 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: GetFileType.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the GetFileType function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+const char* szTextFile = "text.txt";
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE hFile = NULL;
+ DWORD dwRc = 0;
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+
+ /* test FILE_TYPE_UNKNOWN */
+ dwRc = GetFileType(hFile);
+ if (dwRc != FILE_TYPE_UNKNOWN)
+ {
+ Fail("GetFileType: ERROR -> Was expecting a return type of "
+ "FILE_TYPE_UNKNOWN but the function returned %ld.\n",
+ dwRc);
+ }
+
+
+ /* create a test file */
+ hFile = CreateFile(szTextFile,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("GetFileType: ERROR -> Unable to create file \"%s\".\n",
+ szTextFile);
+ }
+
+ dwRc = GetFileType(hFile);
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Fail("GetFileType: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Fail("GetFileType: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+
+ if (dwRc != FILE_TYPE_DISK)
+ {
+ Fail("GetFileType: ERROR -> Was expecting a return type of "
+ "FILE_TYPE_DISK but the function returned %ld.\n",
+ dwRc);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/GetFileType/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/GetFileType/test1/testinfo.dat
new file mode 100644
index 0000000000..f12a81a20b
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileType/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetFileType
+Name = Positive Test for GetFileType (test 1)
+Type = DEFAULT
+EXE1 = getfiletype
+Description
+= Test GetFileType on a NULL handle and a valid handle to a file
+
diff --git a/src/pal/tests/palsuite/file_io/GetFileType/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileType/test2/CMakeLists.txt
new file mode 100644
index 0000000000..382b27e788
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileType/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ getfiletype.c
+)
+
+add_executable(paltest_getfiletype_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getfiletype_test2 coreclrpal)
+
+target_link_libraries(paltest_getfiletype_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetFileType/test2/getfiletype.c b/src/pal/tests/palsuite/file_io/GetFileType/test2/getfiletype.c
new file mode 100644
index 0000000000..c9d4eb6572
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileType/test2/getfiletype.c
@@ -0,0 +1,95 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: getfiletype.c
+**
+** Purpose: Test the PAL implementation of GetFileType to ensure it
+** recognizes opened pipes.
+**
+** Depends: CreatePipe
+** CloseHandle
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char **argv)
+{
+ HANDLE hReadPipe = NULL;
+ HANDLE hWritePipe = NULL;
+ BOOL bRetVal = FALSE;
+ DWORD dwFileType;
+ SECURITY_ATTRIBUTES lpPipeAttributes;
+
+ /*Initialize the PAL*/
+ if ((PAL_Initialize(argc, argv)) != 0)
+ {
+ return (FAIL);
+ }
+
+ /*
+ ** create a pipe and make sure GetFileType returns the correct value
+ */
+
+ /*Setup SECURITY_ATTRIBUTES structure for CreatePipe*/
+ lpPipeAttributes.nLength = sizeof(lpPipeAttributes);
+ lpPipeAttributes.lpSecurityDescriptor = NULL;
+ lpPipeAttributes.bInheritHandle = TRUE;
+
+ /*Create a Pipe*/
+ bRetVal = CreatePipe(&hReadPipe, /* read handle*/
+ &hWritePipe, /* write handle */
+ &lpPipeAttributes, /* security attributes*/
+ 0); /* pipe size*/
+ if (bRetVal == FALSE)
+ {
+ Fail("ERROR: %u :Unable to create pipe.\n", GetLastError());
+ }
+
+ // Get the file type
+ dwFileType = GetFileType(hReadPipe);
+ if (dwFileType != FILE_TYPE_PIPE)
+ {
+ if (!CloseHandle(hWritePipe))
+ {
+ Trace("ERROR: %u : Unable to close write pipe handle "
+ "hWritePipe=0x%lx\n", GetLastError(), hWritePipe);
+ }
+ if (!CloseHandle(hReadPipe))
+ {
+ Trace("ERROR: %u : Unable to close read pipe handle "
+ "hReadPipe=0x%lx\n", GetLastError(), hReadPipe);
+ }
+ Fail("ERROR: GetFileType returned %u for a pipe instead of the "
+ "expected FILE_TYPE_PIPE (%u).\n",
+ dwFileType,
+ FILE_TYPE_PIPE);
+ }
+
+ /*Close write pipe handle*/
+ if (!CloseHandle(hWritePipe))
+ {
+ if (!CloseHandle(hReadPipe))
+ {
+ Trace("ERROR: %u : Unable to close read pipe handle "
+ "hReadPipe=0x%lx\n", GetLastError(), hReadPipe);
+ }
+ Fail("ERROR: %u : Unable to close write pipe handle "
+ "hWritePipe=0x%lx\n", GetLastError(), hWritePipe);
+ }
+
+ /*Close Read pipe handle*/
+ if (!CloseHandle(hReadPipe))
+ {
+ Fail("ERROR: %u : Unable to close read pipe handle "
+ "hReadPipe=0x%lx\n", GetLastError(), hReadPipe);
+ }
+
+ PAL_Terminate();
+ return (PASS);
+}
diff --git a/src/pal/tests/palsuite/file_io/GetFileType/test2/testinfo.dat b/src/pal/tests/palsuite/file_io/GetFileType/test2/testinfo.dat
new file mode 100644
index 0000000000..eb1361d3f6
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileType/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetFileType
+Name = Test for GetFileType
+TYPE = DEFAULT
+EXE1 = getfiletype
+Description
+= Test the PAL implementation of GetFileType to ensure it
+= recognizes opened pipes.
diff --git a/src/pal/tests/palsuite/file_io/GetFileType/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileType/test3/CMakeLists.txt
new file mode 100644
index 0000000000..52b6077570
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileType/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ getfiletype.c
+)
+
+add_executable(paltest_getfiletype_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getfiletype_test3 coreclrpal)
+
+target_link_libraries(paltest_getfiletype_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetFileType/test3/getfiletype.c b/src/pal/tests/palsuite/file_io/GetFileType/test3/getfiletype.c
new file mode 100644
index 0000000000..6a95585bab
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileType/test3/getfiletype.c
@@ -0,0 +1,72 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: getfiletype.c
+**
+** Purpose: Test the PAL implementation of the GetFileType on a handle
+** to a console.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE hFile;
+#if WIN32
+ char *lpFileName = "CONIN$";
+#else
+ char *lpFileName = "/dev/null";
+#endif
+ DWORD dwFileType;
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* get a handle to the console */
+ hFile = CreateFile(lpFileName,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("GetFileType: ERROR: CreateFile failed to open %s with "
+ "error %u.\n",
+ lpFileName,
+ GetLastError());
+ }
+
+ /* Get the file type */
+ if ((dwFileType = GetFileType(hFile)) != FILE_TYPE_CHAR)
+ {
+ if (!CloseHandle(hFile))
+ {
+ Trace("GetFileType: ERROR: %u : Unable to close the handle "
+ "hFile=0x%lx\n", GetLastError(), hFile);
+ }
+ Fail("GetFileType: ERROR: GetFileType returned %u for a device "
+ "instead of the expected FILE_TYPE_CHAR (%u).\n",
+ dwFileType,
+ FILE_TYPE_CHAR);
+ }
+
+ if (!CloseHandle(hFile))
+ {
+ Fail("GetFileType: ERROR: %u : Unable to close the handle "
+ "hFile=0x%lx\n", GetLastError(), hFile);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/GetFileType/test3/testinfo.dat b/src/pal/tests/palsuite/file_io/GetFileType/test3/testinfo.dat
new file mode 100644
index 0000000000..9ffd4c2b15
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFileType/test3/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetFileType
+Name = Test for GetFileTYpe
+TYPE = DEFAULT
+EXE1 = getfiletype
+Description
+= Test the PAL implementation of the GetFileType on a handle
+= to a console.
diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameA/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFullPathNameA/CMakeLists.txt
new file mode 100644
index 0000000000..a3847f8ca9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFullPathNameA/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+
diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/CMakeLists.txt
new file mode 100644
index 0000000000..8c10e479fa
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetFullPathNameA.c
+)
+
+add_executable(paltest_getfullpathnamea_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getfullpathnamea_test1 coreclrpal)
+
+target_link_libraries(paltest_getfullpathnamea_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/GetFullPathNameA.c b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/GetFullPathNameA.c
new file mode 100644
index 0000000000..de9a266f5a
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/GetFullPathNameA.c
@@ -0,0 +1,122 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: GetFullPathNameA.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the GetFullPathNameA function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+const char* szFileName = "testing.tmp";
+
+int __cdecl main(int argc, char *argv[])
+{
+ DWORD dwRc = 0;
+ char szReturnedPath[_MAX_DIR+1];
+ char szShortBuff[2];
+ LPSTR pPathPtr;
+ HANDLE hFile = NULL;
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* perform a short buffer test */
+ if (GetFullPathNameA(szFileName, 2, szShortBuff, &pPathPtr) <= 2)
+ {
+ /* this test should have failed but didn't */
+ Fail("GetFullPathNameA: ERROR -> The API was passed a buffer that was"
+ " too small for the path name and yet it apparently passed.\n");
+ }
+
+ memset(szReturnedPath, 0, _MAX_DIR+1);
+ dwRc = GetFullPathNameA(szFileName,
+ _MAX_DIR,
+ szReturnedPath,
+ &pPathPtr);
+
+ if (dwRc == 0)
+ {
+ // this test should have passed but didn't
+ Fail("GetFullPathNameA: ERROR -> Function failed for the "
+ "file \"%s\" with error code: %ld.\n", szFileName, GetLastError());
+ }
+
+ // the returned value should be the current directory with the
+ // file name appended
+ hFile = CreateFileA(szFileName,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("GetFullPathNameA: ERROR -> CreateFileA failed to create "
+ "file \"%s\" with error code: %ld.\n",
+ szFileName,
+ GetLastError());
+ }
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Fail("GetFullPathNameA: ERROR -> CloseHandle failed with error "
+ "code: %ld.\n", GetLastError());
+ }
+
+ // now try to create the file based on the returned value with the
+ // CREATE_NEW option which should fail since the file should
+ // already exist
+ hFile = CreateFileA(szReturnedPath,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ CREATE_NEW,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (hFile != INVALID_HANDLE_VALUE)
+ {
+ Fail("GetFullPathNameA: ERROR -> CreateFileA was able to "
+ "CREATE_NEW the returned file \"%s\". The returned file "
+ "name is therefore apparently wrong.\n",
+ szReturnedPath);
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Fail("GetFullPathNameA: ERROR -> CloseHandle failed with "
+ "error code: %ld.\n", GetLastError());
+ }
+ if ((DeleteFileA(szReturnedPath) != TRUE) ||
+ (DeleteFileA(szFileName) != TRUE))
+ {
+ Fail("GetFullPathNameA: ERROR -> DeleteFileA failed to "
+ "delete the test files with error code: %ld.\n",
+ GetLastError());
+ }
+ }
+
+ // now make sure the pPathPtr is the same as the file name
+ if (strcmp(pPathPtr, szFileName) != 0)
+ {
+ Fail("GetFullPathNameA: ERROR -> %s != %s\n",
+ pPathPtr, szFileName);
+ }
+ if (DeleteFileA(szFileName) != TRUE)
+ {
+ Fail("GetFullPathNameA: ERROR -> DeleteFileA failed to "
+ "delete \"%s\" with error code: %ld.\n",
+ szFileName,
+ GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/testinfo.dat
new file mode 100644
index 0000000000..a4ccc95348
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetFullPathNameA
+Name = Test for GetFullPathNameA (test 1)
+Type = DEFAULT
+EXE1 = getfullpathnamea
+Description
+= Get the full path for a file name and verify the results.
+= Also, attempt to call GetFullPathNameA with a buffer that is
+= too small for the returned path and verify the results.
+
diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/CMakeLists.txt
new file mode 100644
index 0000000000..382b8fa4bd
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_getfullpathnamea_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getfullpathnamea_test2 coreclrpal)
+
+target_link_libraries(paltest_getfullpathnamea_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/test2.c b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/test2.c
new file mode 100644
index 0000000000..95a1497331
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/test2.c
@@ -0,0 +1,143 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test2.c
+**
+** Purpose: Tests the PAL implementation of the GetFullPathNameA API.
+** GetFullPathA will be passed a directory that contains '..'.
+** To add to this test, we will also call SetCurrentDirectory to
+** ensure this is handled properly.
+** The test will create a file with in the parent directory
+** to verify that the returned directory is valid.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+const char* szDotDot = "..\\";
+const char* szFileName = "testing.tmp";
+
+int __cdecl main(int argc, char *argv[])
+{
+ DWORD dwRc = 0;
+ char szReturnedPath[_MAX_DIR+1];
+ char szFullFileName[_MAX_DIR+1];
+ LPSTR pPathPtr;
+ HANDLE hFile = NULL;
+
+ /* Initialize the PAL.
+ */
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return (FAIL);
+ }
+
+ /* change the directory */
+ if (!SetCurrentDirectoryA(szDotDot))
+ {
+ Fail("ERROR: SetCurrentDirectoryA failed with error code %u"
+ " when passed \"%s\".\n",
+ GetLastError(),
+ szDotDot);
+ }
+
+ /* Initialize the receiving char buffers.
+ */
+ memset(szReturnedPath, 0, _MAX_DIR+1);
+ memset(szFullFileName, 0, _MAX_DIR+1);
+
+ /* Create Full filename to pass, will include '..\'
+ * as a pre-fix. */
+ strcat(szFullFileName, szDotDot);
+ strcat(szFullFileName, szFileName);
+
+ /* Get the full path to the filename.
+ */
+ dwRc = GetFullPathNameA(szFullFileName,
+ _MAX_DIR,
+ szReturnedPath,
+ &pPathPtr);
+ if (dwRc == 0)
+ {
+ Fail("ERROR :%ld: GetFullPathName failed to "
+ "retrieve the path of \"%s\".\n",
+ GetLastError(),
+ szFileName);
+ }
+
+ /* The returned value should be the parent directory with the
+ * file name appended. */
+ hFile = CreateFileA(szReturnedPath,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR :%ld: CreateFileA failed to create \"%s\".\n",
+ GetLastError(),
+ szReturnedPath);
+ }
+
+ /* Close the handle to the created file.
+ */
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("ERROR :%ld: CloseHandle failed close hFile=0x%lx.\n",
+ GetLastError());
+ goto terminate;
+ }
+
+ /* Verify that the file was created, attempt to create
+ * the file again. */
+ hFile = CreateFileA(szReturnedPath,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ CREATE_NEW,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if ((hFile != INVALID_HANDLE_VALUE) &&
+ (GetLastError() != ERROR_ALREADY_EXISTS))
+ {
+ Fail("ERROR :%ld: CreateFileA succeeded to create file "
+ "\"%s\", that already existed.\n",
+ GetLastError(),
+ szFullFileName);
+ }
+
+
+ /* Verify that the returned filename is the same as the supplied.
+ */
+ if (strcmp(pPathPtr, szFileName) != 0)
+ {
+ Trace("ERROR : Returned filename \"%s\" is not equal to "
+ "supplied filename \"%s\".\n",
+ pPathPtr,
+ szFileName);
+ goto terminate;
+ }
+
+terminate:
+ /* Delete the create file.
+ */
+ if (DeleteFileA(szReturnedPath) != TRUE)
+ {
+ Fail("ERROR :%ld: DeleteFileA failed to delete \"%s\".\n",
+ GetLastError(),
+ szFileName);
+ }
+
+ /* Terminate the PAL.*/
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/testinfo.dat b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/testinfo.dat
new file mode 100644
index 0000000000..b75f48114b
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/testinfo.dat
@@ -0,0 +1,18 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetFullPathNameA
+Name = Test for GetFullPathNameA
+Type = DEFAULT
+EXE1 = test2
+Description
+= Tests the PAL implementation of the GetFullPathNameA API.
+= GetFullPathA will be passed a directory that contains '..'.
+= To add to this test, we will also call SetCurrentDirectory to
+= ensure this is handled properly.
+= The test will create a file with in the parent directory
+= to verify that the returned directory is valid.
+
diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/CMakeLists.txt
new file mode 100644
index 0000000000..f0f8929b4a
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_getfullpathnamea_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getfullpathnamea_test3 coreclrpal)
+
+target_link_libraries(paltest_getfullpathnamea_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/test3.c b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/test3.c
new file mode 100644
index 0000000000..0cc39e7300
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/test3.c
@@ -0,0 +1,241 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test3.c
+**
+** Purpose: Tests the PAL implementation of the GetFullPathNameA API.
+** GetFullPathA will be passed a directory that contains '..'.
+** Example: test_directory\level1\..\testing.tmp.
+** To add to this test, we will also call SetCurrentDirectory to
+** ensure this is handled properly.
+** The test will create a file with in the parent directory
+** to verify that the returned directory is valid.
+**
+** Depends: SetCurrentDirectory,
+** CreateDirectory,
+** strcat,
+** memset,
+** CreateFile,
+** CloseHandle,
+** strcmp,
+** DeleteFileA,
+** RemoveDirectory.
+**
+
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+#ifdef WIN32
+ const char* szSeperator = "\\";
+#else
+ const char* szSeperator = "//";
+#endif
+
+const char* szDotDot = "..\\";
+const char* szFileName = "testing.tmp";
+
+int __cdecl main(int argc, char *argv[])
+{
+ DWORD dwRc = 0;
+ char szReturnedPath[_MAX_DIR+1];
+ char szFullFileName[_MAX_DIR+1];
+ char szDirectory[256];
+ char* szCreatedDir = {"test_directory"};
+ char* szCreatedNextDir = {"level1"};
+ WCHAR *szCreatedDirW;
+ LPSTR pPathPtr;
+ HANDLE hFile = NULL;
+ BOOL bRetVal = FAIL;
+
+ /* Initialize the PAL.
+ */
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return (FAIL);
+ }
+
+ /* Initialize the buffer.
+ */
+ memset(szDirectory, '\0', 256);
+
+ /* Change the current working directory.
+ */
+ if (!SetCurrentDirectoryA(szDotDot))
+ {
+ Fail("ERROR: SetCurrentDirectoryA failed with error code %u"
+ " when passed \"%s\".\n",
+ GetLastError(),
+ szDotDot);
+ }
+
+ /* Create the path to the next level of directory to create.
+ */
+ strcat( szDirectory, szCreatedDir );
+
+
+ /* Create a test directory.
+ */
+ if ( !CreateDirectoryA( szDirectory, NULL ) )
+ {
+ Fail("ERROR:%u: Unable to create directories \"%s\".\n",
+ GetLastError(),
+ szDirectory);
+ }
+
+ /* Create the path to the next level of directory to create.
+ */
+ strcat( szDirectory, szSeperator );
+ strcat( szDirectory, szCreatedNextDir );
+
+ /* Create a test directory.
+ */
+ if ( !CreateDirectoryA( szDirectory, NULL ) )
+ {
+ Trace("ERROR:%u: Unable to create directories \"%s\".\n",
+ GetLastError(),
+ szDirectory);
+ bRetVal = FAIL;
+ goto cleanUpOne;
+ }
+
+ /* Initialize the receiving char buffers.
+ */
+ memset(szReturnedPath, 0, _MAX_DIR+1);
+ memset(szFullFileName, 0, _MAX_DIR+1);
+
+ /* Create Full filename to pass, will include '..\'
+ * in the middle of the path.
+ */
+ strcat(szFullFileName, szCreatedDir);
+ strcat(szFullFileName, szDotDot);
+ strcat(szFullFileName, szFileName);
+
+ /* Get the full path to the filename.
+ */
+ dwRc = GetFullPathNameA(szFullFileName,
+ _MAX_DIR,
+ szReturnedPath,
+ &pPathPtr);
+ if (dwRc == 0)
+ {
+ Trace("ERROR :%ld: GetFullPathName failed to "
+ "retrieve the path of \"%s\".\n",
+ GetLastError(),
+ szFileName);
+ bRetVal = FAIL;
+ goto cleanUpTwo;
+ }
+
+ /* The returned value should be the parent directory with the
+ * file name appended. */
+ hFile = CreateFileA(szReturnedPath,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Trace("ERROR :%ld: CreateFileA failed to create \"%s\".\n",
+ GetLastError(),
+ szReturnedPath);
+ bRetVal = FAIL;
+ goto cleanUpTwo;
+ }
+
+ /* Close the handle to the created file.
+ */
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("ERROR :%ld: CloseHandle failed close hFile=0x%lx.\n",
+ GetLastError());
+ bRetVal = FAIL;
+ goto cleanUpThree;
+ }
+
+ /* Verify that the file was created, attempt to create
+ * the file again. */
+ hFile = CreateFileA(szReturnedPath,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ CREATE_NEW,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if ((hFile != INVALID_HANDLE_VALUE) &&
+ (GetLastError() != ERROR_ALREADY_EXISTS))
+ {
+ Trace("ERROR :%ld: CreateFileA succeeded to create file "
+ "\"%s\", that already existed.\n",
+ GetLastError(),
+ szFullFileName);
+ bRetVal = FAIL;
+ goto cleanUpThree;
+ }
+
+ /* Verify that the returned filename is the same as the supplied.
+ */
+ if (strcmp(pPathPtr, szFileName) != 0)
+ {
+ Trace("ERROR : Returned filename \"%s\" is not equal to "
+ "supplied filename \"%s\".\n",
+ pPathPtr,
+ szFileName);
+ bRetVal = FAIL;
+ goto cleanUpThree;
+ }
+
+ /* Successful test.
+ */
+ bRetVal = PASS;
+
+cleanUpThree:
+
+ /* Delete the create file.
+ */
+ if (DeleteFileA(szReturnedPath) != TRUE)
+ {
+ Fail("ERROR :%ld: DeleteFileA failed to delete \"%s\".\n",
+ GetLastError(),
+ szFileName);
+ }
+
+cleanUpTwo:
+
+ /* Remove the empty directory.
+ */
+ szCreatedDirW = convert((LPSTR)szDirectory);
+ if (!RemoveDirectoryW(szCreatedDirW))
+ {
+ free (szCreatedDirW);
+ Fail("ERROR:%u: Unable to remove directory \"%s\".\n",
+ GetLastError(),
+ szCreatedDir);
+ }
+ free (szCreatedDirW);
+
+cleanUpOne:
+
+ /* Remove the empty directory.
+ */
+ szCreatedDirW = convert((LPSTR)szCreatedDir);
+ if (!RemoveDirectoryW(szCreatedDirW))
+ {
+ free (szCreatedDirW);
+ Fail("ERROR:%u: Unable to remove directory \"%s\".\n",
+ GetLastError(),
+ szCreatedDir);
+ }
+ free (szCreatedDirW);
+
+ /* Terminate the PAL.*/
+ PAL_Terminate();
+ return bRetVal;
+}
diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/testinfo.dat b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/testinfo.dat
new file mode 100644
index 0000000000..3991744d42
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/testinfo.dat
@@ -0,0 +1,19 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetFullPathNameA
+Name = Test for GetFullPathNameA
+Type = DEFAULT
+EXE1 = test3
+Description
+= Tests the PAL implementation of the GetFullPathNameA API.
+= GetFullPathA will be passed a directory that contains '..'.
+= Example: test_directory\level1\..\testing.tmp.
+= To add to this test, we will also call SetCurrentDirectory to
+= ensure this is handled properly.
+= The test will create a file with in the parent directory
+= to verify that the returned directory is valid.
+
diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/CMakeLists.txt
new file mode 100644
index 0000000000..cf0d7ff18c
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_getfullpathnamea_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getfullpathnamea_test4 coreclrpal)
+
+target_link_libraries(paltest_getfullpathnamea_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/test4.c b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/test4.c
new file mode 100644
index 0000000000..fb22c1f07b
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/test4.c
@@ -0,0 +1,203 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test4.c
+**
+** Purpose: Tests the PAL implementation of the GetFullPathNameA API.
+** GetFullPathA will be passed a directory that begins with '..'.
+** Example: ..\test_directory\testing.tmp.
+** To add to this test, we will also call SetCurrentDirectory to
+** ensure this is handled properly.
+** The test will create a file with in the parent directory
+** to verify that the returned directory is valid.
+**
+** Depends: SetCurrentDirectory,
+** CreateDirectory,
+** strcat,
+** memset,
+** CreateFile,
+** CloseHandle,
+** strcmp,
+** DeleteFileA,
+** RemoveDirectory.
+**
+
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+#ifdef WIN32
+ const char* szSeperator = "\\";
+#else
+ const char* szSeperator = "//";
+#endif
+
+const char* szDotDot = "..";
+const char* szFileName = "testing.tmp";
+
+int __cdecl main(int argc, char *argv[])
+{
+ DWORD dwRc = 0;
+ char szReturnedPath[_MAX_DIR+1];
+ char szFullFileName[_MAX_DIR+1];
+ char szDirectory[256];
+ char* szCreatedDir = {"test_directory"};
+ WCHAR *szCreatedDirW;
+ LPSTR pPathPtr;
+ HANDLE hFile = NULL;
+ BOOL bRetVal = FAIL;
+
+ /* Initialize the PAL.
+ */
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return (FAIL);
+ }
+
+ /* Initialize the buffer.
+ */
+ memset(szDirectory, '\0', 256);
+
+ /* Create the path to the next level of directory to create.
+ */
+ strcat( szDirectory, szDotDot ); /* .. */
+ strcat( szDirectory, szSeperator ); /* ../ */
+ strcat( szDirectory, szCreatedDir ); /* ../test_directory */
+
+ /* Create a test directory.
+ */
+ if ( !CreateDirectoryA( szDirectory, NULL ) )
+ {
+ Fail("ERROR:%u: Unable to create directories \"%s\".\n",
+ GetLastError(),
+ szDirectory);
+ }
+
+ /* Initialize the receiving char buffers.
+ */
+ memset(szReturnedPath, 0, _MAX_DIR+1);
+ memset(szFullFileName, 0, _MAX_DIR+1);
+
+ /* Create Full filename to pass, will include '..\'
+ * in the middle of the path.
+ */
+ strcat( szFullFileName, szDotDot ); /* .. */
+ strcat( szFullFileName, szSeperator ); /* ../ */
+ strcat( szFullFileName, szCreatedDir ); /* ../test_directory */
+ strcat( szFullFileName, szSeperator ); /* ../test_directory/ */
+ strcat( szFullFileName, szFileName ); /* ../test_directory/testing.tmp */
+
+ /* Get the full path to the filename.
+ */
+ dwRc = GetFullPathNameA(szFullFileName,
+ _MAX_DIR,
+ szReturnedPath,
+ &pPathPtr);
+ if (dwRc == 0)
+ {
+ Trace("ERROR :%ld: GetFullPathName failed to "
+ "retrieve the path of \"%s\".\n",
+ GetLastError(),
+ szFileName);
+ bRetVal = FAIL;
+ goto cleanUpOne;
+ }
+
+ /* The returned value should be the parent directory with the
+ * file name appended. */
+ hFile = CreateFileA(szReturnedPath,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Trace("ERROR :%ld: CreateFileA failed to create \"%s\".\n",
+ GetLastError(),
+ szReturnedPath);
+ bRetVal = FAIL;
+ goto cleanUpOne;
+ }
+
+ /* Close the handle to the created file.
+ */
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("ERROR :%ld: CloseHandle failed close hFile=0x%lx.\n",
+ GetLastError());
+ bRetVal = FAIL;
+ goto cleanUpTwo;
+ }
+
+ /* Verify that the file was created, attempt to create
+ * the file again. */
+ hFile = CreateFileA(szReturnedPath,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ CREATE_NEW,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if ((hFile != INVALID_HANDLE_VALUE) &&
+ (GetLastError() != ERROR_ALREADY_EXISTS))
+ {
+ Trace("ERROR :%ld: CreateFileA succeeded to create file "
+ "\"%s\", that already existed.\n",
+ GetLastError(),
+ szFullFileName);
+ bRetVal = FAIL;
+ goto cleanUpTwo;
+ }
+
+ /* Verify that the returned filename is the same as the supplied.
+ */
+ if (strcmp(pPathPtr, szFileName) != 0)
+ {
+ Trace("ERROR : Returned filename \"%s\" is not equal to "
+ "supplied filename \"%s\".\n",
+ pPathPtr,
+ szFileName);
+ bRetVal = FAIL;
+ goto cleanUpTwo;
+ }
+
+ /* Successful test.
+ */
+ bRetVal = PASS;
+
+cleanUpTwo:
+
+ /* Delete the create file.
+ */
+ if (DeleteFileA(szReturnedPath) != TRUE)
+ {
+ Fail("ERROR :%ld: DeleteFileA failed to delete \"%s\".\n",
+ GetLastError(),
+ szFileName);
+ }
+
+cleanUpOne:
+
+ /* Remove the empty directory.
+ */
+ szCreatedDirW = convert((LPSTR)szDirectory);
+ if (!RemoveDirectoryW(szCreatedDirW))
+ {
+ free (szCreatedDirW);
+ Fail("ERROR:%u: Unable to remove directory \"%s\".\n",
+ GetLastError(),
+ szCreatedDir);
+ }
+ free (szCreatedDirW);
+
+ /* Terminate the PAL.*/
+ PAL_Terminate();
+ return bRetVal;
+}
diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/testinfo.dat b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/testinfo.dat
new file mode 100644
index 0000000000..8a7b3b35da
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/testinfo.dat
@@ -0,0 +1,19 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetFullPathNameA
+Name = Test for GetFullPathNameA
+Type = DEFAULT
+EXE1 = test4
+Description
+= Tests the PAL implementation of the GetFullPathNameA API.
+= GetFullPathA will be passed a directory that begins with '..'.
+= Example: ..\test_directory\level1\testing.tmp.
+= To add to this test, we will also call SetCurrentDirectory to
+= ensure this is handled properly.
+= The test will create a file with in the parent directory
+= to verify that the returned directory is valid.
+
diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameW/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFullPathNameW/CMakeLists.txt
new file mode 100644
index 0000000000..a3847f8ca9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFullPathNameW/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+
diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..a6f354f5a5
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetFullPathNameW.c
+)
+
+add_executable(paltest_getfullpathnamew_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getfullpathnamew_test1 coreclrpal)
+
+target_link_libraries(paltest_getfullpathnamew_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/GetFullPathNameW.c b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/GetFullPathNameW.c
new file mode 100644
index 0000000000..592d3ad4c5
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/GetFullPathNameW.c
@@ -0,0 +1,157 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: GetFullPathNameW.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the GetFullPathNameW function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+const char* szFileName = "testing.tmp";
+
+int __cdecl main(int argc, char *argv[])
+{
+ DWORD dwRc = 0;
+ WCHAR szwReturnedPath[_MAX_DIR+1];
+ WCHAR szwShortBuff[2];
+ LPWSTR pPathPtr;
+ HANDLE hFile = NULL;
+ WCHAR* szwFileName = NULL;
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ szwFileName = convert((char*)szFileName);
+
+ /* perform a short buffer test */
+ if (GetFullPathNameW(szwFileName, 2, szwShortBuff, &pPathPtr) <= 2)
+ {
+ free(szwFileName);
+ /* this test should have failed but didn't */
+ Fail("GetFullPathNameW: ERROR -> The API was passed a buffer that was"
+ " too small for the path name and yet it apparently passed.\n");
+ }
+
+
+ memset(szwReturnedPath, 0, _MAX_DIR+1);
+ dwRc = GetFullPathNameW(szwFileName,
+ _MAX_DIR,
+ szwReturnedPath,
+ &pPathPtr);
+
+ if (dwRc == 0)
+ {
+ /* this test should have passed but didn't */
+ free(szwFileName);
+ Fail("GetFullPathNameW: ERROR -> Function failed for the "
+ "file \"%s\" with error code: %ld.\n", szFileName, GetLastError());
+ }
+ /*
+ * the returned value should be the current directory with the
+ * file name appended
+ */
+ hFile = CreateFileW(szwFileName,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ free(szwFileName);
+ Fail("GetFullPathNameW: ERROR -> CreateFileW failed to create "
+ "file \"%s\" with error code: %ld.\n",
+ szFileName,
+ GetLastError());
+ }
+ if (CloseHandle(hFile) != TRUE)
+ {
+ free(szwFileName);
+ Trace("GetFullPathNameW: ERROR -> CloseHandle failed with error "
+ "code: %ld.\n", GetLastError());
+ if (DeleteFileA(szFileName) != TRUE)
+ {
+ Trace("GetFullPathNameW: ERROR -> DeleteFileW failed to "
+ "delete the test file with error code: %ld.\n",
+ GetLastError());
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ /*
+ * now try to create the file based on the returned value with the
+ * CREATE_NEW option which should fail since the file should
+ * already exist
+ */
+ hFile = CreateFileW(szwReturnedPath,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ CREATE_NEW,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (hFile != INVALID_HANDLE_VALUE)
+ {
+ Trace("GetFullPathNameW: ERROR -> CreateFileW was able to "
+ "CREATE_NEW the returned file \"%s\". The returned file "
+ "name is therefore apparently wrong.\n",
+ szwReturnedPath);
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("GetFullPathNameW: ERROR -> CloseHandle failed with "
+ "error code: %ld.\n", GetLastError());
+ }
+ if ((DeleteFileW(szwReturnedPath) != TRUE) ||
+ (DeleteFileW(szwFileName) != TRUE))
+ {
+ Trace("GetFullPathNameW: ERROR -> DeleteFileW failed to "
+ "delete the test files with error code: %ld.\n",
+ GetLastError());
+ }
+ free(szwFileName);
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ /* now make sure the pPathPtr is the same as the file name */
+ if (wcsncmp(pPathPtr, szwFileName, wcslen(szwFileName)) != 0)
+ {
+ Trace("GetFullPathNameW: ERROR -> %s != %s\n",
+ pPathPtr, szFileName);
+ if ((DeleteFileW(szwReturnedPath) != TRUE) ||
+ (DeleteFileW(szwFileName) != TRUE))
+ {
+ Trace("GetFullPathNameW: ERROR -> DeleteFileW failed to "
+ "delete the test files with error code: %ld.\n",
+ GetLastError());
+ }
+ free(szwFileName);
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ /* clean up */
+ free(szwFileName);
+ if (DeleteFileA(szFileName) != TRUE)
+ {
+ Fail("GetFullPathNameW: ERROR -> DeleteFileW failed to "
+ "delete \"%s\" with error code: %ld.\n",
+ szFileName,
+ GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/testinfo.dat
new file mode 100644
index 0000000000..4f70617d48
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetFullPathNameW
+Name = Test for GetFullPathNameW (test 1)
+Type = DEFAULT
+EXE1 = getfullpathnamew
+Description
+= Get the full path for a file name and verify the results.
+= Also, attempt to call GetFullPathNameW with a buffer that is
+= too small for the returned path and verify the results.
diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/CMakeLists.txt
new file mode 100644
index 0000000000..199aa1efce
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_getfullpathnamew_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getfullpathnamew_test2 coreclrpal)
+
+target_link_libraries(paltest_getfullpathnamew_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/test2.c b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/test2.c
new file mode 100644
index 0000000000..fae042d229
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/test2.c
@@ -0,0 +1,159 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test2.c
+**
+** Purpose: Tests the PAL implementation of the GetFullPathNameW function.
+** Get the full path for a file name and verify the results.
+** This test will use a relative path, containing '..\'. To
+** add to this test, we will also call SetCurrentDirectory to
+** ensure this is handled properly.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+WCHAR szwDotDot[] = {'.','.','\\','\0'};
+WCHAR szwFileName[] = {'t','e','s','t','i','n','g','.','t','m','p','\0'};
+
+int __cdecl main(int argc, char *argv[])
+{
+ DWORD dwRc = 0;
+ WCHAR szwReturnedPath[_MAX_DIR+1];
+ WCHAR szwFullFileName[_MAX_DIR+1];
+ char *szReturnedPath;
+ char *szFileName;
+ LPWSTR pPathPtr;
+ HANDLE hFile = NULL;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* change the directory */
+ if (!SetCurrentDirectoryW(szwDotDot))
+ {
+ Fail("ERROR: SetCurrentDirectoryW failed with error code %u"
+ " when passed \"%S\".\n",
+ GetLastError(),
+ szwDotDot);
+ }
+
+ /* Initialize the receiving char buffers.
+ */
+ memset(szwReturnedPath, 0, _MAX_DIR+1);
+ memset(szwFullFileName, 0, _MAX_DIR+1);
+
+ /* Create Full filename to pass, will include '..\'
+ * as a pre-fix. */
+ wcscat(szwFullFileName, szwDotDot);
+ wcscat(szwFullFileName, szwFileName);
+
+ /* Convert wide char strings to multibyte, to us
+ * incase of error messages.*/
+ szFileName = convertC(szwFileName);
+
+ /* Get the full path to the filename.
+ */
+ dwRc = GetFullPathNameW(szwFullFileName,
+ _MAX_DIR,
+ szwReturnedPath,
+ &pPathPtr);
+
+ szReturnedPath = convertC(szwReturnedPath);
+
+ if (dwRc == 0)
+ {
+ Trace("ERROR :%ld: Failed to get path to \"%s\".\n",
+ GetLastError(),
+ szReturnedPath);
+ free(szReturnedPath);
+ free(szFileName);
+ Fail("");
+ }
+
+ /*
+ * The returned value should be the parent directory with the
+ * file name appended.
+ */
+ hFile = CreateFileW(szwReturnedPath,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Trace("ERROR :%ld: CreateFileW failed to create file \"%s\".\n",
+ GetLastError(),
+ szReturnedPath);
+ free(szFileName);
+ free(szReturnedPath);
+ Fail("");
+ }
+
+ /* Close the handle to the create file.*/
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("ERROR :%ld: Failed to close handle hFile=0x%lx.\n",
+ GetLastError(),
+ hFile);
+ goto terminate;
+ }
+
+ /* Verify that the file was created, attempt to create
+ * the file again. */
+ hFile = CreateFileW(szwReturnedPath,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ CREATE_NEW,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if ((hFile != INVALID_HANDLE_VALUE) &&
+ (GetLastError() != ERROR_ALREADY_EXISTS))
+ {
+ Trace("ERROR :%ld: CreateFileW succeeded to create file "
+ "\"%s\", that already existed.\n",
+ GetLastError(),
+ szReturnedPath);
+ goto terminate;
+ }
+
+ /* Verify that the returned filename is the same as the supplied.
+ */
+ if (wcsncmp(pPathPtr, szwFileName, wcslen(szwFileName)) != 0)
+ {
+ Trace("ERROR : Returned filename is not equal to \"%s\".\n",
+ szFileName);
+ goto terminate;
+ }
+
+terminate:
+ /* Delete the create file.
+ */
+ if (DeleteFileW(szwFullFileName) != TRUE)
+ {
+ Trace("ERROR :%ld: DeleteFileW failed to delete \"%s\".\n",
+ szFileName,
+ GetLastError());
+ free(szFileName);
+ free(szReturnedPath);
+ Fail("");
+ }
+
+ free(szFileName);
+ free(szReturnedPath);
+
+ /* Terminate the PAL.
+ */
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/testinfo.dat b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/testinfo.dat
new file mode 100644
index 0000000000..b8460e0b78
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetFullPathNameW
+Name = Test for GetFullPathNameW (test 2)
+Type = DEFAULT
+EXE1 = test2
+Description
+= Get the full path for a file name and verify the results.
+= This test will use a relative path, containing '..\'. To
+= add to this test, we will also call SetCurrentDirectory to
+= ensure this is handled properly.
diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/CMakeLists.txt
new file mode 100644
index 0000000000..6284958b07
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_getfullpathnamew_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getfullpathnamew_test3 coreclrpal)
+
+target_link_libraries(paltest_getfullpathnamew_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/test3.c b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/test3.c
new file mode 100644
index 0000000000..ba80cf222d
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/test3.c
@@ -0,0 +1,240 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test3.c
+**
+** Purpose: Tests the PAL implementation of the GetFullPathNameW API.
+** GetFullPathW will be passed a directory that contains '..'.
+** Example: test_directory\level1\..\testing.tmp.
+** To add to this test, we will also call SetCurrentDirectory to
+** ensure this is handled properly.
+** The test will create a file with in the parent directory
+** to verify that the returned directory is valid.
+**
+** Depends: SetCurrentDirectory,
+** CreateDirectory,
+** strcat,
+** memset,
+** CreateFile,
+** CloseHandle,
+** strcmp,
+** DeleteFileW,
+** RemoveDirectory.
+**
+
+**
+**===================================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+#ifdef WIN32
+const WCHAR szSeperator[] = {'\\','\\','\0'};
+#else
+const WCHAR szSeperator[] = {'/','/','\0'};
+#endif
+
+const WCHAR szDotDot[] = {'.','.','\0'};
+const WCHAR szFileName[] = {'t','e','s','t','i','n','g','.','t','m','p','\0'};
+
+int __cdecl main(int argc, char *argv[])
+{
+ DWORD dwRc = 0;
+
+ WCHAR szReturnedPath[_MAX_DIR+1];
+ WCHAR szFullFileName[_MAX_DIR+1];
+ WCHAR szDirectory[256];
+ WCHAR szCreatedDir[] = {'t','e','s','t','_','d','i','r','\0'};
+ WCHAR szCreatedNextDir[] = {'l','e','v','e','l','1','\0'};
+
+ LPWSTR pPathPtr;
+ HANDLE hFile = NULL;
+ BOOL bRetVal = FAIL;
+
+ /* Initialize the PAL.
+ */
+ if ( 0 != PAL_Initialize(argc,argv) )
+ {
+ return (FAIL);
+ }
+
+ /* Initialize the buffer.
+ */
+ memset( szDirectory, '\0', 256 );
+
+ /* Change the current working directory.
+ */
+ if ( !SetCurrentDirectoryW(szDotDot) )
+ {
+ Fail("ERROR: SetCurrentDirectoryA failed with error code %u "
+ "when passed \"%S\".\n",
+ GetLastError(),
+ szDotDot);
+ }
+
+ /* Create the path to the next level of directory to create.
+ */
+ wcscat(szDirectory, szCreatedDir); /* test_dir */
+
+
+ /* Create a test directory.
+ */
+ if (!CreateDirectoryW(szDirectory, NULL))
+ {
+ Fail("ERROR:%u: Unable to create directories \"%S\".\n",
+ GetLastError(),
+ szDirectory);
+ }
+
+ /* Create the path to the next level of directory to create.
+ */
+ wcscat(szDirectory, szSeperator); /* / */
+ wcscat(szDirectory, szCreatedNextDir); /* /level1 */
+
+ /* Create a test directory.
+ */
+ if (!CreateDirectoryW(szDirectory, NULL))
+ {
+ Trace("ERROR:%u: Unable to create directories \"%S\".\n",
+ GetLastError(),
+ szDirectory);
+ bRetVal = FAIL;
+ goto cleanUpOne;
+ }
+
+ /* Initialize the receiving char buffers.
+ */
+ memset(szReturnedPath, 0, _MAX_DIR+1);
+ memset(szFullFileName, 0, _MAX_DIR+1);
+
+ /* Create Full filename to pass, will include '..\'
+ * in the middle of the path.
+ */
+ wcscat(szFullFileName, szCreatedDir); /*test_dir */
+ wcscat(szFullFileName, szSeperator); /*test_dir/ */
+ wcscat(szFullFileName, szCreatedNextDir);/*test_dir/level1 */
+ wcscat(szFullFileName, szSeperator); /*test_dir/level1/ */
+ wcscat(szFullFileName, szDotDot); /*test_dir/level1/.. */
+ wcscat(szFullFileName, szSeperator); /*test_dir/level1/../ */
+ wcscat(szFullFileName, szFileName); /*test_dir/level1/../testing.tmp */
+
+ /* Get the full path to the filename.
+ */
+ dwRc = GetFullPathNameW(szFullFileName,
+ _MAX_DIR,
+ szReturnedPath,
+ &pPathPtr);
+ if (dwRc == 0)
+ {
+ Trace("ERROR :%ld: GetFullPathNameW failed to "
+ "retrieve the path of \"%S\".\n",
+ GetLastError(),
+ szFileName);
+ bRetVal = FAIL;
+ goto cleanUpTwo;
+ }
+
+ /* The returned value should be the parent directory with the
+ * file name appended. */
+ hFile = CreateFileW(szReturnedPath,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Trace("ERROR :%ld: CreateFileA failed to create \"%S\".\n",
+ GetLastError(),
+ szReturnedPath);
+ bRetVal = FAIL;
+ goto cleanUpTwo;
+ }
+
+ /* Close the handle to the created file.
+ */
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("ERROR :%ld: CloseHandle failed close hFile=0x%lx.\n",
+ GetLastError());
+ bRetVal = FAIL;
+ goto cleanUpThree;
+ }
+
+ /* Verify that the file was created, attempt to create
+ * the file again. */
+ hFile = CreateFileW(szReturnedPath,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ CREATE_NEW,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if ((hFile != INVALID_HANDLE_VALUE) &&
+ (GetLastError() != ERROR_ALREADY_EXISTS))
+ {
+ Trace("ERROR :%ld: CreateFileA succeeded to create file "
+ "\"%S\", that already existed.\n",
+ GetLastError(),
+ szFullFileName);
+ bRetVal = FAIL;
+ goto cleanUpThree;
+ }
+
+ /* Verify that the returned filename is the same as the supplied.
+ */
+ if (wcscmp(pPathPtr, szFileName) != 0)
+ {
+ Trace("ERROR : Returned filename \"%s\" is not equal to "
+ "supplied filename \"%s\".\n",
+ pPathPtr,
+ szFileName);
+ bRetVal = FAIL;
+ goto cleanUpThree;
+ }
+
+ /* Successful test.
+ */
+ bRetVal = PASS;
+
+cleanUpThree:
+
+ /* Delete the create file.
+ */
+ if (DeleteFileW(szReturnedPath) != TRUE)
+ {
+ Fail("ERROR :%ld: DeleteFileA failed to delete \"%S\".\n",
+ GetLastError(),
+ szFileName);
+ }
+
+cleanUpTwo:
+
+ /* Remove the empty directory.
+ */
+ if (!RemoveDirectoryW(szDirectory))
+ {
+ Fail("ERROR:%u: Unable to remove directory \"%S\".\n",
+ GetLastError(),
+ szCreatedDir);
+ }
+
+cleanUpOne:
+
+ /* Remove the empty directory.
+ */
+ if (!RemoveDirectoryW(szCreatedDir))
+ {
+ Fail("ERROR:%u: Unable to remove directory \"%s\".\n",
+ GetLastError(),
+ szCreatedDir);
+ }
+
+ /* Terminate the PAL.*/
+ PAL_TerminateEx(bRetVal);
+ return bRetVal;
+}
diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/testinfo.dat b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/testinfo.dat
new file mode 100644
index 0000000000..1eb6a27ada
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/testinfo.dat
@@ -0,0 +1,19 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetFullPathNameW
+Name = Test for GetFullPathNameW
+Type = DEFAULT
+EXE1 = test3
+Description
+= Tests the PAL implementation of the GetFullPathNameW API.
+= GetFullPathW will be passed a directory that contains '..'.
+= Example: test_directory\level1\..\testing.tmp.
+= To add to this test, we will also call SetCurrentDirectory to
+= ensure this is handled properly.
+= The test will create a file with in the parent directory
+= to verify that the returned directory is valid.
+
diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/CMakeLists.txt
new file mode 100644
index 0000000000..d479b998cc
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_getfullpathnamew_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getfullpathnamew_test4 coreclrpal)
+
+target_link_libraries(paltest_getfullpathnamew_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/test4.c b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/test4.c
new file mode 100644
index 0000000000..25eb10d654
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/test4.c
@@ -0,0 +1,201 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test4.c
+**
+** Purpose: Tests the PAL implementation of the GetFullPathNameW API.
+** GetFullPathNameW will be passed a directory that begins with '..'.
+** Example: ..\test_directory\testing.tmp.
+** To add to this test, we will also call SetCurrentDirectory to
+** ensure this is handled properly.
+** The test will create a file with in the parent directory
+** to verify that the returned directory is valid.
+**
+** Depends: SetCurrentDirectory,
+** CreateDirectory,
+** strcat,
+** memset,
+** CreateFile,
+** CloseHandle,
+** strcmp,
+** DeleteFileW,
+** RemoveDirectory.
+**
+
+**
+**===================================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+#ifdef WIN32
+ const WCHAR szSeperator[] = {'\\','\\','\0'};
+#else
+ const WCHAR szSeperator[] = {'/','/','\0'};
+#endif
+
+const WCHAR szDotDot[] = {'.','.','\0'};
+const WCHAR szFileName[] = {'t','e','s','t','i','n','g','.','t','m','p','\0'};
+
+int __cdecl main(int argc, char *argv[])
+{
+ DWORD dwRc = 0;
+
+ WCHAR szReturnedPath[_MAX_DIR+1];
+ WCHAR szFullFileName[_MAX_DIR+1];
+ WCHAR szDirectory[256];
+ WCHAR szCreatedDir[] = {'t','e','s','t','_','d','i','r','\0'};
+
+ LPWSTR pPathPtr;
+ HANDLE hFile = NULL;
+ BOOL bRetVal = FAIL;
+
+ /* Initialize the PAL.
+ */
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return (FAIL);
+ }
+
+ /* Initialize the buffer.
+ */
+ memset(szDirectory, '\0', 256);
+
+ /* Create the path to the next level of directory to create.
+ */
+ wcscat(szDirectory, szDotDot); /* .. */
+ wcscat(szDirectory, szSeperator); /* ../ */
+ wcscat(szDirectory, szCreatedDir); /* ../test_directory */
+
+ /* Create a test directory.
+ */
+ if (!CreateDirectoryW(szDirectory, NULL))
+ {
+ Fail("ERROR:%u: Unable to create directories \"%S\".\n",
+ GetLastError(),
+ szDirectory);
+ }
+
+ /* Initialize the receiving char buffers.
+ */
+ memset(szReturnedPath, 0, _MAX_DIR+1);
+ memset(szFullFileName, 0, _MAX_DIR+1);
+
+ /* Create Full filename to pass, will include '..\'
+ * in the middle of the path.
+ */
+ wcscat( szFullFileName, szDotDot ); /* .. */
+ wcscat( szFullFileName, szSeperator ); /* ../ */
+ wcscat( szFullFileName, szCreatedDir ); /* ../test_directory */
+ wcscat( szFullFileName, szSeperator ); /* ../test_directory/ */
+ wcscat( szFullFileName, szFileName ); /* ../test_directory/testing.tmp */
+
+ /* Get the full path to the filename.
+ */
+ dwRc = GetFullPathNameW(szFullFileName,
+ _MAX_DIR,
+ szReturnedPath,
+ &pPathPtr);
+ if (dwRc == 0)
+ {
+ Trace("ERROR :%ld: GetFullPathName failed to "
+ "retrieve the path of \"%S\".\n",
+ GetLastError(),
+ szFileName);
+ bRetVal = FAIL;
+ goto cleanUpOne;
+ }
+
+ /* The returned value should be the parent directory with the
+ * file name appended. */
+ hFile = CreateFileW(szReturnedPath,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Trace("ERROR :%ld: CreateFileA failed to create \"%S\".\n",
+ GetLastError(),
+ szReturnedPath);
+ bRetVal = FAIL;
+ goto cleanUpOne;
+ }
+
+ /* Close the handle to the created file.
+ */
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("ERROR :%ld: CloseHandle failed close hFile=0x%lx.\n",
+ GetLastError());
+ bRetVal = FAIL;
+ goto cleanUpTwo;
+ }
+
+ /* Verify that the file was created, attempt to create
+ * the file again. */
+ hFile = CreateFileW(szReturnedPath,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ CREATE_NEW,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if ((hFile != INVALID_HANDLE_VALUE) &&
+ (GetLastError() != ERROR_ALREADY_EXISTS))
+ {
+ Trace("ERROR :%ld: CreateFileA succeeded to create file "
+ "\"%S\", that already existed.\n",
+ GetLastError(),
+ szFullFileName);
+ bRetVal = FAIL;
+ goto cleanUpTwo;
+ }
+
+ /* Verify that the returned filename is the same as the supplied.
+ */
+ if (wcscmp(pPathPtr, szFileName) != 0)
+ {
+ Trace("ERROR : Returned filename \"%S\" is not equal to "
+ "supplied filename \"%S\".\n",
+ pPathPtr,
+ szFileName);
+ bRetVal = FAIL;
+ goto cleanUpTwo;
+ }
+
+ /* Successful test.
+ */
+ bRetVal = PASS;
+
+cleanUpTwo:
+
+ /* Delete the create file.
+ */
+ if (DeleteFileW(szReturnedPath) != TRUE)
+ {
+ Fail("ERROR :%ld: DeleteFileA failed to delete \"%S\".\n",
+ GetLastError(),
+ szFileName);
+ }
+
+cleanUpOne:
+
+ /* Remove the empty directory.
+ */
+ if (!RemoveDirectoryW(szDirectory))
+ {
+ Fail("ERROR:%u: Unable to remove directory \"%s\".\n",
+ GetLastError(),
+ szCreatedDir);
+ }
+
+ /* Terminate the PAL.*/
+ PAL_TerminateEx(bRetVal);
+ return bRetVal;
+}
diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/testinfo.dat b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/testinfo.dat
new file mode 100644
index 0000000000..8a7b3b35da
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/testinfo.dat
@@ -0,0 +1,19 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetFullPathNameA
+Name = Test for GetFullPathNameA
+Type = DEFAULT
+EXE1 = test4
+Description
+= Tests the PAL implementation of the GetFullPathNameA API.
+= GetFullPathA will be passed a directory that begins with '..'.
+= Example: ..\test_directory\level1\testing.tmp.
+= To add to this test, we will also call SetCurrentDirectory to
+= ensure this is handled properly.
+= The test will create a file with in the parent directory
+= to verify that the returned directory is valid.
+
diff --git a/src/pal/tests/palsuite/file_io/GetLongPathNameW/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetLongPathNameW/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetLongPathNameW/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/file_io/GetLongPathNameW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetLongPathNameW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..cf5dcd0bfc
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetLongPathNameW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetLongPathNameW.c
+)
+
+add_executable(paltest_getlongpathnamew_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getlongpathnamew_test1 coreclrpal)
+
+target_link_libraries(paltest_getlongpathnamew_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetLongPathNameW/test1/GetLongPathNameW.c b/src/pal/tests/palsuite/file_io/GetLongPathNameW/test1/GetLongPathNameW.c
new file mode 100644
index 0000000000..22831dda15
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetLongPathNameW/test1/GetLongPathNameW.c
@@ -0,0 +1,280 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: GetLongPathNameW.c Win32 version(test 1)
+**
+** Purpose: Tests the PAL implementation of the GetLongPathNameW function.
+** as expected under Win32
+**
+** Depends on:
+** CreateDirectoryA
+** RemoveDirectoryW
+**
+**
+**===================================================================*/
+/*
+tests:
+ - test invalid path names
+ - test an already short path name
+ - test a long path name
+ - test with buffer size too small
+*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+/* Since GetLongPathNameW operates differently under FreeBSD and Win32 this test
+ is for Win32 only. It runs the same tests as the FreeBSD version but checks for
+ different results
+*/
+
+#if WIN32
+ DWORD dwRc = 0;
+ WCHAR szwReturnedPath[MAX_LONGPATH];
+ WCHAR szwSmallBuff[3];
+ const char szShortPathName[] = {"testing"};
+ const char szLongPathName[] = {"This_is_a_long_directory_name"};
+ const char szShortenedPathName[] = {"THIS_I~1"};
+ WCHAR* wLongPathPtr = NULL;
+ WCHAR* wShortPathPtr = NULL;
+
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ memset(szwReturnedPath, 0, MAX_LONGPATH*sizeof(WCHAR));
+ memset(szwSmallBuff, 0, 3*sizeof(WCHAR));
+ wLongPathPtr = convert((char*)szLongPathName);
+ wShortPathPtr = convert((char*)szShortenedPathName);
+
+ /* do some clean up just to be safe */
+ RemoveDirectoryW(wLongPathPtr);
+ RemoveDirectoryW(wShortPathPtr);
+
+
+ /* attempt call on an invalid short path name */
+ dwRc = GetLongPathNameW(wShortPathPtr, szwReturnedPath, MAX_LONGPATH);
+ if (dwRc != 0)
+ {
+ Trace("GetLongPathNameW: ERROR -> Call made with an invalid short "
+ "path \"%S\" returned \"%S\"\n",
+ wShortPathPtr,
+ szwReturnedPath);
+ free (wLongPathPtr);
+ free (wShortPathPtr);
+ Fail("");
+ }
+
+
+ /* attempt call on an invalid long path name */
+ dwRc = GetLongPathNameW(wLongPathPtr, szwReturnedPath, MAX_LONGPATH);
+ if (dwRc != 0)
+ {
+ Trace("GetLongPathNameW: ERROR -> Call made with an invalid long "
+ "path \"%S\" returned \"%S\"\n",
+ wLongPathPtr,
+ szwReturnedPath);
+ free (wLongPathPtr);
+ free (wShortPathPtr);
+ Fail("");
+ }
+
+
+ /* create a long directory name */
+ if (TRUE != CreateDirectoryW(wLongPathPtr, NULL))
+ {
+ free(wLongPathPtr);
+ free(wShortPathPtr);
+ Fail("GetLongPathNameW: ERROR -> CreateDirectoryW failed with an error"
+ " code of %ld when asked to create a directory called \"%s\".\n",
+ GetLastError(),
+ szLongPathName);
+ }
+
+
+ /* get the long path name */
+ memset(szwReturnedPath, 0, MAX_LONGPATH*sizeof(WCHAR));
+ dwRc = GetLongPathNameW(wShortPathPtr, szwReturnedPath, MAX_LONGPATH);
+ if (dwRc == 0)
+ {
+ Trace("GetLongPathNameW: ERROR -> failed with an error"
+ " code of %ld when asked for the long version of \"%s\".\n",
+ GetLastError(),
+ szShortenedPathName);
+ if (RemoveDirectoryW(wLongPathPtr) != TRUE)
+ {
+ Trace("GetLongPathNameW: ERROR -> RemoveDirectoryW failed to "
+ " remove the directory \"%S\" with an error code of %ld.\n",
+ wLongPathPtr,
+ GetLastError());
+ }
+ free(wLongPathPtr);
+ free(wShortPathPtr);
+ Fail("");
+ }
+
+ /* does the returned match the expected */
+ if (wcsncmp(wLongPathPtr, szwReturnedPath, wcslen(wLongPathPtr)) ||
+ (wcslen(wLongPathPtr) != wcslen(szwReturnedPath)))
+ {
+ if (RemoveDirectoryW(wLongPathPtr) != TRUE)
+ {
+ Trace("GetLongPathNameW: ERROR -> RemoveDirectoryW failed to "
+ " remove the directory \"%S\" with an error code of %ld.\n",
+ wLongPathPtr,
+ GetLastError());
+ }
+ free(wLongPathPtr);
+ free(wShortPathPtr);
+ Fail("GetLongPathNameW: ERROR -> The returned path, \"%S\" doesn't "
+ "match the expected return, \"%s\".\n",
+ szwReturnedPath,
+ szLongPathName);
+ }
+
+ /* does the length returned match the actual length */
+ if (dwRc != wcslen(szwReturnedPath))
+ {
+ if (RemoveDirectoryW(wLongPathPtr) != TRUE)
+ {
+ Trace("GetLongPathNameW: ERROR -> RemoveDirectoryW failed to "
+ " remove the directory \"%S\" with an error code of %ld.\n",
+ wLongPathPtr,
+ GetLastError());
+ }
+ free(wLongPathPtr);
+ free(wShortPathPtr);
+ Fail("GetLongPathNameW: ERROR -> The returned length, %ld, doesn't "
+ "match the string length, %ld.\n",
+ dwRc,
+ wcslen(szwReturnedPath));
+ }
+
+ if (RemoveDirectoryW(wLongPathPtr) != TRUE)
+ {
+ Trace("GetLongPathNameW: ERROR -> RemoveDirectoryW failed to "
+ " remove the directory \"%S\" with an error code of %ld.\n",
+ wLongPathPtr,
+ GetLastError());
+ free(wShortPathPtr);
+ free(wLongPathPtr);
+ Fail("");
+ }
+ free(wShortPathPtr);
+ free(wLongPathPtr);
+
+
+ /* test an actual short name */
+ /* create a long directory name */
+ wShortPathPtr = convert((char*)szShortPathName);
+ RemoveDirectoryW(wShortPathPtr);
+
+ if (TRUE != CreateDirectoryW(wShortPathPtr, NULL))
+ {
+ Trace("GetLongPathNameW: ERROR -> CreateDirectoryW failed with an error"
+ " code of %ld when asked to create a directory called \"%s\".\n",
+ GetLastError(),
+ szShortPathName);
+ free(wShortPathPtr);
+ Fail("");
+ }
+
+
+ /* get the long path name */
+ memset(szwReturnedPath, 0, MAX_LONGPATH*sizeof(WCHAR));
+ dwRc = GetLongPathNameW(wShortPathPtr, szwReturnedPath, MAX_LONGPATH);
+ if (dwRc == 0)
+ {
+ Trace("GetLongPathNameW: ERROR -> failed with an error"
+ " code of %ld when asked for the long version of \"%s\".\n",
+ GetLastError(),
+ szShortenedPathName);
+ if (RemoveDirectoryW(wShortPathPtr) != TRUE)
+ {
+ Trace("GetLongPathNameW: ERROR -> RemoveDirectoryW failed to "
+ " remove the directory \"%S\" with an error code of %ld.\n",
+ wShortPathPtr,
+ GetLastError());
+ }
+ free(wShortPathPtr);
+ Fail("");
+ }
+
+ /* does the returned match the expected */
+ if (wcsncmp(wShortPathPtr, szwReturnedPath, wcslen(wShortPathPtr)) ||
+ (wcslen(wShortPathPtr) != wcslen(szwReturnedPath)))
+ {
+ if (RemoveDirectoryW(wShortPathPtr) != TRUE)
+ {
+ Trace("GetLongPathNameW: ERROR -> RemoveDirectoryW failed to "
+ " remove the directory \"%S\" with an error code of %ld.\n",
+ wShortPathPtr,
+ GetLastError());
+ }
+ free(wShortPathPtr);
+ Fail("GetLongPathNameW: ERROR -> The returned path, \"%S\" doesn't "
+ "match the expected return, \"%s\".\n",
+ szwReturnedPath,
+ szShortPathName);
+ }
+
+ /* does the length returned match the actual length */
+ if (dwRc != wcslen(szwReturnedPath))
+ {
+ if (RemoveDirectoryW(wShortPathPtr) != TRUE)
+ {
+ Trace("GetLongPathNameW: ERROR -> RemoveDirectoryW failed to "
+ " remove the directory \"%S\" with an error code of %ld.\n",
+ wShortPathPtr,
+ GetLastError());
+ }
+ free(wShortPathPtr);
+ Fail("GetLongPathNameW: ERROR -> The returned length, %ld, doesn't "
+ "match the string length, %ld.\n",
+ dwRc,
+ wcslen(szwReturnedPath));
+ }
+
+ /* test using a too small return buffer */
+ dwRc = GetLongPathNameW(wShortPathPtr, szwSmallBuff, 3);
+ if ((dwRc != (strlen(szShortPathName)+1)) || /* +1 for the required NULL */
+ szwSmallBuff[0] != '\0')
+ {
+ if (RemoveDirectoryW(wShortPathPtr) != TRUE)
+ {
+ Trace("GetLongPathNameW: ERROR -> RemoveDirectoryW failed to "
+ " remove the directory \"%S\" with an error code of %ld.\n",
+ wShortPathPtr,
+ GetLastError());
+ }
+ free(wShortPathPtr);
+ Fail("GetLongPathNameW: ERROR -> using a return buffer that was too"
+ " small was not handled properly.\n");
+ }
+
+ if (RemoveDirectoryW(wShortPathPtr) != TRUE)
+ {
+ Trace("GetLongPathNameW: ERROR -> RemoveDirectoryW failed to "
+ " remove the directory \"%S\" with an error code of %ld.\n",
+ wShortPathPtr,
+ GetLastError());
+ free(wShortPathPtr);
+ Fail("");
+ }
+ free(wShortPathPtr);
+
+ PAL_Terminate();
+
+#endif /* WIN32 */
+
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/file_io/GetLongPathNameW/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/GetLongPathNameW/test1/testinfo.dat
new file mode 100644
index 0000000000..f730300c43
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetLongPathNameW/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetLongPathNameW
+Name = Test for GetLongPathNameW Win32 (test 1)
+Type = DEFAULT
+EXE1 = getlongpathnamew
+Description
+= Tests invalid path names. Tests conversion of short to long
+= path names as well as passing it a path name that is already short.
+= Under BSD, there isn't a shortened version of directory names so
+= I just use a long path name as the short path name to ensure it returns
+= the same thing.
diff --git a/src/pal/tests/palsuite/file_io/GetLongPathNameW/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetLongPathNameW/test2/CMakeLists.txt
new file mode 100644
index 0000000000..5746ef3e04
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetLongPathNameW/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ getlongpathnamew.c
+)
+
+add_executable(paltest_getlongpathnamew_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getlongpathnamew_test2 coreclrpal)
+
+target_link_libraries(paltest_getlongpathnamew_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetLongPathNameW/test2/getlongpathnamew.c b/src/pal/tests/palsuite/file_io/GetLongPathNameW/test2/getlongpathnamew.c
new file mode 100644
index 0000000000..3b033e9a64
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetLongPathNameW/test2/getlongpathnamew.c
@@ -0,0 +1,266 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: GetLongPathNameW.c FreeBSD version(test 2)
+**
+** Purpose: Tests the PAL implementation of the GetLongPathNameW function
+** as expected under FreeBSD
+**
+** Depends on:
+** CreateDirectoryA
+** RemoveDirectoryW
+**
+**
+**===================================================================*/
+/*
+tests:
+ - test invalid path names
+ - test an already short path name
+ - test a long path name
+ - test with buffer size too small
+*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+/* Since GetLongPathNameW operates differently under FreeBSD and Win32 this test
+ is for freeBSD only. It runs the same tests as the Win32 version but checks for
+ different results
+*/
+#if !(WIN32) /* Only execute if the is Free BSD */
+
+ DWORD dwRc = 0;
+ WCHAR szwReturnedPath[MAX_LONGPATH];
+ WCHAR szwSmallBuff[3];
+ const char szShortPathName[] = {"testing"};
+ const char szLongPathName[] = {"This_is_a_long_directory_name"};
+ /* since BSD doesn't shorten long dir names, it will only use the long name */
+ const char szShortenedPathName[] = {"This_is_a_long_directory_name"};
+ WCHAR* wLongPathPtr = NULL;
+ WCHAR* wShortPathPtr = NULL;
+ int StringLen = 0;
+
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+ memset(szwReturnedPath, 0, MAX_LONGPATH*sizeof(WCHAR));
+ memset(szwSmallBuff, 0, 3*sizeof(WCHAR));
+ wLongPathPtr = convert((char*)szLongPathName);
+ wShortPathPtr = convert((char*)szShortenedPathName);
+
+
+ /* do some clean up just to be safe */
+ RemoveDirectoryW(wLongPathPtr);
+ RemoveDirectoryW(wShortPathPtr);
+
+
+ /* attempt call on an invalid short path name */
+ dwRc = GetLongPathNameW(wShortPathPtr, szwReturnedPath, MAX_LONGPATH);
+ if (dwRc != 0)
+ {
+ Trace("GetLongPathNameW: ERROR -> Call made with an invalid short "
+ "path \"%S\" returned \"%S\"\n",
+ wShortPathPtr,
+ szwReturnedPath);
+ free (wLongPathPtr);
+ free (wShortPathPtr);
+ Fail("");
+ }
+
+
+ /* attempt call on an invalid long path name */
+ dwRc = GetLongPathNameW(wLongPathPtr, szwReturnedPath, MAX_LONGPATH);
+ if (dwRc != 0)
+ {
+ Trace("GetLongPathNameW: ERROR -> Call made with an invalid long "
+ "path \"%S\" returned \"%S\"\n",
+ wLongPathPtr,
+ szwReturnedPath);
+ free (wLongPathPtr);
+ free (wShortPathPtr);
+ Fail("");
+ }
+
+
+ /* create a long directory name */
+ if (TRUE != CreateDirectoryW(wLongPathPtr, NULL))
+ {
+ free(wLongPathPtr);
+ free(wShortPathPtr);
+ Fail("GetLongPathNameW: ERROR -> CreateDirectoryW failed with an error"
+ " code of %ld when asked to create a directory called \"%s\".\n",
+ GetLastError(),
+ szLongPathName);
+ }
+
+
+ /* get the long path name */
+ memset(szwReturnedPath, 0, MAX_LONGPATH*sizeof(WCHAR));
+ dwRc = GetLongPathNameW(wShortPathPtr, szwReturnedPath, MAX_LONGPATH);
+ StringLen = wcslen(wShortPathPtr);
+
+ if (dwRc != StringLen)
+ {
+ Trace("GetLongPathNameW: ERROR -> Under FreeBSD, this test should"
+ " have returned %d but instead returned %d.\n",
+ StringLen, dwRc);
+ if (RemoveDirectoryW(wLongPathPtr) != TRUE)
+ {
+ Trace("GetLongPathNameW: ERROR -> RemoveDirectoryW failed to "
+ " remove the directory \"%S\" with an error code of %ld.\n",
+ wLongPathPtr,
+ GetLastError());
+ }
+ free(wLongPathPtr);
+ free(wShortPathPtr);
+ Fail("");
+ }
+ if (wcsncmp(wShortPathPtr,szwReturnedPath, StringLen) != 0)
+ {
+ Trace("GetLongPathNameW: ERROR -> Under Unix,"
+ "the lpszLongPath \"%s\" should have been,"
+ "but was \"%s\".\n",
+ wShortPathPtr, szwReturnedPath);
+
+ if (RemoveDirectoryW(wLongPathPtr) != TRUE)
+ {
+ Trace("GetLongPathNameW: ERROR -> RemoveDirectoryW failed to "
+ " remove the directory \"%S\" with an error code of %ld.\n",
+ wLongPathPtr,
+ GetLastError());
+ }
+ free(wLongPathPtr);
+ free(wShortPathPtr);
+ Fail("");
+ }
+
+ if (RemoveDirectoryW(wLongPathPtr) != TRUE)
+ {
+ Trace("GetLongPathNameW: ERROR -> RemoveDirectoryW failed to "
+ " remove the directory \"%S\" with an error code of %ld.\n",
+ wLongPathPtr,
+ GetLastError());
+ free(wLongPathPtr);
+ free(wShortPathPtr);
+ Fail("");
+ }
+ free(wShortPathPtr);
+ free(wLongPathPtr);
+
+
+ /* test an actual short name */
+ /* create a long directory name */
+ wShortPathPtr = convert((char*)szShortPathName);
+ RemoveDirectoryW(wShortPathPtr);
+
+ if (TRUE != CreateDirectoryW(wShortPathPtr, NULL))
+ {
+ free(wShortPathPtr);
+ Fail("GetLongPathNameW: ERROR -> CreateDirectoryW failed with an error"
+ " code of %ld when asked to create a directory called \"%s\".\n",
+ GetLastError(),
+ szShortPathName);
+ }
+
+
+ /* get the long path name */
+ memset(szwReturnedPath, 0, MAX_LONGPATH*sizeof(WCHAR));
+ dwRc = GetLongPathNameW(wShortPathPtr, szwReturnedPath, MAX_LONGPATH);
+ StringLen = wcslen (wShortPathPtr);
+
+ if (dwRc != StringLen)
+ {
+ Trace("GetLongPathNameW: ERROR -> Under FreeBSD, this test should"
+ " have returned %d but instead returned %d.\n",
+ StringLen, dwRc);
+ if (RemoveDirectoryW(wShortPathPtr) != TRUE)
+ {
+ Trace("GetLongPathNameW: ERROR -> RemoveDirectoryW failed to "
+ " remove the directory \"%S\" with an error code of %ld.\n",
+ wShortPathPtr,
+ GetLastError());
+ }
+ free(wShortPathPtr);
+ Fail("");
+ }
+ if (wcsncmp(wShortPathPtr, szwReturnedPath, StringLen) != 0)
+ {
+ Trace("GetLongPathNameW: ERROR -> Under Unix, the lpszLongPath"
+ "\"%s\" should have been,"
+ "but was \"%s\".\n",
+ wShortPathPtr, szwReturnedPath);
+
+ if (RemoveDirectoryW(wShortPathPtr) != TRUE)
+ {
+ Trace("GetLongPathNameW: ERROR -> RemoveDirectoryW failed to "
+ " remove the directory \"%S\" with an error code of %ld.\n",
+ wShortPathPtr,
+ GetLastError());
+ }
+ free(wShortPathPtr);
+ Fail("");
+ }
+
+
+ /* test using a too small return buffer */
+ dwRc = GetLongPathNameW(wShortPathPtr, szwSmallBuff, 3);
+ StringLen = wcslen (wShortPathPtr);
+
+
+ if (dwRc != (StringLen + 1)) //Return size includes NULL char
+ {
+ Trace("GetLongPathNameW: ERROR -> Under FreeBSD, this test should"
+ " have returned %d but instead returned %d.\n",
+ StringLen, dwRc);
+ if (RemoveDirectoryW(wShortPathPtr) != TRUE)
+ {
+ Trace("GetLongPathNameW: ERROR -> RemoveDirectoryW failed to "
+ " remove the directory \"%S\" with an error code of %ld.\n",
+ wShortPathPtr,
+ GetLastError());
+ }
+ free(wShortPathPtr);
+ Fail("");
+ }
+ if (szwSmallBuff[0] != 0)
+ {
+ Trace("GetLongPathNameW: ERROR -> Under FreeBSD, this test should"
+ " not have touched lpszLongPath but instead it returned\"%s\".\n",
+ szwReturnedPath);
+ if (RemoveDirectoryW(wShortPathPtr) != TRUE)
+ {
+ Trace("GetLongPathNameW: ERROR -> RemoveDirectoryW failed to "
+ " remove the directory \"%S\" with an error code of %ld.\n",
+ wShortPathPtr,
+ GetLastError());
+ }
+ free(wShortPathPtr);
+ Fail("");
+ }
+
+ /* clean up */
+ if (RemoveDirectoryW(wShortPathPtr) != TRUE)
+ {
+ Trace("GetLongPathNameW: ERROR -> RemoveDirectoryW failed to "
+ " remove the directory \"%S\" with an error code of %ld.\n",
+ wShortPathPtr,
+ GetLastError());
+ free(wShortPathPtr);
+ Fail("");
+ }
+ free(wShortPathPtr);
+
+ PAL_Terminate();
+
+#endif /* Free BSD */
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/file_io/GetLongPathNameW/test2/testinfo.dat b/src/pal/tests/palsuite/file_io/GetLongPathNameW/test2/testinfo.dat
new file mode 100644
index 0000000000..5144a35b13
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetLongPathNameW/test2/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetLongPathNameW
+Name = Test for GetLongPathNameW FreeBSD version (test 2)
+Type = DEFAULT
+EXE1 = getlongpathnamew
+Description
+= Tests invalid path names. Tests conversion of short to long
+= path names as well as passing it a path name that is already short.
+= Under BSD, there isn't a shortened version of directory names so
+= I just use a long path name as the short path name to ensure it returns
+= the same thing.
diff --git a/src/pal/tests/palsuite/file_io/GetStdHandle/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetStdHandle/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetStdHandle/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/file_io/GetStdHandle/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetStdHandle/test1/CMakeLists.txt
new file mode 100644
index 0000000000..04bcc5fd67
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetStdHandle/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetStdHandle.c
+)
+
+add_executable(paltest_getstdhandle_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getstdhandle_test1 coreclrpal)
+
+target_link_libraries(paltest_getstdhandle_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetStdHandle/test1/GetStdHandle.c b/src/pal/tests/palsuite/file_io/GetStdHandle/test1/GetStdHandle.c
new file mode 100644
index 0000000000..f4fe03195d
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetStdHandle/test1/GetStdHandle.c
@@ -0,0 +1,132 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: GetStdHandle.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the GetStdHandle function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE hFile = NULL;
+ DWORD dwBytesWritten = 0;
+ DWORD dwFileType;
+ BOOL bRc = FALSE;
+ const char* szText = "this is a test of GetStdHandle\n";
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /*
+ * attempt to get an invalid handle
+ */
+ hFile = GetStdHandle(-2);
+ if (hFile != INVALID_HANDLE_VALUE)
+ {
+ Fail("GetStdHandle: ERROR -> A request for the STD_INPUT_HANDLE "
+ "returned an invalid handle.\n");
+ }
+
+
+ /*
+ * test the STD_INPUT_HANDLE handle
+ */
+ hFile = GetStdHandle(STD_INPUT_HANDLE);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("GetStdHandle: ERROR -> A request for the STD_INPUT_HANDLE "
+ "returned an invalid handle.\n");
+ }
+
+ /* an attempt to write to the input handle should fail */
+ /* I don't know how to automate a read from the input handle */
+ bRc = WriteFile(hFile, szText, (DWORD)strlen(szText), &dwBytesWritten, NULL);
+ if (bRc != FALSE)
+ {
+ Fail("GetStdHandle: ERROR -> WriteFile was able to write to "
+ "STD_INPUT_HANDLE when it should have failed.\n");
+ }
+
+
+ /*
+ * test the STD_OUTPUT_HANDLE handle
+ */
+ hFile = GetStdHandle(STD_OUTPUT_HANDLE);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("GetStdHandle: ERROR -> A request for the STD_OUTPUT_HANDLE "
+ "returned an invalid handle.\n");
+ }
+
+ /* try to write to the output handle */
+ bRc = WriteFile(hFile, szText, (DWORD)strlen(szText), &dwBytesWritten, NULL);
+ if (bRc != TRUE)
+ {
+ Fail("GetStdHandle: ERROR -> WriteFile failed to write to "
+ "STD_OUTPUT_HANDLE with the error %ld\n",
+ GetLastError());
+ }
+
+
+ /* test the STD_ERROR_HANDLE handle */
+ hFile = GetStdHandle(STD_ERROR_HANDLE);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("GetStdHandle: ERROR -> A request for the STD_ERROR_HANDLE "
+ "returned an invalid handle.\n");
+ }
+
+ /* try to write to the error handle */
+ bRc = WriteFile(hFile, szText, (DWORD)strlen(szText), &dwBytesWritten, NULL);
+ if (bRc != TRUE)
+ {
+ Fail("GetStdHandle: ERROR -> WriteFile failed to write to "
+ "STD_ERROR_HANDLE with the error %ld\n",
+ GetLastError());
+ }
+
+ /* check if the file type is correct for the handle */
+ if((dwFileType = GetFileType(hFile)) != FILE_TYPE_CHAR)
+ {
+ Fail("GetStdHandle: ERROR -> GetFileType returned %u for "
+ "STD_ERROR_HANDLE instead of the expected FILE_TYPE_CHAR (%u).\n",
+ dwFileType,
+ FILE_TYPE_CHAR);
+ }
+
+ /* check to see if we can CloseHandle works on the STD_ERROR_HANDLE */
+ if (!CloseHandle(hFile))
+ {
+ Fail("GetStdHandle: ERROR -> CloseHandle failed. GetLastError "
+ "returned %u.\n",
+ GetLastError());
+ }
+
+ /* try to write to the closed error handle */
+ bRc = WriteFile(hFile,
+ szText,
+ (DWORD)strlen(szText),
+ &dwBytesWritten,
+ NULL);
+ if (bRc)
+ {
+ Fail("GetStdHandle: ERROR -> WriteFile was able to write to the closed"
+ " STD_ERROR_HANDLE handle.\n");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/file_io/GetStdHandle/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/GetStdHandle/test1/testinfo.dat
new file mode 100644
index 0000000000..3f7dbf5f42
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetStdHandle/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetStdHandle
+Name = Positive Test for GetStdHandle (test 1)
+Type = DEFAULT
+EXE1 = getstdhandle
+Description
+= Test GetStdHandle on a valid/invalid std handles
+
diff --git a/src/pal/tests/palsuite/file_io/GetStdHandle/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetStdHandle/test2/CMakeLists.txt
new file mode 100644
index 0000000000..97816b4319
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetStdHandle/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetStdHandle.c
+)
+
+add_executable(paltest_getstdhandle_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getstdhandle_test2 coreclrpal)
+
+target_link_libraries(paltest_getstdhandle_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetStdHandle/test2/GetStdHandle.c b/src/pal/tests/palsuite/file_io/GetStdHandle/test2/GetStdHandle.c
new file mode 100644
index 0000000000..45f5ddd243
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetStdHandle/test2/GetStdHandle.c
@@ -0,0 +1,79 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: GetStdHandle.c (test 2)
+**
+** Purpose: Smoke Tests the PAL implementation of the GetStdHandle function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE hFile = NULL;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /*
+ * attempt to get an invalid handle
+ */
+ hFile = GetStdHandle(-2);
+ if (hFile != INVALID_HANDLE_VALUE)
+ {
+ Fail("GetStdHandle: ERROR -> A request for the STD_INPUT_HANDLE "
+ "returned an invalid handle.\n");
+ }
+
+
+ /*
+ * test the STD_INPUT_HANDLE handle
+ */
+ hFile = GetStdHandle(STD_INPUT_HANDLE);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("GetStdHandle: ERROR -> A request for the STD_INPUT_HANDLE "
+ "returned an invalid handle.\n");
+ }
+
+
+ /*
+ * test the STD_OUTPUT_HANDLE handle
+ */
+ hFile = GetStdHandle(STD_OUTPUT_HANDLE);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("GetStdHandle: ERROR -> A request for the STD_OUTPUT_HANDLE "
+ "returned an invalid handle.\n");
+ }
+
+ /* test the STD_ERROR_HANDLE handle */
+ hFile = GetStdHandle(STD_ERROR_HANDLE);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("GetStdHandle: ERROR -> A request for the STD_ERROR_HANDLE "
+ "returned an invalid handle.\n");
+ }
+
+
+ /* check to see if we can CloseHandle works on the STD_ERROR_HANDLE */
+ if (!CloseHandle(hFile))
+ {
+ Fail("GetStdHandle: ERROR -> CloseHandle failed. GetLastError "
+ "returned %u.\n",
+ GetLastError());
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/file_io/GetStdHandle/test2/testinfo.dat b/src/pal/tests/palsuite/file_io/GetStdHandle/test2/testinfo.dat
new file mode 100644
index 0000000000..dcd498c6ef
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetStdHandle/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetStdHandle
+Name = Positive Test for GetStdHandle (test 2)
+Type = DEFAULT
+EXE1 = getstdhandle
+Description
+= Smoke Test GetStdHandle on a valid/invalid std handles
+
diff --git a/src/pal/tests/palsuite/file_io/GetSystemTime/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetSystemTime/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetSystemTime/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/file_io/GetSystemTime/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetSystemTime/test1/CMakeLists.txt
new file mode 100644
index 0000000000..94d5bcded9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetSystemTime/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_getsystemtime_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getsystemtime_test1 coreclrpal)
+
+target_link_libraries(paltest_getsystemtime_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetSystemTime/test1/test.c b/src/pal/tests/palsuite/file_io/GetSystemTime/test1/test.c
new file mode 100644
index 0000000000..361dbef33d
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetSystemTime/test1/test.c
@@ -0,0 +1,124 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for GetSystemTime() function
+**
+**
+**=========================================================*/
+
+/* Note: Some of the range comparisons only check
+ * the high end of the range. Since the structure
+ * contains WORDs, negative values can never be included,
+ * so there is no reason to check and see if the lower
+ * end of the spectrum is <0
+*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ SYSTEMTIME TheTime;
+ SYSTEMTIME firstTime;
+ SYSTEMTIME secondTime;
+
+ WORD avgDeltaFileTime = 0;
+
+ int i=0;
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ GetSystemTime(&TheTime);
+
+ /* Go through each item in the structure and ensure it is a valid value.
+ We can't ensure they have the exact values of the current time, but
+ at least that they have been set to a valid range of values for that
+ item.
+ */
+
+ /* Year */
+ if(TheTime.wYear < (WORD)2001)
+ {
+ Fail("ERROR: The year is %d, when it should be at least 2001.",
+ TheTime.wYear);
+ }
+
+ /* Month */
+ if(TheTime.wMonth > (WORD)12 || TheTime.wMonth < (WORD)1)
+ {
+ Fail("ERROR: The month should be between 1 and 12, and it is "
+ "showing up as %d.",TheTime.wMonth);
+ }
+
+ /* Weekday */
+ if(TheTime.wDayOfWeek > 6)
+ {
+ Fail("ERROR: The day of the week should be between 0 and 6, "
+ "and it is showing up as %d.",TheTime.wDayOfWeek);
+ }
+
+ /* Day of the Month */
+ if(TheTime.wDay > 31 || TheTime.wDay < 1)
+ {
+ Fail("ERROR: The day of the month should be between 1 and "
+ "31, and it is showing up as %d.",TheTime.wDay);
+ }
+
+ /* Hour */
+ if(TheTime.wHour > 23)
+ {
+ Fail("ERROR: The hour should be between 0 and 23, and it is "
+ "showing up as %d.",TheTime.wHour);
+ }
+
+ /* Minute */
+ if(TheTime.wMinute > 59)
+ {
+ Fail("ERROR: The minute should be between 0 and 59 and it is "
+ "showing up as %d.",TheTime.wMinute);
+ }
+
+ /* Second */
+ if(TheTime.wSecond > 59)
+ {
+ Fail("ERROR: The second should be between 0 and 59 and it is"
+ " showing up as %d.",TheTime.wSecond);
+ }
+
+ /* Millisecond */
+ if(TheTime.wMilliseconds > 999)
+ {
+ Fail("ERROR: The milliseconds should be between 0 and 999 "
+ "and it is currently showing %d.",TheTime.wMilliseconds);
+ }
+
+ /* check if two consecutive calls to system time return */
+ /* correct time in ms after sleep() call. */
+ for (i = 0; i<5 ;i++)
+ {
+ GetSystemTime(&firstTime);
+ Sleep(1000);
+ GetSystemTime(&secondTime);
+ avgDeltaFileTime += abs(firstTime.wSecond - secondTime.wSecond );
+
+ }
+
+ if( (avgDeltaFileTime/5) < 1.0)
+ {
+ Fail("ERROR: 2 calls for GetSystemTime interrupted"
+ " by a 1000 ms sleep failed Value[%f]", avgDeltaFileTime/5 );
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/file_io/GetSystemTime/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/GetSystemTime/test1/testinfo.dat
new file mode 100644
index 0000000000..05169f65c6
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetSystemTime/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = GetSystemTime
+Name = Positive test of GetSystemTime
+Type = DEFAULT
+EXE1 = test
+Description
+= Tests the PAL implementation of the GetSystemTime API
diff --git a/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/CMakeLists.txt
new file mode 100644
index 0000000000..977a826e7a
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetSystemTimeAsFileTime.c
+)
+
+add_executable(paltest_getsystemtimeasfiletime_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getsystemtimeasfiletime_test1 coreclrpal)
+
+target_link_libraries(paltest_getsystemtimeasfiletime_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/GetSystemTimeAsFileTime.c b/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/GetSystemTimeAsFileTime.c
new file mode 100644
index 0000000000..bd7e856abd
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/GetSystemTimeAsFileTime.c
@@ -0,0 +1,86 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: GetSystemTimeAsFileTime.c
+**
+** Purpose: Tests the PAL implementation of GetSystemTimeAsFileTime
+** Take two times, three seconds apart, and ensure that the time is
+** increasing, and that it has increased at least 3 seconds.
+**
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char **argv)
+{
+
+ FILETIME TheFirstTime, TheSecondTime;
+ ULONG64 FullFirstTime, FullSecondTime;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* Get two times, 3 seconds apart */
+
+ GetSystemTimeAsFileTime( &TheFirstTime );
+
+ Sleep( 3000 );
+
+ GetSystemTimeAsFileTime( &TheSecondTime );
+
+ /* Convert them to ULONG64 to work with */
+
+ FullFirstTime = ((( (ULONG64)TheFirstTime.dwHighDateTime )<<32) |
+ ( (ULONG64)TheFirstTime.dwLowDateTime ));
+
+ FullSecondTime = ((( (ULONG64)TheSecondTime.dwHighDateTime )<<32) |
+ ( (ULONG64)TheSecondTime.dwLowDateTime ));
+
+ /* Test to ensure the second value is larger than the first */
+
+ if( FullSecondTime <= FullFirstTime )
+ {
+ Fail("ERROR: The system time didn't increase in the last "
+ "three seconds. The second time tested was less than "
+ "or equal to the first.");
+ }
+
+ /* Note: The 30000000 magic number is 3 seconds in hundreds of nano
+ seconds. This test checks to ensure at least 3 seconds passed
+ between the readings.
+ */
+
+ if( ( (LONG64)( FullSecondTime - FullFirstTime ) - 30000000 ) < 0 )
+ {
+ ULONG64 TimeError;
+
+ /* Note: This test used to compare the difference between full times
+ in terms of hundreds of nanoseconds. But the x86 clock seems to be
+ precise only to the level of about 10000 nanoseconds, so we would
+ fail the comparison depending on when we took time slices.
+
+ To fix this, we just check that we're within a millisecond of
+ sleeping 3000 milliseconds. We're not currently ensuring that we
+ haven't slept much more than 3000 ms. We may want to do that.
+ */
+ TimeError = 30000000 - ( FullSecondTime - FullFirstTime );
+ if ( TimeError > 10000)
+ {
+ Fail("ERROR: Two system times were tested, with a sleep of 3 "
+ "seconds between. The time passed should have been at least "
+ "3 seconds. But, it was less according to the function.");
+ }
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/testinfo.dat
new file mode 100644
index 0000000000..3318d1386a
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetSystemTimeAsFileTime
+Name = Positive Test for GetSystemTimeAsFileTime
+TYPE = DEFAULT
+EXE1 = getsystemtimeasfiletime
+Description
+= Test the GetSystemTimeAsFileTime function.
+= Take two times, three seconds apart, and ensure that the time is
+= increasing, and that it has increased at least 3 seconds.
diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameA/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetTempFileNameA/CMakeLists.txt
new file mode 100644
index 0000000000..1962ade358
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetTempFileNameA/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+
diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/CMakeLists.txt
new file mode 100644
index 0000000000..1b759af2eb
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetTempFileNameA.c
+)
+
+add_executable(paltest_gettempfilenamea_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_gettempfilenamea_test1 coreclrpal)
+
+target_link_libraries(paltest_gettempfilenamea_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/GetTempFileNameA.c b/src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/GetTempFileNameA.c
new file mode 100644
index 0000000000..8ede8bab04
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/GetTempFileNameA.c
@@ -0,0 +1,125 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: GetTempFileNameA.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the GetTempFileNameA function.
+**
+** Depends on:
+** GetFileAttributesA
+** DeleteFileA
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ UINT uiError = 0;
+ const UINT uUnique = 0;
+ const char* szDot = {"."};
+ const char* szValidPrefix = {"cfr"};
+ const char* szLongValidPrefix = {"cfrwxyz"};
+ char szReturnedName[256];
+ char szTempString[256];
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* valid path with null prefix */
+ uiError = GetTempFileNameA(szDot, NULL, uUnique, szReturnedName);
+ if (uiError == 0)
+ {
+ Fail("GetTempFileNameA: ERROR -> Call failed with a valid path "
+ "with the error code: %ld\n", GetLastError());
+ }
+ else
+ {
+ /* verify temp file was created */
+ if (GetFileAttributesA(szReturnedName) == -1)
+ {
+ Fail("GetTempFileNameA: ERROR -> GetFileAttributes failed on the "
+ "returned temp file \"%s\" with error code: %ld.\n",
+ szReturnedName,
+ GetLastError());
+ }
+ if (DeleteFileA(szReturnedName) != TRUE)
+ {
+ Fail("GetTempFileNameA: ERROR -> DeleteFileW failed to delete"
+ "the created temp file with error code: %ld.\n", GetLastError());
+ }
+ }
+
+
+ /* valid path with valid prefix */
+ uiError = GetTempFileNameA(szDot, szValidPrefix, uUnique, szReturnedName);
+ if (uiError == 0)
+ {
+ Fail("GetTempFileNameA: ERROR -> Call failed with a valid path and "
+ "prefix with the error code: %ld\n", GetLastError());
+ }
+ else
+ {
+ /* verify temp file was created */
+ if (GetFileAttributesA(szReturnedName) == -1)
+ {
+ Fail("GetTempFileNameA: ERROR -> GetFileAttributes failed on the "
+ "returned temp file \"%s\" with error code: %ld.\n",
+ szReturnedName,
+ GetLastError());
+ }
+ if (DeleteFileA(szReturnedName) != TRUE)
+ {
+ Fail("GetTempFileNameA: ERROR -> DeleteFileW failed to delete"
+ "the created temp \"%s\" file with error code: %ld.\n",
+ szReturnedName,
+ GetLastError());
+ }
+ }
+
+ /* valid path with long prefix */
+ uiError = GetTempFileNameA(szDot, szLongValidPrefix, uUnique, szReturnedName);
+ if (uiError == 0)
+ {
+ Fail("GetTempFileNameA: ERROR -> Call failed with a valid path and "
+ "prefix with the error code: %ld\n", GetLastError());
+ }
+ else
+ {
+ /* verify temp file was created */
+ if (GetFileAttributesA(szReturnedName) == -1)
+ {
+ Fail("GetTempFileNameA: ERROR -> GetFileAttributes failed on the "
+ "returned temp file \"%s\" with error code: %ld.\n",
+ szReturnedName,
+ GetLastError());
+ }
+
+ /* now verify that it only used the first 3 characters of the prefix */
+ sprintf(szTempString, "%s\\%s", szDot, szLongValidPrefix);
+ if (strncmp(szTempString, szReturnedName, 6) == 0)
+ {
+ Fail("GetTempFileNameA: ERROR -> It appears that an improper prefix "
+ "was used.\n");
+ }
+
+ if (DeleteFileA(szReturnedName) != TRUE)
+ {
+ Fail("GetTempFileNameA: ERROR -> DeleteFileW failed to delete"
+ "the created temp file \"%s\" with error code: %ld.\n",
+ szReturnedName,
+ GetLastError());
+ }
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/testinfo.dat
new file mode 100644
index 0000000000..4bf0000b9f
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetTempFileNameA
+Name = Test for GetTempFileNameA (test 1)
+Type = DEFAULT
+EXE1 = gettempfilenamea
+Description
+= Tests the PAL implimentation of GetTempFileNameA by testing
+= various combinations of path and prefix names.
diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/CMakeLists.txt
new file mode 100644
index 0000000000..f4bd9b8797
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetTempFileNameA.c
+)
+
+add_executable(paltest_gettempfilenamea_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_gettempfilenamea_test2 coreclrpal)
+
+target_link_libraries(paltest_gettempfilenamea_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/GetTempFileNameA.c b/src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/GetTempFileNameA.c
new file mode 100644
index 0000000000..861a8b87e8
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/GetTempFileNameA.c
@@ -0,0 +1,80 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: GetTempFileNameA.c (test 2)
+**
+** Purpose: Tests the number of files GetTempFileNameA can create.
+**
+** Depends on:
+** GetFileAttributesA
+** oodles of free disk space (>4.07GB)
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ UINT uiError = 0;
+ DWORD dwError = 0;
+ const UINT uUnique = 0;
+ const char* szDot = {"."};
+ const char* szValidPrefix = {"cfr"};
+ char szReturnedName[256];
+ DWORD i;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /* test the number of temp files that can be created */
+ for (i = 0; i < 0x10005; i++)
+ {
+ uiError = GetTempFileNameA(szDot, szValidPrefix, uUnique, szReturnedName);
+ if (uiError == 0)
+ {
+ dwError = GetLastError();
+ if (dwError == ERROR_FILE_EXISTS)
+ {
+ /* file already existes so break out of the loop */
+ i--; /* decrement the count because it wasn't successful */
+ break;
+ }
+ else
+ {
+ /* it was something other than the file already existing? */
+ Fail("GetTempFileNameA: ERROR -> Call failed with a valid "
+ "path and prefix with the error code: %ld\n", GetLastError());
+ }
+ }
+ else
+ {
+ /* verify temp file was created */
+ if (GetFileAttributesA(szReturnedName) == -1)
+ {
+ Fail("GetTempFileNameA: ERROR -> GetFileAttributes failed "
+ "on the returned temp file \"%s\" with error code: %ld.\n",
+ szReturnedName,
+ GetLastError());
+ }
+ }
+ }
+
+ /* did it create more than 0xffff files */
+ if (i > 0xffff)
+ {
+ Fail("GetTempFileNameA: ERROR -> Was able to create more than 0xffff"
+ " temp files.\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/testinfo.dat b/src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/testinfo.dat
new file mode 100644
index 0000000000..ca46f6d842
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetTempFileNameA
+Name = Test for GetTempFileNameA (test 2)
+Type = DEFAULT
+EXE1 = gettempfilenamea
+Description
+= Test the number of files that can be created. Since
+= GetTempFileNameA only handles 8.3 file names, the test
+= attempts to create more than the maximum temp files possible
+= with a 3 character prefix. Since this test takes so long, it
+= is not to be included in the standard test harness.
+= This test will also need more than 4.07 GB free disk space.
diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/CMakeLists.txt
new file mode 100644
index 0000000000..9c02865575
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ gettempfilenamea.c
+)
+
+add_executable(paltest_gettempfilenamea_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_gettempfilenamea_test3 coreclrpal)
+
+target_link_libraries(paltest_gettempfilenamea_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/gettempfilenamea.c b/src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/gettempfilenamea.c
new file mode 100644
index 0000000000..8eccc3d2e8
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/gettempfilenamea.c
@@ -0,0 +1,159 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: GetTempFileNameA.c (test 3)
+**
+** Purpose: Tests the PAL implementation of the GetTempFileNameA function.
+** Checks the file attributes and ensures that getting a file name,
+** deleting the file and getting another doesn't produce the same
+** as the just deleted file. Also checks the file size is 0.
+**
+** Depends on:
+** GetFileAttributesA
+** CloseHandle
+** DeleteFileA
+** CreateFileA
+** GetFileSize
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ const UINT uUnique = 0;
+ UINT uiError;
+ const char* szDot = {"."};
+ char szReturnedName[MAX_LONGPATH];
+ char szReturnedName_02[MAX_LONGPATH];
+ DWORD dwFileSize = 0;
+ HANDLE hFile;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /* valid path with null prefix */
+ uiError = GetTempFileNameA(szDot, NULL, uUnique, szReturnedName);
+ if (uiError == 0)
+ {
+ Fail("GetTempFileNameA: ERROR -> Call failed with a valid path "
+ "with the error code: %u.\n",
+ GetLastError());
+ }
+
+ /* verify temp file was created */
+ if (GetFileAttributesA(szReturnedName) == -1)
+ {
+ Fail("GetTempFileNameA: ERROR -> GetFileAttributes failed on the "
+ "returned temp file \"%s\" with error code: %u.\n",
+ szReturnedName,
+ GetLastError());
+ }
+
+ /*
+ ** verify that the file size is 0 bytes
+ */
+
+ hFile = CreateFileA(szReturnedName,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Trace("GetTempFileNameA: ERROR -> CreateFileA failed to open"
+ " the created temp file with error code: %u.\n",
+ GetLastError());
+ if (!DeleteFileA(szReturnedName))
+ {
+ Trace("GetTempFileNameA: ERROR -> DeleteFileA failed to delete"
+ " the created temp file with error code: %u.\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ if ((dwFileSize = GetFileSize(hFile, NULL)) != (DWORD)0)
+ {
+ Trace("GetTempFileNameA: ERROR -> GetFileSize returned %u whereas"
+ "it should have returned 0.\n",
+ dwFileSize);
+ if (!CloseHandle(hFile))
+ {
+ Trace("GetTempFileNameA: ERROR -> CloseHandle failed. "
+ "GetLastError returned: %u.\n",
+ GetLastError());
+ }
+ if (!DeleteFileA(szReturnedName))
+ {
+ Trace("GetTempFileNameA: ERROR -> DeleteFileA failed to delete"
+ " the created temp file with error code: %u.\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+
+ if (!CloseHandle(hFile))
+ {
+ Fail("GetTempFileNameA: ERROR -> CloseHandle failed. "
+ "GetLastError returned: %u.\n",
+ GetLastError());
+ }
+
+ if (DeleteFileA(szReturnedName) != TRUE)
+ {
+ Fail("GetTempFileNameA: ERROR -> DeleteFileA failed to delete"
+ " the created temp file with error code: %u.\n",
+ GetLastError());
+ }
+
+ /* get another and make sure it's not the same as the last */
+ uiError = GetTempFileNameA(szDot, NULL, uUnique, szReturnedName_02);
+ if (uiError == 0)
+ {
+ Fail("GetTempFileNameA: ERROR -> Call failed with a valid path "
+ "with the error code: %u.\n",
+ GetLastError());
+ }
+
+ /* did we get different names? */
+ if (strcmp(szReturnedName, szReturnedName_02) == 0)
+ {
+ Trace("GetTempFileNameA: ERROR -> The first call returned \"%s\". "
+ "The second call returned \"%s\" and the two should not be"
+ " the same.\n",
+ szReturnedName,
+ szReturnedName_02);
+ if (!DeleteFileA(szReturnedName_02))
+ {
+ Trace("GetTempFileNameA: ERROR -> DeleteFileA failed to delete"
+ " the created temp file with error code: %u.\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ /* clean up */
+ if (!DeleteFileA(szReturnedName_02))
+ {
+ Fail("GetTempFileNameA: ERROR -> DeleteFileA failed to delete"
+ " the created temp file with error code: %u.\n",
+ GetLastError());
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/testinfo.dat b/src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/testinfo.dat
new file mode 100644
index 0000000000..f1f5bf5764
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetTempFileNameA
+Name = Test for GetTempFileNameA (test 3)
+Type = DEFAULT
+EXE1 = gettempfilenamea
+Description
+= Tests the PAL implementation of the GetTempFileNameA function.
+= Checks the file attributes and ensures that getting a file name,
+= deleting the file and getting another doesn't produce the same
+= as the just deleted file. Also checks the file size is 0.
diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameW/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetTempFileNameW/CMakeLists.txt
new file mode 100644
index 0000000000..1962ade358
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetTempFileNameW/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+
diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..1b6c599da4
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetTempFileNameW.c
+)
+
+add_executable(paltest_gettempfilenamew_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_gettempfilenamew_test1 coreclrpal)
+
+target_link_libraries(paltest_gettempfilenamew_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/GetTempFileNameW.c b/src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/GetTempFileNameW.c
new file mode 100644
index 0000000000..43cda8f447
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/GetTempFileNameW.c
@@ -0,0 +1,129 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: GetTempFileNameW.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the GetTempFileNameW function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ UINT uiError = 0;
+ const UINT uUnique = 0;
+ WCHAR* wPrefix = NULL;
+ WCHAR* wPath = NULL;
+ WCHAR wReturnedName[256];
+ WCHAR wTempString[256];
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+
+ // valid path with null ext
+ wPath = convert(".");
+ uiError = GetTempFileNameW(wPath, wPrefix, uUnique, wReturnedName);
+ free (wPath);
+ if (uiError == 0)
+ {
+ Fail("GetTempFileNameW: ERROR -> Call failed with a valid path "
+ "with the error code: %ld\n", GetLastError());
+ }
+ else
+ {
+ // verify temp file was created
+ if (GetFileAttributesW(wReturnedName) == -1)
+ {
+ Fail("GetTempFileNameW: ERROR -> GetFileAttributes failed on the "
+ "returned temp file with error code: %ld.\n", GetLastError());
+ }
+ if (DeleteFileW(wReturnedName) != TRUE)
+ {
+ Fail("GetTempFileNameW: ERROR -> DeleteFileW failed to delete"
+ "the created temp file with error code: %lld.\n", GetLastError());
+ }
+ }
+
+
+ // valid path with valid prefix
+ wPath = convert(".");
+ wPrefix = convert("cfr");
+ uiError = GetTempFileNameW(wPath, wPrefix, uUnique, wReturnedName);
+ free (wPath);
+ free (wPrefix);
+ if (uiError == 0)
+ {
+ Fail("GetTempFileNameW: ERROR -> Call failed with a valid path and "
+ "prefix with the error code: %ld\n", GetLastError());
+ }
+ else
+ {
+ // verify temp file was created
+ if (GetFileAttributesW(wReturnedName) == -1)
+ {
+ Fail("GetTempFileNameW: ERROR -> GetFileAttributes failed on the "
+ "returned temp file with error code: %ld.\n", GetLastError());
+ }
+ if (DeleteFileW(wReturnedName) != TRUE)
+ {
+ Fail("GetTempFileNameW: ERROR -> DeleteFileW failed to delete"
+ "the created temp file with error code: %lld.\n", GetLastError());
+ }
+ }
+
+ // valid path with long prefix
+ wPath = convert(".");
+ wPrefix = convert("cfrwxyz");
+ uiError = GetTempFileNameW(wPath, wPrefix, uUnique, wReturnedName);
+ if (uiError == 0)
+ {
+ free (wPath);
+ free (wPrefix);
+ Fail("GetTempFileNameW: ERROR -> Call failed with a valid path and "
+ "prefix with the error code: %ld\n", GetLastError());
+ }
+ else
+ {
+ // verify temp file was created
+ if (GetFileAttributesW(wReturnedName) == -1)
+ {
+ free (wPath);
+ free (wPrefix);
+ Fail("GetTempFileNameW: ERROR -> GetFileAttributes failed on the "
+ "returned temp file with error code: %ld.\n", GetLastError());
+ }
+
+ // now verify that it only used the first 3 characters of the prefix
+ swprintf(wTempString, convert("%s\\%s"), wPath, wPrefix);
+ if (memcmp(wTempString, wReturnedName, wcslen(wTempString)*sizeof(WCHAR)) == 0)
+ {
+ free (wPath);
+ free (wPrefix);
+ Fail("GetTempFileNameW: ERROR -> It appears that an improper prefix "
+ "was used.\n");
+ }
+
+ if (DeleteFileW(wReturnedName) != TRUE)
+ {
+ free (wPath);
+ free (wPrefix);
+ Fail("GetTempFileNameW: ERROR -> DeleteFileW failed to delete"
+ "the created temp file with error code: %lld.\n", GetLastError());
+ }
+ }
+
+ free (wPath);
+ free (wPrefix);
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/testinfo.dat
new file mode 100644
index 0000000000..72af6930d9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetTempFileNameW
+Name = Test for GetTempFileNameW (test 1)
+Type = DEFAULT
+EXE1 = gettempfilenamew
+Description
+= Test all the different options of GetTempFileNameW
+
diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/CMakeLists.txt
new file mode 100644
index 0000000000..851030d9ae
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetTempFileNameW.c
+)
+
+add_executable(paltest_gettempfilenamew_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_gettempfilenamew_test2 coreclrpal)
+
+target_link_libraries(paltest_gettempfilenamew_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/GetTempFileNameW.c b/src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/GetTempFileNameW.c
new file mode 100644
index 0000000000..2c8b19e081
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/GetTempFileNameW.c
@@ -0,0 +1,84 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: GetTempFileNameW.c (test 2)
+**
+** Purpose: Tests the PAL implementation of the GetTempFileNameW function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ UINT uiError = 0;
+ DWORD dwError = 0;
+ const UINT uUnique = 0;
+ WCHAR* wPrefix = NULL;
+ WCHAR* wPath = NULL;
+ WCHAR wReturnedName[256];
+ DWORD i;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+
+ // test the number of temp files that can be created
+ wPrefix = convert("cfr");
+ wPath = convert(".");
+ for (i = 0; i < 0x10005; i++)
+ {
+ uiError = GetTempFileNameW(wPath, wPrefix, uUnique, wReturnedName);
+ if (uiError == 0)
+ {
+ dwError = GetLastError();
+ if (dwError == ERROR_FILE_EXISTS)
+ {
+ // file already existes so break out of the loop
+ i--; // decrement the count because it wasn't successful
+ break;
+ }
+ else
+ {
+ // it was something other than the file already existing?
+ free (wPath);
+ free (wPrefix);
+ Fail("GetTempFileNameW: ERROR -> Call failed with a valid "
+ "path and prefix with the error code: %ld\n", GetLastError());
+ }
+ }
+ else
+ {
+ // verify temp file was created
+ if (GetFileAttributesW(wReturnedName) == -1)
+ {
+ free (wPath);
+ free (wPrefix);
+ Fail("GetTempFileNameW: ERROR -> GetFileAttributes failed "
+ "on the returned temp file with error code: %ld.\n",
+ GetLastError());
+ }
+ }
+ }
+
+ free (wPath);
+ free (wPrefix);
+
+ // did it create more than 0xffff files
+ if (i > 0xffff)
+ {
+ Fail("GetTempFileNameW: ERROR -> Was able to create more than 0xffff"
+ " temp files.\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/testinfo.dat b/src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/testinfo.dat
new file mode 100644
index 0000000000..72500111ad
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetTempFileNameW
+Name = Test for GetTempFileNameW (test 2)
+Type = DEFAULT
+EXE1 = gettempfilenamew
+Description
+= This test attempts to create over 65000 files and will
+= have to be run manually because it will take longer than
+= the maximum 60 seconds allowed per test
+
diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/CMakeLists.txt
new file mode 100644
index 0000000000..82dd0a9f3f
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ gettempfilenamew.c
+)
+
+add_executable(paltest_gettempfilenamew_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_gettempfilenamew_test3 coreclrpal)
+
+target_link_libraries(paltest_gettempfilenamew_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/gettempfilenamew.c b/src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/gettempfilenamew.c
new file mode 100644
index 0000000000..96d8e66410
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/gettempfilenamew.c
@@ -0,0 +1,161 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: GetTempFileNameW.c (test 3)
+**
+** Purpose: Tests the PAL implementation of the GetTempFileNameW function.
+** Checks the file attributes and ensures that getting a file name,
+** deleting the file and getting another doesn't produce the same
+** as the just deleted file. Also checks the file size is 0.
+**
+** Depends on:
+** GetFileAttributesW
+** DeleteFileW
+** CreateFileW
+** GetFileSize
+** CloseHandle
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ const UINT uUnique = 0;
+ UINT uiError;
+ WCHAR szwReturnedName[MAX_LONGPATH];
+ WCHAR szwReturnedName_02[MAX_LONGPATH];
+ DWORD dwFileSize = 0;
+ HANDLE hFile;
+ const WCHAR szwDot[] = {'.','\0'};
+ const WCHAR szwPre[] = {'c','\0'};
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /* valid path with null prefix */
+ uiError = GetTempFileNameW(szwDot, szwPre, uUnique, szwReturnedName);
+ if (uiError == 0)
+ {
+ Fail("GetTempFileNameW: ERROR -> Call failed with a valid path "
+ "with the error code: %u.\n",
+ GetLastError());
+ }
+
+ /* verify temp file was created */
+ if (GetFileAttributesW(szwReturnedName) == -1)
+ {
+ Fail("GetTempFileNameW: ERROR -> GetFileAttributes failed on the "
+ "returned temp file \"%S\" with error code: %u.\n",
+ szwReturnedName,
+ GetLastError());
+ }
+
+ /*
+ ** verify that the file size is 0 bytes
+ */
+
+ hFile = CreateFileW(szwReturnedName,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Trace("GetTempFileNameW: ERROR -> CreateFileW failed to open"
+ " the created temp file with error code: %u.\n",
+ GetLastError());
+ if (!DeleteFileW(szwReturnedName))
+ {
+ Trace("GetTempFileNameW: ERROR -> DeleteFileW failed to delete"
+ " the created temp file with error code: %u.\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ if ((dwFileSize = GetFileSize(hFile, NULL)) != (DWORD)0)
+ {
+ Trace("GetTempFileNameW: ERROR -> GetFileSize returned %u whereas"
+ "it should have returned 0.\n",
+ dwFileSize);
+ if (!CloseHandle(hFile))
+ {
+ Trace("GetTempFileNameW: ERROR -> CloseHandle was unable to close the "
+ "opened file. GetLastError returned %u.\n",
+ GetLastError());
+ }
+ if (!DeleteFileW(szwReturnedName))
+ {
+ Trace("GetTempFileNameW: ERROR -> DeleteFileW failed to delete"
+ " the created temp file with error code: %u.\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ if (!CloseHandle(hFile))
+ {
+ Fail("GetTempFileNameW: ERROR -> CloseHandle was unable to close the "
+ "opened file. GetLastError returned %u.\n",
+ GetLastError());
+ }
+
+
+ /* delete the file to see if we get the same name next time around */
+ if (DeleteFileW(szwReturnedName) != TRUE)
+ {
+ Fail("GetTempFileNameW: ERROR -> DeleteFileW failed to delete"
+ " the created temp file with error code: %u.\n",
+ GetLastError());
+ }
+
+ /* get another and make sure it's not the same as the last */
+ uiError = GetTempFileNameW(szwDot, szwPre, uUnique, szwReturnedName_02);
+ if (uiError == 0)
+ {
+ Fail("GetTempFileNameW: ERROR -> Call failed with a valid path "
+ "with the error code: %u.\n",
+ GetLastError());
+ }
+
+ /* did we get different names? */
+ if (wcsncmp(szwReturnedName, szwReturnedName_02, wcslen(szwReturnedName)) == 0)
+ {
+ Fail("GetTempFileNameW: ERROR -> The first call returned \"%S\". "
+ "The second call returned \"%S\" and the two should not be"
+ " the same.\n",
+ szwReturnedName,
+ szwReturnedName_02);
+ if (!DeleteFileW(szwReturnedName_02))
+ {
+ Trace("GetTempFileNameW: ERROR -> DeleteFileW failed to delete"
+ " the created temp file with error code: %u.\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ /* clean up */
+ if (!DeleteFileW(szwReturnedName_02))
+ {
+ Fail("GetTempFileNameW: ERROR -> DeleteFileW failed to delete"
+ " the created temp file with error code: %u.\n",
+ GetLastError());
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/testinfo.dat b/src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/testinfo.dat
new file mode 100644
index 0000000000..dd482dbde5
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetTempFileNameW
+Name = Test for GetTempFileNameW (test 3)
+Type = DEFAULT
+EXE1 = gettempfilenamew
+Description
+= Tests the PAL implementation of the GetTempFileNameW function.
+= Checks the file attributes and ensures that getting a file name,
+= deleting the file and getting another doesn't produce the same
+= as the just deleted file. Also checks the file size is 0.
diff --git a/src/pal/tests/palsuite/file_io/GetTempPathW/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetTempPathW/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetTempPathW/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/file_io/GetTempPathW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetTempPathW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..f2979e9536
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetTempPathW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetTempPathW.c
+)
+
+add_executable(paltest_gettemppathw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_gettemppathw_test1 coreclrpal)
+
+target_link_libraries(paltest_gettemppathw_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/GetTempPathW/test1/GetTempPathW.c b/src/pal/tests/palsuite/file_io/GetTempPathW/test1/GetTempPathW.c
new file mode 100644
index 0000000000..08c88075ca
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetTempPathW/test1/GetTempPathW.c
@@ -0,0 +1,103 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: GetTempPathW.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the GetTempPathW function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+static void SetTmpDir(WCHAR path[])
+{
+ DWORD result = SetEnvironmentVariableW(W("TMPDIR"), path);
+ if (!result)
+ {
+ Fail("ERROR -> SetEnvironmentVariableW failed with result %d and error code %d.\n",
+ result, GetLastError());
+ }
+}
+
+static void SetAndCompare(WCHAR tmpDirPath[], WCHAR expected[])
+{
+ DWORD dwBufferLength = _MAX_DIR;
+ WCHAR path[dwBufferLength];
+
+ SetTmpDir(tmpDirPath);
+
+ DWORD dwResultLen = GetTempPathW(dwBufferLength, path);
+ if (dwResultLen <= 0)
+ {
+ Fail("ERROR: GetTempPathW returned %d with error code %d.\n", dwResultLen, GetLastError());
+ }
+ if (dwResultLen >= dwBufferLength)
+ {
+ Fail("ERROR: Buffer of length %d passed to GetTempPathA was too small to hold %d chars..\n", dwBufferLength, dwResultLen);
+ }
+ if (wcscmp(expected, path) != 0)
+ {
+ Fail("ERROR: GetTempPathW expected to get '%S' but instead got '%S'.\n", expected, path);
+ }
+ if (expected[dwResultLen - 1] != '/')
+ {
+ Fail("ERROR: GetTempPathW returned '%S', which should have ended in '/'.\n", path);
+ }
+}
+
+static void SetAndCheckLength(WCHAR tmpDirPath [], int bufferLength, int expectedResultLength)
+{
+ WCHAR path[bufferLength];
+
+ SetTmpDir(tmpDirPath);
+ DWORD dwResultLen = GetTempPathW(bufferLength, path);
+
+ if (dwResultLen != expectedResultLength)
+ {
+ Fail("GetTempPathW(%d, %S) expected to return %d but returned %d.\n",
+ bufferLength, tmpDirPath?tmpDirPath:W("NULL"), expectedResultLength, dwResultLen);
+ }
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ SetAndCompare(W("/tmp"), W("/tmp/"));
+ SetAndCompare(W("/tmp/"), W("/tmp/"));
+ SetAndCompare(W(""), W("/tmp/"));
+ SetAndCompare(NULL, W("/tmp/"));
+ SetAndCompare(W("/"), W("/"));
+ SetAndCompare(W("/var/tmp"), W("/var/tmp/"));
+ SetAndCompare(W("/var/tmp/"), W("/var/tmp/"));
+ SetAndCompare(W("~"), W("~/"));
+ SetAndCompare(W("~/"), W("~/"));
+ SetAndCompare(W(".tmp"), W(".tmp/"));
+ SetAndCompare(W("./tmp"), W("./tmp/"));
+ SetAndCompare(W("/home/someuser/sometempdir"), W("/home/someuser/sometempdir/"));
+ SetAndCompare(NULL, W("/tmp/"));
+
+ DWORD dwResultLen = GetTempPathA(0, NULL);
+ if (dwResultLen != 0 || GetLastError() != ERROR_INVALID_PARAMETER)
+ {
+ Fail("GetTempPathW(NULL, ...) returned %d with error code %d but "
+ "should have failed with ERROR_INVALID_PARAMETER (%d).\n",
+ dwResultLen, GetLastError(), ERROR_INVALID_PARAMETER);
+ }
+
+ SetAndCheckLength(W("abc/"), 5, 4);
+ SetAndCheckLength(W("abcd"), 5, 6);
+ SetAndCheckLength(W("abcde"), 5, 7);
+ SetAndCheckLength(W("abcdef/"), 5, 9);
+ SetAndCheckLength(NULL, 5, 6);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/GetTempPathW/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/GetTempPathW/test1/testinfo.dat
new file mode 100644
index 0000000000..84dc33832c
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/GetTempPathW/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetTempPathW
+Name = Test for GetTempPathW (test 1)
+Type = DEFAULT
+EXE1 = gettemppathw
+Description
+= Calls GetTempPathW and verifies by passing the returned
+= value to CreateDirectoryW. If the returned path exists,
+= CreateDirectoryW will fail.
+
diff --git a/src/pal/tests/palsuite/file_io/MoveFileA/CMakeLists.txt b/src/pal/tests/palsuite/file_io/MoveFileA/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/MoveFileA/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/file_io/MoveFileA/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/MoveFileA/test1/CMakeLists.txt
new file mode 100644
index 0000000000..9a3d0069db
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/MoveFileA/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ MoveFileA.c
+)
+
+add_executable(paltest_movefilea_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_movefilea_test1 coreclrpal)
+
+target_link_libraries(paltest_movefilea_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/MoveFileA/test1/ExpectedResults.txt b/src/pal/tests/palsuite/file_io/MoveFileA/test1/ExpectedResults.txt
new file mode 100644
index 0000000000..43b67af6b2
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/MoveFileA/test1/ExpectedResults.txt
@@ -0,0 +1 @@
+0101000001010000 \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/MoveFileA/test1/MoveFileA.c b/src/pal/tests/palsuite/file_io/MoveFileA/test1/MoveFileA.c
new file mode 100644
index 0000000000..8d1bc0eded
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/MoveFileA/test1/MoveFileA.c
@@ -0,0 +1,469 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: MoveFileA.c
+**
+** Purpose: Tests the PAL implementation of the MoveFileA function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+LPSTR lpSource[4] = {"src_existing.txt",
+ "src_non-existant.txt",
+ "src_dir_existing",
+ "src_dir_non-existant"};
+LPSTR lpDestination[4] = {"dst_existing.txt",
+ "dst_non-existant.txt",
+ "dst_dir_existing",
+ "dst_dir_non-existant"};
+
+
+/* Create all the required test files */
+int createExisting(void)
+{
+ FILE* tempFile = NULL;
+ DWORD dwError;
+ BOOL bRc = FALSE;
+ char szBuffer[100];
+
+ /* create the src_existing file */
+ tempFile = fopen(lpSource[0], "w");
+ if (tempFile != NULL)
+ {
+ fprintf(tempFile, "MoveFileA test file: src_existing.txt\n");
+ fclose(tempFile);
+ }
+ else
+ {
+ Trace("ERROR: couldn't create %s\n", lpSource[0]);
+ return FAIL;
+ }
+
+ /* create the src_dir_existing directory and files */
+ bRc = CreateDirectoryA(lpSource[2], NULL);
+ if (bRc != TRUE)
+ {
+ Trace("MoveFileA: ERROR: couldn't create \"%s\" because of "
+ "error code %ld\n",
+ lpSource[2],
+ GetLastError());
+ return FAIL;
+ }
+
+ memset(szBuffer, 0, 100);
+ sprintf(szBuffer, "%s/test01.txt", lpSource[2]);
+ tempFile = fopen(szBuffer, "w");
+ if (tempFile != NULL)
+ {
+ fprintf(tempFile, "MoveFileA test file: %s\n", szBuffer);
+ fclose(tempFile);
+ }
+ else
+ {
+ Trace("ERROR[%ld]:MoveFileA couldn't create %s\n", GetLastError(), szBuffer);
+ return FAIL;
+ }
+
+ memset(szBuffer, 0, 100);
+ sprintf(szBuffer, "%s/test02.txt", lpSource[2]);
+ tempFile = fopen(szBuffer, "w");
+ if (tempFile != NULL)
+ {
+ fprintf(tempFile, "MoveFileA test file: %s\n", szBuffer);
+ fclose(tempFile);
+ }
+ else
+ {
+ Trace("ERROR[%ld]: couldn't create %s\n", GetLastError(), szBuffer);
+ return FAIL;
+ }
+
+
+ /* create the dst_existing file */
+ tempFile = fopen(lpDestination[0], "w");
+ if (tempFile != NULL)
+ {
+ fprintf(tempFile, "MoveFileA test file: dst_existing.txt\n");
+ fclose(tempFile);
+ }
+ else
+ {
+ Trace("ERROR[%ld]:MoveFileA couldn't create \"%s\"\n", GetLastError(), lpDestination[0]);
+ return FAIL;
+ }
+
+ /* create the dst_dir_existing directory and files */
+ bRc = CreateDirectoryA(lpDestination[2], NULL);
+ if (bRc != TRUE)
+ {
+ dwError = GetLastError();
+ Trace("Error[%ld]:MoveFileA: couldn't create \"%s\"\n", GetLastError(), lpDestination[2]);
+ return FAIL;
+ }
+
+ tempFile = fopen("dst_dir_existing/test01.txt", "w");
+ if (tempFile != NULL)
+ {
+ fprintf(tempFile, "MoveFileA test file: dst_dir_existing/test01.txt\n");
+ fclose(tempFile);
+ }
+ else
+ {
+ Trace("ERROR: couldn't create dst_dir_existing/test01.txt\n");
+ return FAIL;
+ }
+ tempFile = fopen("dst_dir_existing/test02.txt", "w");
+ if (tempFile != NULL)
+ {
+ fprintf(tempFile, "MoveFileA test file: dst_dir_existing/test02.txt\n");
+ fclose(tempFile);
+ }
+ else
+ {
+ Trace("ERROR[%ul]: couldn't create dst_dir_existing/test02.txt\n", GetLastError());
+ return FAIL;
+ }
+
+ return PASS;
+}
+
+
+
+void removeDirectoryHelper(LPSTR dir, int location)
+{
+ DWORD dwAtt = GetFileAttributesA(dir);
+ if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) )
+ {
+ if(!RemoveDirectoryA(dir))
+ {
+ Fail("ERROR: Failed to remove Directory [%s], Error Code [%d], location [%d]\n", dir, GetLastError(), location);
+ }
+ }
+}
+
+void removeFileHelper(LPSTR pfile, int location)
+{
+ FILE *fp;
+ fp = fopen( pfile, "r");
+
+ if (fp != NULL)
+ {
+ if(fclose(fp))
+ {
+ Fail("ERROR: Failed to close the file [%s], Error Code [%d], location [%d]\n", pfile, GetLastError(), location);
+ }
+
+ if(!DeleteFileA(pfile))
+ {
+ Fail("ERROR: Failed to delete file [%s], Error Code [%d], location [%d]\n", pfile, GetLastError(), location);
+ }
+ else
+ {
+ // Trace("Success: deleted file [%S], Error Code [%d], location [%d]\n", wfile, GetLastError(), location);
+ }
+ }
+
+}
+
+
+/* remove all created files in preparation for the next test */
+void removeAll(void)
+{
+ char szTemp[40];
+ DWORD dwAtt;
+
+ /* get rid of source dirs and files */
+ removeFileHelper(lpSource[0], 1);
+ removeFileHelper(lpSource[1], 2);
+
+ dwAtt = GetFileAttributesA(lpSource[2]);
+ if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) )
+ {
+ sprintf(szTemp, "%s/test01.txt", lpSource[2]);
+ removeFileHelper(szTemp, 18);
+
+ sprintf(szTemp, "%s/test02.txt", lpSource[2]);
+ removeFileHelper(szTemp, 19);
+ removeDirectoryHelper(lpSource[2], 103);
+ }
+ else
+ {
+ removeFileHelper(lpSource[2], 17);
+ }
+
+
+ dwAtt = GetFileAttributesA(lpSource[3]);
+ if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) )
+ {
+ sprintf(szTemp, "%s/test01.txt", lpSource[3]);
+ removeFileHelper(szTemp, 18);
+
+ sprintf(szTemp, "%s/test02.txt", lpSource[3]);
+ removeFileHelper(szTemp, 19);
+ removeDirectoryHelper(lpSource[3], 103);
+ }
+ else
+ {
+ removeFileHelper(lpSource[3], 17);
+ }
+
+ /* get rid of destination dirs and files */
+ dwAtt = GetFileAttributesA(lpDestination[0]);
+ if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) )
+ {
+ sprintf(szTemp, "%s/test01.txt", lpDestination[0]);
+ removeFileHelper(szTemp, 18);
+
+ sprintf(szTemp, "%s/test02.txt", lpDestination[0]);
+ removeFileHelper(szTemp, 19);
+ removeDirectoryHelper(lpDestination[0], 103);
+ }
+ else
+ {
+ removeFileHelper(lpDestination[0], 17);
+ }
+
+ dwAtt = GetFileAttributesA(lpDestination[1]);
+ if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) )
+ {
+ sprintf(szTemp, "%s/test01.txt", lpDestination[1]);
+ removeFileHelper(szTemp, 18);
+
+ sprintf(szTemp, "%s/test02.txt", lpDestination[1]);
+ removeFileHelper(szTemp, 19);
+ removeDirectoryHelper(lpDestination[1], 103);
+ }
+ else
+ {
+ removeFileHelper(lpDestination[1], 17);
+ }
+
+ dwAtt = GetFileAttributesA(lpDestination[2]);
+ if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) )
+ {
+ sprintf(szTemp, "%s/test01.txt", lpDestination[2]);
+ removeFileHelper(szTemp, 18);
+
+ sprintf(szTemp, "%s/test02.txt", lpDestination[2]);
+ removeFileHelper(szTemp, 19);
+ removeDirectoryHelper(lpDestination[2], 103);
+ }
+ else
+ {
+ removeFileHelper(lpDestination[2], 17);
+ }
+
+ dwAtt = GetFileAttributesA(lpDestination[3]);
+ if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) )
+ {
+ sprintf(szTemp, "%s/test01.txt", lpDestination[3]);
+ removeFileHelper(szTemp, 18);
+
+ sprintf(szTemp, "%s/test02.txt", lpDestination[3]);
+ removeFileHelper(szTemp, 19);
+ removeDirectoryHelper(lpDestination[3], 103);
+ }
+ else
+ {
+ removeFileHelper(lpDestination[3], 17);
+ }
+
+}
+
+
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ BOOL bRc = TRUE;
+ BOOL bSuccess = TRUE;
+ char results[40];
+ FILE* resultsFile = NULL;
+ int nCounter = 0;
+ int i, j;
+ char tempSource[] = {'t','e','m','p','k','.','t','m','p','\0'};
+ char tempDest[] = {'t','e','m','p','2','.','t','m','p','\0'};
+ HANDLE hFile;
+ DWORD result;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* read in the expected results to compare with actual results */
+ memset (results, 0, 20);
+ resultsFile = fopen("expectedresults.txt", "r");
+ if (resultsFile == NULL)
+ {
+ Fail("MoveFileA ERROR[%ul]: Unable to open \"expectedresults.txt\"\n", GetLastError());
+ }
+
+ fgets(results, 20, resultsFile);
+ fclose(resultsFile);
+
+ /* clean the slate */
+ removeAll();
+
+ if (createExisting() != 0)
+ {
+ removeAll();
+ }
+
+
+ /* lpSource loop */
+ for (i = 0; i < 4; i++)
+ {
+ /* lpDestination loop */
+ for (j = 0; j < 4; j++)
+ {
+ bRc = MoveFileA(lpSource[i], lpDestination[j]);
+ if (!(
+ ((bRc == TRUE) && (results[nCounter] == '1'))
+ ||
+ ((bRc == FALSE ) && (results[nCounter] == '0')) )
+ )
+ {
+ Trace("MoveFileA: FAILED: test[%d][%d]: \"%s\" -> \"%s\"\n",
+ i, j, lpSource[i], lpDestination[j]);
+ bSuccess = FALSE;
+ }
+
+ /* undo the last move */
+ removeAll();
+ createExisting();
+
+ nCounter++;
+ }
+ }
+
+ removeAll();
+ if (bSuccess == FALSE)
+ {
+ Fail("MoveFileA: Test Failed");
+ }
+
+ /* create the temp source file */
+ hFile = CreateFileA(tempSource, GENERIC_WRITE, 0, 0, CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, 0);
+
+ if( hFile == INVALID_HANDLE_VALUE )
+ {
+ Fail("Error[%ul]:MoveFileA: CreateFile failed to "
+ "create the file correctly.\n", GetLastError());
+ }
+
+ bRc = CloseHandle(hFile);
+ if(!bRc)
+ {
+ Trace("MoveFileA: CloseHandle failed to close the "
+ "handle correctly. ERROR:%u\n",GetLastError());
+
+ /* delete the created file */
+ bRc = DeleteFileA(tempSource);
+ if(!bRc)
+ {
+ Fail("Error[%ul]:MoveFileA: DeleteFileA failed to delete the"
+ "file correctly.\n", GetLastError());
+ }
+ Fail("");
+ }
+
+ /* set the file attributes to be readonly */
+ bRc = SetFileAttributesA(tempSource, FILE_ATTRIBUTE_READONLY);
+ if(!bRc)
+ {
+ Trace("MoveFileA: SetFileAttributes failed to set file "
+ "attributes correctly. GetLastError returned %u\n",GetLastError());
+ /* delete the created file */
+ bRc = DeleteFileA(tempSource);
+ if(!bRc)
+ {
+ Fail("Error[%ul]:MoveFileA: DeleteFileA failed to delete the"
+ "file correctly.\n", GetLastError());
+ }
+ Fail("");
+ }
+
+ /* move the file to the new location */
+ bRc = MoveFileA(tempSource, tempDest);
+ if(!bRc)
+ {
+ /* delete the created file */
+ bRc = DeleteFileA(tempSource);
+ if(!bRc)
+ {
+ Fail("Error[%ul]:MoveFileA: DeleteFileA failed to delete the"
+ "file correctly.\n", GetLastError());
+ }
+
+ Fail("Error[%ul]:MoveFileA(%S, %S): GetFileAttributes "
+ "failed to get the file's attributes.\n",
+ GetLastError(), tempSource, tempDest);
+ }
+
+ /* check that the newly moved file has the same file attributes
+ as the original */
+ result = GetFileAttributesA(tempDest);
+ if(result == 0)
+ {
+ /* delete the created file */
+ bRc = DeleteFileA(tempDest);
+ if(!bRc)
+ {
+ Fail("Error[%ul]:MoveFileA: DeleteFileA failed to delete the"
+ "file correctly.\n", GetLastError());
+ }
+
+ Fail("Error[%ul]:MoveFileA: GetFileAttributes failed to get "
+ "the file's attributes.\n", GetLastError());
+ }
+
+ if((result & FILE_ATTRIBUTE_READONLY) != FILE_ATTRIBUTE_READONLY)
+ {
+ /* delete the newly moved file */
+ bRc = DeleteFileA(tempDest);
+ if(!bRc)
+ {
+ Fail("Error[%ul]:MoveFileA: DeleteFileA failed to delete the"
+ "file correctly.\n", GetLastError());
+ }
+
+ Fail("Error[%ul]MoveFileA: GetFileAttributes failed to get "
+ "the correct file attributes.\n", GetLastError());
+ }
+
+ /* set the file attributes back to normal, to be deleted */
+ bRc = SetFileAttributesA(tempDest, FILE_ATTRIBUTE_NORMAL);
+ if(!bRc)
+ {
+ /* delete the newly moved file */
+ bRc = DeleteFileA(tempDest);
+ if(!bRc)
+ {
+ Fail("Error[%ul]:MoveFileA: DeleteFileA failed to delete the"
+ "file correctly.\n", GetLastError());
+ }
+
+ Fail("Error[%ul]:MoveFileA: SetFileAttributes failed to set "
+ "file attributes correctly.\n", GetLastError());
+ }
+
+ /* delete the newly moved file */
+ bRc = DeleteFileA(tempDest);
+ if(!bRc)
+ {
+ Fail("Error[%ul]:MoveFileA: DeleteFileA failed to delete the"
+ "file correctly.\n", GetLastError());
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/MoveFileA/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/MoveFileA/test1/testinfo.dat
new file mode 100644
index 0000000000..685072fcd9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/MoveFileA/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = MoveFileA
+Name = Positive Test for MoveFileA
+TYPE = DEFAULT
+EXE1 = movefilea
+Description
+=Performs a number of MoveFileA tests and uses the
+=file ExpectedResults.txt to determine if the test passed/failed
diff --git a/src/pal/tests/palsuite/file_io/MoveFileExA/CMakeLists.txt b/src/pal/tests/palsuite/file_io/MoveFileExA/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/MoveFileExA/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/file_io/MoveFileExA/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/MoveFileExA/test1/CMakeLists.txt
new file mode 100644
index 0000000000..f41dd7fd08
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/MoveFileExA/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ MoveFileExA.c
+)
+
+add_executable(paltest_movefileexa_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_movefileexa_test1 coreclrpal)
+
+target_link_libraries(paltest_movefileexa_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/MoveFileExA/test1/ExpectedResults.txt b/src/pal/tests/palsuite/file_io/MoveFileExA/test1/ExpectedResults.txt
new file mode 100644
index 0000000000..684b8a536f
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/MoveFileExA/test1/ExpectedResults.txt
@@ -0,0 +1 @@
+01110011000000000111001100000000
diff --git a/src/pal/tests/palsuite/file_io/MoveFileExA/test1/MoveFileExA.c b/src/pal/tests/palsuite/file_io/MoveFileExA/test1/MoveFileExA.c
new file mode 100644
index 0000000000..0bce2b08d1
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/MoveFileExA/test1/MoveFileExA.c
@@ -0,0 +1,360 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: MoveFileExA.c
+**
+** Purpose: Tests the PAL implementation of the MoveFileExA function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+LPSTR lpSource[4] = {
+ "src_existing.tmp",
+ "src_non-existant.tmp",
+ "src_dir_existing",
+ "src_dir_non-existant"
+ };
+LPSTR lpDestination[4]={
+ "dst_existing.tmp",
+ "dst_non-existant.tmp",
+ "dst_dir_existing",
+ "dst_dir_non-existant"
+ };
+
+LPSTR lpFiles[14] ={
+ "src_dir_existing\\test01.tmp",
+ "src_dir_existing\\test02.tmp",
+ "dst_dir_existing\\test01.tmp",
+ "dst_dir_existing\\test02.tmp",
+ "src_dir_non-existant\\test01.tmp",
+ "src_dir_non-existant\\test02.tmp",
+ "dst_existing.tmp\\test01.tmp",
+ "dst_existing.tmp\\test02.tmp",
+ "dst_non-existant.tmp\\test01.tmp",
+ "dst_non-existant.tmp\\test02.tmp",
+ "dst_dir_existing\\test01.tmp",
+ "dst_dir_existing\\test02.tmp",
+ "dst_dir_non-existant\\test01.tmp",
+ "dst_dir_non-existant\\test02.tmp"
+ };
+
+DWORD dwFlag[2] = {MOVEFILE_COPY_ALLOWED, MOVEFILE_REPLACE_EXISTING};
+
+
+
+
+int createExisting(void)
+{
+ HANDLE tempFile = NULL;
+ HANDLE tempFile2 = NULL;
+
+ /* create the src_existing file and dst_existing file */
+ tempFile = CreateFileA(lpSource[0], GENERIC_WRITE, 0, 0, CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, 0);
+ tempFile2 = CreateFileA(lpDestination[0], GENERIC_WRITE, 0, 0, CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, 0);
+ CloseHandle(tempFile2);
+ CloseHandle(tempFile);
+
+ if ((tempFile == NULL) || (tempFile2 == NULL))
+ {
+ Trace("ERROR[%ul]: couldn't create %S or %S\n", GetLastError(), lpSource[0],
+ lpDestination[0]);
+ return FAIL;
+ }
+
+ /* create the src_dir_existing and dst_dir_existing directory and files */
+ CreateDirectoryA(lpSource[2], NULL);
+
+ tempFile = CreateFileA(lpFiles[0], GENERIC_WRITE, 0, 0, CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, 0);
+ tempFile2 = CreateFileA(lpFiles[1], GENERIC_WRITE, 0, 0, CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, 0);
+ CloseHandle(tempFile2);
+ CloseHandle(tempFile);
+
+ if ((tempFile == NULL) || (tempFile2 == NULL))
+ {
+ Trace("ERROR[%ul]: couldn't create src_dir_existing\\test01.tmp\n", GetLastError());
+ return FAIL;
+ }
+
+ CreateDirectoryA(lpDestination[2], NULL);
+ tempFile = CreateFileA(lpFiles[2], GENERIC_WRITE, 0, 0, CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, 0);
+ tempFile2 = CreateFileA(lpFiles[3], GENERIC_WRITE, 0, 0, CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, 0);
+ CloseHandle(tempFile2);
+ CloseHandle(tempFile);
+
+ if ((tempFile == NULL) || (tempFile2 == NULL))
+ {
+ Trace("ERROR[%ul]: couldn't create dst_dir_existing\\test01.tmp\n" , GetLastError());
+ return FAIL;
+ }
+ return PASS;
+
+}
+
+void removeDirectoryHelper(LPSTR dir, int location)
+{
+ DWORD dwAtt = GetFileAttributesA(dir);
+
+ if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) )
+ {
+ if(!RemoveDirectoryA(dir))
+ {
+ Fail("ERROR: Failed to remove Directory [%s], Error Code [%d], location [%d]\n", dir, GetLastError(), location);
+ }
+ }
+}
+
+void removeFileHelper(LPSTR pfile, int location)
+{
+ FILE *fp;
+ fp = fopen( pfile, "r");
+
+ if (fp != NULL)
+ {
+ if(fclose(fp))
+ {
+ Fail("ERROR: Failed to close the file [%s], Error Code [%d], location [%d]\n", pfile, GetLastError(), location);
+ }
+
+ if(!DeleteFileA(pfile))
+ {
+ Fail("ERROR: Failed to delete file [%s], Error Code [%d], location [%d]\n", pfile, GetLastError(), location);
+ }
+ }
+
+}
+
+void removeAll(void)
+{
+ DWORD dwAtt;
+ /* get rid of destination dirs and files */
+ removeFileHelper(lpSource[0], 11);
+ removeFileHelper(lpSource[1], 12);
+ removeFileHelper(lpFiles[0], 13);
+ removeFileHelper(lpFiles[1], 14);
+
+ removeDirectoryHelper(lpSource[2], 101);
+ removeFileHelper(lpFiles[4], 15);
+ removeFileHelper(lpFiles[5], 16);
+ removeDirectoryHelper(lpSource[3], 102);
+
+ /* get rid of destination dirs and files */
+ dwAtt = GetFileAttributesA(lpDestination[0]);
+ if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) )
+ {
+ removeFileHelper(lpFiles[6], 18);
+ removeFileHelper(lpFiles[7], 19);
+ removeDirectoryHelper(lpDestination[0], 103);
+ }
+ else
+ {
+ removeFileHelper(lpDestination[0], 17);
+ }
+
+ dwAtt = GetFileAttributesA(lpDestination[1]);
+ if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) )
+ {
+ removeFileHelper(lpFiles[8], 21);
+ removeFileHelper(lpFiles[9], 22);
+ removeDirectoryHelper(lpDestination[1], 104);
+ }
+ else
+ {
+ removeFileHelper(lpDestination[1], 19);
+ }
+
+ dwAtt = GetFileAttributesA(lpDestination[2]);
+ if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) )
+ {
+ removeFileHelper(lpFiles[10], 24);
+ removeFileHelper(lpFiles[11], 25);
+ removeDirectoryHelper(lpDestination[2], 105);
+ }
+ else
+ {
+ removeFileHelper(lpDestination[2], 23);
+ }
+
+ dwAtt = GetFileAttributesA(lpDestination[3]);
+ if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) )
+ {
+ removeFileHelper(lpFiles[12], 26);
+ removeFileHelper(lpFiles[13], 27);
+ removeDirectoryHelper(lpDestination[3], 106);
+ }
+ else
+ {
+ removeFileHelper(lpDestination[3], 107);
+ }
+
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ BOOL bRc = TRUE;
+ char results[40];
+ FILE* resultsFile = NULL;
+ int i, j, k, nCounter = 0;
+ int res = FAIL;
+ char tempSource[] = {'t','e','m','p','k','.','t','m','p','\0'};
+ char tempDest[] = {'t','e','m','p','2','.','t','m','p','\0'};
+ HANDLE hFile;
+ DWORD result;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* read in the expected results to compare with actual results */
+ memset (results, 0, 34);
+ resultsFile = fopen("expectedresults.txt", "r");
+ if (resultsFile == NULL)
+ {
+ Trace("MoveFileExA ERROR: Unable to open \"expectedresults.txt\"\n");
+ goto EXIT;
+ }
+
+ fgets(results, 34, resultsFile);
+ fclose(resultsFile);
+
+ nCounter = 0;
+
+
+ /* clean the slate */
+ removeAll();
+ if (createExisting() != PASS)
+ {
+ goto EXIT;
+ }
+
+ /* lpSource loop */
+ for (i = 0; i < 4; i++)
+ {
+ /* lpDestination loop */
+ for (j = 0; j < 4; j++)
+ {
+ /* dwFlag loop */
+ for (k = 0; k < 2; k++)
+ {
+
+ /* move the file to the new location */
+ bRc = MoveFileExA(lpSource[i], lpDestination[j], dwFlag[k]);
+
+ if (!(
+ ((bRc == TRUE) && (results[nCounter] == '1'))
+ ||
+ ((bRc == FALSE ) && (results[nCounter] == '0')) )
+ )
+ {
+ Trace("MoveFileExA(%s, %s, %s): Values of i[%d], j[%d], k [%d] and results[%d]=%c LastError[%d]Flag[%d]FAILED\n",
+ lpSource[i], lpDestination[j],
+ k == 1 ?
+ "MOVEFILE_REPLACE_EXISTING":"MOVEFILE_COPY_ALLOWED", i, j, k, nCounter, results[nCounter], GetLastError(), bRc);
+ goto EXIT;
+ }
+
+ /* undo the last move */
+ removeAll();
+ if (createExisting() != PASS)
+ {
+ goto EXIT;
+ }
+ nCounter++;
+ }
+ }
+ }
+
+ /* create the temp source file */
+ hFile = CreateFileA(tempSource, GENERIC_WRITE, 0, 0, CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, 0);
+
+ if( hFile == INVALID_HANDLE_VALUE )
+ {
+ Trace("MoveFileExA: CreateFile failed to "
+ "create the file correctly.\n");
+ goto EXIT;
+ }
+
+ bRc = CloseHandle(hFile);
+ if(!bRc)
+ {
+ Trace("MoveFileExA: CloseHandle failed to close the "
+ "handle correctly. yo %u\n",GetLastError());
+ goto EXIT;
+ }
+
+ /* set the file attributes to be readonly */
+ bRc = SetFileAttributesA(tempSource, FILE_ATTRIBUTE_READONLY);
+ if(!bRc)
+ {
+ Trace("MoveFileExA: SetFileAttributes failed to set file "
+ "attributes correctly. ERROR:%u\n",GetLastError());
+ goto EXIT;
+ }
+
+ /* move the file to the new location */
+ bRc = MoveFileExA(tempSource, tempDest, MOVEFILE_COPY_ALLOWED );
+ if(!bRc)
+ {
+ Trace("MoveFileExA(%S, %S, %s): GetFileAttributes "
+ "failed to get the file's attributes.\n",
+ tempSource, tempDest, "MOVEFILE_COPY_ALLOWED");
+ goto EXIT;
+ }
+
+ /* check that the newly moved file has the same file attributes
+ as the original */
+ result = GetFileAttributesA(tempDest);
+ if(result == 0)
+ {
+ Trace("MoveFileExA: GetFileAttributes failed to get "
+ "the file's attributes.\n");
+ goto EXIT;
+ }
+
+ if((result & FILE_ATTRIBUTE_READONLY) != FILE_ATTRIBUTE_READONLY)
+ {
+ Trace("MoveFileExA: GetFileAttributes failed to get "
+ "the correct file attributes.\n");
+ goto EXIT;
+ }
+
+ /* set the file attributes back to normal, to be deleted */
+ bRc = SetFileAttributesA(tempDest, FILE_ATTRIBUTE_NORMAL);
+ if(!bRc)
+ {
+ Trace("MoveFileExA: SetFileAttributes "
+ "failed to set file attributes correctly.\n");
+ goto EXIT;
+ }
+
+ /* delete the newly moved file */
+ bRc = DeleteFileA(tempDest);
+ if(!bRc)
+ {
+ Trace("MoveFileExA: DeleteFileA failed to delete the"
+ "file correctly.\n");
+ goto EXIT;
+ }
+
+ res = PASS;
+
+EXIT:
+ removeAll();
+
+ PAL_TerminateEx(res);
+ return res;
+}
+
diff --git a/src/pal/tests/palsuite/file_io/MoveFileExA/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/MoveFileExA/test1/testinfo.dat
new file mode 100644
index 0000000000..d8d19af880
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/MoveFileExA/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = MoveFileExA
+Name = Test for MoveFileExA (test 1)
+Type = DEFAULT
+EXE1 = movefileexa
+Description
+= Creates a number of files/directories and attempts to move them.
+
diff --git a/src/pal/tests/palsuite/file_io/MoveFileExW/CMakeLists.txt b/src/pal/tests/palsuite/file_io/MoveFileExW/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/MoveFileExW/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/file_io/MoveFileExW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/MoveFileExW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..4c6a70f050
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/MoveFileExW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ MoveFileExW.c
+)
+
+add_executable(paltest_movefileexw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_movefileexw_test1 coreclrpal)
+
+target_link_libraries(paltest_movefileexw_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/MoveFileExW/test1/ExpectedResults.txt b/src/pal/tests/palsuite/file_io/MoveFileExW/test1/ExpectedResults.txt
new file mode 100644
index 0000000000..684b8a536f
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/MoveFileExW/test1/ExpectedResults.txt
@@ -0,0 +1 @@
+01110011000000000111001100000000
diff --git a/src/pal/tests/palsuite/file_io/MoveFileExW/test1/MoveFileExW.c b/src/pal/tests/palsuite/file_io/MoveFileExW/test1/MoveFileExW.c
new file mode 100644
index 0000000000..4f5b72dcf7
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/MoveFileExW/test1/MoveFileExW.c
@@ -0,0 +1,431 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: MoveFileExW.c
+**
+** Purpose: Tests the PAL implementation of the MoveFileExW function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+LPWSTR lpSource[4];
+LPWSTR lpDestination[4];
+LPWSTR lpFiles[14];
+
+DWORD dwFlag[2] = {MOVEFILE_COPY_ALLOWED, MOVEFILE_REPLACE_EXISTING};
+
+
+
+int createExisting(void)
+{
+ HANDLE tempFile = NULL;
+ HANDLE tempFile2 = NULL;
+
+ /* create the src_existing file and dst_existing file */
+ tempFile = CreateFileW(lpSource[0], GENERIC_WRITE, 0, 0, CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, 0);
+ tempFile2 = CreateFileW(lpDestination[0], GENERIC_WRITE, 0, 0, CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, 0);
+ CloseHandle(tempFile2);
+ CloseHandle(tempFile);
+
+ if ((tempFile == NULL) || (tempFile2 == NULL))
+ {
+ Trace("ERROR: couldn't create %S or %S\n", lpSource[0],
+ lpDestination[0]);
+ return FAIL;
+ }
+
+ /* create the src_dir_existing and dst_dir_existing directory and files */
+ CreateDirectoryW(lpSource[2], NULL);
+
+ tempFile = CreateFileW(lpFiles[0], GENERIC_WRITE, 0, 0, CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, 0);
+ tempFile2 = CreateFileW(lpFiles[1], GENERIC_WRITE, 0, 0, CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, 0);
+ CloseHandle(tempFile2);
+ CloseHandle(tempFile);
+
+ if ((tempFile == NULL) || (tempFile2 == NULL))
+ {
+ Trace("ERROR: couldn't create src_dir_existing\\test01.tmp\n");
+ return FAIL;
+ }
+
+ CreateDirectoryW(lpDestination[2], NULL);
+ tempFile = CreateFileW(lpFiles[2], GENERIC_WRITE, 0, 0, CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, 0);
+ tempFile2 = CreateFileW(lpFiles[3], GENERIC_WRITE, 0, 0, CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, 0);
+ CloseHandle(tempFile2);
+ CloseHandle(tempFile);
+
+ if ((tempFile == NULL) || (tempFile2 == NULL))
+ {
+ Trace("ERROR: couldn't create dst_dir_existing\\test01.tmp\n");
+ return FAIL;
+ }
+ return PASS;
+}
+
+void removeDirectoryHelper(LPWSTR dir, int location)
+{
+ DWORD dwAtt = GetFileAttributesW(dir);
+// Trace(" Value of location[%d], and directorye [%S]\n", location, dir);
+
+ if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) )
+ {
+ if(!RemoveDirectoryW(dir))
+ {
+ Fail("ERROR: Failed to remove Directory [%S], Error Code [%d], location [%d]\n", dir, GetLastError(), location);
+ }
+ }
+}
+
+void removeFileHelper(LPWSTR wfile, int location)
+{
+ FILE *fp;
+ char * pfile = convertC(wfile);
+
+// Trace(" Value of location[%d], and file [%s]\n", location, pfile);
+ fp = fopen( pfile, "r");
+
+ if (fp != NULL)
+ {
+ if(fclose(fp))
+ {
+ Fail("ERROR: Failed to close the file [%S], Error Code [%d], location [%d]\n", wfile, GetLastError(), location);
+ }
+
+ if(!DeleteFileW(wfile))
+ {
+ Fail("ERROR: Failed to delete file [%S], Error Code [%d], location [%d]\n", wfile, GetLastError(), location);
+ }
+ else
+ {
+ // Trace("Success: deleted file [%S], Error Code [%d], location [%d]\n", wfile, GetLastError(), location);
+ }
+ }
+
+ free(pfile);
+}
+
+void removeAll(void)
+{
+ DWORD dwAtt;
+ /* get rid of destination dirs and files */
+ removeFileHelper(lpSource[0], 11);
+// lpSource[0] = convert("src_existing.tmp");
+
+ removeFileHelper(lpSource[1], 12);
+ //lpSource[1] = convert("src_non-existant.tmp");
+
+ removeFileHelper(lpFiles[0], 13);
+// lpFiles[0] = convert("src_dir_existing\\test01.tmp");
+
+ removeFileHelper(lpFiles[1], 14);
+// lpFiles[1] = convert("src_dir_existing\\test02.tmp");
+
+ removeDirectoryHelper(lpSource[2], 101);
+// lpSource[2] = convert("src_dir_existing");
+
+ removeFileHelper(lpFiles[4], 15);
+// lpFiles[4] = convert("src_dir_non-existant\\test01.tmp");
+
+ removeFileHelper(lpFiles[5], 16);
+// lpFiles[5] = convert("src_dir_non-existant\\test02.tmp");
+
+ removeDirectoryHelper(lpSource[3], 102);
+// lpSource[3] = convert("src_dir_non-existant");
+
+ /* get rid of destination dirs and files */
+ dwAtt = GetFileAttributesW(lpDestination[0]);
+ if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) )
+ {
+ removeFileHelper(lpFiles[6], 18);
+ // lpFiles[6] = convert("dst_existing.tmp\\test01.tmp");
+ removeFileHelper(lpFiles[7], 19);
+ // lpFiles[7] = convert("dst_existing.tmp\\test02.tmp");
+ removeDirectoryHelper(lpDestination[0], 103);
+ // lpDestination[0] = convert("dst_existing.tmp");
+
+ }
+ else
+ {
+ removeFileHelper(lpDestination[0], 17);
+ // lpDestination[0] = convert("dst_existing.tmp");
+ }
+
+ dwAtt = GetFileAttributesW(lpDestination[1]);
+ if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) )
+ {
+ removeFileHelper(lpFiles[8], 21);
+ // lpFiles[8] = convert("dst_non-existant.tmp\\test01.tmp");
+ removeFileHelper(lpFiles[9], 22);
+ // lpFiles[9] = convert("dst_non-existant.tmp\\test02.tmp");
+ removeDirectoryHelper(lpDestination[1], 104);
+ // lpDestination[1] = convert("dst_non-existant.tmp");
+
+ }
+ else
+ {
+ removeFileHelper(lpDestination[1], 19);
+ //lpDestination[1] = convert("dst_non-existant.tmp");
+ }
+
+ dwAtt = GetFileAttributesW(lpDestination[2]);
+ if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) )
+ {
+ removeFileHelper(lpFiles[10], 24);
+ // lpFiles[10] = convert("dst_dir_existing\\test01.tmp");
+ removeFileHelper(lpFiles[11], 25);
+ // lpFiles[11] = convert("dst_dir_existing\\test02.tmp");
+ removeDirectoryHelper(lpDestination[2], 105);
+ // lpDestination[2] = convert("dst_dir_existing");
+
+ }
+ else
+ {
+ removeFileHelper(lpDestination[2], 23);
+ // lpDestination[2] = convert("dst_dir_existing");
+
+ }
+
+ dwAtt = GetFileAttributesW(lpDestination[3]);
+ if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) )
+ {
+ removeFileHelper(lpFiles[12], 26);
+ // lpFiles[12] = convert("dst_dir_non-existant\\test01.tmp");
+ removeFileHelper(lpFiles[13], 27);
+ // lpFiles[13] = convert("dst_dir_non-existant\\test02.tmp");
+ removeDirectoryHelper(lpDestination[3], 106);
+ // lpDestination[3] = convert("dst_dir_non-existant");
+
+ }
+ else
+ {
+ removeFileHelper(lpDestination[3], 107);
+ // lpDestination[3] = convert("dst_dir_non-existant");
+
+ }
+
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ BOOL bRc = TRUE;
+ char results[40];
+ FILE* resultsFile = NULL;
+ int i, j, k, nCounter = 0;
+ int res = FAIL;
+ WCHAR tempSource[] = {'t','e','m','p','k','.','t','m','p','\0'};
+ WCHAR tempDest[] = {'t','e','m','p','2','.','t','m','p','\0'};
+ HANDLE hFile;
+ DWORD result;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ lpSource[0] = convert("src_existing.tmp");
+ lpSource[1] = convert("src_non-existant.tmp");
+ lpSource[2] = convert("src_dir_existing");
+ lpSource[3] = convert("src_dir_non-existant");
+
+ lpDestination[0] = convert("dst_existing.tmp");
+ lpDestination[1] = convert("dst_non-existant.tmp");
+ lpDestination[2] = convert("dst_dir_existing");
+ lpDestination[3] = convert("dst_dir_non-existant");
+
+ lpFiles[0] = convert("src_dir_existing\\test01.tmp");
+ lpFiles[1] = convert("src_dir_existing\\test02.tmp");
+ lpFiles[2] = convert("dst_dir_existing\\test01.tmp");
+ lpFiles[3] = convert("dst_dir_existing\\test02.tmp");
+ lpFiles[4] = convert("src_dir_non-existant\\test01.tmp");
+ lpFiles[5] = convert("src_dir_non-existant\\test02.tmp");
+
+ lpFiles[6] = convert("dst_existing.tmp\\test01.tmp");
+ lpFiles[7] = convert("dst_existing.tmp\\test02.tmp");
+
+ lpFiles[8] = convert("dst_non-existant.tmp\\test01.tmp");
+ lpFiles[9] = convert("dst_non-existant.tmp\\test02.tmp");
+
+ lpFiles[10] = convert("dst_dir_existing\\test01.tmp");
+ lpFiles[11] = convert("dst_dir_existing\\test02.tmp");
+
+ lpFiles[12] = convert("dst_dir_non-existant\\test01.tmp");
+ lpFiles[13] = convert("dst_dir_non-existant\\test02.tmp");
+
+ /* read in the expected results to compare with actual results */
+ memset (results, 0, 34);
+ resultsFile = fopen("expectedresults.txt", "r");
+ if (resultsFile == NULL)
+ {
+ Trace("MoveFileExW ERROR: Unable to open \"expectedresults.txt\"\n");
+ goto EXIT;
+ }
+
+ fgets(results, 34, resultsFile);
+ fclose(resultsFile);
+
+// Trace("Value of results[%]=%s\n", i, results);
+ for( i = 0; i < 32; i++)
+ {
+ Trace("Value of results[%d]=%c\n", i, results[i]);
+ }
+ nCounter = 0;
+
+
+ /* clean the slate */
+ removeAll();
+ if (createExisting() != PASS)
+ {
+ goto EXIT;
+ }
+
+ /* lpSource loop */
+ for (i = 0; i < 4; i++)
+ {
+ /* lpDestination loop */
+ for (j = 0; j < 4; j++)
+ {
+ /* dwFlag loop */
+ for (k = 0; k < 2; k++)
+ {
+
+ //if(nCounter == 22)
+ //{
+ //exit(1);
+ //}
+ /* move the file to the new location */
+ bRc = MoveFileExW(lpSource[i], lpDestination[j], dwFlag[k]);
+
+ if (!(
+ ((bRc == TRUE) && (results[nCounter] == '1'))
+ ||
+ ((bRc == FALSE ) && (results[nCounter] == '0')) )
+ )
+ {
+ Trace("MoveFileExW(%S, %S, %s): Values of i[%d], j[%d], k [%d] and results[%d]=%c LastError[%d]Flag[%d]FAILED\n",
+ lpSource[i], lpDestination[j],
+ k == 1 ?
+ "MOVEFILE_REPLACE_EXISTING":"MOVEFILE_COPY_ALLOWED", i, j, k, nCounter, results[nCounter], GetLastError(), bRc);
+ goto EXIT;
+ }
+
+ //Trace("MoveFileExW(%S, %S, %s): Values of i[%d], j[%d], k [%d] and results[%d]=%c \n",
+ // lpSource[i], lpDestination[j],
+ // k == 1 ?
+ // "MOVEFILE_REPLACE_EXISTING":"MOVEFILE_COPY_ALLOWED", i, j, k, nCounter, results[nCounter]);
+
+
+ /* undo the last move */
+ removeAll();
+ if (createExisting() != PASS)
+ {
+ goto EXIT;
+ }
+ //Trace("Counter [%d] over \n", nCounter);
+ nCounter++;
+ }
+ }
+ }
+
+ /* create the temp source file */
+ hFile = CreateFileW(tempSource, GENERIC_WRITE, 0, 0, CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, 0);
+
+ if( hFile == INVALID_HANDLE_VALUE )
+ {
+ Trace("MoveFileExW: CreateFile failed to "
+ "create the file correctly.\n");
+ goto EXIT;
+ }
+
+ bRc = CloseHandle(hFile);
+ if(!bRc)
+ {
+ Trace("MoveFileExW: CloseHandle failed to close the "
+ "handle correctly. yo %u\n",GetLastError());
+ goto EXIT;
+ }
+
+ /* set the file attributes to be readonly */
+ bRc = SetFileAttributesW(tempSource, FILE_ATTRIBUTE_READONLY);
+ if(!bRc)
+ {
+ Trace("MoveFileExW: SetFileAttributes failed to set file "
+ "attributes correctly. ERROR:%u\n",GetLastError());
+ goto EXIT;
+ }
+
+ /* move the file to the new location */
+ bRc = MoveFileExW(tempSource, tempDest, MOVEFILE_COPY_ALLOWED );
+ if(!bRc)
+ {
+ Trace("MoveFileExW(%S, %S, %s): GetFileAttributes "
+ "failed to get the file's attributes.\n",
+ tempSource, tempDest, "MOVEFILE_COPY_ALLOWED");
+ goto EXIT;
+ }
+
+ /* check that the newly moved file has the same file attributes
+ as the original */
+ result = GetFileAttributesW(tempDest);
+ if(result == 0)
+ {
+ Trace("MoveFileExW: GetFileAttributes failed to get "
+ "the file's attributes.\n");
+ goto EXIT;
+ }
+
+ if((result & FILE_ATTRIBUTE_READONLY) != FILE_ATTRIBUTE_READONLY)
+ {
+ Trace("MoveFileExW: GetFileAttributes failed to get "
+ "the correct file attributes.\n");
+ goto EXIT;
+ }
+
+ /* set the file attributes back to normal, to be deleted */
+ bRc = SetFileAttributesW(tempDest, FILE_ATTRIBUTE_NORMAL);
+ if(!bRc)
+ {
+ Trace("MoveFileExW: SetFileAttributes "
+ "failed to set file attributes correctly.\n");
+ goto EXIT;
+ }
+
+ /* delete the newly moved file */
+ bRc = DeleteFileW(tempDest);
+ if(!bRc)
+ {
+ Trace("MoveFileExW: DeleteFileW failed to delete the"
+ "file correctly.\n");
+ goto EXIT;
+ }
+
+ res = PASS;
+
+EXIT:
+ removeAll();
+ for (i=0; i<4; i++)
+ {
+ free(lpSource[i]);
+ free(lpDestination[i]);
+ }
+ for (i=0; i<14; i++)
+ {
+ free(lpFiles[i]);
+ }
+
+ PAL_TerminateEx(res);
+ return res;
+}
+
diff --git a/src/pal/tests/palsuite/file_io/MoveFileExW/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/MoveFileExW/test1/testinfo.dat
new file mode 100644
index 0000000000..9b001b5c38
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/MoveFileExW/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = MoveFileExW
+Name = Test for MoveFileExW (test 1)
+Type = DEFAULT
+EXE1 = movefileexw
+Description
+= Creates a number of files/directories and attempts to move them.
+
diff --git a/src/pal/tests/palsuite/file_io/MoveFileW/CMakeLists.txt b/src/pal/tests/palsuite/file_io/MoveFileW/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/MoveFileW/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/file_io/MoveFileW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/MoveFileW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..497f654122
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/MoveFileW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ MoveFileW.c
+)
+
+add_executable(paltest_movefilew_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_movefilew_test1 coreclrpal)
+
+target_link_libraries(paltest_movefilew_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/MoveFileW/test1/ExpectedResults.txt b/src/pal/tests/palsuite/file_io/MoveFileW/test1/ExpectedResults.txt
new file mode 100644
index 0000000000..43b67af6b2
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/MoveFileW/test1/ExpectedResults.txt
@@ -0,0 +1 @@
+0101000001010000 \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/MoveFileW/test1/MoveFileW.c b/src/pal/tests/palsuite/file_io/MoveFileW/test1/MoveFileW.c
new file mode 100644
index 0000000000..58999302d0
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/MoveFileW/test1/MoveFileW.c
@@ -0,0 +1,478 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: MoveFileW.c
+**
+** Purpose: Tests the PAL implementation of the MoveFileW function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+LPSTR lpSource[4] = {"src_existing.txt",
+ "src_non-existant.txt",
+ "src_dir_existing",
+ "src_dir_non-existant"};
+LPSTR lpDestination[4] = {"dst_existing.txt",
+ "dst_non-existant.txt",
+ "dst_dir_existing",
+ "dst_dir_non-existant"};
+
+
+/* Create all the required test files */
+int createExisting(void)
+{
+ FILE* tempFile = NULL;
+ DWORD dwError;
+ BOOL bRc = FALSE;
+ WCHAR* wPtr = NULL;
+ char szBuffer[100];
+
+ /* create the src_existing file */
+ tempFile = fopen(lpSource[0], "w");
+ if (tempFile != NULL)
+ {
+ fprintf(tempFile, "MoveFile test file: src_existing.txt\n");
+ fclose(tempFile);
+ }
+ else
+ {
+ Trace("ERROR: couldn't create %s\n", lpSource[0]);
+ return FAIL;
+ }
+
+ /* create the src_dir_existing directory and files */
+ wPtr = convert(lpSource[2]);
+ bRc = CreateDirectoryW(wPtr, NULL);
+ free(wPtr);
+ if (bRc != TRUE)
+ {
+ Trace("MoveFileW: ERROR: couldn't create \"%s\" because of "
+ "error code %ld\n",
+ lpSource[2],
+ GetLastError());
+ return FAIL;
+ }
+
+ memset(szBuffer, 0, 100);
+ sprintf(szBuffer, "%s/test01.txt", lpSource[2]);
+ tempFile = fopen(szBuffer, "w");
+ if (tempFile != NULL)
+ {
+ fprintf(tempFile, "MoveFileW test file: %s\n", szBuffer);
+ fclose(tempFile);
+ }
+ else
+ {
+ Trace("ERROR: couldn't create %s\n", szBuffer);
+ return FAIL;
+ }
+
+ memset(szBuffer, 0, 100);
+ sprintf(szBuffer, "%s/test02.txt", lpSource[2]);
+ tempFile = fopen(szBuffer, "w");
+ if (tempFile != NULL)
+ {
+ fprintf(tempFile, "MoveFileW test file: %s\n", szBuffer);
+ fclose(tempFile);
+ }
+ else
+ {
+ Trace("ERROR: couldn't create %s\n", szBuffer);
+ return FAIL;
+ }
+
+
+ /* create the dst_existing file */
+ tempFile = fopen(lpDestination[0], "w");
+ if (tempFile != NULL)
+ {
+ fprintf(tempFile, "MoveFileW test file: dst_existing.txt\n");
+ fclose(tempFile);
+ }
+ else
+ {
+ Trace("ERROR: couldn't create \"%s\"\n", lpDestination[0]);
+ return FAIL;
+ }
+
+ /* create the dst_dir_existing directory and files */
+ wPtr = convert(lpDestination[2]);
+ bRc = CreateDirectoryW(wPtr, NULL);
+ free(wPtr);
+ if (bRc != TRUE)
+ {
+ dwError = GetLastError();
+ Trace("MoveFileW: ERROR: couldn't create \"%s\"\n", lpDestination[2]);
+ return FAIL;
+ }
+
+ tempFile = fopen("dst_dir_existing/test01.txt", "w");
+ if (tempFile != NULL)
+ {
+ fprintf(tempFile, "MoveFileW test file: dst_dir_existing/test01.txt\n");
+ fclose(tempFile);
+ }
+ else
+ {
+ Trace("ERROR: couldn't create dst_dir_existing/test01.txt\n");
+ return FAIL;
+ }
+ tempFile = fopen("dst_dir_existing/test02.txt", "w");
+ if (tempFile != NULL)
+ {
+ fprintf(tempFile, "MoveFileW test file: dst_dir_existing/test02.txt\n");
+ fclose(tempFile);
+ }
+ else
+ {
+ Trace("ERROR: couldn't create dst_dir_existing/test02.txt\n");
+ return FAIL;
+ }
+
+ return PASS;
+}
+
+void removeDirectoryHelper(LPSTR dir, int location)
+{
+ DWORD dwAtt = GetFileAttributesA(dir);
+ if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) )
+ {
+ if(!RemoveDirectoryA(dir))
+ {
+ Fail("ERROR: Failed to remove Directory [%s], Error Code [%d], location [%d]\n", dir, GetLastError(), location);
+ }
+ }
+}
+
+void removeFileHelper(LPSTR pfile, int location)
+{
+ FILE *fp;
+ fp = fopen( pfile, "r");
+
+ if (fp != NULL)
+ {
+ if(fclose(fp))
+ {
+ Fail("ERROR: Failed to close the file [%s], Error Code [%d], location [%d]\n", pfile, GetLastError(), location);
+ }
+
+ if(!DeleteFileA(pfile))
+ {
+ Fail("ERROR: Failed to delete file [%s], Error Code [%d], location [%d]\n", pfile, GetLastError(), location);
+ }
+ else
+ {
+ // Trace("Success: deleted file [%S], Error Code [%d], location [%d]\n", wfile, GetLastError(), location);
+ }
+ }
+
+}
+
+/* remove all created files in preparation for the next test */
+void removeAll(void)
+{
+ char szTemp[40];
+ DWORD dwAtt;
+
+ /* get rid of source dirs and files */
+ removeFileHelper(lpSource[0], 1);
+ removeFileHelper(lpSource[1], 2);
+
+ dwAtt = GetFileAttributesA(lpSource[2]);
+ if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) )
+ {
+ sprintf(szTemp, "%s/test01.txt", lpSource[2]);
+ removeFileHelper(szTemp, 18);
+
+ sprintf(szTemp, "%s/test02.txt", lpSource[2]);
+ removeFileHelper(szTemp, 19);
+ removeDirectoryHelper(lpSource[2], 103);
+ }
+ else
+ {
+ removeFileHelper(lpSource[2], 17);
+ }
+
+
+ dwAtt = GetFileAttributesA(lpSource[3]);
+ if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) )
+ {
+ sprintf(szTemp, "%s/test01.txt", lpSource[3]);
+ removeFileHelper(szTemp, 18);
+
+ sprintf(szTemp, "%s/test02.txt", lpSource[3]);
+ removeFileHelper(szTemp, 19);
+ removeDirectoryHelper(lpSource[3], 103);
+ }
+ else
+ {
+ removeFileHelper(lpSource[3], 17);
+ }
+
+ /* get rid of destination dirs and files */
+ dwAtt = GetFileAttributesA(lpDestination[0]);
+ if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) )
+ {
+ sprintf(szTemp, "%s/test01.txt", lpDestination[0]);
+ removeFileHelper(szTemp, 18);
+
+ sprintf(szTemp, "%s/test02.txt", lpDestination[0]);
+ removeFileHelper(szTemp, 19);
+ removeDirectoryHelper(lpDestination[0], 103);
+ }
+ else
+ {
+ removeFileHelper(lpDestination[0], 17);
+ }
+
+ dwAtt = GetFileAttributesA(lpDestination[1]);
+ if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) )
+ {
+ sprintf(szTemp, "%s/test01.txt", lpDestination[1]);
+ removeFileHelper(szTemp, 18);
+
+ sprintf(szTemp, "%s/test02.txt", lpDestination[1]);
+ removeFileHelper(szTemp, 19);
+ removeDirectoryHelper(lpDestination[1], 103);
+ }
+ else
+ {
+ removeFileHelper(lpDestination[1], 17);
+ }
+
+ dwAtt = GetFileAttributesA(lpDestination[2]);
+ if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) )
+ {
+ sprintf(szTemp, "%s/test01.txt", lpDestination[2]);
+ removeFileHelper(szTemp, 18);
+
+ sprintf(szTemp, "%s/test02.txt", lpDestination[2]);
+ removeFileHelper(szTemp, 19);
+ removeDirectoryHelper(lpDestination[2], 103);
+ }
+ else
+ {
+ removeFileHelper(lpDestination[2], 17);
+ }
+
+ dwAtt = GetFileAttributesA(lpDestination[3]);
+ if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) )
+ {
+ sprintf(szTemp, "%s/test01.txt", lpDestination[3]);
+ removeFileHelper(szTemp, 18);
+
+ sprintf(szTemp, "%s/test02.txt", lpDestination[3]);
+ removeFileHelper(szTemp, 19);
+ removeDirectoryHelper(lpDestination[3], 103);
+ }
+ else
+ {
+ removeFileHelper(lpDestination[3], 17);
+ }
+
+}
+
+
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ BOOL bRc = TRUE;
+ BOOL bSuccess = TRUE;
+ char results[40];
+ FILE* resultsFile = NULL;
+ int nCounter = 0;
+ int i, j;
+ WCHAR* wSource = NULL;
+ WCHAR* wDest = NULL;
+ WCHAR tempSource[] = {'t','e','m','p','k','.','t','m','p','\0'};
+ WCHAR tempDest[] = {'t','e','m','p','2','.','t','m','p','\0'};
+ HANDLE hFile;
+ DWORD result;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* read in the expected results to compare with actual results */
+ memset (results, 0, 20);
+ resultsFile = fopen("expectedresults.txt", "r");
+ if (resultsFile == NULL)
+ {
+ Fail("MoveFileW ERROR: Unable to open \"expectedresults.txt\"\n");
+ }
+
+ fgets(results, 20, resultsFile);
+ fclose(resultsFile);
+
+ /* clean the slate */
+ removeAll();
+
+ if (createExisting() != 0)
+ {
+ removeAll();
+ }
+
+
+ /* lpSource loop */
+ for (i = 0; i < 4; i++)
+ {
+ /* lpDestination loop */
+ for (j = 0; j < 4; j++)
+ {
+
+ wSource = convert(lpSource[i]);
+ wDest = convert(lpDestination[j]);
+ bRc = MoveFileW(wSource, wDest);
+ free(wSource);
+ free(wDest);
+ if (!(
+ ((bRc == TRUE) && (results[nCounter] == '1'))
+ ||
+ ((bRc == FALSE ) && (results[nCounter] == '0')) )
+ )
+ {
+ Trace("MoveFileW: FAILED: test[%d][%d]: \"%s\" -> \"%s\"\n",
+ i, j, lpSource[i], lpDestination[j]);
+ bSuccess = FALSE;
+ }
+
+ /* undo the last move */
+ removeAll();
+ createExisting();
+
+ nCounter++;
+ }
+ }
+
+ removeAll();
+ if (bSuccess == FALSE)
+ {
+ Fail("MoveFileW: Test Failed");
+ }
+
+ /* create the temp source file */
+ hFile = CreateFileW(tempSource, GENERIC_WRITE, 0, 0, CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, 0);
+
+ if( hFile == INVALID_HANDLE_VALUE )
+ {
+ Fail("MoveFileW: CreateFile failed to "
+ "create the file correctly.\n");
+ }
+
+ bRc = CloseHandle(hFile);
+ if(!bRc)
+ {
+ Trace("MoveFileW: CloseHandle failed to close the "
+ "handle correctly. ERROR:%u\n",GetLastError());
+
+ /* delete the created file */
+ bRc = DeleteFileW(tempSource);
+ if(!bRc)
+ {
+ Fail("MoveFileW: DeleteFileW failed to delete the"
+ "file correctly.\n");
+ }
+ Fail("");
+ }
+
+ /* set the file attributes to be readonly */
+ bRc = SetFileAttributesW(tempSource, FILE_ATTRIBUTE_READONLY);
+ if(!bRc)
+ {
+ Trace("MoveFileW: SetFileAttributes failed to set file "
+ "attributes correctly. GetLastError returned %u\n",GetLastError());
+ /* delete the created file */
+ bRc = DeleteFileW(tempSource);
+ if(!bRc)
+ {
+ Fail("MoveFileW: DeleteFileW failed to delete the"
+ "file correctly.\n");
+ }
+ Fail("");
+ }
+
+ /* move the file to the new location */
+ bRc = MoveFileW(tempSource, tempDest);
+ if(!bRc)
+ {
+ /* delete the created file */
+ bRc = DeleteFileW(tempSource);
+ if(!bRc)
+ {
+ Fail("MoveFileW: DeleteFileW failed to delete the"
+ "file correctly.\n");
+ }
+
+ Fail("MoveFileW(%S, %S): GetFileAttributes "
+ "failed to get the file's attributes.\n",
+ tempSource, tempDest);
+ }
+
+ /* check that the newly moved file has the same file attributes
+ as the original */
+ result = GetFileAttributesW(tempDest);
+ if(result == 0)
+ {
+ /* delete the created file */
+ bRc = DeleteFileW(tempDest);
+ if(!bRc)
+ {
+ Fail("MoveFileW: DeleteFileW failed to delete the"
+ "file correctly.\n");
+ }
+
+ Fail("MoveFileW: GetFileAttributes failed to get "
+ "the file's attributes.\n");
+ }
+
+ if((result & FILE_ATTRIBUTE_READONLY) != FILE_ATTRIBUTE_READONLY)
+ {
+ /* delete the newly moved file */
+ bRc = DeleteFileW(tempDest);
+ if(!bRc)
+ {
+ Fail("MoveFileW: DeleteFileW failed to delete the"
+ "file correctly.\n");
+ }
+
+ Fail("MoveFileW: GetFileAttributes failed to get "
+ "the correct file attributes.\n");
+ }
+
+ /* set the file attributes back to normal, to be deleted */
+ bRc = SetFileAttributesW(tempDest, FILE_ATTRIBUTE_NORMAL);
+ if(!bRc)
+ {
+ /* delete the newly moved file */
+ bRc = DeleteFileW(tempDest);
+ if(!bRc)
+ {
+ Fail("MoveFileW: DeleteFileW failed to delete the"
+ "file correctly.\n");
+ }
+
+ Fail("MoveFileW: SetFileAttributes failed to set "
+ "file attributes correctly.\n");
+ }
+
+ /* delete the newly moved file */
+ bRc = DeleteFileW(tempDest);
+ if(!bRc)
+ {
+ Fail("MoveFileW: DeleteFileW failed to delete the"
+ "file correctly.\n");
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/MoveFileW/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/MoveFileW/test1/testinfo.dat
new file mode 100644
index 0000000000..8852a03ca2
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/MoveFileW/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = MoveFileW
+Name = Positive Test for MoveFileW
+TYPE = DEFAULT
+EXE1 = movefilew
+Description
+=Performs a number of MoveFileW tests and uses the
+=file ExpectedResults.txt to determine if the test passed/failed
diff --git a/src/pal/tests/palsuite/file_io/ReadFile/CMakeLists.txt b/src/pal/tests/palsuite/file_io/ReadFile/CMakeLists.txt
new file mode 100644
index 0000000000..a3847f8ca9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/ReadFile/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+
diff --git a/src/pal/tests/palsuite/file_io/ReadFile/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/ReadFile/test1/CMakeLists.txt
new file mode 100644
index 0000000000..7b166e17b0
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/ReadFile/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ ReadFile.c
+)
+
+add_executable(paltest_readfile_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_readfile_test1 coreclrpal)
+
+target_link_libraries(paltest_readfile_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/ReadFile/test1/NonReadableFile.txt b/src/pal/tests/palsuite/file_io/ReadFile/test1/NonReadableFile.txt
new file mode 100644
index 0000000000..a8a940627d
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/ReadFile/test1/NonReadableFile.txt
@@ -0,0 +1 @@
+this is a test \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/ReadFile/test1/ReadFile.c b/src/pal/tests/palsuite/file_io/ReadFile/test1/ReadFile.c
new file mode 100644
index 0000000000..a59e29212e
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/ReadFile/test1/ReadFile.c
@@ -0,0 +1,82 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: ReadFile.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the ReadFile function.
+** This test will attempt to read from a NULL handle and from
+** a file without read permissions set.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE hFile = NULL;
+ DWORD dwByteCount = 0;
+ DWORD dwBytesRead = 0;
+ BOOL bRc = FALSE;
+ char szBuffer[256];
+ char* szNonReadableFile = {"nonreadablefile.txt"};
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ memset(szBuffer, 0, 256);
+
+ /* Read from a NULL handle
+ */
+
+ bRc = ReadFile(hFile, szBuffer, 20, &dwBytesRead, NULL);
+
+ if (bRc == TRUE)
+ {
+ Fail("ReadFile: ERROR -> Able to read from a NULL handle\n");
+ }
+
+
+ /* Read from a file without read permissions
+ */
+
+#if WIN32
+
+#else
+ /* attempt to read from the unreadable file
+ * open a file without read permissions
+ */
+ hFile = CreateFile(szNonReadableFile,
+ GENERIC_WRITE,
+ FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ dwByteCount = GetLastError();
+ Fail("ReadFile: ERROR -> Unable to create file \"%s\".\n",
+ szNonReadableFile);
+ }
+
+ bRc = ReadFile(hFile, szBuffer, 20, &dwBytesRead, NULL);
+
+ if (bRc == TRUE)
+ {
+ Fail("ReadFile: ERROR -> Able to read from a file without read "
+ "permissions\n");
+ }
+#endif
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/ReadFile/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/ReadFile/test1/testinfo.dat
new file mode 100644
index 0000000000..b0df11a3ab
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/ReadFile/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = ReadFile
+Name = Positive Test for ReadFile
+Type = DEFAULT
+EXE1 = readfile
+Description
+=Attempt to read from a NULL handle and a file without read permissions
+
diff --git a/src/pal/tests/palsuite/file_io/ReadFile/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/ReadFile/test2/CMakeLists.txt
new file mode 100644
index 0000000000..fc4870e73d
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/ReadFile/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ ReadFile.c
+)
+
+add_executable(paltest_readfile_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_readfile_test2 coreclrpal)
+
+target_link_libraries(paltest_readfile_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/ReadFile/test2/ReadFile.c b/src/pal/tests/palsuite/file_io/ReadFile/test2/ReadFile.c
new file mode 100644
index 0000000000..f16858e573
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/ReadFile/test2/ReadFile.c
@@ -0,0 +1,198 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: ReadFile.c (test 2)
+**
+** Purpose: Tests the PAL implementation of the ReadFile function.
+** Creates a test file and performs an array of read tests.
+**
+** Assumes successful:
+** CreateFile
+** CloseHandle
+** WriteFile
+** GetLastError
+**
+**
+**===================================================================*/
+
+
+#include <palsuite.h>
+
+
+const char* szStringTest = "The quick fox jumped over the lazy dog's back.\0";
+const char* szEmptyString = "";
+const char* szReadableFile = "Readable.txt";
+const char* szResultsFile = "Results.txt";
+
+//Previously number of tests was 6, now 4 refer VSW 312690
+#define NOOFTESTS 4
+
+#ifdef __sparc__
+const int PAGESIZE = 8192;
+#else // __sparc__
+const int PAGESIZE = 4096;
+#endif // __sparc__
+
+char *readBuffer;
+
+BOOL validateResults(const char* szString, // string read
+ DWORD dwByteCount, // amount requested
+ DWORD dwBytesRead) // amount read
+{
+ // were the correct number of bytes read?
+ if (dwBytesRead > dwByteCount)
+ {
+ Trace("bytes read > bytes asked for\n");
+ return FALSE;
+ }
+ if (dwBytesRead != strlen(szString))
+ {
+ Trace("bytes read != length of read string\n");
+ return FALSE;
+ }
+
+ //
+ // compare results
+ //
+
+ if (memcmp(szString, szStringTest, dwBytesRead) != 0)
+ {
+ Trace("read = %s string = %s", szString, szStringTest);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+BOOL readTest(DWORD dwByteCount, char cResult)
+{
+ HANDLE hFile = NULL;
+ DWORD dwBytesRead;
+ BOOL bRc = FALSE;
+
+ // open the test file
+ hFile = CreateFile(szReadableFile,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ Trace("ReadFile: ERROR -> Unable to open file \"%s\".\n",
+ szReadableFile);
+ return FALSE;
+ }
+
+ memset(readBuffer, 0, PAGESIZE);
+
+ bRc = ReadFile(hFile, readBuffer, dwByteCount, &dwBytesRead, NULL);
+
+ if (bRc == FALSE)
+ {
+ // if it failed, was it supposed to fail?
+ if (cResult == '1')
+ {
+ Trace("\nbRc = %d\n", bRc);
+ Trace("readBuffer = [%s] dwByteCount = %d dwBytesRead = %d\n", readBuffer, dwByteCount, dwBytesRead);
+ Trace("cresult = 1\n");
+ Trace("getlasterror = %d\n", GetLastError());
+ CloseHandle(hFile);
+ return FALSE;
+ }
+ }
+ else
+ {
+ CloseHandle(hFile);
+ // if it passed, was it supposed to pass?
+ if (cResult == '0')
+ {
+ Trace("cresult = 0\n");
+ return FALSE;
+ }
+ else
+ {
+ return (validateResults(readBuffer, dwByteCount, dwBytesRead));
+ }
+ }
+
+ CloseHandle(hFile);
+ return TRUE;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE hFile = NULL;
+ const int BUFFER_SIZE = 2 * PAGESIZE;
+
+ DWORD dwByteCount[] = { 0,
+ 10,
+ strlen(szStringTest),
+ PAGESIZE
+ // Commented out two negative test cases : Refer VSW 312690
+ // 2 * PAGESIZE,
+ // -1
+ };
+
+ DWORD oldProt;
+ char szResults[] = "1111"; // Was "111100": Refer VSW 312690
+ int i;
+ BOOL bRc = FALSE;
+ DWORD dwBytesWritten = 0;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* aloocate read-write memery for readBuffer */
+ if (!(readBuffer = (char*) VirtualAlloc(NULL, BUFFER_SIZE, MEM_COMMIT, PAGE_READWRITE)))
+ {
+ Fail("VirtualAlloc failed: GetLastError returns %d\n", GetLastError());
+ return FAIL;
+ }
+
+ /* write protect the second page of readBuffer */
+ if (!VirtualProtect(&readBuffer[PAGESIZE], PAGESIZE, PAGE_NOACCESS, &oldProt))
+ {
+ Fail("VirtualProtect failed: GetLastError returns %d\n", GetLastError());
+ return FAIL;
+ }
+
+ // create the test file
+ hFile = CreateFile(szReadableFile,
+ GENERIC_WRITE,
+ FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ReadFile: ERROR -> Unable to create file \"%s\" (%d).\n",
+ szReadableFile, GetLastError());
+ }
+
+ bRc = WriteFile(hFile, szStringTest, strlen(szStringTest), &dwBytesWritten, NULL);
+ CloseHandle(hFile);
+
+
+ for (i = 0; i< NOOFTESTS; i++)
+ {
+ bRc = readTest(dwByteCount[i], szResults[i]);
+ if (bRc != TRUE)
+ {
+ Fail("ReadFile: ERROR -> Failed on test[%d]\n", i);
+ }
+ }
+
+ VirtualFree(readBuffer, BUFFER_SIZE, MEM_RELEASE);
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/file_io/ReadFile/test2/testinfo.dat b/src/pal/tests/palsuite/file_io/ReadFile/test2/testinfo.dat
new file mode 100644
index 0000000000..82b6326170
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/ReadFile/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = ReadFile
+Name = Positive Test for ReadFile
+Type = DEFAULT
+EXE1 = readfile
+Description
+=Multiple tests of reads of varying sizes with verification
+
diff --git a/src/pal/tests/palsuite/file_io/ReadFile/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/ReadFile/test3/CMakeLists.txt
new file mode 100644
index 0000000000..77397743d4
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/ReadFile/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ ReadFile.c
+)
+
+add_executable(paltest_readfile_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_readfile_test3 coreclrpal)
+
+target_link_libraries(paltest_readfile_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/ReadFile/test3/ReadFile.c b/src/pal/tests/palsuite/file_io/ReadFile/test3/ReadFile.c
new file mode 100644
index 0000000000..c5d6b1d155
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/ReadFile/test3/ReadFile.c
@@ -0,0 +1,184 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: ReadFile.c (test 3)
+**
+** Purpose: Tests the PAL implementation of the ReadFile function.
+** Creates a test file and performs an array of sequential read
+** tests.
+**
+** Assumes successful:
+** CreateFile
+** CloseHandle
+** memset
+** WriteFile
+** CreateFile
+** CloseHandle
+** GetLastError
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+const char* szStringTest = "The quick fox jumped over the lazy dog's back.\0";
+const char* szEmptyString = "";
+const char* szReadableFile = "Readable.txt";
+const char* szResultsFile = "Results.txt";
+
+
+BOOL validateResults(const char* szString, // string read
+ DWORD dwByteCount, // amount requested
+ DWORD dwBytesRead) // amount read
+{
+ // were the correct number of bytes read?
+ if (dwBytesRead > dwByteCount)
+ {
+ Trace("bytes read > bytes asked for\n");
+ return FALSE;
+ }
+ if (dwBytesRead != strlen(szString))
+ {
+ Trace("bytes read != length of read string\n");
+ return FALSE;
+ }
+
+
+ //
+ // compare results
+ //
+
+ if (memcmp(szString, szStringTest, dwByteCount) != 0)
+ {
+ Trace("read = %s string = %s", szString, szStringTest);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+
+
+BOOL readTest(DWORD dwByteCount, char cResult)
+{
+ HANDLE hFile = NULL;
+ DWORD dwBytesRead = 0;
+ DWORD dwTotal = 0;
+ DWORD dwRequested = 0;
+ BOOL bRc = FALSE;
+ char szString[100];
+ char* szPtr = szString;
+ int i = 0;
+
+ // open the test file
+ hFile = CreateFile(szReadableFile,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ Trace("ReadFile: ERROR -> Unable to open file \"%s\".\n",
+ szReadableFile);
+ return FALSE;
+ }
+
+ memset(szString, 0, 100);
+
+ for (i = 0; i < 5; i++)
+ {
+ bRc = ReadFile(hFile, szPtr, dwByteCount, &dwBytesRead, NULL);
+ szPtr += dwByteCount;
+ dwTotal += dwBytesRead;
+ dwRequested += dwByteCount;
+ }
+
+ if (bRc == FALSE)
+ {
+ // if it failed, was it supposed to fail?
+ if (cResult == '1')
+ {
+ Trace("\nbRc = %d\n", bRc);
+ Trace("szString = [%s] dwByteCount = %d dwBytesRead = %d\n",
+ szString,
+ dwByteCount,
+ dwBytesRead);
+ Trace ("cresult = 1\n");
+ Trace ("getlasterror = %d\n", GetLastError());
+ CloseHandle(hFile);
+ return FALSE;
+ }
+ }
+ else
+ {
+ CloseHandle(hFile);
+ // if it passed, was it supposed to pass?
+ if (cResult == '0')
+ {
+ Trace ("cresult = 0\n");
+ return FALSE;
+ }
+ else
+ {
+ return (validateResults(szString, dwRequested, dwTotal));
+ }
+ }
+
+ CloseHandle(hFile);
+ return TRUE;
+}
+
+
+
+int __cdecl main(int argc, char **argv)
+{
+ HANDLE hFile = NULL;
+ DWORD dwByteCount[4] = {0, 1, 2, 3};
+ char szResults[4] = {'1', '1', '1', '1'};
+ int i;
+ BOOL bRc = FALSE;
+ DWORD dwBytesWritten = 0;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+
+ // create the test file
+ hFile = CreateFile(szReadableFile,
+ GENERIC_WRITE,
+ FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ReadFile: ERROR -> Unable to create file \"%s\".\n",
+ szReadableFile);
+ }
+
+ bRc = WriteFile(hFile, szStringTest, strlen(szStringTest),
+ &dwBytesWritten,
+ NULL);
+ CloseHandle(hFile);
+
+ for (i = 0; i < 4; i++)
+ {
+ bRc = readTest(dwByteCount[i], szResults[i]);
+ if (bRc != TRUE)
+ {
+ Fail("ReadFile: ERROR -> Failed on test[%d]\n", i);
+ }
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/ReadFile/test3/testinfo.dat b/src/pal/tests/palsuite/file_io/ReadFile/test3/testinfo.dat
new file mode 100644
index 0000000000..82b6326170
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/ReadFile/test3/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = ReadFile
+Name = Positive Test for ReadFile
+Type = DEFAULT
+EXE1 = readfile
+Description
+=Multiple tests of reads of varying sizes with verification
+
diff --git a/src/pal/tests/palsuite/file_io/ReadFile/test4/CMakeLists.txt b/src/pal/tests/palsuite/file_io/ReadFile/test4/CMakeLists.txt
new file mode 100644
index 0000000000..37f227aced
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/ReadFile/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ readfile.c
+)
+
+add_executable(paltest_readfile_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_readfile_test4 coreclrpal)
+
+target_link_libraries(paltest_readfile_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/ReadFile/test4/readfile.c b/src/pal/tests/palsuite/file_io/ReadFile/test4/readfile.c
new file mode 100644
index 0000000000..3ec939f63a
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/ReadFile/test4/readfile.c
@@ -0,0 +1,147 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: ReadFile.c (test 4)
+**
+** Purpose: Tests the PAL implementation of the ReadFile function.
+** Creates a file and writes a small string to it, attempt
+** to read many more characters that exist. The returned
+** number of chars should be the amount written originally
+** not the number requested.
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE hFile = NULL;
+ DWORD dwBytesWritten;
+ BOOL bRc = FALSE;
+ char szBuffer[256];
+ DWORD dwBytesRead = 0;
+ int szRequestSize = 256;
+ char testFile[] = "testfile.tmp";
+ char testString[] = "people stop and stare";
+ DWORD res = 0;
+
+ /* Initialize the PAL.
+ */
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* Initialize the buffer.
+ */
+ memset(szBuffer, 0, 256);
+
+ /* Create a file to test with.
+ */
+ hFile = CreateFile(testFile,
+ GENERIC_WRITE|GENERIC_READ,
+ FILE_SHARE_WRITE|FILE_SHARE_READ,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR:%u: Unable to create file \"%s\".\n",
+ GetLastError(),
+ testFile);
+ }
+
+ /* Write to the File handle.
+ */
+ bRc = WriteFile(hFile,
+ testString,
+ strlen(testString),
+ &dwBytesWritten,
+ NULL);
+
+ if (bRc == FALSE)
+ {
+ Trace("ERROR:%u: Unable to write to file handle "
+ "hFile=0x%lx\n",
+ GetLastError(),
+ hFile);
+ if (!CloseHandle(hFile))
+ {
+ Trace("ERROR:%u%: Unable to close handle 0x%lx.\n",
+ GetLastError(),
+ hFile);
+ }
+ Fail("");
+ }
+
+ /* Set the file pointer to beginning of file.
+ */
+ res = SetFilePointer(hFile, (LONG)NULL, NULL, FILE_BEGIN);
+
+ if( (res == INVALID_SET_FILE_POINTER) &&
+ (GetLastError() != NO_ERROR))
+ {
+ Trace("ERROR:%u: Unable to set file pointer to the beginning of file.",
+ GetLastError());
+
+ if (!CloseHandle(hFile))
+ {
+ Trace("ERROR:%u%: Unable to close handle 0x%lx.\n",
+ GetLastError(),
+ hFile);
+ }
+ Fail("");
+ }
+
+
+ /* Attempt to read 256 characters from a file
+ * that does not contain that many.
+ */
+ bRc = ReadFile(hFile,
+ szBuffer,
+ szRequestSize,
+ &dwBytesRead,
+ NULL);
+
+ if (bRc == FALSE)
+ {
+ Trace("ERROR:%u: Unable to read from file handle 0x%lx.\n",
+ GetLastError(),
+ hFile);
+ if (!CloseHandle(hFile))
+ {
+ Trace("ERROR:%u%: Unable to close handle 0x%lx.\n",
+ GetLastError(),
+ hFile);
+ }
+ Fail("");
+ }
+
+ /* Confirm the number of bytes read with that requested.
+ */
+ if (dwBytesRead != strlen(testString))
+ {
+ Trace("ERROR: The number of bytes read \"%d\" is not equal to the "
+ "number originally written \"%d\" to the file.\n",
+ dwBytesRead,
+ strlen(testString));
+ if (!CloseHandle(hFile))
+ {
+ Trace("ERROR:%u%: Unable to close handle 0x%lx.\n",
+ GetLastError(),
+ hFile);
+ }
+ Fail("");
+ }
+
+ /* Terminate the PAL.
+ */
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/file_io/ReadFile/test4/testinfo.dat b/src/pal/tests/palsuite/file_io/ReadFile/test4/testinfo.dat
new file mode 100644
index 0000000000..6f3267d591
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/ReadFile/test4/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = ReadFile
+Name = Positive Test for ReadFile
+Type = DEFAULT
+EXE1 = readfile
+Description
+= Tests the PAL implementation of the ReadFile function.
+= Creates a file and writes a small string to it, attempt
+= to read many more characters that exist. The returned
+= number of chars should be the amount written originally
+= not the number requested.
+
diff --git a/src/pal/tests/palsuite/file_io/RemoveDirectoryA/CMakeLists.txt b/src/pal/tests/palsuite/file_io/RemoveDirectoryA/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/RemoveDirectoryA/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/file_io/RemoveDirectoryA/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/RemoveDirectoryA/test1/CMakeLists.txt
new file mode 100644
index 0000000000..7a8d1c9d57
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/RemoveDirectoryA/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ RemoveDirectoryA.cpp
+)
+
+add_executable(paltest_removedirectorya_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_removedirectorya_test1 coreclrpal)
+
+target_link_libraries(paltest_removedirectorya_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/RemoveDirectoryA/test1/RemoveDirectoryA.cpp b/src/pal/tests/palsuite/file_io/RemoveDirectoryA/test1/RemoveDirectoryA.cpp
new file mode 100644
index 0000000000..167af58163
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/RemoveDirectoryA/test1/RemoveDirectoryA.cpp
@@ -0,0 +1,315 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: RemoveDirectoryA.c
+**
+** Purpose: Tests the PAL implementation of the RemoveDirectoryA function.
+**
+**
+**===================================================================*/
+
+
+#define PAL_STDCPP_COMPAT
+#include <palsuite.h>
+#undef PAL_STDCPP_COMPAT
+
+#include <unistd.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ BOOL bRc = FALSE;
+ char szDirName[252];
+ DWORD curDirLen;
+ char *szTemp = NULL;
+ char *szTemp2 = NULL;
+ char szwCurrentDir[MAX_PATH];
+ char szwSubDir[MAX_PATH];
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /*
+ * remove a NULL directory
+ */
+ bRc = RemoveDirectoryA(NULL);
+ if (bRc != FALSE)
+ {
+ Fail("Error[%ul]:RemoveDirectoryA: Failed since it was able to remove a"
+ " NULL directory name\n", GetLastError());
+ }
+
+ /*
+ * remove a directory that does not exist
+ */
+ szTemp = (char *) malloc (sizeof("test_directory"));
+ sprintf(szTemp, "test_directory");
+ bRc = RemoveDirectoryA(szTemp);
+ if (bRc != FALSE)
+ {
+ free(szTemp);
+ Fail("Error[%ul]:RemoveDirectoryA: Failed since it was able to remove"
+ " the non-existant directory \"test_directory\"\n", GetLastError());
+ }
+
+ /*
+ * remove a symlink to a directory
+ */
+ bRc = CreateDirectoryA(szTemp, NULL);
+ if (bRc != TRUE)
+ {
+ free(szTemp);
+ Fail("Error[%ul]:RemoveDirectoryA: Failed to create the directory "
+ "\"test_directory\".\n", GetLastError());
+ }
+
+ char *szSymlinkName = (char *) malloc (sizeof("test_directory_symlink"));
+ sprintf(szSymlinkName, "test_directory_symlink");
+ if (symlink(szTemp, szSymlinkName) != 0)
+ {
+ Fail("Error:RemoveDirectoryA: Failed to create a symlink to the directory \"test_directory\".\n");
+ }
+
+ bRc = RemoveDirectoryA(szSymlinkName);
+ if (bRc != FALSE)
+ {
+ Fail("Error:RemoveDirectoryA: RemoveDirectoryA should return FALSE when passed a symlink.\n");
+ }
+
+ unlink(szSymlinkName);
+
+ /*
+ * remove a directory that exists
+ */
+ bRc = RemoveDirectoryA(szTemp);
+ if (bRc == FALSE)
+ {
+ free(szTemp);
+ Fail("Error[%ul]:RemoveDirectoryW: Failed to remove the directory "
+ "\"test_directory\"\n",
+ GetLastError());
+ }
+ /* Make sure the directory was removed */
+ if( -1 != GetFileAttributesA(szTemp) )
+ {
+ free(szTemp);
+ Fail("Error[%ul]:RemoveDirectoryA: Able to get the attributes of "
+ "the removed directory\n" , GetLastError());
+ }
+ free(szTemp);
+
+ /*
+ * remove long directory names (245 characters)
+ */
+ curDirLen = GetCurrentDirectoryA(0, NULL) + 1;
+ memset(szDirName, 0, 252);
+ memset(szDirName, 'a', 245 - curDirLen);
+ szTemp = (char *) malloc (sizeof(szDirName));
+ szTemp = strncpy(szTemp, szDirName, strlen(szDirName) + 1);
+
+ bRc = CreateDirectoryA(szTemp, NULL);
+ if (bRc == FALSE)
+ {
+ free(szTemp);
+ Fail("Error[%ul]:RemoveDirectoryA: Failed to create a directory name "
+ "245 chars long\n" , GetLastError());
+ }
+ bRc = RemoveDirectoryA(szTemp);
+ if (bRc == FALSE)
+ {
+ free(szTemp);
+ Fail("Error[%ul]:RemoveDirectoryA: Failed to remove a 245 char "
+ "long directory\n", GetLastError());
+ }
+
+ /* Make sure the directory was removed */
+ if( -1 != GetFileAttributesA(szTemp) )
+ {
+ free(szTemp);
+ Fail("Error[%ul]:RemoveDirectoryA: Able to get the attributes of "
+ "the removed directory\n", GetLastError());
+ }
+ free(szTemp);
+
+ /*
+ * directories with dots
+ */
+ memset(szDirName, 0, 252);
+ sprintf(szDirName, ".dotDirectory");
+ szTemp = (char *) malloc (sizeof(szDirName));
+ szTemp = strncpy(szTemp, szDirName, strlen(szDirName) + 1);
+
+ bRc = CreateDirectoryA(szTemp, NULL);
+ if (bRc == FALSE)
+ {
+ free(szTemp);
+ Fail("Error[%ul]:RemoveDirectoryA: Failed to create \"%s\"\n", GetLastError(), szDirName);
+ }
+ bRc = RemoveDirectoryA(szTemp);
+ if (bRc == FALSE)
+ {
+ free(szTemp);
+ Fail("Error[%ul]:RemoveDirectoryA: Failed to remove \"%s\"\n", GetLastError(), szDirName);
+ }
+
+ /* Make sure the directory was removed */
+ if( -1 != GetFileAttributesA(szTemp) )
+ {
+ free(szTemp);
+ Fail("Error[%ul]:RemoveDirectoryA: Able to get the attributes of "
+ "the removed directory\n", GetLastError());
+ }
+ free(szTemp);
+
+ /*
+ * Try calling RemoveDirectory with a file name
+ */
+ memset(szDirName, 0, 252);
+ sprintf(szDirName, "removedirectoryw.c");
+ szTemp = (char *) malloc (sizeof(szDirName));
+ szTemp = strncpy(szTemp, szDirName, strlen(szDirName) + 1);
+
+ bRc = RemoveDirectoryA(szTemp);
+ free(szTemp);
+ if (bRc != FALSE)
+ {
+ Fail("Error[%ul]:RemoveDirectoryA: should have failed when "
+ "called with a valid file name", GetLastError() );
+ }
+
+ /*
+ * remove a non empty directory
+ *
+ * To test that, we'll first create non_empty_dir, we'll
+ * set the current dir to non_empty_dir in which we'll
+ * create sub_dir. We'll go back to the root of non_empty_dir
+ * and we'll try to delete it (it shouldn't work).
+ * After that we'll cleanup sub_dir and non_empty_dir
+ */
+
+ /* Get the current directory so it is easy to get back
+ to it later */
+ if( 0 == GetCurrentDirectoryA(MAX_PATH, szwCurrentDir) )
+ {
+ Fail("RemoveDirectoryA: Failed to get current directory "
+ "with GetCurrentDirectoryA.\n");
+ }
+
+ /* Create non_empty_dir */
+ sprintf( szDirName, "non_empty_dir");
+ szTemp = (char *) malloc (sizeof(szDirName));
+ szTemp = strncpy(szTemp, szDirName, strlen(szDirName) + 1);
+ bRc = CreateDirectoryA(szTemp, NULL);
+ if (bRc != TRUE)
+ {
+ free(szTemp);
+ Fail("Error[%ul]:RemoveDirectoryA: Failed to create the directory "
+ "\"non_empty_dir\" when it exists already.\n", GetLastError());
+ }
+
+ if( 0 == SetCurrentDirectoryA(szTemp) )
+ {
+ free(szTemp);
+ Fail("Error[%ul]:RemoveDirectoryA: Failed to set current directory to "
+ "\"non_empty_dir\" with SetCurrentDirectoryA.\n", GetLastError());
+ }
+
+ /* Get the directory full path so it is easy to get back
+ to it later */
+ if( 0 == GetCurrentDirectoryA(MAX_PATH, szwSubDir) )
+ {
+ free(szTemp);
+ Fail("Error[%ul]:RemoveDirectoryA: Failed to get current directory "
+ "with GetCurrentDirectoryA.\n", GetLastError());
+ }
+
+ /* Create sub_dir */
+ sprintf (szDirName, "sub_dir");
+ szTemp2 = (char *) malloc (sizeof(szDirName));
+ szTemp2 = strncpy(szTemp2, szDirName, strlen(szDirName) + 1);
+ bRc = CreateDirectoryA(szTemp2, NULL);
+ if (bRc != TRUE)
+ {
+ free(szTemp);
+ free(szTemp2);
+ Fail("Error[%ul]:RemoveDirectoryA: Failed to create the directory "
+ "\"sub_dir\" when it exists already.\n", GetLastError());
+ }
+
+ /* Set the current dir to the parent of non_empty_dir/sub_dir */
+ if( 0 == SetCurrentDirectoryA(szwCurrentDir) )
+ {
+ free(szTemp);
+ free(szTemp2);
+ Fail("Error[%ul]:RemoveDirectoryA: Failed to set current directory to "
+ "\"non_empty_dir\" with SetCurrentDirectoryA.\n", GetLastError());
+ }
+
+ /* Try to remove non_empty_dir (shouldn't work) */
+ bRc = RemoveDirectoryA(szTemp);
+ if (bRc == TRUE)
+ {
+ free(szTemp);
+ free(szTemp2);
+ Fail("Error[%ul]:RemoveDirectoryA: shouldn't have been able to remove "
+ "the non empty directory \"non_empty_dir\"\n", GetLastError());
+ }
+
+ /* Go back to non_empty_dir and remove sub_dir */
+ if( 0 == SetCurrentDirectoryA(szwSubDir) )
+ {
+ free(szTemp);
+ free(szTemp2);
+ Fail("Error[%ul]:RemoveDirectoryA: Failed to set current directory to "
+ "\"non_empty_dir\" with SetCurrentDirectoryA.\n", GetLastError());
+ }
+
+ bRc = RemoveDirectoryA(szTemp2);
+ if (bRc == FALSE)
+ {
+ free(szTemp);
+ free(szTemp2);
+ Fail("Error[%ul]:RemoveDirectoryA: unable to remove "
+ "directory \"sub_dir\" \n",
+ GetLastError());
+ }
+ /* Make sure the directory was removed */
+ if( -1 != GetFileAttributesA(szTemp2) )
+ {
+ Fail("Error[%ul]RemoveDirectoryA: Able to get the attributes of "
+ "the removed directory\n", GetLastError());
+ }
+ free(szTemp2);
+
+ /* Go back to parent of non_empty_dir and remove non_empty_dir */
+ if( 0 == SetCurrentDirectoryA(szwCurrentDir) )
+ {
+ free(szTemp);
+ Fail("Error[%ul]:RemoveDirectoryA: Failed to set current directory to "
+ "\"..\non_empty_dir\" with SetCurrentDirectoryA.\n", GetLastError());
+ }
+ bRc = RemoveDirectoryA(szTemp);
+ if (bRc == FALSE)
+ {
+ free(szTemp);
+ Fail("Error[%ul]RemoveDirectoryA: unable to remove "
+ "the directory \"non_empty_dir\"\n",
+ GetLastError());
+ }
+ /* Make sure the directory was removed */
+ if( -1 != GetFileAttributesA(szTemp) )
+ {
+ Fail("Error[%ul]:RemoveDirectoryA: Able to get the attributes of "
+ "the removed directory\n", GetLastError());
+ }
+ free(szTemp);
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/RemoveDirectoryA/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/RemoveDirectoryA/test1/testinfo.dat
new file mode 100644
index 0000000000..6d8f72d27e
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/RemoveDirectoryA/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = RemoveDirectoryA
+Name = Test for RemoveDirectoryA (test 1)
+Type = DEFAULT
+EXE1 = removedirectorya
+Description
+= Create directories and attempt to remove them.
+
diff --git a/src/pal/tests/palsuite/file_io/RemoveDirectoryW/CMakeLists.txt b/src/pal/tests/palsuite/file_io/RemoveDirectoryW/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/RemoveDirectoryW/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/file_io/RemoveDirectoryW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/RemoveDirectoryW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..45b51cec30
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/RemoveDirectoryW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ RemoveDirectoryW.c
+)
+
+add_executable(paltest_removedirectoryw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_removedirectoryw_test1 coreclrpal)
+
+target_link_libraries(paltest_removedirectoryw_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/RemoveDirectoryW/test1/RemoveDirectoryW.c b/src/pal/tests/palsuite/file_io/RemoveDirectoryW/test1/RemoveDirectoryW.c
new file mode 100644
index 0000000000..ae1dd0fb97
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/RemoveDirectoryW/test1/RemoveDirectoryW.c
@@ -0,0 +1,282 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: RemoveDirectoryW.c
+**
+** Purpose: Tests the PAL implementation of the RemoveDirectoryW function.
+**
+**
+**===================================================================*/
+
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ BOOL bRc = FALSE;
+ char szDirName[252];
+ DWORD curDirLen;
+ WCHAR *szwTemp = NULL;
+ WCHAR *szwTemp2 = NULL;
+ WCHAR szwCurrentDir[MAX_PATH];
+ WCHAR szwSubDir[MAX_PATH];
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /*
+ * remove a NULL directory
+ */
+ bRc = RemoveDirectoryW(NULL);
+ if (bRc != FALSE)
+ {
+ Fail("RemoveDirectoryW: Failed since it was able to remove a"
+ " NULL directory name\n");
+ }
+
+ /*
+ * remove a directory that does not exist
+ */
+ szwTemp = convert("test_directory");
+ bRc = RemoveDirectoryW(szwTemp);
+ if (bRc != FALSE)
+ {
+ free(szwTemp);
+ Fail("RemoveDirectoryW: Failed since it was able to remove"
+ " the non-existant directory \"test_directory\"\n");
+ }
+
+ /*
+ * remove a directory that exists
+ */
+ bRc = CreateDirectoryW(szwTemp, NULL);
+ if (bRc != TRUE)
+ {
+ free(szwTemp);
+ Fail("RemoveDirectoryW: Failed to create the directory "
+ "\"test_directory\" when it exists already.\n");
+ }
+ bRc = RemoveDirectoryW(szwTemp);
+ if (bRc == FALSE)
+ {
+ free(szwTemp);
+ Fail("RemoveDirectoryW: Failed to remove the directory "
+ "\"test_directory\" (error code %d)\n",
+ GetLastError());
+ }
+ /* Make sure the directory was removed */
+ if( -1 != GetFileAttributesW(szwTemp) )
+ {
+ free(szwTemp);
+ Fail("RemoveDirectoryW: Able to get the attributes of "
+ "the removed directory\n");
+ }
+ free(szwTemp);
+
+ /*
+ * remove long directory names (245 characters)
+ */
+ curDirLen = GetCurrentDirectoryA(0, NULL) + 1;
+ memset(szDirName, 0, 252);
+ memset(szDirName, 'a', 245 - curDirLen);
+ szwTemp = convert(szDirName);
+ bRc = CreateDirectoryW(szwTemp, NULL);
+ if (bRc == FALSE)
+ {
+ free(szwTemp);
+ Fail("RemoveDirectoryW: Failed to create a directory name "
+ "245 chars long\n");
+ }
+ bRc = RemoveDirectoryW(szwTemp);
+ if (bRc == FALSE)
+ {
+ free(szwTemp);
+ Fail("RemoveDirectoryW: Failed to remove a 245 char "
+ "long directory\n");
+ }
+
+ /* Make sure the directory was removed */
+ if( -1 != GetFileAttributesW(szwTemp) )
+ {
+ free(szwTemp);
+ Fail("RemoveDirectoryW: Able to get the attributes of "
+ "the removed directory\n");
+ }
+ free(szwTemp);
+
+ /*
+ * directories with dots
+ */
+ memset(szDirName, 0, 252);
+ sprintf(szDirName, ".dotDirectory");
+ szwTemp = convert(szDirName);
+ bRc = CreateDirectoryW(szwTemp, NULL);
+ if (bRc == FALSE)
+ {
+ free(szwTemp);
+ Fail("RemoveDirectoryW: Failed to create \"%s\"\n", szDirName);
+ }
+ bRc = RemoveDirectoryW(szwTemp);
+ if (bRc == FALSE)
+ {
+ free(szwTemp);
+ Fail("RemoveDirectoryW: Failed to remove \"%s\"\n", szDirName);
+ }
+
+ /* Make sure the directory was removed */
+ if( -1 != GetFileAttributesW(szwTemp) )
+ {
+ free(szwTemp);
+ Fail("RemoveDirectoryW: Able to get the attributes of "
+ "the removed directory\n");
+ }
+ free(szwTemp);
+
+ /*
+ * Try calling RemoveDirectory with a file name
+ */
+ memset(szDirName, 0, 252);
+ sprintf(szDirName, "removedirectoryw.c");
+ szwTemp = convert(szDirName);
+
+ bRc = RemoveDirectoryW(szwTemp);
+ free(szwTemp);
+ if (bRc != FALSE)
+ {
+ Fail("RemoveDirectoryW: should have failed when "
+ "called with a valid file name" );
+ }
+
+ /*
+ * remove a non empty directory
+ *
+ * To test that, we'll first create non_empty_dir, we'll
+ * set the current dir to non_empty_dir in which we'll
+ * create sub_dir. We'll go back to the root of non_empty_dir
+ * and we'll try to delete it (it shouldn't work).
+ * After that we'll cleanup sub_dir and non_empty_dir
+ */
+
+ /* Get the current directory so it is easy to get back
+ to it later */
+ if( 0 == GetCurrentDirectoryW(MAX_PATH, szwCurrentDir) )
+ {
+ Fail("RemoveDirectoryW: Failed to get current directory "
+ "with GetCurrentDirectoryW.\n");
+ }
+
+ /* Create non_empty_dir */
+ szwTemp = convert("non_empty_dir");
+ bRc = CreateDirectoryW(szwTemp, NULL);
+ if (bRc != TRUE)
+ {
+ free(szwTemp);
+ Fail("RemoveDirectoryW: Failed to create the directory "
+ "\"non_empty_dir\" when it exists already.\n");
+ }
+
+ if( 0 == SetCurrentDirectoryW(szwTemp) )
+ {
+ free(szwTemp);
+ Fail("RemoveDirectoryW: Failed to set current directory to "
+ "\"non_empty_dir\" with SetCurrentDirectoryW.\n");
+ }
+
+ /* Get the directory full path so it is easy to get back
+ to it later */
+ if( 0 == GetCurrentDirectoryW(MAX_PATH, szwSubDir) )
+ {
+ free(szwTemp);
+ Fail("RemoveDirectoryW: Failed to get current directory "
+ "with GetCurrentDirectoryW.\n");
+ }
+
+ /* Create sub_dir */
+ szwTemp2 = convert("sub_dir");
+ bRc = CreateDirectoryW(szwTemp2, NULL);
+ if (bRc != TRUE)
+ {
+ free(szwTemp);
+ free(szwTemp2);
+ Fail("RemoveDirectoryW: Failed to create the directory "
+ "\"sub_dir\" when it exists already.\n");
+ }
+
+ /* Set the current dir to the parent of non_empty_dir/sub_dir */
+ if( 0 == SetCurrentDirectoryW(szwCurrentDir) )
+ {
+ free(szwTemp);
+ free(szwTemp2);
+ Fail("RemoveDirectoryW: Failed to set current directory to "
+ "\"non_empty_dir\" with SetCurrentDirectoryW.\n");
+ }
+
+ /* Try to remove non_empty_dir (shouldn't work) */
+ bRc = RemoveDirectoryW(szwTemp);
+ if (bRc == TRUE)
+ {
+ free(szwTemp);
+ free(szwTemp2);
+ Fail("RemoveDirectoryW: shouldn't have been able to remove "
+ "the non empty directory \"non_empty_dir\"\n");
+ }
+
+ /* Go back to non_empty_dir and remove sub_dir */
+ if( 0 == SetCurrentDirectoryW(szwSubDir) )
+ {
+ free(szwTemp);
+ free(szwTemp2);
+ Fail("RemoveDirectoryW: Failed to set current directory to "
+ "\"non_empty_dir\" with SetCurrentDirectoryW.\n");
+ }
+
+ bRc = RemoveDirectoryW(szwTemp2);
+ if (bRc == FALSE)
+ {
+ free(szwTemp);
+ free(szwTemp2);
+ Fail("RemoveDirectoryW: unable to remove "
+ "directory \"sub_dir\"(error code %d)\n",
+ GetLastError());
+ }
+ /* Make sure the directory was removed */
+ if( -1 != GetFileAttributesW(szwTemp2) )
+ {
+ Fail("RemoveDirectoryW: Able to get the attributes of "
+ "the removed directory\n");
+ }
+ free(szwTemp2);
+
+ /* Go back to parent of non_empty_dir and remove non_empty_dir */
+ if( 0 == SetCurrentDirectoryW(szwCurrentDir) )
+ {
+ free(szwTemp);
+ Fail("RemoveDirectoryW: Failed to set current directory to "
+ "\"..\non_empty_dir\" with SetCurrentDirectoryW.\n");
+ }
+ bRc = RemoveDirectoryW(szwTemp);
+ if (bRc == FALSE)
+ {
+ free(szwTemp);
+ Fail("RemoveDirectoryW: unable to remove "
+ "the directory \"non_empty_dir\"(error code %d)\n",
+ GetLastError());
+ }
+ /* Make sure the directory was removed */
+ if( -1 != GetFileAttributesW(szwTemp) )
+ {
+ Fail("RemoveDirectoryW: Able to get the attributes of "
+ "the removed directory\n");
+ }
+ free(szwTemp);
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/RemoveDirectoryW/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/RemoveDirectoryW/test1/testinfo.dat
new file mode 100644
index 0000000000..f94b9b2445
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/RemoveDirectoryW/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = RemoveDirectoryW
+Name = Test for RemoveDirectoryW (test 1)
+Type = DEFAULT
+EXE1 = removedirectoryw
+Description
+= Create directories and attempt to remove them.
+
diff --git a/src/pal/tests/palsuite/file_io/SearchPathA/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SearchPathA/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SearchPathA/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/file_io/SearchPathA/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SearchPathA/test1/CMakeLists.txt
new file mode 100644
index 0000000000..d1ac975d18
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SearchPathA/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ SearchPathA.c
+)
+
+add_executable(paltest_searchpatha_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_searchpatha_test1 coreclrpal)
+
+target_link_libraries(paltest_searchpatha_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/SearchPathA/test1/SearchPathA.c b/src/pal/tests/palsuite/file_io/SearchPathA/test1/SearchPathA.c
new file mode 100644
index 0000000000..ab9eecdebc
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SearchPathA/test1/SearchPathA.c
@@ -0,0 +1,144 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: SearchPathA.c
+**
+** Purpose: Tests the PAL implementation of the SearchFileA function.
+**
+**
+** TODO: Write a test where complete path is passed (say c:\?)
+**===================================================================*/
+//SearchPath
+//
+//The SearchPath function searches for the specified file in the specified path.
+//
+
+
+#include <palsuite.h>
+char* szDir = ".";
+
+char* szNoFileName = "333asdf";
+char* szNoFileNameExt = ".x77t";
+
+char* szFileNameExists = "searchfile";
+char* szFileNameExtExists = ".txt";
+
+char* szFileNameExistsWithExt = "searchfile.txt";
+char fileloc[_MAX_PATH];
+
+void removeFileHelper(LPSTR pfile, int location)
+{
+ FILE *fp;
+ fp = fopen( pfile, "r");
+
+ if (fp != NULL)
+ {
+ if(fclose(fp))
+ {
+ Fail("ERROR: Failed to close the file [%s], Error Code [%d], location [%d]\n", pfile, GetLastError(), location);
+ }
+
+ if(!DeleteFileA(pfile))
+ {
+ Fail("ERROR: Failed to delete file [%s], Error Code [%d], location [%d]\n", pfile, GetLastError(), location);
+ }
+ }
+
+}
+
+
+void RemoveAll()
+{
+ removeFileHelper(fileloc, 1);
+}
+
+int __cdecl main(int argc, char *argv[]) {
+
+ char* lpPath = NULL;
+ char* lpFileName = NULL;
+ char* lpExtension = NULL;
+ DWORD nBufferLength = 0;
+ char lpBuffer[_MAX_PATH];
+ char** lpFilePart = NULL;
+ DWORD error = 0;
+ DWORD result = 0;
+
+ HANDLE hsearchfile;
+ char fname[_MAX_FNAME];
+ char ext[_MAX_EXT];
+ char fullPath[_MAX_DIR];
+ char drive[_MAX_DRIVE];
+ char dir[_MAX_DIR];
+
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+
+ /* Initalize the buffer.
+ */
+ memset(fullPath, 0, _MAX_DIR);
+
+ /* Get the full path to the library (DLL).
+ */
+
+ if ( NULL != _fullpath( fullPath, argv[0], _MAX_DIR )) {
+ _splitpath(fullPath,drive,dir,fname,ext);
+ _makepath(fullPath,drive,dir,"","");
+ } else {
+ Fail("ERROR: conversion from relative path \" %s \" to absolute path failed. _fullpath returned NULL\n",argv[0]);
+ }
+
+ memset(fileloc, 0, _MAX_PATH);
+ sprintf(fileloc, "%s%s", fullPath, szFileNameExistsWithExt);
+
+ RemoveAll();
+
+ hsearchfile = CreateFileA(fileloc, GENERIC_WRITE, 0, 0, CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, 0);
+
+ if (hsearchfile == INVALID_HANDLE_VALUE)
+ {
+ Trace("ERROR[%ul]: couldn't create %s\n", GetLastError(), fileloc);
+ return FAIL;
+ }
+
+ CloseHandle(hsearchfile);
+
+ //
+ // find a file that doesn't exist
+ //
+ ZeroMemory( lpBuffer, sizeof(lpBuffer));
+ lpPath = fullPath;
+ lpFileName = szNoFileName;
+ lpExtension = NULL;
+
+ if( SearchPathA( lpPath, lpFileName, lpExtension, nBufferLength, lpBuffer, lpFilePart) != 0 ){
+ error = GetLastError();
+ Fail ("SearchPathA: ERROR1 -> Found invalid file[%s][%s][%s][%d]\n", lpPath, szNoFileName, szNoFileNameExt, error);
+ }
+
+ //
+ // find a file that exists, when path is mentioned explicitly
+ //
+ ZeroMemory( lpBuffer, sizeof(lpBuffer));
+ lpPath = fullPath;
+ lpFileName = szFileNameExistsWithExt;
+ lpExtension = NULL;
+
+ result = SearchPathA( lpPath, lpFileName, lpExtension, nBufferLength, lpBuffer, lpFilePart);
+
+ if( result == 0 ){
+ error = GetLastError();
+ Fail ("SearchPathA: ERROR2 -> Did not Find valid file[%s][%s][%d]\n", lpPath, szFileNameExistsWithExt, error);
+ }
+
+ RemoveAll();
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/SearchPathA/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/SearchPathA/test1/testinfo.dat
new file mode 100644
index 0000000000..82401eeeb2
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SearchPathA/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = SearchPathA
+Name = Test #1 for SearchPathA
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Tests the PAL implementation of the SearchFileA function
diff --git a/src/pal/tests/palsuite/file_io/SearchPathW/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SearchPathW/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SearchPathW/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/file_io/SearchPathW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SearchPathW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..d0c6252472
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SearchPathW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ SearchPathW.c
+)
+
+add_executable(paltest_searchpathw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_searchpathw_test1 coreclrpal)
+
+target_link_libraries(paltest_searchpathw_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/SearchPathW/test1/SearchPathW.c b/src/pal/tests/palsuite/file_io/SearchPathW/test1/SearchPathW.c
new file mode 100644
index 0000000000..2bc7694dc0
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SearchPathW/test1/SearchPathW.c
@@ -0,0 +1,198 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: SearchPathW.c
+**
+** Purpose: Tests the PAL implementation of the SearchFileW function.
+**
+**
+** TODO: Write a test where complete path is passed (say c:\?)
+**===================================================================*/
+//SearchPath
+//
+//The SearchPath function searches for the specified file in the specified path.
+//
+//
+//DWORD SearchPath(
+// LPCTSTR lpPath,
+// LPCTSTR lpFileName,
+// LPCTSTR lpExtension,
+// DWORD nBufferLength,
+// LPTSTR lpBuffer,
+// LPTSTR* lpFilePart
+//);
+//
+//Parameters
+//lpPath
+//[in] Pointer to a null-terminated string that specifies the path to be searched for the file. If this parameter is NULL, the function searches for a matching file in the following directories in the following sequence:
+//The directory from which the application loaded.
+//The current directory.
+//The system directory. Use the GetSystemDirectory function to get the path of this directory.
+//The 16-bit system directory. There is no function that retrieves the path of this directory, but it is searched.
+//The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
+//The directories that are listed in the PATH environment variable.
+
+//lpFileName
+//[in] Pointer to a null-terminated string that specifies the name of the file to search for.
+
+//lpExtension
+//[in] Pointer to a null-terminated string that specifies an extension to be added to the file name when searching for the file. The first character of the file name extension must be a period (.). The extension is added only if the specified file name does not end with an extension.
+//If a file name extension is not required or if the file name contains an extension, this parameter can be NULL.
+//
+//nBufferLength
+//[in] Size of the buffer that receives the valid path and file name, in TCHARs.
+
+//lpBuffer
+//[out] Pointer to the buffer that receives the path and file name of the file found.
+
+//lpFilePart
+//[out] Pointer to the variable that receives the address (within lpBuffer) of the last component of the valid path and file name, which is the address of the character immediately following the final backslash (\) in the path.
+
+//Return Values
+//If the function succeeds, the value returned is the length, in TCHARs, of the string copied to the buffer, not including the terminating null character. If the return value is greater than nBufferLength, the value returned is the size of the buffer required to hold the path.
+//
+//If the function fails, the return value is zero. To get extended error information, call GetLastError.
+
+
+#include <palsuite.h>
+const char* szDir = ".";
+
+const char* szNoFileName = "333asdf";
+const char* szNoFileNameExt = ".x77t";
+
+const char* szFileNameExists = "searchpathw";
+const char* szFileNameExtExists = ".c";
+
+const char* szFileNameExistsWithExt = "searchpathw.c";
+
+char fileloc[_MAX_PATH];
+
+void removeFileHelper(LPSTR pfile, int location)
+{
+ FILE *fp;
+ fp = fopen( pfile, "r");
+
+ if (fp != NULL)
+ {
+ if(fclose(fp))
+ {
+ Fail("ERROR: Failed to close the file [%s], Error Code [%d], location [%d]\n", pfile, GetLastError(), location);
+ }
+
+ if(!DeleteFileA(pfile))
+ {
+ Fail("ERROR: Failed to delete file [%s], Error Code [%d], location [%d]\n", pfile, GetLastError(), location);
+ }
+ else
+ {
+ // Trace("Success: deleted file [%S], Error Code [%d], location [%d]\n", wfile, GetLastError(), location);
+ }
+ }
+
+}
+
+void RemoveAll()
+{
+ removeFileHelper(fileloc, 1);
+}
+
+int __cdecl main(int argc, char *argv[]) {
+
+ WCHAR* lpPath = NULL;
+ WCHAR* lpFileName = NULL;
+ WCHAR* lpExtension = NULL;
+ DWORD nBufferLength = 0;
+ WCHAR lpBuffer[_MAX_PATH];
+ WCHAR** lpFilePart = NULL;
+ DWORD error = 0;
+ DWORD result = 0;
+
+ HANDLE hsearchfile;
+ char fname[_MAX_FNAME];
+ char ext[_MAX_EXT];
+ char fullPath[_MAX_DIR];
+ char drive[_MAX_DRIVE];
+ char dir[_MAX_DIR];
+
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Initalize the buffer.
+ */
+ memset(fullPath, 0, _MAX_DIR);
+
+ /* Get the full path to the library (DLL).
+ */
+
+ if ( NULL != _fullpath( fullPath, argv[0], _MAX_DIR )) {
+ _splitpath(fullPath,drive,dir,fname,ext);
+ _makepath(fullPath,drive,dir,"","");
+ } else {
+ Fail("ERROR: conversion from relative path \" %s \" to absolute path failed. _fullpath returned NULL\n",argv[0]);
+ }
+
+ memset(fileloc, 0, _MAX_PATH);
+ sprintf(fileloc, "%s%s", fullPath, szFileNameExistsWithExt);
+
+ RemoveAll();
+
+ hsearchfile = CreateFileA(fileloc, GENERIC_WRITE, 0, 0, CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, 0);
+
+ if (hsearchfile == NULL)
+ {
+ Trace("ERROR[%ul]: couldn't create %s\n", GetLastError(), fileloc);
+ return FAIL;
+ }
+
+ CloseHandle(hsearchfile);
+
+ //
+ // find a file that doesn't exist
+ //
+ ZeroMemory( lpBuffer, sizeof(lpBuffer));
+ lpPath = convert((LPSTR)fullPath);
+ lpFileName = convert((LPSTR)szNoFileName);
+ lpExtension = NULL;
+
+ if( SearchPathW( lpPath, lpFileName, lpExtension, nBufferLength, lpBuffer, lpFilePart) != 0 ){
+ error = GetLastError();
+ free(lpPath);
+ free(lpFileName);
+ Fail ("SearchPathW: ERROR1 -> Found invalid file[%s][%s][%s][%d]\n", lpPath, szNoFileName, szNoFileNameExt, error);
+ }
+
+ free(lpPath);
+ free(lpFileName);
+
+ //
+ // find a file that exists, when path is mentioned explicitly
+ //
+ ZeroMemory( lpBuffer, sizeof(lpBuffer));
+ lpPath = convert((LPSTR)fullPath);
+ lpFileName = convert((LPSTR)szFileNameExistsWithExt);
+ lpExtension = NULL;
+
+ result = SearchPathW( lpPath, lpFileName, lpExtension, nBufferLength, lpBuffer, lpFilePart);
+
+ if( result == 0 ){
+ error = GetLastError();
+ free(lpPath);
+ free(lpFileName);
+ Fail ("SearchPathA: ERROR2 -> Did not Find valid file[%s][%s][%d]\n", lpPath, szFileNameExistsWithExt, error);
+ }
+
+ free(lpPath);
+ free(lpFileName);
+
+ RemoveAll();
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/SearchPathW/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/SearchPathW/test1/testinfo.dat
new file mode 100644
index 0000000000..f7a36eb53b
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SearchPathW/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = SearchPathW
+Name = Test #1 for SearchPathW
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Tests the PAL implementation of the SearchFileW function
diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/CMakeLists.txt
new file mode 100644
index 0000000000..1962ade358
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+
diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test1/CMakeLists.txt
new file mode 100644
index 0000000000..7376b22226
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ SetCurrentDirectoryA.c
+)
+
+add_executable(paltest_setcurrentdirectorya_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setcurrentdirectorya_test1 coreclrpal)
+
+target_link_libraries(paltest_setcurrentdirectorya_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test1/SetCurrentDirectoryA.c b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test1/SetCurrentDirectoryA.c
new file mode 100644
index 0000000000..c07a62412b
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test1/SetCurrentDirectoryA.c
@@ -0,0 +1,215 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: SetCurrentDirectoryA.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the SetCurrentDirectoryA function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+
+/* In order to avoid the "chicken and egg" scenario, this is another
+ method of getting the current directory. GetFullPathNameA is called with
+ a dummy file name and then the file name is stripped off leaving the
+ current working directory
+*/
+
+BOOL GetCurrentDir(char* szCurrentDir)
+{
+ const char* szFileName = "blah";
+ DWORD dwRc = 0;
+ char szReturnedPath[_MAX_DIR+1];
+ LPSTR pPathPtr;
+ size_t nCount = 0;
+
+ /* use GetFullPathNameA to to get the current path by stripping
+ the file name off the end */
+ memset(szReturnedPath, 0, (_MAX_DIR+1));
+ dwRc = GetFullPathNameA(szFileName,
+ _MAX_DIR,
+ szReturnedPath,
+ &pPathPtr);
+
+ if (dwRc == 0)
+ {
+ /* GetFullPathNameA failed */
+ Trace("SetCurrentDirectoryA: ERROR -> GetFullPathNameA failed "
+ "with error code: %ld.\n", GetLastError());
+ return(FALSE);
+ }
+
+ /* now strip the file name from the full path to get the current path */
+ nCount = strlen(szReturnedPath) - strlen(szFileName);
+ memset(szCurrentDir, 0, (_MAX_DIR+1));
+ strncpy(szCurrentDir, szReturnedPath, nCount);
+
+ return(TRUE);
+}
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ const char* szDirName = "testing";
+ /* directory name longer than MAX_PATH characters */
+ char szLongDirName[MAX_LONGPATH+1];
+ char szNewDir[_MAX_DIR+1];
+ char szBuiltDir[_MAX_DIR+1];
+ char szHomeDir[_MAX_DIR+1];
+ WCHAR* szwPtr = NULL;
+
+ memset(szLongDirName, 'a', MAX_LONGPATH+1);
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* remove the directory just in case a previous run of the test didn't */
+ szwPtr = convert((LPSTR)szDirName);
+
+ /* clean up. Remove the directory
+ * if it exists */
+ RemoveDirectoryW(szwPtr);
+
+ /* create a temp directory off the current directory */
+ if (CreateDirectoryA(szDirName, NULL) != TRUE)
+ {
+ free(szwPtr);
+ Fail("SetCurrentDirectoryA: ERROR -> CreateDirectoryW failed "
+ "with error code: %ld.\n", GetLastError());
+ }
+
+ /* find out what the current "home" directory is */
+ memset(szHomeDir, 0, (_MAX_DIR+1));
+ if(GetCurrentDir(szHomeDir) != TRUE)
+ {
+ if (!RemoveDirectoryW(szwPtr))
+ {
+ Trace("SetCurrentDirectoryA: ERROR -> RemoveDirectoryW failed "
+ "with error code: %ld.\n", GetLastError());
+ }
+ free(szwPtr);
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ /* set the current directory to the temp directory */
+
+ if (SetCurrentDirectoryA(szDirName) != TRUE)
+ {
+ Trace("SetCurrentDirectoryA: ERROR -> Unable to set current "
+ "directory. Failed with error code: %ld.\n", GetLastError());
+ if (!RemoveDirectoryW(szwPtr))
+ {
+ Trace("SetCurrentDirectoryA: ERROR -> RemoveDirectoryW failed "
+ "with error code: %ld.\n", GetLastError());
+ }
+ free(szwPtr);
+ Fail("");
+ }
+
+ /* append the temp name to the "home" directory */
+ memset(szBuiltDir, 0, (_MAX_DIR+1));
+#if WIN32
+ sprintf(szBuiltDir,"%s%s\\", szHomeDir, szDirName);
+#else
+ sprintf(szBuiltDir,"%s%s/", szHomeDir, szDirName);
+#endif
+
+ /* get the new current directory */
+ memset(szNewDir, 0, (_MAX_DIR+1));
+ if(GetCurrentDir(szNewDir) != TRUE)
+ {
+ if (!RemoveDirectoryW(szwPtr))
+ {
+ Trace("SetCurrentDirectoryA: ERROR -> RemoveDirectoryW failed "
+ "with error code: %ld.\n", GetLastError());
+ }
+ free(szwPtr);
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ /*compare the new current dir to the compiled current dir */
+ if (strncmp(szNewDir, szBuiltDir, strlen(szNewDir)) != 0)
+ {
+ if (!RemoveDirectoryW(szwPtr))
+ {
+ Trace("SetCurrentDirectoryA: ERROR -> RemoveDirectoryW failed "
+ "with error code: %ld.\n", GetLastError());
+ }
+ free(szwPtr);
+ Fail("SetCurrentDirectoryA: ERROR -> The set directory \"%s\" does not"
+ " compare to the built directory \"%s\".\n",
+ szNewDir,
+ szBuiltDir);
+ }
+
+
+
+ /* set the current dir back to the original */
+ if (SetCurrentDirectoryA(szHomeDir) != TRUE)
+ {
+ Trace("SetCurrentDirectoryA: ERROR -> Unable to set current "
+ "directory. Failed with error code: %ld.\n", GetLastError());
+ if (!RemoveDirectoryW(szwPtr))
+ {
+ Trace("SetCurrentDirectoryA: ERROR -> RemoveDirectoryW failed "
+ "with error code: %ld.\n", GetLastError());
+ }
+ free(szwPtr);
+ Fail("");
+ }
+
+
+ /* get the new current directory */
+ memset(szNewDir, 0, sizeof(char)*(_MAX_DIR+1));
+ if(GetCurrentDir(szNewDir) != TRUE)
+ {
+ if (!RemoveDirectoryW(szwPtr))
+ {
+ Trace("SetCurrentDirectoryA: ERROR -> RemoveDirectoryW failed "
+ "with error code: %ld.\n", GetLastError());
+ }
+ free(szwPtr);
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ /* ensure it compares to the "home" directory which is where
+ we should be now */
+ if (strncmp(szNewDir, szHomeDir, strlen(szNewDir)) != 0)
+ {
+ if (!RemoveDirectoryW(szwPtr))
+ {
+ Trace("SetCurrentDirectoryA: ERROR -> RemoveDirectoryW failed "
+ "with error code: %ld.\n", GetLastError());
+ }
+ free(szwPtr);
+ Fail("SetCurrentDirectoryA: ERROR -> The set directory does not "
+ "compare to the built directory.\n");
+ }
+
+
+ /* clean up */
+ if (!RemoveDirectoryW(szwPtr))
+ {
+ free(szwPtr);
+ Fail("SetCurrentDirectoryA: ERROR -> RemoveDirectoryW failed "
+ "with error code: %ld.\n", GetLastError());
+ }
+
+ free(szwPtr);
+ PAL_Terminate();
+
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test1/testinfo.dat
new file mode 100644
index 0000000000..743b2ea3db
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = SetCurrentDirectoryA
+Name = Test for SetCurrentDirectoryA (test 1)
+Type = DEFAULT
+EXE1 = setcurrentdirectorya
+Description
+= Change the current directory and verify the results.
diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test2/CMakeLists.txt
new file mode 100644
index 0000000000..7c9caf8081
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ setcurrentdirectorya.c
+)
+
+add_executable(paltest_setcurrentdirectorya_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setcurrentdirectorya_test2 coreclrpal)
+
+target_link_libraries(paltest_setcurrentdirectorya_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test2/setcurrentdirectorya.c b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test2/setcurrentdirectorya.c
new file mode 100644
index 0000000000..415dbbf045
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test2/setcurrentdirectorya.c
@@ -0,0 +1,142 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: SetCurrentDirectoryA.c (test 2)
+**
+** Purpose: Tests the PAL implementation of the SetCurrentDirectoryA function
+** by setting the current directory with ../
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ const char szDirName[MAX_PATH] = "testing";
+ char szBuiltDir[_MAX_DIR+1];
+ char szHomeDirBefore[_MAX_DIR+1];
+ char szHomeDirAfter[_MAX_DIR+1];
+ WCHAR* szwPtr = NULL;
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* create a temp directory off the current directory */
+ szwPtr = convert((LPSTR)szDirName);
+
+ if (CreateDirectoryA(szDirName, NULL) != TRUE)
+ {
+ free(szwPtr);
+ Fail("Unexpected error: CreateDirectoryW failed "
+ "with error code: %ld.\n",
+ GetLastError());
+ }
+
+ /* find out what the current "home" directory is */
+ memset(szHomeDirBefore, 0, (_MAX_DIR+1));
+
+ if( 0 == GetCurrentDirectoryA((_MAX_DIR+1), szHomeDirBefore) )
+ {
+ Trace("Unexpected error: Unable to get current directory "
+ "with GetCurrentDirectoryA that returned %ld\n",
+ GetLastError());
+
+ if (!RemoveDirectoryW(szwPtr))
+ {
+ Trace("Unexpected error: RemoveDirectoryW failed "
+ "with error code: %ld.\n",
+ GetLastError());
+ }
+ free(szwPtr);
+
+ Fail("");
+ }
+
+ /* append the temp name to the "home" directory */
+ memset(szBuiltDir, 0, (_MAX_DIR+1));
+#if WIN32
+ sprintf(szBuiltDir,"%s\\..\\", szDirName);
+#else
+ sprintf(szBuiltDir,"%s/../", szDirName);
+#endif
+
+
+ /* set the current directory to the temp directory */
+ if (SetCurrentDirectoryA(szBuiltDir) != TRUE)
+ {
+ Trace("ERROR: Unable to set current "
+ "directory to %s. Failed with error code: %ld.\n",
+ szBuiltDir,
+ GetLastError());
+
+ if (!RemoveDirectoryW(szwPtr))
+ {
+ Trace("SetCurrentDirectoryA: ERROR -> RemoveDirectoryW failed "
+ "with error code: %ld.\n",
+ GetLastError());
+ }
+ free(szwPtr);
+ Fail("");
+ }
+
+ /* find out what the current "home" directory is */
+ memset(szHomeDirAfter, 0, (_MAX_DIR+1));
+
+ if( 0 == GetCurrentDirectoryA((_MAX_DIR+1), szHomeDirAfter) )
+ {
+ Trace("Unexpected error: Unable to get current directory "
+ "with GetCurrentDirectoryA that returned %ld\n",
+ GetLastError());
+
+ if (!RemoveDirectoryW(szwPtr))
+ {
+ Trace("Unexpected error: RemoveDirectoryW failed "
+ "with error code: %ld.\n",
+ GetLastError());
+ }
+ free(szwPtr);
+
+ Fail("");
+ }
+
+ /*compare the new current dir to the compiled current dir */
+ if (strncmp(szHomeDirBefore, szHomeDirAfter, strlen(szHomeDirBefore)) != 0)
+ {
+ Trace("ERROR: The set directory \"%s\" does not "
+ "compare to the built directory \"%s\".\n",
+ szHomeDirAfter,
+ szHomeDirBefore);
+
+ if (!RemoveDirectoryW(szwPtr))
+ {
+ Trace("Unexpected error: RemoveDirectoryW failed "
+ "with error code: %ld.\n",
+ GetLastError());
+ }
+ free(szwPtr);
+ Fail("");
+ }
+
+ /* clean up */
+ if (!RemoveDirectoryW(szwPtr))
+ {
+ free(szwPtr);
+ Fail("Unexpected error: RemoveDirectoryW failed "
+ "with error code: %ld.\n",
+ GetLastError());
+ }
+
+ free(szwPtr);
+ PAL_Terminate();
+
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test2/testinfo.dat b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test2/testinfo.dat
new file mode 100644
index 0000000000..677c484062
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test2/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = SetCurrentDirectoryA
+Name = Positive test for SetCurrentDirectoryA (test 2)
+Type = DEFAULT
+EXE1 = setcurrentdirectorya
+Description
+= Set the current directory with ../ and verify the results.
diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test3/CMakeLists.txt
new file mode 100644
index 0000000000..57d3577d8f
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ setcurrentdirectorya.c
+)
+
+add_executable(paltest_setcurrentdirectorya_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setcurrentdirectorya_test3 coreclrpal)
+
+target_link_libraries(paltest_setcurrentdirectorya_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test3/setcurrentdirectorya.c b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test3/setcurrentdirectorya.c
new file mode 100644
index 0000000000..a23a7a6314
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test3/setcurrentdirectorya.c
@@ -0,0 +1,56 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: SetCurrentDirectoryA.c (test 3)
+**
+** Purpose: Try calling SetCurrentDirectoryA with an invalid path,
+** with a valid filename and with NULL
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ const char szDirName[MAX_PATH] = "testing";
+ const char szFileName[MAX_PATH] = "setcurrentdirectorya.c";
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* set the current directory to an unexistant folder */
+ if (0 != SetCurrentDirectoryA(szDirName))
+ {
+ Fail("ERROR: SetCurrentDirectoryA should have failed "
+ "when trying to set the current directory to "
+ "an invalid folder\n");
+ }
+
+ /* set the current directory to an unexistant folder */
+ if (0 != SetCurrentDirectoryA(szFileName))
+ {
+ Fail("ERROR: SetCurrentDirectoryA should have failed "
+ "when trying to set the current directory to "
+ "a valid file name\n");
+ }
+
+ /* set the current directory to NULL */
+ if (0 != SetCurrentDirectoryA(NULL))
+ {
+ Fail("ERROR: SetCurrentDirectoryA should have failed "
+ "when trying to set the current directory to "
+ "NULL\n");
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test3/testinfo.dat b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test3/testinfo.dat
new file mode 100644
index 0000000000..d5520f7993
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test3/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = SetCurrentDirectoryA
+Name = Negative test for SetCurrentDirectoryA (test 3)
+Type = DEFAULT
+EXE1 = setcurrentdirectorya
+Description
+= Try calling SetCurrentDirectoryA with an invalid path,
+= with a valid filename and with NULL
diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/CMakeLists.txt
new file mode 100644
index 0000000000..1962ade358
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+
diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..a0c1dff62a
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ SetCurrentDirectoryW.c
+)
+
+add_executable(paltest_setcurrentdirectoryw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setcurrentdirectoryw_test1 coreclrpal)
+
+target_link_libraries(paltest_setcurrentdirectoryw_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test1/SetCurrentDirectoryW.c b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test1/SetCurrentDirectoryW.c
new file mode 100644
index 0000000000..257d016ffb
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test1/SetCurrentDirectoryW.c
@@ -0,0 +1,178 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: SetCurrentDirectoryW.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the SetCurrentDirectoryW function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+const char* szFileName = "blah";
+const char* szDirName = "testing";
+
+
+// In order to avoid the "chicken and egg" scenario, this is another
+// method of getting the current directory. GetFullPathNameW is called with
+// a dummy file name and then the file name is stripped off leaving the
+// current working directory
+BOOL GetCurrentDir(WCHAR* szwCurrentDir)
+{
+ DWORD dwRc = 0;
+ WCHAR szwReturnedPath[_MAX_DIR+1];
+ LPWSTR pPathPtr;
+ WCHAR* szwFileName = NULL;
+ WCHAR* szwDirName = NULL;
+ int nCount = 0;
+
+ // use GetFullPathName to to get the current path by stripping
+ // the file name off the end
+ memset(szwReturnedPath, 0, sizeof(WCHAR)*(_MAX_DIR+1));
+ szwFileName = convert((char*)szFileName);
+ dwRc = GetFullPathNameW(szwFileName,
+ _MAX_DIR,
+ szwReturnedPath,
+ &pPathPtr);
+
+ if (dwRc == 0)
+ {
+ // GetFullPathName failed
+ Trace("SetCurrentDirectoryW: ERROR -> GetFullPathNameW failed "
+ "with error code: %ld.\n", GetLastError());
+ RemoveDirectoryW(szwDirName);
+ free(szwFileName);
+ return(FALSE);
+ }
+
+ // now strip the file name from the full path to get the current path
+ nCount = lstrlenW(szwReturnedPath) - lstrlenW(szwFileName);
+ memset(szwCurrentDir, 0, sizeof(WCHAR)*(_MAX_DIR+1));
+ lstrcpynW(szwCurrentDir, szwReturnedPath, nCount);
+
+ free(szwFileName);
+ return(TRUE);
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR* szwDirName = NULL;
+ WCHAR szwNewDir[_MAX_DIR+1];
+ WCHAR szwBuiltDir[_MAX_DIR+1];
+ WCHAR szwHomeDir[_MAX_DIR+1];
+#if WIN32
+ WCHAR szwSlash[] = {'\\','\0'};
+#else
+ WCHAR szwSlash[] = {'/','\0'};
+#endif
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ // remove the directory just in case a previous run of the test didn't
+ szwDirName = convert((char*)szDirName);
+ RemoveDirectoryW(szwDirName);
+
+ // create a temp directory off the current directory
+ if (CreateDirectoryW(szwDirName, NULL) != TRUE)
+ {
+ Trace("SetCurrentDirectoryW: ERROR -> CreateDirectoryW failed "
+ "with error code: %ld.\n", GetLastError());
+ RemoveDirectoryW(szwDirName);
+ free(szwDirName);
+ Fail("");
+ }
+
+ // find out what the current "home" directory is
+ memset(szwHomeDir, 0, sizeof(WCHAR)*(_MAX_DIR+1));
+ if(GetCurrentDir(szwHomeDir) != TRUE)
+ {
+ RemoveDirectoryW(szwDirName);
+ free(szwDirName);
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ // set the current directory to the temp directory
+ if (SetCurrentDirectoryW(szwDirName) != TRUE)
+ {
+ Trace("SetCurrentDirectoryW: ERROR -> Unable to set current "
+ "directory. Failed with error code: %ld.\n", GetLastError());
+ RemoveDirectoryW(szwDirName);
+ free(szwDirName);
+ Fail("");
+ }
+
+ // append the temp name to the "home" directory
+ memset(szwBuiltDir, 0, sizeof(WCHAR)*(_MAX_DIR+1));
+ wcscpy(szwBuiltDir, szwHomeDir);
+ wcscat(szwBuiltDir, szwSlash);
+ wcscat(szwBuiltDir, szwDirName);
+
+ // get the new current directory
+ memset(szwNewDir, 0, sizeof(WCHAR)*(_MAX_DIR+1));
+ if(GetCurrentDir(szwNewDir) != TRUE)
+ {
+ RemoveDirectoryW(szwDirName);
+ free(szwDirName);
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ // compare the new current dir to the compiled current dir
+ if (wcsncmp(szwNewDir, szwBuiltDir, wcslen(szwNewDir)) != 0)
+ {
+ RemoveDirectoryW(szwDirName);
+ free(szwDirName);
+ Fail("SetCurrentDirectoryW: ERROR -> The set directory does not "
+ "compare to the built directory.\n");
+ }
+
+
+
+ // set the current dir back to the original
+ if (SetCurrentDirectoryW(szwHomeDir) != TRUE)
+ {
+ Trace("SetCurrentDirectoryW: ERROR -> Unable to set current "
+ "directory. Failed with error code: %ld.\n", GetLastError());
+ RemoveDirectoryW(szwDirName);
+ free(szwDirName);
+ Fail("");
+ }
+
+
+ // get the new current directory
+ memset(szwNewDir, 0, sizeof(WCHAR)*(_MAX_DIR+1));
+ if(GetCurrentDir(szwNewDir) != TRUE)
+ {
+ RemoveDirectoryW(szwDirName);
+ free(szwDirName);
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ // ensure it compares to the "home" directory which is where
+ // we should be now
+ if (wcsncmp(szwNewDir, szwHomeDir, wcslen(szwNewDir)) != 0)
+ {
+ RemoveDirectoryW(szwDirName);
+ free(szwDirName);
+ Fail("SetCurrentDirectoryW: ERROR -> The set directory does not "
+ "compare to the built directory.\n");
+ }
+
+
+ RemoveDirectoryW(szwDirName);
+ free(szwDirName);
+ PAL_Terminate();
+
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test1/testinfo.dat
new file mode 100644
index 0000000000..3a63887e07
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = SetCurrentDirectoryW
+Name = Test for SetCurrentDirectoryW (test 1)
+Type = DEFAULT
+EXE1 = setcurrentdirectoryw
+Description
+= Change the current directory and verify the results.
+
diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test2/CMakeLists.txt
new file mode 100644
index 0000000000..a032462d19
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ setcurrentdirectoryw.c
+)
+
+add_executable(paltest_setcurrentdirectoryw_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setcurrentdirectoryw_test2 coreclrpal)
+
+target_link_libraries(paltest_setcurrentdirectoryw_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test2/setcurrentdirectoryw.c b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test2/setcurrentdirectoryw.c
new file mode 100644
index 0000000000..7e3d7b785f
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test2/setcurrentdirectoryw.c
@@ -0,0 +1,147 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: SetCurrentDirectoryW.c (test 2)
+**
+** Purpose: Tests the PAL implementation of the SetCurrentDirectoryW function
+** by setting the current directory with ../
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ const char szDirName[MAX_PATH] = "testing";
+ char szBuiltDir[MAX_PATH];
+ WCHAR* szwBuiltDir = NULL;
+ WCHAR szwHomeDirBefore[MAX_PATH];
+ WCHAR szwHomeDirAfter[MAX_PATH];
+ WCHAR* szwPtr = NULL;
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* create a temp directory off the current directory */
+ szwPtr = convert((LPSTR)szDirName);
+
+ if (CreateDirectoryW(szwPtr, NULL) != TRUE)
+ {
+ free(szwPtr);
+ Fail("Unexpected error: CreateDirectoryW failed "
+ "with error code: %ld.\n",
+ GetLastError());
+ }
+
+ /* find out what the current "home" directory is */
+ memset(szwHomeDirBefore, 0, MAX_PATH * sizeof(WCHAR));
+
+ if( 0 == GetCurrentDirectoryW(MAX_PATH, szwHomeDirBefore) )
+ {
+ Trace("Unexpected error: Unable to get current directory "
+ "with GetCurrentDirectoryW that returned %ld\n",
+ GetLastError());
+
+ if (!RemoveDirectoryW(szwPtr))
+ {
+ Trace("Unexpected error: RemoveDirectoryW failed "
+ "with error code: %ld.\n",
+ GetLastError());
+ }
+ free(szwPtr);
+
+ Fail("");
+ }
+
+ /* append the temp name to the "home" directory */
+ memset(szBuiltDir, 0, MAX_PATH);
+#if WIN32
+ sprintf(szBuiltDir,"%s\\..\\", szDirName);
+#else
+ sprintf(szBuiltDir,"%s/../", szDirName);
+#endif
+
+ szwBuiltDir = convert(szBuiltDir);
+
+ /* set the current directory to the temp directory */
+ if (SetCurrentDirectoryW(szwBuiltDir) != TRUE)
+ {
+ Trace("ERROR: Unable to set current "
+ "directory to %S. Failed with error code: %ld.\n",
+ szwBuiltDir,
+ GetLastError());
+
+ if (!RemoveDirectoryW(szwPtr))
+ {
+ Trace("Unexpected error: RemoveDirectoryW failed "
+ "with error code: %ld.\n",
+ GetLastError());
+ }
+ free(szwPtr);
+ free(szwBuiltDir);
+ Fail("");
+ }
+
+ free(szwBuiltDir);
+
+ /* find out what the current "home" directory is */
+ memset(szwHomeDirAfter, 0, MAX_PATH * sizeof(WCHAR));
+
+ if( 0 == GetCurrentDirectoryW(MAX_PATH, szwHomeDirAfter) )
+ {
+ Trace("Unexpected error: Unable to get current directory "
+ "with GetCurrentDirectoryW that returned %ld\n",
+ GetLastError());
+
+ if (!RemoveDirectoryW(szwPtr))
+ {
+ Trace("ERROR: RemoveDirectoryW failed "
+ "with error code: %ld.\n",
+ GetLastError());
+ }
+ free(szwPtr);
+
+ Fail("");
+ }
+
+ /*compare the new current dir to the compiled current dir */
+ if (wcsncmp(szwHomeDirBefore, szwHomeDirAfter, wcslen(szwHomeDirBefore)) != 0)
+ {
+ Trace("ERROR:The set directory \"%S\" does not "
+ "compare to the built directory \"%S\".\n",
+ szwHomeDirAfter,
+ szwHomeDirBefore);
+
+ if (!RemoveDirectoryW(szwPtr))
+ {
+ Trace("Unexpected error: RemoveDirectoryW failed "
+ "with error code: %ld.\n",
+ GetLastError());
+ }
+ free(szwPtr);
+ Fail("");
+ }
+
+ /* clean up */
+ if (!RemoveDirectoryW(szwPtr))
+ {
+ free(szwPtr);
+ Fail("Unexpected error: RemoveDirectoryW failed "
+ "with error code: %ld.\n",
+ GetLastError());
+ }
+
+ free(szwPtr);
+ PAL_Terminate();
+
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test2/testinfo.dat b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test2/testinfo.dat
new file mode 100644
index 0000000000..a739688d4d
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test2/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = SetCurrentDirectoryW
+Name = Positive test for SetCurrentDirectoryW (test 2)
+Type = DEFAULT
+EXE1 = setcurrentdirectoryw
+Description
+= Set the current directory with ../ and verify the results.
diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test3/CMakeLists.txt
new file mode 100644
index 0000000000..3b981f9564
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ setcurrentdirectoryw.c
+)
+
+add_executable(paltest_setcurrentdirectoryw_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setcurrentdirectoryw_test3 coreclrpal)
+
+target_link_libraries(paltest_setcurrentdirectoryw_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test3/setcurrentdirectoryw.c b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test3/setcurrentdirectoryw.c
new file mode 100644
index 0000000000..e8c4be2ad4
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test3/setcurrentdirectoryw.c
@@ -0,0 +1,64 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: SetCurrentDirectoryW.c (test 3)
+**
+** Purpose: Try calling SetCurrentDirectoryW with an invalid path,
+** with a valid filename and with NULL
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ char szDirName[MAX_PATH] = "testing";
+ WCHAR* szwDirName = NULL;
+ char szFileName[MAX_PATH] = "setcurrentdirectorya.c";
+ WCHAR* szwFileName = NULL;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* set the current directory to an unexistant folder */
+ szwDirName = convert(szDirName);
+ if (0 != SetCurrentDirectoryW(szwDirName))
+ {
+ free(szwDirName);
+ Fail("ERROR: SetCurrentDirectoryW should have failed "
+ "when trying to set the current directory to "
+ "an invalid folder\n");
+ }
+ free(szwDirName);
+
+ /* set the current directory to an unexistant folder */
+ szwFileName = convert(szFileName);
+ if (0 != SetCurrentDirectoryW(szwFileName))
+ {
+ free(szwFileName);
+ Fail("ERROR: SetCurrentDirectoryW should have failed "
+ "when trying to set the current directory to "
+ "a valid file name\n");
+ }
+ free(szwFileName);
+
+ /* set the current directory to NULL */
+ if (0 != SetCurrentDirectoryW(NULL))
+ {
+ Fail("ERROR: SetCurrentDirectoryW should have failed "
+ "when trying to set the current directory to "
+ "NULL\n");
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test3/testinfo.dat b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test3/testinfo.dat
new file mode 100644
index 0000000000..fc931291ec
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test3/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = SetCurrentDirectoryW
+Name = Negative test for SetCurrentDirectoryW (test 3)
+Type = DEFAULT
+EXE1 = setcurrentdirectoryw
+Description
+= Try calling SetCurrentDirectoryW with an invalid path,
+= with a valid filename and with NULL
diff --git a/src/pal/tests/palsuite/file_io/SetEndOfFile/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetEndOfFile/CMakeLists.txt
new file mode 100644
index 0000000000..8083faf655
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetEndOfFile/CMakeLists.txt
@@ -0,0 +1,8 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+
diff --git a/src/pal/tests/palsuite/file_io/SetEndOfFile/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetEndOfFile/test1/CMakeLists.txt
new file mode 100644
index 0000000000..e77ab30b86
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetEndOfFile/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ SetEndOfFile.c
+)
+
+add_executable(paltest_setendoffile_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setendoffile_test1 coreclrpal)
+
+target_link_libraries(paltest_setendoffile_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/SetEndOfFile/test1/SetEndOfFile.c b/src/pal/tests/palsuite/file_io/SetEndOfFile/test1/SetEndOfFile.c
new file mode 100644
index 0000000000..9078ddc65b
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetEndOfFile/test1/SetEndOfFile.c
@@ -0,0 +1,85 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: SetEndOfFile.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the SetEndOfFile function.
+** This test will attempt to operate on a NULL file handle and
+** also test truncating a file not opened with GENERIC_WRITE
+**
+** Assumes successful:
+** SetEndOfFile
+** CreateFile
+** CloseHandle
+**
+
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+const char* szTextFile = "text.txt";
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE hFile = NULL;
+ BOOL bRc = FALSE;
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ bRc = SetEndOfFile(NULL);
+ if (bRc == TRUE)
+ {
+ Fail("SetEndOfFile: ERROR -> Operation succeeded on a NULL file "
+ "handle\n");
+ }
+
+ /* create a test file */
+ hFile = CreateFile(szTextFile,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("SetEndOfFile: ERROR -> Unable to create file \"%s\".\n",
+ szTextFile);
+ }
+
+ bRc = SetEndOfFile(hFile);
+ if (bRc == TRUE)
+ {
+ Trace("SetEndOfFile: ERROR -> Operation succeeded on read-only"
+ " file.\n");
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ {
+ Trace("SetEndOfFile: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ {
+ Fail("SetEndOfFile: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/SetEndOfFile/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/SetEndOfFile/test1/testinfo.dat
new file mode 100644
index 0000000000..72fc5e59e6
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetEndOfFile/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = SetEndOfFile
+Name = Positive Test for SetEndOfFile
+Type = DEFAULT
+EXE1 = setendoffile
+Description
+=Truncate a file
+
diff --git a/src/pal/tests/palsuite/file_io/SetEndOfFile/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetEndOfFile/test2/CMakeLists.txt
new file mode 100644
index 0000000000..b04dea04a6
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetEndOfFile/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ SetEndOfFile.c
+)
+
+add_executable(paltest_setendoffile_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setendoffile_test2 coreclrpal)
+
+target_link_libraries(paltest_setendoffile_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/SetEndOfFile/test2/SetEndOfFile.c b/src/pal/tests/palsuite/file_io/SetEndOfFile/test2/SetEndOfFile.c
new file mode 100644
index 0000000000..6b3c05088e
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetEndOfFile/test2/SetEndOfFile.c
@@ -0,0 +1,154 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: SetEndOfFile.c (test 2)
+**
+** Purpose: Tests the PAL implementation of the SetEndOfFile function.
+** This test will attempt to truncate a file
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+const char* szStringTest = "The quick fox jumped over the lazy dog's back.";
+const char* szTextFile = "text.txt";
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE hFile = NULL;
+ DWORD dwByteCount = 0;
+ DWORD dwBytesWritten;
+ BOOL bRc = FALSE;
+ char szBuffer[100];
+ DWORD dwBytesRead = 0;
+ FILE *pFile = NULL;
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ // create a test file
+ hFile = CreateFile(szTextFile,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("SetEndOfFile: ERROR -> Unable to create file \"%s\".\n",
+ szTextFile);
+ }
+
+ bRc = WriteFile(hFile, szStringTest, 20, &dwBytesWritten, NULL);
+ if (bRc != TRUE)
+ {
+ Trace("SetEndOfFile: ERROR -> Uable to write to \"%s\".\n",
+ szTextFile);
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ {
+ Trace("SetEndOfFile: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ {
+ Fail("SetEndOfFile: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+
+ // open the test file
+ hFile = CreateFile(szTextFile,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("SetEndOfFile: ERROR -> Unable to open file \"%s\".\n",
+ szTextFile);
+ }
+
+ // read a bit of the file to move the file pointer
+ dwByteCount = 10;
+ bRc = ReadFile(hFile, szBuffer, dwByteCount, &dwBytesRead, NULL);
+ if (bRc != TRUE)
+ {
+ Trace("SetEndOfFile: ERROR -> Uable to read from \"%s\".\n",
+ szTextFile);
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ {
+ Trace("SetEndOfFile: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ bRc = SetEndOfFile(hFile);
+ if (bRc != TRUE)
+ {
+ Trace("SetEndOfFile: ERROR -> Uable to set end of file.\n");
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ {
+ Trace("SetEndOfFile: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ {
+ Fail("SetEndOfFile: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+
+ // open and read the test file
+ pFile = fopen(szTextFile, "r");
+ if (pFile == NULL)
+ {
+ Fail("SetEndOfFile: ERROR -> fopen was unable to open file \"%s\".\n",
+ szTextFile);
+ }
+
+ // since we truncated the file at 10 characters,
+ // try reading 20 just to be safe
+ memset(szBuffer, 0, 100);
+ fgets(szBuffer, 20, pFile);
+ fclose(pFile);
+ if (strlen(szBuffer) != dwByteCount)
+ {
+ Fail("SetEndOfFile: ERROR -> file apparently not truncated at "
+ "correct position.\n");
+ }
+ if (strncmp(szBuffer, szStringTest, dwByteCount) != 0)
+ {
+ Fail("SetEndOfFile: ERROR -> truncated file contents doesn't "
+ "compare with what should be there\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/SetEndOfFile/test2/testinfo.dat b/src/pal/tests/palsuite/file_io/SetEndOfFile/test2/testinfo.dat
new file mode 100644
index 0000000000..555f0d823f
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetEndOfFile/test2/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = SetEndOfFile
+Name = Positive Test for SetEndOfFile
+Type = DEFAULT
+EXE1 = setendoffile
+Description
+=Truncate the test file using SetEndOfFile
diff --git a/src/pal/tests/palsuite/file_io/SetEndOfFile/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetEndOfFile/test3/CMakeLists.txt
new file mode 100644
index 0000000000..1ab177d00a
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetEndOfFile/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ SetEndOfFile.c
+)
+
+add_executable(paltest_setendoffile_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setendoffile_test3 coreclrpal)
+
+target_link_libraries(paltest_setendoffile_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/SetEndOfFile/test3/SetEndOfFile.c b/src/pal/tests/palsuite/file_io/SetEndOfFile/test3/SetEndOfFile.c
new file mode 100644
index 0000000000..dfd9194465
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetEndOfFile/test3/SetEndOfFile.c
@@ -0,0 +1,109 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: SetEndOfFile.c (test 3)
+**
+** Purpose: Tests the PAL implementation of the SetEndOfFile function.
+** This test will attempt to expand a file. Assumes successful
+** SetFilePointer and GetFileSize tests.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+const char* szTextFile = "text.txt";
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE hFile = NULL;
+ DWORD dwByteCount = 0;
+ DWORD dwOffset = 25;
+ DWORD dwRc = 0;
+ BOOL bRc = FALSE;
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* create a test file */
+ hFile = CreateFile(szTextFile,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("SetEndOfFile: ERROR -> Unable to create file \"%s\".\n",
+ szTextFile);
+ }
+
+ /* move the file pointer */
+ /* assumes a successful SetFilePointer test */
+ dwRc = SetFilePointer(hFile, dwOffset, NULL, FILE_BEGIN);
+ if (dwRc == INVALID_SET_FILE_POINTER)
+ {
+ Trace("SetEndOfFile: ERROR -> Call to SetFilePointer failed\n");
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ {
+ Trace("SetEndOfFile: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_Terminate();
+ return FAIL;
+ }
+
+ bRc = SetEndOfFile(hFile);
+ if (bRc != TRUE)
+ {
+ Trace("SetEndOfFile: ERROR -> Uable to set end of file.\n");
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ {
+ Trace("SetEndOfFile: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+
+ /* call GetFileSize to verify pointer position */
+ /* assumes a successful GetFileSize test */
+
+ dwByteCount = GetFileSize(hFile, NULL);
+ if (dwByteCount != dwOffset)
+ {
+ Trace("SetEndOfFile: ERROR -> file apparently not expanded to the"
+ " correct size.\n");
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ {
+ Trace("SetEndOfFile: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ {
+ Fail("SetEndOfFile: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/SetEndOfFile/test3/testinfo.dat b/src/pal/tests/palsuite/file_io/SetEndOfFile/test3/testinfo.dat
new file mode 100644
index 0000000000..7f3868d6ca
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetEndOfFile/test3/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = SetEndOfFile
+Name = Positive Test for SetEndOfFile
+Type = DEFAULT
+EXE1 = setendoffile
+Description
+=Set the end of file past the actual end
+=of file thereby, extending it.
+
diff --git a/src/pal/tests/palsuite/file_io/SetEndOfFile/test4/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetEndOfFile/test4/CMakeLists.txt
new file mode 100644
index 0000000000..ff0b6f999c
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetEndOfFile/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ setendoffile.c
+)
+
+add_executable(paltest_setendoffile_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setendoffile_test4 coreclrpal)
+
+target_link_libraries(paltest_setendoffile_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/SetEndOfFile/test4/setendoffile.c b/src/pal/tests/palsuite/file_io/SetEndOfFile/test4/setendoffile.c
new file mode 100644
index 0000000000..98a6ec63da
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetEndOfFile/test4/setendoffile.c
@@ -0,0 +1,138 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: setendoffile.c (test 4)
+**
+** Purpose: Tests the PAL implementation of the SetEndOfFile function.
+** Verify that the file pointer is the same before
+** and after a SetEndOfFile using SetFilePointer with
+** FILE_BEGIN, FILE_CURRENT and FILE_END
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+const char* szStringTest = "The quick fox jumped over the lazy dog's back.";
+const char* szTextFile = "test.tmp";
+
+static void Cleanup(HANDLE hFile)
+{
+ if (!CloseHandle(hFile))
+ {
+ Trace("SetEndOfFile: ERROR -> Unable to close file \"%s\". ",
+ "GetLastError returned %u.\n",
+ szTextFile,
+ GetLastError());
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetEndOfFile: ERROR -> Unable to delete file \"%s\". ",
+ "GetLastError returned %u.\n",
+ szTextFile,
+ GetLastError());
+ }
+}
+
+static void DoTest(HANDLE hFile, DWORD dwOffset, DWORD dwMethod)
+{
+ DWORD dwFP1 = 0;
+ DWORD dwFP2 = 0;
+ DWORD dwError;
+
+ /* set the pointer*/
+ dwFP1 = SetFilePointer(hFile, dwOffset, NULL, dwMethod);
+ if ((dwFP1 == INVALID_SET_FILE_POINTER) &&
+ ((dwError = GetLastError()) != ERROR_SUCCESS))
+ {
+ Trace("SetEndOfFile: ERROR -> Unable to set the pointer to the "
+ "end of the file. GetLastError returned %u.\n",
+ dwError);
+ Cleanup(hFile);
+ Fail("");
+ }
+
+ /* set EOF */
+ if (!SetEndOfFile(hFile))
+ {
+ Trace("SetEndOfFile: ERROR -> Unable to set end of file. "
+ "GetLastError returned %u.\n",
+ GetLastError());
+ Cleanup(hFile);
+ Fail("");
+ }
+
+ /* get current file pointer pointer */
+ dwFP2 = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
+ if ((dwFP1 == INVALID_SET_FILE_POINTER) &&
+ ((dwError = GetLastError()) != ERROR_SUCCESS))
+ {
+ Trace("SetEndOfFile: ERROR -> Unable to set the pointer to the "
+ "end of the file. GetLastError returned %u.\n",
+ dwError);
+ Cleanup(hFile);
+ Fail("");
+ }
+
+ /* are they the same? */
+ if (dwFP1 != dwFP2)
+ {
+ Trace("SetEndOfFile: ERROR -> File pointer before (%u) the "
+ "SetEndOfFile call was different than after (%u).\n",
+ dwFP1,
+ dwFP2);
+ Cleanup(hFile);
+ Fail("");
+ }
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE hFile = NULL;
+ DWORD dwBytesWritten;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* create a test file */
+ hFile = CreateFile(szTextFile,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("SetEndOfFile: ERROR -> Unable to create file \"%s\". "
+ "GetLastError returned %u.\n",
+ szTextFile,
+ GetLastError());
+ }
+
+ if (!WriteFile(hFile, szStringTest, strlen(szStringTest), &dwBytesWritten, NULL))
+ {
+ Trace("SetEndOfFile: ERROR -> Unable to write to \"%s\". ",
+ "GetLastError returned %u.\n",
+ szTextFile,
+ GetLastError());
+ Cleanup(hFile);
+ Fail("");
+ }
+
+ DoTest(hFile, -2, FILE_END); /* test the end */
+ DoTest(hFile, -10, FILE_CURRENT); /* test the middle-ish */
+ DoTest(hFile, 0, FILE_BEGIN); /* test the start */
+
+ Cleanup(hFile);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/SetEndOfFile/test4/testinfo.dat b/src/pal/tests/palsuite/file_io/SetEndOfFile/test4/testinfo.dat
new file mode 100644
index 0000000000..51d9185343
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetEndOfFile/test4/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = SetEndOfFile
+Name = Positive Test for SetEndOfFile (test 4)
+Type = DEFAULT
+EXE1 = setendoffile
+Description
+= Tests the PAL implementation of the SetEndOfFile function.
+= Verify that the file pointer is the same before
+= and after a SetEndOfFile using SetFilePointer with
+= FILE_BEGIN, FILE_CURRENT and FILE_END
diff --git a/src/pal/tests/palsuite/file_io/SetEndOfFile/test5/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetEndOfFile/test5/CMakeLists.txt
new file mode 100644
index 0000000000..cca7167762
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetEndOfFile/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test5.c
+)
+
+add_executable(paltest_setendoffile_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setendoffile_test5 coreclrpal)
+
+target_link_libraries(paltest_setendoffile_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/SetEndOfFile/test5/test5.c b/src/pal/tests/palsuite/file_io/SetEndOfFile/test5/test5.c
new file mode 100644
index 0000000000..7000d1af15
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetEndOfFile/test5/test5.c
@@ -0,0 +1,183 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test5.c
+**
+** Purpose: Tests the PAL implementation of the SetEndOfFile function.
+** Test attempts to read the number of characters up to
+** the EOF pointer, which was specified.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE hFile = NULL;
+ DWORD dwBytesWritten;
+ DWORD retCode;
+ BOOL bRc = FALSE;
+ char szBuffer[256];
+ DWORD dwBytesRead = 0;
+ char testFile[] = "testfile.tmp";
+ char testString[] = "watch what happens";
+ LONG shiftAmount = 10;
+
+ /* Initialize the PAL.
+ */
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* Initialize the buffer.
+ */
+ memset(szBuffer, 0, 256);
+
+ /* Create a file to test with.
+ */
+ hFile = CreateFile(testFile,
+ GENERIC_WRITE|GENERIC_READ,
+ FILE_SHARE_WRITE|FILE_SHARE_READ,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR:%u: Unable to create file \"%s\".\n",
+ GetLastError(),
+ testFile);
+ }
+
+ /* Write to the File handle.
+ */
+ bRc = WriteFile(hFile,
+ testString,
+ strlen(testString),
+ &dwBytesWritten,
+ NULL);
+
+ if (bRc == FALSE)
+ {
+ Trace("ERROR:%u: Unable to write to file handle "
+ "hFile=0x%lx\n",
+ GetLastError(),
+ hFile);
+ if (!CloseHandle(hFile))
+ {
+ Fail("ERROR:%u%: Unable to close handle 0x%lx.\n",
+ GetLastError(),
+ hFile);
+ }
+ Fail("");
+ }
+
+ /* Set the file pointer to shiftAmount bytes from the front of the file
+ */
+ retCode = SetFilePointer(hFile, shiftAmount, NULL, FILE_BEGIN);
+ if(retCode == INVALID_SET_FILE_POINTER)
+ {
+ Trace("ERROR:%u: Unable to set the file pointer to %d\n",
+ GetLastError(),
+ shiftAmount);
+ if (!CloseHandle(hFile))
+ {
+ Fail("ERROR:%u%: Unable to close handle 0x%lx.\n",
+ GetLastError(),
+ hFile);
+ }
+ Fail("");
+ }
+
+ /* set the end of file pointer to 'shiftAmount' */
+ bRc = SetEndOfFile(hFile);
+ if (bRc == FALSE)
+ {
+ Trace("ERROR:%u: Unable to set file pointer of file handle 0x%lx.\n",
+ GetLastError(),
+ hFile);
+ if (!CloseHandle(hFile))
+ {
+ Fail("ERROR:%u%: Unable to close handle 0x%lx.\n",
+ GetLastError(),
+ hFile);
+ }
+ Fail("");
+ }
+
+ /* Set the file pointer to 10 bytes from the front of the file
+ */
+ retCode = SetFilePointer(hFile, (LONG)NULL, NULL, FILE_BEGIN);
+ if(retCode == INVALID_SET_FILE_POINTER)
+ {
+ Trace("ERROR:%u: Unable to set the file pointer to %d\n",
+ GetLastError(),
+ FILE_BEGIN);
+ if (!CloseHandle(hFile))
+ {
+ Fail("ERROR:%u%: Unable to close handle 0x%lx.\n",
+ GetLastError(),
+ hFile);
+ }
+ Fail("");
+ }
+
+ /* Attempt to read the entire string, 'testString' from a file
+ * that has it's end of pointer set at shiftAmount;
+ */
+ bRc = ReadFile(hFile,
+ szBuffer,
+ strlen(testString),
+ &dwBytesRead,
+ NULL);
+
+ if (bRc == FALSE)
+ {
+ Trace("ERROR:%u: Unable to read from file handle 0x%lx.\n",
+ GetLastError(),
+ hFile);
+ if (!CloseHandle(hFile))
+ {
+ Fail("ERROR:%u%: Unable to close handle 0x%lx.\n",
+ GetLastError(),
+ hFile);
+ }
+ Fail("");
+ }
+
+ /* Confirm the number of bytes read with that requested.
+ */
+ if (dwBytesRead != shiftAmount)
+ {
+ Trace("ERROR: The number of bytes read \"%d\" is not equal to the "
+ "number that should have been written \"%d\".\n",
+ dwBytesRead,
+ shiftAmount);
+ if (!CloseHandle(hFile))
+ {
+ Fail("ERROR:%u%: Unable to close handle 0x%lx.\n",
+ GetLastError(),
+ hFile);
+ }
+ Fail("");
+ }
+
+ bRc = CloseHandle(hFile);
+ if(!bRc)
+ {
+ Fail("ERROR:%u CloseHandle failed to close the handle\n",
+ GetLastError());
+ }
+
+ /* Terminate the PAL.
+ */
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/file_io/SetEndOfFile/test5/testinfo.dat b/src/pal/tests/palsuite/file_io/SetEndOfFile/test5/testinfo.dat
new file mode 100644
index 0000000000..3a226ff8ad
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetEndOfFile/test5/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = SetEndOfFile
+Name = Positive Test for SetEndOfFile
+Type = DEFAULT
+EXE1 = test5
+Description
+= Tests the PAL implementation of the SetEndOfFile function.
+= Test attempts to set the end of file pointer to a position
+= which has data before and after it. Then it attempts to
+= read text beyond the end of file pointer.
+
diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesA/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFileAttributesA/CMakeLists.txt
new file mode 100644
index 0000000000..a3847f8ca9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileAttributesA/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+
diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesA/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test1/CMakeLists.txt
new file mode 100644
index 0000000000..81e2dfdea2
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ SetFileAttributesA.c
+)
+
+add_executable(paltest_setfileattributesa_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setfileattributesa_test1 coreclrpal)
+
+target_link_libraries(paltest_setfileattributesa_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesA/test1/SetFileAttributesA.c b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test1/SetFileAttributesA.c
new file mode 100644
index 0000000000..bacab2a0ad
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test1/SetFileAttributesA.c
@@ -0,0 +1,168 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: SetFileAttributesA.c
+**
+**
+** Purpose: Tests the PAL implementation of the SetFileAttributesA function
+** Test that we can set a file READONLY, and then that we're unable to
+** open that file with WRITE access. Then change it to NORMAL attributes, and
+** try to open it again -- it should work now.
+**
+** Depends:
+** CreateFile
+** CloseHandle
+**
+**
+**===================================================================*/
+
+/* According to the spec, only READONLY attribute can be set
+ in FreeBSD.
+*/
+
+#include <palsuite.h>
+
+
+
+int __cdecl main(int argc, char **argv)
+{
+ DWORD TheResult;
+ HANDLE TheFile;
+ char* FileName = {"test_file"};
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ // Create the test file
+ FILE *testFile = fopen(FileName, "w");
+ if (testFile == NULL)
+ {
+ Fail("Unexpected error: Unable to open file %S with fopen. \n", FileName);
+ }
+ if (fputs("testing", testFile) == EOF)
+ {
+ Fail("Unexpected error: Unable to write to file %S with fputs. \n", FileName);
+ }
+ if (fclose(testFile) != 0)
+ {
+ Fail("Unexpected error: Unable to close file %S with fclose. \n", FileName);
+ }
+ testFile = NULL;
+
+ /* Try to set the file to Read-only */
+
+ TheResult = SetFileAttributesA(FileName, FILE_ATTRIBUTE_READONLY);
+
+ if(TheResult == 0)
+ {
+ Fail("ERROR: SetFileAttributesA returned 0, failure, when trying "
+ "to set the FILE_ATTRIBUTE_READONLY attribute.");
+ }
+
+ /* Attempt to open this READONLY file with WRITE access,
+ The open should fail and the HANDLE should be invalid.
+ */
+
+ TheFile = CreateFileA(
+ FileName, // file name
+ GENERIC_READ|GENERIC_WRITE, // access mode
+ 0, // share mode
+ NULL, // SD
+ OPEN_ALWAYS, // how to create
+ FILE_ATTRIBUTE_NORMAL, // file attributes
+ NULL // handle to template file
+ );
+
+ if(TheFile != INVALID_HANDLE_VALUE)
+ {
+ TheResult = CloseHandle(TheFile);
+ if(TheResult == 0)
+ {
+ Fail("ERROR: CloseHandle failed. This tests relies upon it "
+ "working properly.");
+ }
+ Fail("ERROR: Tried to open a file that was created as "
+ "READONLY with the GENERIC_WRITE access mode. This should"
+ " cause CreateFile to return an INVALID_HANDLE_VALUE.");
+ }
+
+ /* Try to open the file with READ access, this should be ok.
+ The HANDLE will be valid.
+ */
+
+ TheFile = CreateFileA(
+ FileName, // file name
+ GENERIC_READ, // access mode
+ 0, // share mode
+ NULL, // SD
+ OPEN_ALWAYS, // how to create
+ FILE_ATTRIBUTE_NORMAL, // file attributes
+ NULL // handle to template file
+ );
+
+ if(TheFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Tried to open a file that was created as "
+ "READONLY with the GENERIC_READ access mode. This should"
+ " cause CreateFile to return an valid handle, but "
+ "INVALID_HANDLE_VALUE was returned!.");
+ }
+
+ /* Close that HANDLE */
+
+ TheResult = CloseHandle(TheFile);
+
+ if(TheResult == 0)
+ {
+ Fail("ERROR: CloseHandle failed. This tests relies upon it "
+ "working properly.");
+ }
+
+ /* Set the file to NORMAL */
+
+ TheResult = SetFileAttributesA(FileName, FILE_ATTRIBUTE_NORMAL);
+
+ if(TheResult == 0)
+ {
+ Fail("ERROR: SetFileAttributesA returned 0, failure, when trying "
+ "to set the FILE_ATTRIBUTE_NORMAL attribute.");
+ }
+
+ /* To ensure that the set worked correctly, try to open the file
+ with WRITE access again -- this time it should succeed.
+ */
+
+ TheFile = CreateFileA(
+ FileName, // file name
+ GENERIC_READ|GENERIC_WRITE, // access mode
+ 0, // share mode
+ NULL, // SD
+ OPEN_ALWAYS, // how to create
+ FILE_ATTRIBUTE_NORMAL, // file attributes
+ NULL // handle to template file
+ );
+
+ if(TheFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Tried to open a file that was created as "
+ "NORMAL with the GENERIC_WRITE access mode. This should"
+ " cause CreateFile to return an valid handle, but "
+ "INVALID_HANDLE_VALUE was returned!.");
+ }
+
+ TheResult = CloseHandle(TheFile);
+
+ if(TheResult == 0)
+ {
+ Fail("ERROR: CloseHandle failed. This tests relies upon it "
+ "working properly.");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesA/test1/test_file b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test1/test_file
new file mode 100644
index 0000000000..1b4bcfe1b5
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test1/test_file
@@ -0,0 +1 @@
+Don't delete me. I'm needed. The File. \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesA/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test1/testinfo.dat
new file mode 100644
index 0000000000..e39eac71b4
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = SetFileAttributesA
+Name = Test for SetFileAttributesA which tests READONLY and NORMAL attributes
+TYPE = DEFAULT
+EXE1 = setfileattributesa
+Description
+= Test the SetFileAttributesA function. Set a file as READONLY and
+= attempt to open it with WRITE access, to ensure that this doesn't work.
+= Then switch to NORMAL attributes, and try again -- it should work.
diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesA/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test2/CMakeLists.txt
new file mode 100644
index 0000000000..03445c1df0
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ SetFileAttributesA.c
+)
+
+add_executable(paltest_setfileattributesa_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setfileattributesa_test2 coreclrpal)
+
+target_link_libraries(paltest_setfileattributesa_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesA/test2/SetFileAttributesA.c b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test2/SetFileAttributesA.c
new file mode 100644
index 0000000000..5c04a6b181
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test2/SetFileAttributesA.c
@@ -0,0 +1,114 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: SetFileAttributesA.c
+**
+**
+** Purpose: Tests the PAL implementation of the SetFileAttributesA function
+** Test that we can set the defined attributes aside from READONLY on a
+** file, and that it doesn't return failure. Note, these attributes won't
+** do anything to the file, however.
+**
+**
+**===================================================================*/
+
+
+#include <palsuite.h>
+
+/* this cleanup method tries to revert the file back to its initial attributes */
+void do_cleanup(char* filename, DWORD attributes)
+{
+ DWORD result;
+ result = SetFileAttributesA(filename, attributes);
+ if (result == 0)
+ {
+ Fail("ERROR:SetFileAttributesA returned 0,failure in the do_cleanup "
+ "method when trying to revert the file back to its initial attributes (%u)", GetLastError());
+ }
+}
+
+int __cdecl main(int argc, char **argv)
+{
+ DWORD TheResult;
+ DWORD initialAttr;
+
+ char* FileName = {"test_file"};
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ // Create the test file
+ FILE *testFile = fopen(FileName, "w");
+ if (testFile == NULL)
+ {
+ Fail("Unexpected error: Unable to open file %S with fopen. \n", FileName);
+ }
+ if (fputs("testing", testFile) == EOF)
+ {
+ Fail("Unexpected error: Unable to write to file %S with fputs. \n", FileName);
+ }
+ if (fclose(testFile) != 0)
+ {
+ Fail("Unexpected error: Unable to close file %S with fclose. \n", FileName);
+ }
+ testFile = NULL;
+
+ /* Get the initial attributes of the file */
+
+ initialAttr = GetFileAttributesA(FileName);
+
+ /* Try to set the file to HIDDEN */
+
+ TheResult = SetFileAttributesA(FileName, FILE_ATTRIBUTE_HIDDEN);
+
+ if(TheResult == 0)
+ {
+ do_cleanup(FileName,initialAttr);
+ Fail("ERROR: SetFileAttributesA returned 0, failure, when trying "
+ "to set the FILE_ATTRIBUTE_HIDDEN attribute. This should "
+ "not do anything in FreeBSD, but it shouldn't fail.");
+ }
+
+ /* Try to set the file to ARCHIVE */
+
+ TheResult = SetFileAttributesA(FileName, FILE_ATTRIBUTE_ARCHIVE);
+
+ if(TheResult == 0)
+ {
+ do_cleanup(FileName,initialAttr);
+ Fail("ERROR: SetFileAttributesA returned 0, failure, when trying "
+ "to set the FILE_ATTRIBUTE_ARCHIVE attribute.");
+ }
+
+ /* Try to set the file to SYSTEM */
+
+ TheResult = SetFileAttributesA(FileName, FILE_ATTRIBUTE_SYSTEM);
+
+ if(TheResult == 0)
+ {
+ do_cleanup(FileName,initialAttr);
+ Fail("ERROR: SetFileAttributesA returned 0, failure, when trying "
+ "to set the FILE_ATTRIBUTE_SYSTEM attribute.");
+ }
+
+ /* Try to set the file to DIRECTORY */
+
+ TheResult = SetFileAttributesA(FileName, FILE_ATTRIBUTE_DIRECTORY);
+
+ if(TheResult == 0)
+ {
+ do_cleanup(FileName,initialAttr);
+ Fail("ERROR: SetFileAttributesA returned 0, failure, when trying "
+ "to set the FILE_ATTRIBUTE_DIRECTORY attribute.");
+ }
+
+
+ do_cleanup(FileName,initialAttr);
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesA/test2/test_file b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test2/test_file
new file mode 100644
index 0000000000..18d630a34d
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test2/test_file
@@ -0,0 +1 @@
+The File. \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesA/test2/testinfo.dat b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test2/testinfo.dat
new file mode 100644
index 0000000000..778335258d
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test2/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = SetFileAttributesA
+Name = smoke test for SetFileAttributesA
+TYPE = DEFAULT
+EXE1 = setfileattributesa
+Description
+= Test the SetFileAttributesA function
+= Try to set the attributes that are not valid in FreeBSD. These should
+= return success in either WIN32 or FreeBSD, just have no effect in FreeBSD.
diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesA/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test3/CMakeLists.txt
new file mode 100644
index 0000000000..3c35172d7c
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ SetFileAttributesA.c
+)
+
+add_executable(paltest_setfileattributesa_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setfileattributesa_test3 coreclrpal)
+
+target_link_libraries(paltest_setfileattributesa_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesA/test3/SetFileAttributesA.c b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test3/SetFileAttributesA.c
new file mode 100644
index 0000000000..445b515c7f
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test3/SetFileAttributesA.c
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: SetFileAttributesA.c
+**
+**
+** Purpose: Tests the PAL implementation of the SetFileAttributesA function
+** Test that the function fails if the file doesn't exist..
+**
+**
+**===================================================================*/
+
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char **argv)
+{
+ DWORD TheResult;
+ char* FileName = {"no_file"};
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+
+ /* Try to set the file to NORMAL on a file that doesn't
+ exist.
+ */
+
+ TheResult = SetFileAttributesA(FileName, FILE_ATTRIBUTE_NORMAL);
+
+ if(TheResult != 0)
+ {
+ Fail("ERROR: SetFileAttributesA returned non-zero0, success, when"
+ " trying to set the FILE_ATTRIBUTE_NORMAL attribute on a non "
+ "existant file. This should fail.");
+ }
+
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesA/test3/testinfo.dat b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test3/testinfo.dat
new file mode 100644
index 0000000000..33a4b03d64
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test3/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = SetFileAttributesA
+Name = Test SetFileAttributesA on an invalid file
+TYPE = DEFAULT
+EXE1 = setfileattributesa
+Description
+= Test the SetFileAttributesA function
+= Try the function on a file that doesn't exist. It should fail.
diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesA/test4/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test4/CMakeLists.txt
new file mode 100644
index 0000000000..f30969ad04
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ SetFileAttributesA.c
+)
+
+add_executable(paltest_setfileattributesa_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setfileattributesa_test4 coreclrpal)
+
+target_link_libraries(paltest_setfileattributesa_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesA/test4/SetFileAttributesA.c b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test4/SetFileAttributesA.c
new file mode 100644
index 0000000000..240e89ff6f
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test4/SetFileAttributesA.c
@@ -0,0 +1,128 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: SetFileAttributesA.c
+**
+**
+** Purpose: Tests the PAL implementation of the SetFileAttributesA function
+** Check that using two flags (READONLY and NORMAL) only sets the file
+** as READONLY, as MSDN notes that everything else overrides NORMAL.
+**
+** Depends:
+** CreateFileA
+** CloseHandle
+**
+**
+**===================================================================*/
+
+
+#include <palsuite.h>
+
+
+
+int __cdecl main(int argc, char **argv)
+{
+ DWORD TheResult;
+ HANDLE TheFile;
+ char* FileName = {"test_file"};
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ // Create the test file
+ FILE *testFile = fopen(FileName, "w");
+ if (testFile == NULL)
+ {
+ Fail("Unexpected error: Unable to open file %S with fopen. \n", FileName);
+ }
+ if (fputs("testing", testFile) == EOF)
+ {
+ Fail("Unexpected error: Unable to write to file %S with fputs. \n", FileName);
+ }
+ if (fclose(testFile) != 0)
+ {
+ Fail("Unexpected error: Unable to close file %S with fclose. \n", FileName);
+ }
+ testFile = NULL;
+
+ /* Try to set the file to Read-only|Normal ... It should
+ end up as Readonly, since this overrides Normal*/
+
+ TheResult = SetFileAttributesA(FileName,
+ FILE_ATTRIBUTE_NORMAL|
+ FILE_ATTRIBUTE_READONLY);
+
+ if(TheResult == 0)
+ {
+ Fail("ERROR: SetFileAttributesA returned 0, failure, when trying "
+ "to set the FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_NORMAL "
+ "attribute.");
+ }
+
+ /* Attempt to open this READONLY file with WRITE access,
+ The open should fail and the HANDLE should be invalid.
+ */
+
+ TheFile = CreateFileA(
+ FileName, // file name
+ GENERIC_READ|GENERIC_WRITE, // access mode
+ 0, // share mode
+ NULL, // SD
+ OPEN_ALWAYS, // how to create
+ FILE_ATTRIBUTE_NORMAL, // file attributes
+ NULL // handle to template file
+ );
+
+ if(TheFile != INVALID_HANDLE_VALUE)
+ {
+ TheResult = CloseHandle(TheFile);
+ if(TheResult == 0)
+ {
+ Trace("ERROR: CloseHandle failed. This tests relies upon it "
+ "working properly.");
+ }
+ Fail("ERROR: Tried to open a file that was created as "
+ "READONLY with the GENERIC_WRITE access mode. This should"
+ " cause CreateFileA to return an INVALID_HANDLE_VALUE.");
+ }
+
+ /* Try to open the file with READ access, this should be ok.
+ The HANDLE will be valid.
+ */
+
+ TheFile = CreateFileA(
+ FileName, // file name
+ GENERIC_READ, // access mode
+ 0, // share mode
+ NULL, // SD
+ OPEN_ALWAYS, // how to create
+ FILE_ATTRIBUTE_NORMAL, // file attributes
+ NULL // handle to template file
+ );
+
+ if(TheFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Tried to open a file that was created as "
+ "READONLY with the GENERIC_READ access mode. This should"
+ " cause CreateFileA to return an valid handle, but "
+ "INVALID_HANDLE_VALUE was returned!.");
+ }
+
+ /* Close that HANDLE */
+
+ TheResult = CloseHandle(TheFile);
+
+ if(TheResult == 0)
+ {
+ Fail("ERROR: CloseHandle failed. This tests relies upon it "
+ "working properly.");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesA/test4/test_file b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test4/test_file
new file mode 100644
index 0000000000..1b4bcfe1b5
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test4/test_file
@@ -0,0 +1 @@
+Don't delete me. I'm needed. The File. \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesA/test4/testinfo.dat b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test4/testinfo.dat
new file mode 100644
index 0000000000..d8df0625bc
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test4/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = SetFileAttributesA
+Name = Tests SetFileAttributesA properly overrides NORMAL
+TYPE = DEFAULT
+EXE1 = setfileattributesa
+Description
+= Test the SetFileAttributesA function. Check that using two flags
+= (READONLY and NORMAL) only sets the file as READONLY, as MSDN
+= notes that everything else overrides NORMAL.
diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesW/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFileAttributesW/CMakeLists.txt
new file mode 100644
index 0000000000..a3847f8ca9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileAttributesW/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+
diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..35927b4b1d
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ SetFileAttributesW.c
+)
+
+add_executable(paltest_setfileattributesw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setfileattributesw_test1 coreclrpal)
+
+target_link_libraries(paltest_setfileattributesw_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesW/test1/SetFileAttributesW.c b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test1/SetFileAttributesW.c
new file mode 100644
index 0000000000..753c396d1f
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test1/SetFileAttributesW.c
@@ -0,0 +1,167 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: SetFileAttributesW.c
+**
+** Purpose: Tests the PAL implementation of the SetFileAttributesW function
+** Test that we can set a file READONLY, and then that we're unable to
+** open that file with WRITE access. Then change it to NORMAL attributes, and
+** try to open it again -- it should work now.
+**
+** Depends:
+** CreateFile
+** CloseHandle
+**
+**
+**===================================================================*/
+
+/* According to the spec, only READONLY attribute can be set
+ in FreeBSD.
+*/
+
+#define UNICODE
+
+#include <palsuite.h>
+
+
+
+int __cdecl main(int argc, char **argv)
+{
+ DWORD TheResult;
+ HANDLE TheFile;
+ CHAR *FileName_Multibyte = "test_file";
+ WCHAR FileName[MAX_PATH];
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ // Create the test file
+ FILE *testFile = fopen(FileName_Multibyte, "w");
+ if (testFile == NULL)
+ {
+ Fail("Unexpected error: Unable to open file %S with fopen. \n", FileName);
+ }
+ if (fputs("testing", testFile) == EOF)
+ {
+ Fail("Unexpected error: Unable to write to file %S with fputs. \n", FileName);
+ }
+ if (fclose(testFile) != 0)
+ {
+ Fail("Unexpected error: Unable to close file %S with fclose. \n", FileName);
+ }
+ testFile = NULL;
+
+ /* Make a wide character string for the file name */
+
+ MultiByteToWideChar(CP_ACP,
+ 0,
+ FileName_Multibyte,
+ -1,
+ FileName,
+ MAX_PATH);
+
+
+ /* Try to set the file to Read-only */
+
+ TheResult = SetFileAttributes(FileName,FILE_ATTRIBUTE_READONLY);
+
+ if(TheResult == 0)
+ {
+ Fail("ERROR: SetFileAttributes returned 0, failure, when trying "
+ "to set the FILE_ATTRIBUTE_READONLY attribute.");
+ }
+
+ /* Attempt to open this READONLY file with WRITE access,
+ The open should fail and the HANDLE should be invalid.
+ */
+
+ TheFile = CreateFile(
+ FileName, // file name
+ GENERIC_READ|GENERIC_WRITE, // access mode
+ 0, // share mode
+ NULL, // SD
+ OPEN_ALWAYS, // how to create
+ FILE_ATTRIBUTE_NORMAL, // file attributes
+ NULL // handle to template file
+ );
+
+ if(TheFile != INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Tried to open a file that was created as "
+ "READONLY with the GENERIC_WRITE access mode. This should"
+ " cause CreateFile to return an INVALID_HANDLE_VALUE.");
+ }
+
+ /* Try to open the file with READ access, this should be ok.
+ The HANDLE will be valid.
+ */
+
+ TheFile = CreateFile(
+ FileName, // file name
+ GENERIC_READ, // access mode
+ 0, // share mode
+ NULL, // SD
+ OPEN_ALWAYS, // how to create
+ FILE_ATTRIBUTE_NORMAL, // file attributes
+ NULL // handle to template file
+ );
+
+ if(TheFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Tried to open a file that was created as "
+ "READONLY with the GENERIC_READ access mode. This should"
+ " cause CreateFile to return an valid handle, but "
+ "INVALID_HANDLE_VALUE was returned!.");
+ }
+
+ /* Close that HANDLE */
+
+ TheResult = CloseHandle(TheFile);
+
+ if(TheResult == 0)
+ {
+ Fail("ERROR: CloseHandle failed. This tests relies upon it "
+ "working properly.");
+ }
+
+ /* Set the file to NORMAL */
+
+ TheResult = SetFileAttributes(FileName,FILE_ATTRIBUTE_NORMAL);
+
+ if(TheResult == 0)
+ {
+ Fail("ERROR: SetFileAttributes returned 0, failure, when trying "
+ "to set the FILE_ATTRIBUTE_NORMAL attribute.");
+ }
+
+ /* To ensure that the set worked correctly, try to open the file
+ with WRITE access again -- this time it should succeed.
+ */
+
+ TheFile = CreateFile(
+ FileName, // file name
+ GENERIC_READ|GENERIC_WRITE, // access mode
+ 0, // share mode
+ NULL, // SD
+ OPEN_ALWAYS, // how to create
+ FILE_ATTRIBUTE_NORMAL, // file attributes
+ NULL // handle to template file
+ );
+
+ if(TheFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Tried to open a file that was created as "
+ "NORMAL with the GENERIC_WRITE access mode. This should"
+ " cause CreateFile to return an valid handle, but "
+ "INVALID_HANDLE_VALUE was returned!.");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesW/test1/test_file b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test1/test_file
new file mode 100644
index 0000000000..1b4bcfe1b5
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test1/test_file
@@ -0,0 +1 @@
+Don't delete me. I'm needed. The File. \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesW/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test1/testinfo.dat
new file mode 100644
index 0000000000..75cdc3b719
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = SetFileAttributesW
+Name = Positive Test for SetFileAttributesW
+TYPE = DEFAULT
+EXE1 = setfileattributesw
+Description
+= Test the SetFileAttributesW function. Set a file as READONLY and
+= attempt to open it with WRITE access, to ensure that this doesn't work.
+= Then switch to NORMAL attributes, and try again -- it should work.
diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesW/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test2/CMakeLists.txt
new file mode 100644
index 0000000000..81fa02c1dd
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ SetFileAttributesW.c
+)
+
+add_executable(paltest_setfileattributesw_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setfileattributesw_test2 coreclrpal)
+
+target_link_libraries(paltest_setfileattributesw_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesW/test2/SetFileAttributesW.c b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test2/SetFileAttributesW.c
new file mode 100644
index 0000000000..f657436845
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test2/SetFileAttributesW.c
@@ -0,0 +1,121 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: SetFileAttributesW.c
+**
+** Purpose: Tests the PAL implementation of the SetFileAttributesW function
+** Test that we can set the defined attributes aside from READONLY on a
+** file, and that it doesn't return failure. Note, these attributes won't
+** do anything to the file, however.
+**
+**
+**===================================================================*/
+
+#define UNICODE
+
+#include <palsuite.h>
+
+/* this cleanup method tries to revert the file back to its initial attributes */
+void do_cleanup(WCHAR* filename, DWORD attributes)
+{
+ DWORD result;
+ result = SetFileAttributes(filename, attributes);
+ if (result == 0)
+ {
+ Fail("ERROR:SetFileAttributesW returned 0,failure in the do_cleanup "
+ "method when trying to revert the file back to its initial attributes (%u)", GetLastError());
+ }
+}
+
+int __cdecl main(int argc, char **argv)
+{
+ DWORD TheResult;
+ DWORD initialAttr;
+ CHAR *FileName_Multibyte = "test_file";
+ WCHAR FileName[MAX_PATH];
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ // Create the test file
+ FILE *testFile = fopen(FileName_Multibyte, "w");
+ if (testFile == NULL)
+ {
+ Fail("Unexpected error: Unable to open file %S with fopen. \n", FileName);
+ }
+ if (fputs("testing", testFile) == EOF)
+ {
+ Fail("Unexpected error: Unable to write to file %S with fputs. \n", FileName);
+ }
+ if (fclose(testFile) != 0)
+ {
+ Fail("Unexpected error: Unable to close file %S with fclose. \n", FileName);
+ }
+ testFile = NULL;
+
+ /* Make a wide character string for the file name */
+
+ MultiByteToWideChar(CP_ACP,
+ 0,
+ FileName_Multibyte,
+ -1,
+ FileName,
+ MAX_PATH);
+
+ /* Get the initial attributes of the file */
+ initialAttr = GetFileAttributesW(FileName);
+
+ /* Try to set the file to HIDDEN */
+
+ TheResult = SetFileAttributes(FileName,FILE_ATTRIBUTE_HIDDEN);
+
+ if(TheResult == 0)
+ {
+ do_cleanup(FileName,initialAttr);
+ Fail("ERROR: SetFileAttributes returned 0, failure, when trying "
+ "to set the FILE_ATTRIBUTE_HIDDEN attribute. This should "
+ "not do anything in FreeBSD, but it shouldn't fail.");
+ }
+
+ /* Try to set the file to ARCHIVE */
+
+ TheResult = SetFileAttributes(FileName,FILE_ATTRIBUTE_ARCHIVE);
+
+ if(TheResult == 0)
+ {
+ do_cleanup(FileName,initialAttr);
+ Fail("ERROR: SetFileAttributes returned 0, failure, when trying "
+ "to set the FILE_ATTRIBUTE_ARCHIVE attribute.");
+ }
+
+ /* Try to set the file to SYSTEM */
+
+ TheResult = SetFileAttributes(FileName,FILE_ATTRIBUTE_SYSTEM);
+
+ if(TheResult == 0)
+ {
+ do_cleanup(FileName,initialAttr);
+ Fail("ERROR: SetFileAttributes returned 0, failure, when trying "
+ "to set the FILE_ATTRIBUTE_SYSTEM attribute.");
+ }
+
+ /* Try to set the file to DIRECTORY */
+
+ TheResult = SetFileAttributes(FileName,FILE_ATTRIBUTE_DIRECTORY);
+
+ if(TheResult == 0)
+ {
+ do_cleanup(FileName,initialAttr);
+ Fail("ERROR: SetFileAttributes returned 0, failure, when trying "
+ "to set the FILE_ATTRIBUTE_DIRECTORY attribute.");
+ }
+
+ do_cleanup(FileName,initialAttr);
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesW/test2/test_file b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test2/test_file
new file mode 100644
index 0000000000..18d630a34d
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test2/test_file
@@ -0,0 +1 @@
+The File. \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesW/test2/testinfo.dat b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test2/testinfo.dat
new file mode 100644
index 0000000000..e3161a9bd6
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test2/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = SetFileAttributesW
+Name = Positive Test for SetFileAttributesW
+TYPE = DEFAULT
+EXE1 = setfileattributesw
+Description
+= Test the SetFileAttributesW function
+= Try to set the attributes that are not valid in FreeBSD. These should
+= return success in either WIN32 or FreeBSD, just have no effect in FreeBSD.
diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesW/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test3/CMakeLists.txt
new file mode 100644
index 0000000000..c2cdacb0d0
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ SetFileAttributesW.c
+)
+
+add_executable(paltest_setfileattributesw_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setfileattributesw_test3 coreclrpal)
+
+target_link_libraries(paltest_setfileattributesw_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesW/test3/SetFileAttributesW.c b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test3/SetFileAttributesW.c
new file mode 100644
index 0000000000..8a8bafac68
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test3/SetFileAttributesW.c
@@ -0,0 +1,57 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: SetFileAttributesW.c
+**
+** Purpose: Tests the PAL implementation of the SetFileAttributesW function
+** Test that the function fails if the file doesn't exist..
+**
+**
+**===================================================================*/
+
+#define UNICODE
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char **argv)
+{
+ DWORD TheResult;
+ WCHAR FileName[MAX_PATH];
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* Make a wide character string for the file name */
+
+ MultiByteToWideChar(CP_ACP,
+ 0,
+ "no_file",
+ -1,
+ FileName,
+ MAX_PATH);
+
+
+ /* Try to set the file to NORMAL on a file that doesn't
+ exist.
+ */
+
+ TheResult = SetFileAttributes(FileName,FILE_ATTRIBUTE_NORMAL);
+
+ if(TheResult != 0)
+ {
+ Fail("ERROR: SetFileAttributes returned non-zero0, success, when"
+ " trying to set the FILE_ATTRIBUTE_NORMAL attribute on a non "
+ "existant file. This should fail.");
+ }
+
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesW/test3/testinfo.dat b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test3/testinfo.dat
new file mode 100644
index 0000000000..4b264898df
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test3/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = SetFileAttributesW
+Name = Positive Test for SetFileAttributesW
+TYPE = DEFAULT
+EXE1 = setfileattributesw
+Description
+= Test the SetFileAttributesW function
+= Try the function on a file that doesn't exist. It should fail.
diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesW/test4/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test4/CMakeLists.txt
new file mode 100644
index 0000000000..6a4aa8adc3
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ SetFileAttributesW.c
+)
+
+add_executable(paltest_setfileattributesw_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setfileattributesw_test4 coreclrpal)
+
+target_link_libraries(paltest_setfileattributesw_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesW/test4/SetFileAttributesW.c b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test4/SetFileAttributesW.c
new file mode 100644
index 0000000000..bebadfa264
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test4/SetFileAttributesW.c
@@ -0,0 +1,133 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: SetFileAttributesW.c
+**
+** Purpose: Tests the PAL implementation of the SetFileAttributesW function
+** Check that using two flags (READONLY and NORMAL) only sets the file
+** as READONLY, as MSDN notes that everything else overrides NORMAL.
+**
+** Depends:
+** CreateFile
+** CloseHandle
+**
+**
+**===================================================================*/
+
+#define UNICODE
+
+#include <palsuite.h>
+
+
+
+int __cdecl main(int argc, char **argv)
+{
+ DWORD TheResult;
+ HANDLE TheFile;
+ CHAR *FileName_Multibyte = "test_file";
+ WCHAR FileName[MAX_PATH];
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ // Create the test file
+ FILE *testFile = fopen(FileName_Multibyte, "w");
+ if (testFile == NULL)
+ {
+ Fail("Unexpected error: Unable to open file %S with fopen. \n", FileName);
+ }
+ if (fputs("testing", testFile) == EOF)
+ {
+ Fail("Unexpected error: Unable to write to file %S with fputs. \n", FileName);
+ }
+ if (fclose(testFile) != 0)
+ {
+ Fail("Unexpected error: Unable to close file %S with fclose. \n", FileName);
+ }
+ testFile = NULL;
+
+ /* Make a wide character string for the file name */
+
+ MultiByteToWideChar(CP_ACP,
+ 0,
+ FileName_Multibyte,
+ -1,
+ FileName,
+ MAX_PATH);
+
+
+ /* Try to set the file to Read-only|Normal ... It should
+ end up as Readonly, since this overrides Normal*/
+
+ TheResult = SetFileAttributes(FileName,
+ FILE_ATTRIBUTE_NORMAL|
+ FILE_ATTRIBUTE_READONLY);
+
+ if(TheResult == 0)
+ {
+ Fail("ERROR: SetFileAttributes returned 0, failure, when trying "
+ "to set the FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_NORMAL "
+ "attribute.");
+ }
+
+ /* Attempt to open this READONLY file with WRITE access,
+ The open should fail and the HANDLE should be invalid.
+ */
+
+ TheFile = CreateFile(
+ FileName, // file name
+ GENERIC_READ|GENERIC_WRITE, // access mode
+ 0, // share mode
+ NULL, // SD
+ OPEN_ALWAYS, // how to create
+ FILE_ATTRIBUTE_NORMAL, // file attributes
+ NULL // handle to template file
+ );
+
+ if(TheFile != INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Tried to open a file that was created as "
+ "READONLY with the GENERIC_WRITE access mode. This should"
+ " cause CreateFile to return an INVALID_HANDLE_VALUE.");
+ }
+
+ /* Try to open the file with READ access, this should be ok.
+ The HANDLE will be valid.
+ */
+
+ TheFile = CreateFile(
+ FileName, // file name
+ GENERIC_READ, // access mode
+ 0, // share mode
+ NULL, // SD
+ OPEN_ALWAYS, // how to create
+ FILE_ATTRIBUTE_NORMAL, // file attributes
+ NULL // handle to template file
+ );
+
+ if(TheFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Tried to open a file that was created as "
+ "READONLY with the GENERIC_READ access mode. This should"
+ " cause CreateFile to return an valid handle, but "
+ "INVALID_HANDLE_VALUE was returned!.");
+ }
+
+ /* Close that HANDLE */
+
+ TheResult = CloseHandle(TheFile);
+
+ if(TheResult == 0)
+ {
+ Fail("ERROR: CloseHandle failed. This tests relies upon it "
+ "working properly.");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesW/test4/test_file b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test4/test_file
new file mode 100644
index 0000000000..1b4bcfe1b5
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test4/test_file
@@ -0,0 +1 @@
+Don't delete me. I'm needed. The File. \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesW/test4/testinfo.dat b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test4/testinfo.dat
new file mode 100644
index 0000000000..75cdc3b719
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test4/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = SetFileAttributesW
+Name = Positive Test for SetFileAttributesW
+TYPE = DEFAULT
+EXE1 = setfileattributesw
+Description
+= Test the SetFileAttributesW function. Set a file as READONLY and
+= attempt to open it with WRITE access, to ensure that this doesn't work.
+= Then switch to NORMAL attributes, and try again -- it should work.
diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFilePointer/CMakeLists.txt
new file mode 100644
index 0000000000..19ee487a6a
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFilePointer/CMakeLists.txt
@@ -0,0 +1,10 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+add_subdirectory(test7)
+
diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFilePointer/test1/CMakeLists.txt
new file mode 100644
index 0000000000..e352449981
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFilePointer/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ SetFilePointer.c
+)
+
+add_executable(paltest_setfilepointer_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setfilepointer_test1 coreclrpal)
+
+target_link_libraries(paltest_setfilepointer_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test1/SetFilePointer.c b/src/pal/tests/palsuite/file_io/SetFilePointer/test1/SetFilePointer.c
new file mode 100644
index 0000000000..14b5f85e69
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFilePointer/test1/SetFilePointer.c
@@ -0,0 +1,123 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: SetFilePointer.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the SetFilePointer function.
+** Set the file pointer using a NULL handle and other invalid
+** options.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+const char* szTextFile = "text.txt";
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE hFile = NULL;
+ DWORD dwByteCount = 0;
+ DWORD dwOffset = 25;
+ DWORD dwRc = 0;
+ BOOL bRc = FALSE;
+ char buffer[100];
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* set the file pointer on a NULL file handle */
+ dwRc = SetFilePointer(NULL, dwOffset, NULL, FILE_BEGIN);
+ if (dwRc != INVALID_SET_FILE_POINTER)
+ {
+ Fail("SetFilePointer: ERROR -> Call to SetFilePointer succeeded "
+ "with a NULL pointer\n");
+ }
+
+
+ /* create a test file without proper permission */
+ hFile = CreateFile(szTextFile,
+ 0,
+ 0,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("SetFilePointer: ERROR -> Unable to create file \"%s\".\n",
+ szTextFile);
+ }
+
+ /* ReadFile fails as expected */
+ bRc = ReadFile(hFile, buffer, 1, &dwByteCount, NULL);
+ if (bRc != FALSE)
+ {
+ Trace("SetFilePointer: ERROR -> ReadFile was successful when it was "
+ "expected to fail\n");
+ if (!CloseHandle(hFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ /* move the file pointer before the beginning of the file */
+ dwRc = SetFilePointer(hFile, -1, NULL, FILE_BEGIN);
+ if (dwRc != INVALID_SET_FILE_POINTER)
+ {
+ Trace("SetFilePointer: ERROR -> Was able to move the pointer before "
+ "the beginning of the file.\n");
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ if (!DeleteFileA(szTextFile))
+ {
+ Fail("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/SetFilePointer/test1/testinfo.dat
new file mode 100644
index 0000000000..dfd4b6bd42
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFilePointer/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = SetFilePointer
+Name = Test for SetFilePointer (test 1)
+Type = DEFAULT
+EXE1 = setfilepointer
+Description
+=Set the file pointer on a NULL file handle and other invalid options
+
diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFilePointer/test2/CMakeLists.txt
new file mode 100644
index 0000000000..290a01107f
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFilePointer/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ SetFilePointer.c
+)
+
+add_executable(paltest_setfilepointer_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setfilepointer_test2 coreclrpal)
+
+target_link_libraries(paltest_setfilepointer_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test2/SetFilePointer.c b/src/pal/tests/palsuite/file_io/SetFilePointer/test2/SetFilePointer.c
new file mode 100644
index 0000000000..19e99a74b3
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFilePointer/test2/SetFilePointer.c
@@ -0,0 +1,356 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: SetFilePointer.c (test 2)
+**
+** Purpose: Tests the PAL implementation of the SetFilePointer function.
+** Test the FILE_BEGIN option
+**
+** Assumes Successful:
+** CreateFile
+** ReadFile
+** WriteFile
+** strlen
+** CloseHandle
+** strcmp
+** GetFileSize
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+const char * const szText =
+ "The quick brown fox jumped over the lazy dog's back.";
+const char* szTextFile = "text.txt";
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE hFile = NULL;
+ DWORD dwByteCount = 0;
+ DWORD dwRc = 0;
+ BOOL bRc = FALSE;
+ char szBuffer[100];
+ const char *szPtr;
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* create a test file */
+ hFile = CreateFile(szTextFile,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("SetFilePointer: ERROR -> Unable to create file \"%s\".\n",
+ szTextFile);
+ }
+
+ bRc = WriteFile(hFile, szText, (DWORD)strlen(szText), &dwByteCount, NULL);
+ if (bRc == FALSE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to write to file \"%s\".\n",
+ szTextFile);
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+
+ /* move -1 from beginning which should fail */
+ dwRc = SetFilePointer(hFile, -1, NULL, FILE_BEGIN);
+ if ((dwRc != INVALID_SET_FILE_POINTER) ||
+ (GetLastError() == ERROR_SUCCESS))
+ {
+ Trace("SetFilePointer: ERROR -> Succeeded to move the pointer "
+ "before the beginning of the file.\n");
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ /* move the file pointer 0 bytes from the beginning and verify */
+ dwRc = SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
+ if (dwRc != 0)
+ {
+ Trace("SetFilePointer: ERROR -> Asked to move 0 bytes from the "
+ "beginning of the file but moved %ld bytes.\n", dwRc);
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ /* move the pointer ahead in the file and verify */
+ dwRc = SetFilePointer(hFile, 20, NULL, FILE_BEGIN);
+ if (dwRc != 20)
+ {
+ Trace("SetFilePointer: ERROR -> Asked to move 0 bytes from the "
+ "beginning of the file but moved %ld bytes.\n", dwRc);
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ else
+ {
+ /* verify results */
+ memset(szBuffer, 0, 100);
+ bRc = ReadFile(hFile, szBuffer, (DWORD)strlen(szText)-20, &dwByteCount,
+ NULL);
+ if ((bRc != TRUE) || (dwByteCount != strlen(szText)-20))
+ {
+ Trace("SetFilePointer: ERROR -> ReadFile failed to read correctly");
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file"
+ "\"%s\".\n", szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file"
+ "\"%s\".\n", szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ szPtr = szText + 20;
+ if (strcmp(szPtr, szBuffer) != 0)
+ {
+ Trace("SetFilePointer: ERROR -> Apparently failed to move the "
+ "pointer properly\n");
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file"
+ " \"%s\".\n", szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file"
+ " \"%s\".\n", szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ }
+
+ /* move the file pointer back to the beginning and verify */
+ dwRc = SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
+ if (dwRc != 0)
+ {
+ Trace("SetFilePointer: ERROR -> Asked to move 0 bytes from the "
+ "beginning of the file but moved %ld bytes.\n", dwRc);
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ else
+ {
+ /* verify results */
+ memset(szBuffer, 0, 100);
+ bRc = ReadFile(hFile, szBuffer, (DWORD)strlen(szText), &dwByteCount,
+ NULL);
+ if ((bRc != TRUE) || (dwByteCount != strlen(szText)))
+ {
+ Trace("SetFilePointer: ERROR -> ReadFile failed to read correctly");
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file"
+ " \"%s\".\n", szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file"
+ " \"%s\".\n", szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ if (strcmp(szText, szBuffer) != 0)
+ {
+ Trace("SetFilePointer: ERROR -> Failed to return the pointer "
+ "properly to the beginning of the file\n");
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file"
+ " \"%s\".\n", szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file"
+ " \"%s\".\n", szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ }
+
+ /* return the pointer to the beginning of the file */
+ dwRc = SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
+ if (dwRc != 0)
+ {
+ Trace("SetFilePointer: ERROR -> Asked to move 0 bytes from the "
+ "beginning of the file but moved %ld bytes.\n", dwRc);
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ /* set the pointer past the end of the file and verify */
+ dwRc = SetFilePointer(hFile, (DWORD)strlen(szText)+20, NULL, FILE_BEGIN);
+ if ((dwRc == INVALID_SET_FILE_POINTER) && (GetLastError() != ERROR_SUCCESS))
+ {
+ Trace("SetFilePointer: ERROR -> Failed to move pointer past EOF.\n");
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ else
+ {
+ /* verify */
+ bRc = SetEndOfFile(hFile);
+ if (bRc != TRUE)
+ {
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file"
+ " \"%s\".\n", szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file"
+ " \"%s\".\n", szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ if (GetFileSize(hFile, NULL) != strlen(szText)+20)
+ {
+ Trace("SetFilePointer: ERROR -> Failed to move pointer past"
+ " EOF.\n");
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file"
+ " \"%s\".\n", szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file"
+ " \"%s\".\n", szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ }
+
+
+
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ if (!DeleteFileA(szTextFile))
+ {
+ Fail("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test2/testinfo.dat b/src/pal/tests/palsuite/file_io/SetFilePointer/test2/testinfo.dat
new file mode 100644
index 0000000000..e3a0a861f4
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFilePointer/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = SetFilePointer
+Name = Positive Test for SetFilePointer (test 2)
+Type = DEFAULT
+EXE1 = setfilepointer
+Description
+=Tests the FILE_BEGIN option
+
diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFilePointer/test3/CMakeLists.txt
new file mode 100644
index 0000000000..daa7553a1a
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFilePointer/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ SetFilePointer.c
+)
+
+add_executable(paltest_setfilepointer_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setfilepointer_test3 coreclrpal)
+
+target_link_libraries(paltest_setfilepointer_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test3/SetFilePointer.c b/src/pal/tests/palsuite/file_io/SetFilePointer/test3/SetFilePointer.c
new file mode 100644
index 0000000000..dd53829629
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFilePointer/test3/SetFilePointer.c
@@ -0,0 +1,350 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: SetFilePointer.c (test 3)
+**
+** Purpose: Tests the PAL implementation of the SetFilePointer function.
+** Test the FILE_CURRENT option
+**
+** Assumes Successful:
+** CreateFile
+** ReadFile
+** WriteFile
+** strlen
+** CloseHandle
+** strcmp
+** GetFileSize
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+const char* const szText =
+ "The quick brown fox jumped over the lazy dog's back.";
+const char* szTextFile = "text.txt";
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE hFile = NULL;
+ DWORD dwByteCount = 0;
+ DWORD dwRc = 0;
+ BOOL bRc = FALSE;
+ char szBuffer[100];
+ const char* szPtr;
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* create a test file */
+ hFile = CreateFile(szTextFile,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("SetFilePointer: ERROR -> Unable to create file \"%s\".\n",
+ szTextFile);
+ }
+
+ bRc = WriteFile(hFile, szText, (DWORD)strlen(szText), &dwByteCount, NULL);
+ if (bRc == FALSE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to write to file \"%s\".\n",
+ szTextFile);
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ /* reset the pointer to the beginning */
+ if (SetFilePointer(hFile, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
+ {
+ if (GetLastError() != ERROR_SUCCESS)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to reset the pointer to the "
+ "beginning of the file");
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file"
+ " \"%s\".\n", szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ }
+
+ /* move -1 from beginning which should fail */
+ dwRc = SetFilePointer(hFile, -1, NULL, FILE_CURRENT);
+ if ((dwRc != INVALID_SET_FILE_POINTER) ||
+ (GetLastError() == ERROR_SUCCESS))
+ {
+ Trace("SetFilePointer: ERROR -> Succeeded to move the pointer "
+ "before the beginning of the file.\n");
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+
+ /* move the file pointer 0 bytes from the beginning and verify */
+ dwRc = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
+ if (dwRc != 0)
+ {
+ Trace("SetFilePointer: ERROR -> Asked to move 0 bytes from the "
+ "beginning of the file but moved %ld bytes.\n", dwRc);
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ /* move the pointer ahead in the file and verify */
+ dwRc = SetFilePointer(hFile, 20, NULL, FILE_CURRENT);
+ if (dwRc != 20)
+ {
+ Trace("SetFilePointer: ERROR -> Asked to move 20 bytes from the "
+ "beginning of the file but moved %ld bytes.\n", dwRc);
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ else
+ {
+ /* verify results */
+ memset(szBuffer, 0, 100);
+ bRc = ReadFile(hFile, szBuffer, (DWORD)strlen(szText)-20, &dwByteCount,
+ NULL);
+ if ((bRc != TRUE) || (dwByteCount != strlen(szText)-20))
+ {
+ Trace("SetFilePointer: ERROR -> ReadFile failed to read correctly");
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file"
+ " \"%s\".\n", szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ szPtr = szText + 20;;
+ if (strcmp(szPtr, szBuffer) != 0)
+ {
+ Trace("SetFilePointer: ERROR -> Apparently failed to move the"
+ " pointer properly\n");
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file"
+ " \"%s\".\n", szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ }
+
+
+ /* get the current file pointer position (should be 52) */
+ dwRc = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
+ if (dwRc != 52)
+ {
+ Trace("SetFilePointer: ERROR -> Asked for current position."
+ " Should be 52 but was %ld.\n", dwRc);
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+
+ /* move the pointer backwards in the file and verify */
+ dwRc = SetFilePointer(hFile, -10, NULL, FILE_CURRENT);
+ if (dwRc != 42)
+ {
+ Trace("SetFilePointer: ERROR -> Asked to move back 10 bytes from the"
+ "end of the file but moved it to position %ld.\n", dwRc);
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ else
+ {
+ /* verify results */
+ memset(szBuffer, 0, 100);
+ bRc = ReadFile(hFile, szBuffer, 10, &dwByteCount, NULL);
+ if ((bRc != TRUE) || (dwByteCount != 10))
+ {
+ Trace("SetFilePointer: ERROR -> ReadFile failed to read correctly");
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file"
+ " \"%s\".\n", szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ szPtr = szText + 42;
+ if (strcmp(szPtr, szBuffer) != 0)
+ {
+ Trace("SetFilePointer: ERROR -> Apparently failed to move the"
+ " pointer properly\n");
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file"
+ " \"%s\".\n", szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ }
+
+ /*
+ * the file pointer is currently at the end of the file so...
+ * set the pointer past the end of the file and verify
+ */
+ dwRc = SetFilePointer(hFile, 20, NULL, FILE_CURRENT);
+ if ((dwRc == INVALID_SET_FILE_POINTER) && (GetLastError() != ERROR_SUCCESS))
+ {
+ Trace("SetFilePointer: ERROR -> Failed to move pointer past EOF.\n");
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ else
+ {
+ if (SetFilePointer(hFile, 0, NULL, FILE_CURRENT) != strlen(szText)+20)
+ {
+ Trace("SetFilePointer: ERROR -> Failed to move pointer past"
+ " EOF.\n");
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file"
+ " \"%s\".\n", szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ }
+
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ if (!DeleteFileA(szTextFile))
+ {
+ Fail("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test3/testinfo.dat b/src/pal/tests/palsuite/file_io/SetFilePointer/test3/testinfo.dat
new file mode 100644
index 0000000000..7c51fbc384
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFilePointer/test3/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = SetFilePointer
+Name = Positive Test for SetFilePointer (test 3)
+Type = DEFAULT
+EXE1 = setfilepointer
+Description
+=Tests the FILE_CURRENT option
+
diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test4/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFilePointer/test4/CMakeLists.txt
new file mode 100644
index 0000000000..1117893350
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFilePointer/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ SetFilePointer.c
+)
+
+add_executable(paltest_setfilepointer_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setfilepointer_test4 coreclrpal)
+
+target_link_libraries(paltest_setfilepointer_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test4/SetFilePointer.c b/src/pal/tests/palsuite/file_io/SetFilePointer/test4/SetFilePointer.c
new file mode 100644
index 0000000000..2993cfd354
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFilePointer/test4/SetFilePointer.c
@@ -0,0 +1,242 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: SetFilePointer.c (test 4)
+**
+** Purpose: Tests the PAL implementation of the SetFilePointer function.
+** Test the FILE_END option
+**
+** Assumes Successful:
+** CreateFile
+** ReadFile
+** WriteFile
+** strlen
+** CloseHandle
+** strcmp
+** GetFileSize
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+const char* szText = "The quick brown fox jumped over the lazy dog's back.";
+const char* szTextFile = "text.txt";
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE hFile = NULL;
+ DWORD dwByteCount = 0;
+ DWORD dwOffset = 0;
+ DWORD dwRc = 0;
+ BOOL bRc = FALSE;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* create a test file */
+ hFile = CreateFile(szTextFile,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("SetFilePointer: ERROR -> Unable to create file \"%s\".\n",
+ szTextFile);
+ }
+
+ bRc = WriteFile(hFile, szText, (DWORD)strlen(szText), &dwByteCount, NULL);
+ if (bRc == FALSE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to write to file \"%s\".\n",
+ szTextFile);
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+
+ /*
+ * move -1 from the end
+ */
+ dwRc = SetFilePointer(hFile, -1, NULL, FILE_END);
+ if (dwRc == INVALID_SET_FILE_POINTER)
+ {
+ if (GetLastError() != ERROR_SUCCESS)
+ {
+ Trace("SetFilePointer: ERROR -> Failed to move the pointer "
+ "back one character from EOF.\n");
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file"
+ " \"%s\".\n", szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file"
+ " \"%s\".\n", szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ }
+ else
+ {
+ /* verify */
+ if ((dwRc != strlen(szText)-1))
+ {
+ Trace("SetFilePointer: ERROR -> Failed to move the pointer"
+ " -1 bytes from EOF\n");
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file"
+ " \"%s\".\n", szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file"
+ " \"%s\".\n", szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ }
+
+ /*
+ * move the file pointer 0 bytes from the end and verify
+ */
+ dwRc = SetFilePointer(hFile, 0, NULL, FILE_END);
+ if (dwRc != strlen(szText))
+ {
+ Trace("SetFilePointer: ERROR -> Asked to move 0 bytes from the "
+ "end of the file. Function returned %ld instead of 52.\n", dwRc);
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ /*
+ * move the pointer past the end of the file and verify
+ */
+ dwRc = SetFilePointer(hFile, 20, NULL, FILE_END);
+ if (dwRc != strlen(szText)+20)
+ {
+ Trace("SetFilePointer: ERROR -> Asked to move 20 bytes past the "
+ "end of the file. Function returned %ld instead of %d.\n",
+ dwRc,
+ strlen(szText)+20);
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ else
+ {
+ /* verify results */
+ bRc = SetEndOfFile(hFile);
+ if ((dwRc = GetFileSize(hFile, NULL)) != strlen(szText)+20)
+ {
+ Trace("SetFilePointer: ERROR -> Asked to move back 20 bytes past"
+ " theend of the file. GetFileSize returned %ld whereas it "
+ "should have been %d.\n",
+ dwRc,
+ strlen(szText)+20);
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file"
+ " \"%s\".\n", szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file"
+ " \"%s\".\n", szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ }
+
+
+ /*
+ * move the pointer backwards to before the start of the file and verify
+ */
+
+ dwOffset = (dwRc + 20) * -1;
+ dwRc = SetFilePointer(hFile, dwOffset, NULL, FILE_END);
+ if ((dwRc != INVALID_SET_FILE_POINTER) ||
+ (GetLastError() == ERROR_SUCCESS))
+ {
+ Trace("SetFilePointer: ERROR -> Was able to move the pointer "
+ "to before the beginning of the file.\n");
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ if (!DeleteFileA(szTextFile))
+ {
+ Fail("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test4/testinfo.dat b/src/pal/tests/palsuite/file_io/SetFilePointer/test4/testinfo.dat
new file mode 100644
index 0000000000..dce6f9eb21
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFilePointer/test4/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = SetFilePointer
+Name = Positive Test for SetFilePointer (test 4)
+Type = DEFAULT
+EXE1 = setfilepointer
+Description
+=Tests the FILE_END option
+
diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test5/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFilePointer/test5/CMakeLists.txt
new file mode 100644
index 0000000000..b37bf42ffc
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFilePointer/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ SetFilePointer.c
+)
+
+add_executable(paltest_setfilepointer_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setfilepointer_test5 coreclrpal)
+
+target_link_libraries(paltest_setfilepointer_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test5/SetFilePointer.c b/src/pal/tests/palsuite/file_io/SetFilePointer/test5/SetFilePointer.c
new file mode 100644
index 0000000000..f1d392da38
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFilePointer/test5/SetFilePointer.c
@@ -0,0 +1,182 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: SetFilePointer.c (test 5)
+**
+** Purpose: Tests the PAL implementation of the SetFilePointer function.
+** Test the FILE_BEGIN option using the high word parameter
+**
+** Assumes Successful:
+** CreateFile
+** ReadFile
+** WriteFile
+** strlen
+** CloseHandle
+** strcmp
+** GetFileSize
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+const char* szTextFile = "text.txt";
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE hFile = NULL;
+ DWORD dwOffset = 1;
+ LONG dwHighWord = 1;
+ DWORD dwReturnedOffset = 0;
+ DWORD dwReturnedHighWord = 0;
+ DWORD dwRc = 0;
+ DWORD dwError = 0;
+ BOOL bRc = FALSE;
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* create a test file */
+ hFile = CreateFile(szTextFile,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ dwError = GetLastError();
+ Fail("SetFilePointer: ERROR -> Unable to create file \"%s\".\n with "
+ "error %ld",
+ szTextFile,
+ GetLastError());
+ }
+
+
+
+ /* move -1 from beginning which should fail */
+ dwRc = SetFilePointer(hFile, -1, &dwHighWord, FILE_BEGIN);
+ if (dwRc != INVALID_SET_FILE_POINTER)
+ {
+ Trace("SetFilePointer: ERROR -> Succeeded to move the pointer "
+ "before the beginning of the file using the high word.\n");
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ /* set the pointer past the end of the file and verify */
+ dwRc = SetFilePointer(hFile, dwOffset, &dwHighWord, FILE_BEGIN);
+ if ((dwRc == INVALID_SET_FILE_POINTER) &&
+ ((dwError = GetLastError()) != ERROR_SUCCESS))
+ {
+ Trace("SetFilePointer: ERROR -> Failed to move pointer past EOF.\n");
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ else
+ {
+ /* verify */
+ bRc = SetEndOfFile(hFile);
+ if (bRc != TRUE)
+ {
+ dwError = GetLastError();
+ if (dwError == 112)
+ {
+ Trace("SetFilePointer: ERROR -> SetEndOfFile failed due to "
+ "lack of disk space\n");
+ }
+ else
+ {
+ Trace("SetFilePointer: ERROR -> SetEndOfFile call failed with "
+ "error %ld\n", dwError);
+ }
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file"
+ " \"%s\".\n", szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file"
+ " \"%s\".\n", szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ dwReturnedOffset = GetFileSize(hFile, &dwReturnedHighWord);
+ if ((dwOffset != dwReturnedOffset) ||
+ (dwHighWord != dwReturnedHighWord))
+ {
+ Trace("SetFilePointer: ERROR -> Failed to move pointer past"
+ " EOF.\n");
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file"
+ " \"%s\".\n", szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file"
+ " \"%s\".\n", szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ }
+
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ if (!DeleteFileA(szTextFile))
+ {
+ Fail("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test5/testinfo.dat b/src/pal/tests/palsuite/file_io/SetFilePointer/test5/testinfo.dat
new file mode 100644
index 0000000000..64745c0e98
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFilePointer/test5/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = SetFilePointer
+Name = Positive Test for SetFilePointer (test 5)
+Type = DEFAULT
+EXE1 = setfilepointer
+Description
+=Tests the FILE_BEGIN option with the high word parameter.
+=This test requires about 4 gig free disk space
+
diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test6/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFilePointer/test6/CMakeLists.txt
new file mode 100644
index 0000000000..8f99ed2d76
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFilePointer/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ SetFilePointer.c
+)
+
+add_executable(paltest_setfilepointer_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setfilepointer_test6 coreclrpal)
+
+target_link_libraries(paltest_setfilepointer_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test6/SetFilePointer.c b/src/pal/tests/palsuite/file_io/SetFilePointer/test6/SetFilePointer.c
new file mode 100644
index 0000000000..b35247ec24
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFilePointer/test6/SetFilePointer.c
@@ -0,0 +1,213 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: SetFilePointer.c (test 6)
+**
+** Purpose: Tests the PAL implementation of the SetFilePointer function.
+** Test the FILE_CURRENT option with high order support
+**
+** Assumes Successful:
+** CreateFile
+** ReadFile
+** WriteFile
+** strlen
+** CloseHandle
+** strcmp
+** GetFileSize
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+const char* szTextFile = "text.txt";
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE hFile = NULL;
+ DWORD dwOffset = 0;
+ LONG dwHighOrder = 0;
+ DWORD dwReturnedOffset = 0;
+ LONG dwReturnedHighOrder = 0;
+ DWORD dwRc = 0;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* create a test file */
+ hFile = CreateFile(szTextFile,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("SetFilePointer: ERROR -> Unable to create file \"%s\".\n",
+ szTextFile);
+ }
+
+
+ /* move waaaay before the beginning which should fail */
+ dwHighOrder = -1;
+ dwOffset = 0;
+ dwRc = SetFilePointer(hFile, dwOffset, &dwHighOrder, FILE_CURRENT);
+ if (dwRc != INVALID_SET_FILE_POINTER)
+ {
+ Trace("SetFilePointer: ERROR -> Succeeded to move the pointer "
+ "before the beginning of the file.\n");
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ /* move the pointer ahead in the file and verify */
+ dwHighOrder = 1;
+ dwOffset = 10;
+ dwRc = SetFilePointer(hFile, dwOffset, &dwHighOrder, FILE_CURRENT);
+ if ((dwRc != 10) || (dwHighOrder != 1))
+ {
+ Trace("SetFilePointer: ERROR -> Asked to move 2GB plus 10 bytes from "
+ "the beginning of the file but didn't.\n");
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ else
+ {
+ /* verify results */
+ if (SetEndOfFile(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Call to SetEndOfFile failed with "
+ "error code: %d\n", GetLastError());
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file"
+ " \"%s\".\n", szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file"
+ " \"%s\".\n", szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ dwReturnedOffset = GetFileSize(hFile, (DWORD*)&dwReturnedHighOrder);
+ if ((dwReturnedOffset != dwOffset) ||
+ (dwReturnedHighOrder != dwHighOrder))
+ {
+ Trace("SetFilePointer: ERROR -> Asked to move far past the "
+ "current file pointer. "
+ "low order sent: %ld low order returned: %ld "
+ "high order sent: %ld high order returned: %ld",
+ dwOffset, dwReturnedOffset,
+ dwHighOrder, dwReturnedHighOrder);
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file"
+ " \"%s\".\n", szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ }
+
+
+ /*
+ * move the pointer backwards in the file and verify
+ */
+ dwOffset = 0;
+ dwHighOrder = -1;
+ dwRc = SetFilePointer(hFile, dwOffset, &dwHighOrder, FILE_CURRENT);
+ if (dwRc != 10)
+ {
+ Trace("SetFilePointer: ERROR -> Asked to move back to 10 bytes from the"
+ "beginning of the file but moved it to position %ld.\n", dwRc);
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ else
+ {
+ /* verify results */
+ dwReturnedHighOrder = 0;
+ dwRc = SetFilePointer(hFile, 0, &dwReturnedHighOrder, FILE_CURRENT);
+ if (dwRc != 10)
+ {
+ Trace("SetFilePointer: ERROR -> Asked for current position. "
+ "Should be 10 but was %ld.\n", dwRc);
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file"
+ " \"%s\".\n", szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file"
+ " \"%s\".\n", szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ }
+
+
+ /* clean up, clean up, everybody do their share... */
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ if (!DeleteFileA(szTextFile))
+ {
+ Fail("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test6/testinfo.dat b/src/pal/tests/palsuite/file_io/SetFilePointer/test6/testinfo.dat
new file mode 100644
index 0000000000..3138e9bb40
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFilePointer/test6/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = SetFilePointer
+Name = Positive Test for SetFilePointer (test 6)
+Type = DEFAULT
+EXE1 = setfilepointer
+Description
+=Tests the FILE_CURRENT option with the high word parameter.
+=This test requires about 4 GB free disk space.
+
diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test7/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFilePointer/test7/CMakeLists.txt
new file mode 100644
index 0000000000..c5a46a531a
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFilePointer/test7/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ SetFilePointer.c
+)
+
+add_executable(paltest_setfilepointer_test7
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setfilepointer_test7 coreclrpal)
+
+target_link_libraries(paltest_setfilepointer_test7
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test7/SetFilePointer.c b/src/pal/tests/palsuite/file_io/SetFilePointer/test7/SetFilePointer.c
new file mode 100644
index 0000000000..33dfd5e711
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFilePointer/test7/SetFilePointer.c
@@ -0,0 +1,213 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: SetFilePointer.c (test 7)
+**
+** Purpose: Tests the PAL implementation of the SetFilePointer function.
+** Test the FILE_END option with high order support
+**
+** Assumes Successful:
+** CreateFile
+** ReadFile
+** WriteFile
+** strlen
+** CloseHandle
+** strcmp
+** GetFileSize
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+const char* szTextFile = "text.txt";
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE hFile = NULL;
+ DWORD dwOffset = 0;
+ LONG dwHighOrder = 0;
+ DWORD dwReturnedOffset = 0;
+ LONG dwReturnedHighOrder = 0;
+ DWORD dwRc = 0;
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* create a test file */
+ hFile = CreateFile(szTextFile,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("SetFilePointer: ERROR -> Unable to create file \"%s\".\n",
+ szTextFile);
+ }
+
+
+ /* move -1 from beginning which should fail */
+ dwHighOrder = -1;
+ dwOffset = 0;
+ dwRc = SetFilePointer(hFile, dwOffset, &dwHighOrder, FILE_END);
+ if (dwRc != INVALID_SET_FILE_POINTER)
+ {
+ Trace("SetFilePointer: ERROR -> Succeeded to move the pointer "
+ "before the beginning of the file.\n");
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ /* move the pointer ahead in the file and verify */
+ dwHighOrder = 1;
+ dwOffset = 10;
+ dwRc = SetFilePointer(hFile, dwOffset, &dwHighOrder, FILE_END);
+ if ((dwRc != 10) || (dwHighOrder != 1))
+ {
+ Trace("SetFilePointer: ERROR -> Asked to move 4GB plus 10 bytes from "
+ "the beginning of the file but didn't.\n");
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ else
+ {
+ /* verify results */
+ if (SetEndOfFile(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Call to SetEndOfFile failed with "
+ "error code: %d\n",
+ GetLastError());
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ dwReturnedOffset = GetFileSize(hFile, (DWORD*)&dwReturnedHighOrder);
+ if ((dwReturnedOffset != dwOffset) || (dwReturnedHighOrder != dwHighOrder))
+ {
+ Trace("SetFilePointer: ERROR -> Asked to move far past the "
+ "end of the file. low order sent: %ld low order returned: %ld "
+ "high order sent: %ld high order returned: %ld",
+ dwOffset, dwReturnedOffset,
+ dwHighOrder, dwReturnedHighOrder);
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ }
+
+
+ /*
+ * move the pointer backwards in the file and verify
+ */
+ dwOffset = 0;
+ dwHighOrder = -1;
+ dwRc = SetFilePointer(hFile, dwOffset, &dwHighOrder, FILE_END);
+ if (dwRc != 10)
+ {
+ Trace("SetFilePointer: ERROR -> Asked to move back to 10 bytes from the"
+ "beginning of the file but moved it to position %ld.\n", dwRc);
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ else
+ {
+ /* verify results */
+ dwReturnedHighOrder = 0;
+ dwRc = SetFilePointer(hFile, 0, &dwReturnedHighOrder, FILE_CURRENT);
+ if (dwRc != 10)
+ {
+ Trace("SetFilePointer: ERROR -> Asked for current position. "
+ "Should be 10 but was %ld.\n", dwRc);
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file"
+ " \"%s\".\n", szTextFile);
+ }
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file"
+ " \"%s\".\n", szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+ }
+
+
+ /* clean up, clean up, everybody do their share... */
+ if (CloseHandle(hFile) != TRUE)
+ {
+ Trace("SetFilePointer: ERROR -> Unable to close file \"%s\".\n",
+ szTextFile);
+ if (!DeleteFileA(szTextFile))
+ {
+ Trace("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ if (!DeleteFileA(szTextFile))
+ {
+ Fail("SetFilePointer: ERROR -> Unable to delete file \"%s\".\n",
+ szTextFile);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test7/testinfo.dat b/src/pal/tests/palsuite/file_io/SetFilePointer/test7/testinfo.dat
new file mode 100644
index 0000000000..6e8826291f
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFilePointer/test7/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = SetFilePointer
+Name = Positive Test for SetFilePointer (test 7)
+Type = DEFAULT
+EXE1 = setfilepointer
+Description
+=Tests the FILE_END option with the high word parameter
+=This test requires about 4 GB of free disk space.
+
diff --git a/src/pal/tests/palsuite/file_io/SetFileTime/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFileTime/CMakeLists.txt
new file mode 100644
index 0000000000..a3847f8ca9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileTime/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+
diff --git a/src/pal/tests/palsuite/file_io/SetFileTime/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFileTime/test1/CMakeLists.txt
new file mode 100644
index 0000000000..4c4b5d7611
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileTime/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ SetFileTime.c
+)
+
+add_executable(paltest_setfiletime_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setfiletime_test1 coreclrpal)
+
+target_link_libraries(paltest_setfiletime_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/SetFileTime/test1/SetFileTime.c b/src/pal/tests/palsuite/file_io/SetFileTime/test1/SetFileTime.c
new file mode 100644
index 0000000000..4711aeba89
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileTime/test1/SetFileTime.c
@@ -0,0 +1,129 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: SetFileTime.c
+**
+** Purpose: Tests the PAL implementation of the SetFileTime function.
+** This test first sets a valid file time on the file which is opened.
+** Then it calls GetFileTime, and compares the values. They should
+** be the same. Note: Access time isn't checked in this test. It will
+** be dealt with seperatly due to odd behaviour.
+**
+** Depends:
+** CreateFile
+** GetFileTime
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+
+#if WIN32
+ FILETIME Creation;
+ FILETIME SetCreation;
+#endif
+ FILETIME LastWrite;
+ FILETIME SetLastWrite;
+ HANDLE TheFileHandle;
+ BOOL result;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* Populate some FILETIME structures with values
+ These values are valid Creation, Access and Write times
+ which I generated, and should work properly.
+ */
+#if WIN32
+ SetCreation.dwLowDateTime = 458108416;
+ SetCreation.dwHighDateTime = 29436904;
+#endif
+
+ SetLastWrite.dwLowDateTime = -1995099136;
+ SetLastWrite.dwHighDateTime = 29436915;
+
+
+ /* Open the file to get a HANDLE */
+ TheFileHandle = CreateFile("the_file",
+ GENERIC_READ|GENERIC_WRITE,
+ 0,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(TheFileHandle == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Failed to open the file. The error number "
+ "returned was %d.\n",GetLastError());
+ }
+
+ /* Set the new file time */
+#if WIN32
+ result = SetFileTime(TheFileHandle,
+ &SetCreation, NULL, &SetLastWrite);
+#else
+ result = SetFileTime(TheFileHandle,
+ NULL, NULL, &SetLastWrite);
+#endif
+ if(result == 0)
+ {
+ Fail("ERROR: SetFileTime failed when trying to set the "
+ "new file time. The GetLastError was %d.\n",GetLastError());
+ }
+
+
+ /* Then get the file time of the file */
+#if WIN32
+ result = GetFileTime(TheFileHandle, &Creation, NULL, &LastWrite);
+#else
+ result = GetFileTime(TheFileHandle, NULL, NULL, &LastWrite);
+#endif
+
+ if(result == 0)
+ {
+ Fail("ERROR: GetFileTime failed, and this tests depends "
+ "upon it working properly, in order to ensure that the "
+ "file time was set with SetFileTime. GetLastError() "
+ "returned %d.\n",GetLastError());
+ }
+
+ /* Compare the write time we Set to the write time aquired with
+ Get. They should be the same.
+ */
+
+ if(LastWrite.dwLowDateTime != SetLastWrite.dwLowDateTime ||
+ LastWrite.dwHighDateTime != SetLastWrite.dwHighDateTime)
+ {
+ Fail("ERROR: After setting the write time, it is not "
+ "equal to what it was set to. Either Set of GetFileTime are "
+ "broken.\n");
+ }
+
+ /* Within FreeBSD, the Creation time is ignored when SetFileTime
+ is called. Since FreeBSD has no equivalent. For that reason,
+ it is not checked with the following test.
+ */
+
+#if WIN32
+ if(Creation.dwHighDateTime != SetCreation.dwHighDateTime ||
+ Creation.dwLowDateTime != SetCreation.dwLowDateTime)
+ {
+ Fail("ERROR: After setting the file time, the Creation "
+ "time is not what it should be. Either Set or GetFileTime "
+ "are broken.");
+ }
+#endif
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/file_io/SetFileTime/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/SetFileTime/test1/testinfo.dat
new file mode 100644
index 0000000000..09dfa0b623
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileTime/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = SetFileTime
+Name = Positive Test for SetFileTime
+TYPE = DEFAULT
+EXE1 = setfiletime
+Description
+= Test the SetFileTime function.
+= This test calls SetFileTime and sets a file to a given time. It then
+= calls GetFileTime, and compares the values of the two, which should be
+= equal
diff --git a/src/pal/tests/palsuite/file_io/SetFileTime/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFileTime/test2/CMakeLists.txt
new file mode 100644
index 0000000000..35c18c8d8d
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileTime/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ SetFileTime.c
+)
+
+add_executable(paltest_setfiletime_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setfiletime_test2 coreclrpal)
+
+target_link_libraries(paltest_setfiletime_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/SetFileTime/test2/SetFileTime.c b/src/pal/tests/palsuite/file_io/SetFileTime/test2/SetFileTime.c
new file mode 100644
index 0000000000..e950153bb0
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileTime/test2/SetFileTime.c
@@ -0,0 +1,101 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: SetFileTime.c
+**
+** Purpose: Tests the PAL implementation of the SetFileTime
+** This test first tries to SetFileTime on a HANDLE which doesn't have
+** GENERIC_WRITE set, which should fail.
+**
+**
+** Depends:
+** CreateFile
+** CloseHandle
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+
+
+int __cdecl main(int argc, char **argv)
+{
+
+ FILETIME SetCreation,SetLastAccess,SetLastWrite;
+ HANDLE TheFileHandle;
+ BOOL result;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* Populate some FILETIME structures with values
+ These values are valid Creation, Access and Write times
+ which I generated, and should work properly.
+
+ The access times are not seperated into WIN32 and FreeBSD here,
+ but it should be fine, as no comparisons are being done in this
+ test.
+ */
+
+ SetCreation.dwLowDateTime = 458108416;
+ SetCreation.dwHighDateTime = 29436904;
+
+ SetLastAccess.dwLowDateTime = 341368832;
+ SetLastAccess.dwHighDateTime = 29436808;
+
+ SetLastWrite.dwLowDateTime = -1995099136;
+ SetLastWrite.dwHighDateTime = 29436915;
+
+
+/* Open the file to get a HANDLE, without GENERIC WRITE */
+
+ TheFileHandle =
+ CreateFile(
+ "the_file",
+ GENERIC_READ,
+ 0,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+
+ if(TheFileHandle == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Failed to open the file. The error number "
+ "returned was %d.",GetLastError());
+ }
+
+ /* This SetFileTime should fail, because the HANDLE isn't set with
+ GENERIC_WRITE
+ */
+ result = SetFileTime(TheFileHandle,
+ &SetCreation,&SetLastAccess,&SetLastWrite);
+
+ if(result != 0)
+ {
+ Fail("ERROR: SetFileTime should have failed, but returned a "
+ "non-zero result. The File HANDLE passed was no set Writable "
+ "which should cause failure.");
+ }
+
+ result = CloseHandle(TheFileHandle);
+
+ if(result == 0)
+ {
+ Fail("ERROR: CloseHandle failed. This test depends upon "
+ "it working.");
+ }
+
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/SetFileTime/test2/testinfo.dat b/src/pal/tests/palsuite/file_io/SetFileTime/test2/testinfo.dat
new file mode 100644
index 0000000000..f1699facaf
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileTime/test2/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = SetFileTime
+Name = Negative Test for SetFileTime
+TYPE = DEFAULT
+EXE1 = setfiletime
+Description
+= Test the SetFileTime function.
+= This test first tries to SetFileTime on a HANDLE which doesn't have
+= GENERIC_WRITE set, which should fail. Then it attempts to set the file
+= time with bad FILETIME structures, which should also fail
diff --git a/src/pal/tests/palsuite/file_io/SetFileTime/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFileTime/test3/CMakeLists.txt
new file mode 100644
index 0000000000..0a85d30c51
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileTime/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ SetFileTime.c
+)
+
+add_executable(paltest_setfiletime_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setfiletime_test3 coreclrpal)
+
+target_link_libraries(paltest_setfiletime_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/SetFileTime/test3/SetFileTime.c b/src/pal/tests/palsuite/file_io/SetFileTime/test3/SetFileTime.c
new file mode 100644
index 0000000000..97f49495d7
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileTime/test3/SetFileTime.c
@@ -0,0 +1,66 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: SetFileTime.c
+**
+** Purpose: Tests the PAL implementation of the SetFileTime function.
+** This test checks to ensure that the function fails when passed an
+** invalid file HANDLE
+**
+**
+**===================================================================*/
+
+
+
+#include <palsuite.h>
+
+
+
+
+int __cdecl main(int argc, char **argv)
+{
+
+ FILETIME SetCreation, SetLastWrite, SetLastAccess;
+ HANDLE TheFileHandle = NULL;
+ BOOL result;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* Populate some FILETIME structures with values
+ These values are valid Creation, Access and Write times
+ which I generated, and should work properly.
+ */
+
+ SetCreation.dwLowDateTime = 458108416;
+ SetCreation.dwHighDateTime = 29436904;
+
+ SetLastAccess.dwLowDateTime = 341368832;
+ SetLastAccess.dwHighDateTime = 29436808;
+
+ SetLastWrite.dwLowDateTime = -1995099136;
+ SetLastWrite.dwHighDateTime = 29436915;
+
+
+ /* Pass this function an invalid file HANDLE and it should
+ fail.
+ */
+
+ result = SetFileTime(TheFileHandle,
+ &SetCreation,&SetLastAccess,&SetLastWrite);
+
+ if(result != 0)
+ {
+ Fail("ERROR: Passed an invalid file HANDLE to SetFileTime, but it "
+ "returned non-zero. This should return zero for failure.");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/SetFileTime/test3/testinfo.dat b/src/pal/tests/palsuite/file_io/SetFileTime/test3/testinfo.dat
new file mode 100644
index 0000000000..e27280469e
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileTime/test3/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = SetFileTime
+Name = Negative Test for SetFileTime
+TYPE = DEFAULT
+EXE1 = setfiletime
+Description
+= Test the SetFileTime function.
+= This test checks to ensure that the function fails when passed an
+= invalid file HANDLE
diff --git a/src/pal/tests/palsuite/file_io/SetFileTime/test4/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFileTime/test4/CMakeLists.txt
new file mode 100644
index 0000000000..086e35e535
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileTime/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ SetFileTime.c
+)
+
+add_executable(paltest_setfiletime_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setfiletime_test4 coreclrpal)
+
+target_link_libraries(paltest_setfiletime_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/SetFileTime/test4/SetFileTime.c b/src/pal/tests/palsuite/file_io/SetFileTime/test4/SetFileTime.c
new file mode 100644
index 0000000000..3edd2403c4
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileTime/test4/SetFileTime.c
@@ -0,0 +1,108 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: SetFileTime.c
+**
+** Purpose: Tests the PAL implementation of the SetFileTime function
+** This passes a variety of NULL values as parameters to the function.
+** It should still succeed.
+**
+** Depends:
+** CreateFile
+**
+
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+
+int __cdecl main(int argc, char **argv)
+{
+#if WIN32
+ FILETIME Creation;
+#endif
+ FILETIME LastWrite,LastAccess;
+ HANDLE TheFileHandle;
+
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* Populate some FILETIME structures with values
+ These values are valid Creation, Access and Write times
+ which I generated, and should work properly.
+
+ These values aren't being used for comparison, so they should
+ work ok, even though they weren't generated specifically for
+ FreeBSD or WIN32 ...
+ */
+#if WIN32
+ Creation.dwLowDateTime = 458108416;
+ Creation.dwHighDateTime = 29436904;
+#endif
+ LastAccess.dwLowDateTime = 341368832;
+ LastAccess.dwHighDateTime = 29436808;
+
+ LastWrite.dwLowDateTime = -1995099136;
+ LastWrite.dwHighDateTime = 29436915;
+
+ /* Open the file to get a HANDLE */
+ TheFileHandle =
+ CreateFile(
+ "the_file",
+ GENERIC_READ|GENERIC_WRITE,
+ 0,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+
+ if(TheFileHandle == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Failed to open the file. The error number "
+ "returned was %d.",GetLastError());
+ }
+
+ /* Pass all NULLs, this is useless but should still work. */
+ if(SetFileTime(TheFileHandle,NULL,NULL,NULL)==0)
+ {
+ Fail("ERROR: SetFileTime returned 0, indicating failure. "
+ "Three of the params were NULL in this case, did they "
+ "cause the problem?");
+ }
+
+#if WIN32
+ /* Set the Creation time of the File */
+ if(SetFileTime(TheFileHandle,&Creation,NULL,NULL)==0)
+ {
+ Fail("ERROR: SetFileTime returned 0, indicating failure. "
+ "Two of the params were NULL in this case, did they "
+ "cause the problem?");
+ }
+#endif
+
+#if WIN32
+ /* Set the Creation, LastWrite time of the File */
+ if(SetFileTime(TheFileHandle,&Creation,&LastWrite,NULL)==0)
+#else
+ /* Set the LastWrite time of the File */
+ if(SetFileTime(TheFileHandle,NULL,&LastWrite,NULL)==0)
+#endif
+ {
+ Fail("ERROR: SetFileTime returned 0, indicating failure. "
+ "One of the params were NULL in this case, did it "
+ "cause the problem?");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/SetFileTime/test4/testinfo.dat b/src/pal/tests/palsuite/file_io/SetFileTime/test4/testinfo.dat
new file mode 100644
index 0000000000..a3dfdd02f0
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/SetFileTime/test4/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = SetFileTime
+Name = Positive Test for SetFileTime
+TYPE = DEFAULT
+EXE1 = setfiletime
+Description
+= Test the SetFileTime function.
+= This passes a variety of NULL values as parameters to the function.
+= It should still succeed
diff --git a/src/pal/tests/palsuite/file_io/WriteFile/CMakeLists.txt b/src/pal/tests/palsuite/file_io/WriteFile/CMakeLists.txt
new file mode 100644
index 0000000000..8083faf655
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/WriteFile/CMakeLists.txt
@@ -0,0 +1,8 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+
diff --git a/src/pal/tests/palsuite/file_io/WriteFile/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/WriteFile/test1/CMakeLists.txt
new file mode 100644
index 0000000000..0c6760a2ce
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/WriteFile/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ WriteFile.c
+)
+
+add_executable(paltest_writefile_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_writefile_test1 coreclrpal)
+
+target_link_libraries(paltest_writefile_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/WriteFile/test1/WriteFile.c b/src/pal/tests/palsuite/file_io/WriteFile/test1/WriteFile.c
new file mode 100644
index 0000000000..1ac38ddaf0
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/WriteFile/test1/WriteFile.c
@@ -0,0 +1,114 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: WriteFile.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the WriteFile function.
+** This test will attempt to write to a NULL handle and a
+** read-only file
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+const char* szStringTest = "The quick fox jumped over the lazy dog's back.";
+const char* szReadOnlyFile = "ReadOnly.txt";
+void do_cleanup()
+{
+ BOOL bRc = FALSE;
+ bRc = DeleteFileA(szReadOnlyFile);
+ if (bRc != TRUE)
+ {
+ Fail ("DeleteFileA: ERROR[%ld]: During Cleanup: Couldn't delete WriteFile's"
+ " \"ReadOnly.txt\"\n", GetLastError());
+ }
+
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE hFile = NULL;
+ DWORD dwBytesWritten;
+ BOOL bRc = FALSE;
+ DWORD last_error;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ //
+ // Write to a NULL handle
+ //
+
+ bRc = WriteFile(hFile, szStringTest, 20, &dwBytesWritten, NULL);
+
+ if (bRc == TRUE)
+ {
+ last_error = GetLastError();
+ Fail("WriteFile: ERROR[%ld] -> Able to write to a NULL handle\n", last_error);
+ }
+
+
+ //
+ // Write to a file with read-only permissions
+ //
+
+ // create a file without write permissions
+ hFile = CreateFile(szReadOnlyFile,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ last_error = GetLastError();
+ Fail("WriteFile: ERROR[%ld] -> Unable to create file \"%s\".\n",
+ last_error, szReadOnlyFile);
+ }
+
+ if (!SetFileAttributes(szReadOnlyFile, FILE_ATTRIBUTE_READONLY))
+ {
+ last_error = GetLastError();
+ Trace("WriteFile: ERROR[%ld] -> Unable to make the file read-only.\n", last_error);
+ do_cleanup();
+ Fail("WriteFile: ERROR[%ld] -> Unable to make the file read-only.\n", last_error);
+ }
+
+ bRc = WriteFile(hFile, szStringTest, 20, &dwBytesWritten, NULL);
+ if (bRc == TRUE)
+ { last_error = GetLastError();
+ Trace("WriteFile: ERROR[%ld] -> Able to write to a read-only file.\n", last_error);
+ do_cleanup();
+ Fail("WriteFile: ERROR[%ld] -> Able to write to a read-only file.\n", last_error);
+ }
+
+
+ bRc = CloseHandle(hFile);
+ if (bRc != TRUE)
+ { last_error = GetLastError();
+ Trace("WriteFile: ERROR[%ld] -> Unable to close file \"%s\".\n", last_error, szReadOnlyFile);
+ do_cleanup();
+ Fail("WriteFile: ERROR -> Unable to close file \"%s\".\n",
+ szReadOnlyFile);
+ }
+
+ //To delete file need to make it normal
+ if(!SetFileAttributesA(szReadOnlyFile,FILE_ATTRIBUTE_NORMAL))
+ {
+ last_error = GetLastError();
+ Fail("WriteFile: ERROR[%ld] -> Unable to make the file attribute NORMAL.\n", last_error);
+
+ }
+ do_cleanup();
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/WriteFile/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/WriteFile/test1/testinfo.dat
new file mode 100644
index 0000000000..148a2678e5
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/WriteFile/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = WriteFile
+Name = test for WriteFile
+Type = DEFAULT
+EXE1 = writefile
+Description
+=Attempt to write to a NULL handle and to a read-only file
+
diff --git a/src/pal/tests/palsuite/file_io/WriteFile/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/WriteFile/test2/CMakeLists.txt
new file mode 100644
index 0000000000..a9b51efa3d
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/WriteFile/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ WriteFile.c
+)
+
+add_executable(paltest_writefile_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_writefile_test2 coreclrpal)
+
+target_link_libraries(paltest_writefile_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/WriteFile/test2/Results.txt b/src/pal/tests/palsuite/file_io/WriteFile/test2/Results.txt
new file mode 100644
index 0000000000..1c4c37885a
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/WriteFile/test2/Results.txt
@@ -0,0 +1 @@
+0011100111 \ No newline at end of file
diff --git a/src/pal/tests/palsuite/file_io/WriteFile/test2/WriteFile.c b/src/pal/tests/palsuite/file_io/WriteFile/test2/WriteFile.c
new file mode 100644
index 0000000000..24c148afb8
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/WriteFile/test2/WriteFile.c
@@ -0,0 +1,109 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: WriteFile.c (test 2)
+**
+** Purpose: Tests the PAL implementation of the WriteFile function.
+** Creates a number of files and writes different amounts of
+** data and verifies the writes.
+**
+**
+**===================================================================*/
+
+
+#include <palsuite.h>
+
+
+char* writeBuffer;
+const char* szWritableFile = "Writeable.txt";
+const char* szResultsFile = "Results.txt";
+#ifdef __sparc__
+const int PAGESIZE = 8192;
+#else // __sparc__
+const int PAGESIZE = 4096;
+#endif // __sparc__
+
+BOOL writeTest(DWORD dwByteCount, DWORD dwBytesWrittenResult, BOOL bResult)
+{
+ HANDLE hFile = NULL;
+ DWORD dwBytesWritten;
+ BOOL bRc = FALSE;
+
+ /* create the test file */
+ DeleteFile(szWritableFile);
+ hFile = CreateFile(szWritableFile, GENERIC_WRITE, FILE_SHARE_WRITE,
+ NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ Trace("WriteFile: ERROR -> Unable to create file \"%s\".\n",
+ szWritableFile);
+ return FALSE;
+ }
+
+ bRc = WriteFile(hFile, writeBuffer, dwByteCount, &dwBytesWritten, NULL);
+ CloseHandle(hFile);
+
+ if ((bRc != bResult) || (dwBytesWrittenResult != dwBytesWritten))
+ {
+ Trace("WriteFile returned BOOL:%d and dwWritten:%d what we do expect is"
+ " BOOL:%d and dwWritten:%d\n", bRc, dwBytesWritten, bResult,
+ dwBytesWrittenResult);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ const char * testString = "The quick fox jumped over the lazy dog's back.";
+ const int testStringLen = strlen(testString);
+
+ DWORD dwByteCount[4] = {-1, 10, testStringLen, 0};
+ DWORD dwByteWritten[4] = {0, 10, testStringLen, 0};
+ BOOL bResults[] = {FALSE, TRUE, TRUE, TRUE};
+
+ const int BUFFER_SIZE = 2 * PAGESIZE;
+ int j;
+ BOOL bRc = FALSE;
+ DWORD oldProt;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* allocate read-write memery for writeBuffer */
+ if (!(writeBuffer = (char*) VirtualAlloc(NULL, BUFFER_SIZE, MEM_COMMIT,
+ PAGE_READWRITE)))
+ {
+ Fail("VirtualAlloc failed: GetLastError returns %d\n", GetLastError());
+ return FAIL;
+ }
+
+ memset((void*) writeBuffer, '.', BUFFER_SIZE);
+ strcpy(writeBuffer, testString);
+
+ /* write protect the second page of writeBuffer */
+ if (!VirtualProtect(&writeBuffer[PAGESIZE], PAGESIZE, PAGE_NOACCESS, &oldProt))
+ {
+ Fail("VirtualProtect failed: GetLastError returns %d\n", GetLastError());
+ return FAIL;
+ }
+
+ for (j = 0; j< 4; j++)
+ {
+ bRc = writeTest(dwByteCount[j], dwByteWritten[j], bResults[j]);
+ if (bRc != TRUE)
+ {
+ Fail("WriteFile: ERROR -> Failed on test[%d]\n", j);
+ }
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/WriteFile/test2/testinfo.dat b/src/pal/tests/palsuite/file_io/WriteFile/test2/testinfo.dat
new file mode 100644
index 0000000000..a09df962f3
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/WriteFile/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = WriteFile
+Name = Positive Test for WriteFile
+Type = DEFAULT
+EXE1 = writefile
+Description
+=Multiple tests of writes of varying sizes with verification
+
diff --git a/src/pal/tests/palsuite/file_io/WriteFile/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/WriteFile/test3/CMakeLists.txt
new file mode 100644
index 0000000000..e16e8a48f6
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/WriteFile/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ WriteFile.c
+)
+
+add_executable(paltest_writefile_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_writefile_test3 coreclrpal)
+
+target_link_libraries(paltest_writefile_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/WriteFile/test3/WriteFile.c b/src/pal/tests/palsuite/file_io/WriteFile/test3/WriteFile.c
new file mode 100644
index 0000000000..751f89ff2c
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/WriteFile/test3/WriteFile.c
@@ -0,0 +1,136 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: WriteFile.c (test 3)
+**
+** Purpose: Tests the PAL implementation of the WriteFile function.
+** Performs multiple writes to a file and verifies the results.
+**
+**
+**===================================================================*/
+
+
+#include <palsuite.h>
+
+
+const char* szStringTest = "The quick fox jumped over the lazy dog's back.\0";
+const char* szWritableFile = "writeable.txt";
+
+
+BOOL validateResults(const char* szString)
+{
+ FILE *pFile = NULL;
+ char szReadString[100];
+ DWORD dwBytesRead;
+ DWORD dwStringLength = strlen(szString);
+
+
+
+ memset(szReadString, 0, 100);
+
+ /* open the file */
+ pFile = fopen(szWritableFile, "r");
+ if (pFile == NULL)
+ {
+ Trace("couldn't open test file\n");
+ return FALSE;
+ }
+
+ dwBytesRead = fread(szReadString, sizeof(char), dwStringLength, pFile);
+ fclose(pFile);
+
+ if(dwBytesRead != dwStringLength)
+ {
+ Trace("dwbyteread != string length\n");
+ return FALSE;
+ }
+
+ if (strcmp(szReadString, szString))
+ {
+ Trace("read = %s string = %s", szReadString, szString);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+
+
+BOOL writeTest(const char* szString)
+{
+ HANDLE hFile = NULL;
+ DWORD dwBytesWritten;
+ BOOL bRc = FALSE;
+ BOOL bAllPassed = TRUE;
+ int nStringLength = 0;
+ char* szPtr = NULL;
+ int i = 0;
+
+ // create the test file
+ hFile = CreateFile(szWritableFile,
+ GENERIC_WRITE,
+ FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ Trace("WriteFile: ERROR -> Unable to create file \"%s\".\n",
+ szWritableFile);
+ return FALSE;
+ }
+
+ nStringLength = strlen(szString);
+ szPtr = (char*) szString;
+
+ for (i = 0; i < nStringLength; i++)
+ {
+ bRc = WriteFile(hFile, szPtr++, 1, &dwBytesWritten, NULL);
+ if ((bRc == FALSE) || (dwBytesWritten != 1))
+ {
+ bAllPassed = FALSE;
+ }
+ }
+ CloseHandle(hFile);
+
+ if (bAllPassed == FALSE)
+ {
+ Trace ("WriteFile: ERROR: Failed to write data.\n");
+ return FALSE;
+ }
+ else
+ {
+ return (validateResults(szString));
+ }
+
+ return TRUE;
+}
+
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ const char *pString = szStringTest;
+ BOOL bRc = FALSE;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+
+ bRc = writeTest(pString);
+ if (bRc != TRUE)
+ {
+ Fail("WriteFile: ERROR -> Failed\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/WriteFile/test3/testinfo.dat b/src/pal/tests/palsuite/file_io/WriteFile/test3/testinfo.dat
new file mode 100644
index 0000000000..e88e985b44
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/WriteFile/test3/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = WriteFile
+Name = Positive Test for WriteFile
+Type = DEFAULT
+EXE1 = writefile
+Description
+=Multiple consecutive writes to a file with verification
+
diff --git a/src/pal/tests/palsuite/file_io/WriteFile/test4/CMakeLists.txt b/src/pal/tests/palsuite/file_io/WriteFile/test4/CMakeLists.txt
new file mode 100644
index 0000000000..fff886b430
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/WriteFile/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ writefile.c
+)
+
+add_executable(paltest_writefile_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_writefile_test4 coreclrpal)
+
+target_link_libraries(paltest_writefile_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/WriteFile/test4/testinfo.dat b/src/pal/tests/palsuite/file_io/WriteFile/test4/testinfo.dat
new file mode 100644
index 0000000000..87ddf9d857
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/WriteFile/test4/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = WriteFile
+Name = Positive Test for WriteFile
+Type = DEFAULT
+EXE1 = writefile
+Description
+= writes to a file at different locations with verification
+
diff --git a/src/pal/tests/palsuite/file_io/WriteFile/test4/writefile.c b/src/pal/tests/palsuite/file_io/WriteFile/test4/writefile.c
new file mode 100644
index 0000000000..47a0066ec9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/WriteFile/test4/writefile.c
@@ -0,0 +1,155 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: WriteFile.c (test 4)
+**
+** Purpose: Tests the PAL implementation of the WriteFile function.
+** Performs multiple writes to a file at different locations
+** then verifies the results with GetFileSize.
+**
+** dependency:
+** CreateFile.
+** GetFileSize.
+** FlushFileBuffers
+** SetFilePointer.
+** CloseHandle.
+** DeleteFile.
+**
+**
+**
+**===================================================================*/
+
+
+#include <palsuite.h>
+
+BOOL CleanUp(HANDLE hFile, const char * fileName)
+{
+ BOOL bRc = TRUE;
+ if (CloseHandle(hFile) != TRUE)
+ {
+ bRc = FALSE;
+ Trace("WriteFile: ERROR -> Unable to close file \"%s\","
+ " error: %ld.\n", fileName, GetLastError());
+ }
+ if (!DeleteFileA(fileName))
+ {
+ bRc = FALSE;
+ Trace("WriteFile: ERROR -> Unable to delete file \"%s\","
+ " error: %ld.\n", fileName, GetLastError());
+ }
+ return bRc;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ const char* szStringTest = "1234567890";
+ const char* szWritableFile = "writeable.txt";
+ HANDLE hFile = NULL;
+ DWORD dwBytesWritten;
+
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* create the test file */
+ hFile = CreateFile(szWritableFile,
+ GENERIC_WRITE,
+ FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("WriteFile: ERROR -> Unable to create file \"%s\".\n",
+ szWritableFile);
+ }
+
+
+ /* test wtriting to the file */
+ if( WriteFile(hFile, /* HANDLE handle to file */
+ szStringTest, /* data buffer */
+ strlen(szStringTest), /* number of bytes to write */
+ &dwBytesWritten, /* number of bytes written */
+ NULL) /* overlapped buffer */
+ ==0)
+ {
+ Trace("WriteFile: ERROR -> Unable to write to file error: %ld \n",
+ GetLastError());
+ CleanUp(hFile,szWritableFile);
+ Fail("");
+ }
+
+ if(!FlushFileBuffers(hFile))
+ { Trace("WriteFile: ERROR -> Call to FlushFile Buffers failed "
+ "error %ld \n",GetLastError());
+ CleanUp(hFile,szWritableFile);
+ Fail("");
+ }
+
+ /* check the file size */
+ if(GetFileSize(hFile, NULL)!=strlen(szStringTest))
+ {
+ Trace("WriteFile: ERROR -> writing %u chars to empty file "
+ "caused its size to become %u\n",strlen(szStringTest),
+ GetFileSize(hFile, NULL));
+ CleanUp(hFile,szWritableFile);
+ Fail("");
+ }
+
+ /* test writing to the file at position 5. */
+ SetFilePointer(
+ hFile, /* handle to file */
+ 0x5, /* bytes to move pointer */
+ NULL, /* bytes to move pointer */
+ FILE_BEGIN /* starting point */
+ );
+
+
+ if( WriteFile(hFile, /* HANDLE handle to file */
+ szStringTest, /* data buffer */
+ strlen(szStringTest), /* number of bytes to write */
+ &dwBytesWritten, /* number of bytes written */
+ NULL) /* overlapped buffer */
+ ==0)
+ {
+ Trace("WriteFile: ERROR -> Unable to write to file after "
+ " moiving the file poiner to 5 error: %ld \n",
+ GetLastError());
+ CleanUp(hFile,szWritableFile);
+ Fail("");
+ }
+
+
+ if(!FlushFileBuffers(hFile))
+ {
+ Trace("WriteFile: ERROR -> Call to FlushFile Buffers failed "
+ "error %ld \n",GetLastError());
+ CleanUp(hFile,szWritableFile);
+ Fail("");
+ }
+
+ /* Check the file size */
+ if(GetFileSize(hFile, NULL)!=(strlen(szStringTest)+5))
+ {
+ Trace("WriteFile: ERROR -> writing %u chars to the file after "
+ "sitting the file pointer to 5 resulted in wrong file size; "
+ "Expected %u resulted %u.",strlen(szStringTest),
+ (strlen(szStringTest)+5),GetFileSize(hFile, NULL));
+ CleanUp(hFile,szWritableFile);
+ Fail("");
+ }
+
+ if (!CleanUp(hFile,szWritableFile))
+ {
+ Fail("");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/WriteFile/test5/CMakeLists.txt b/src/pal/tests/palsuite/file_io/WriteFile/test5/CMakeLists.txt
new file mode 100644
index 0000000000..978eb7f1e7
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/WriteFile/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ writefile.c
+)
+
+add_executable(paltest_writefile_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_writefile_test5 coreclrpal)
+
+target_link_libraries(paltest_writefile_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/WriteFile/test5/testinfo.dat b/src/pal/tests/palsuite/file_io/WriteFile/test5/testinfo.dat
new file mode 100644
index 0000000000..ffde30ea23
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/WriteFile/test5/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = WriteFile
+Name = Positive Test for WriteFile
+Type = DEFAULT
+EXE1 = writefile
+Description
+= write lots of data to a file. then check with
+= GetFileSize
+= This test is disabled due to its time overhead.
+
diff --git a/src/pal/tests/palsuite/file_io/WriteFile/test5/writefile.c b/src/pal/tests/palsuite/file_io/WriteFile/test5/writefile.c
new file mode 100644
index 0000000000..46920b3335
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/WriteFile/test5/writefile.c
@@ -0,0 +1,117 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: WriteFile.c (test 5)
+**
+** Purpose: Tests the PAL implementation of the WriteFile function.
+** Performs writing a huge file.
+**
+** dependency:
+** CreateFile.
+** GetFileSize.
+** FlushFileBuffers
+** CloseHandle
+** DeleteFile
+**
+**
+**===================================================================*/
+
+
+#include <palsuite.h>
+
+BOOL CleanUp(HANDLE hFile, const char * fileName)
+{
+ BOOL bRc = TRUE;
+ if (CloseHandle(hFile) != TRUE)
+ {
+ bRc = FALSE;
+ Trace("WriteFile: ERROR -> Unable to close file \"%s\","
+ " error: %ld.\n", fileName, GetLastError());
+ }
+ if (!DeleteFileA(fileName))
+ {
+ bRc = FALSE;
+ Trace("WriteFile: ERROR -> Unable to delete file \"%s\","
+ " error: %ld.\n", fileName, GetLastError());
+ }
+ return bRc;
+}
+
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ HANDLE hFile = NULL;
+ DWORD dwBytesWritten;
+ const char* hugeStringTest =
+ "1234567890123456789012345678901234567890";
+ const char* szWritableFile = "writeable.txt";
+ int i =0;
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ /* create the test file */
+ hFile = CreateFile(szWritableFile,
+ GENERIC_WRITE,
+ FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("WriteFile: ERROR -> Unable to create file \"%s\".\n",
+ szWritableFile);
+ }
+
+ /* write 4000 000 chars to the file.*/
+ for (i=0; i<100000;i++)
+ {
+ if( WriteFile(hFile, /* HANDLE handle to file */
+ hugeStringTest, /* data buffer */
+ strlen(hugeStringTest), /* number of bytes to write */
+ &dwBytesWritten, /* number of bytes written */
+ NULL) /* overlapped buffer */
+ ==0)
+ {
+ Trace("WriteFile: ERROR -> Unable to write to file error: %ld \n",
+ GetLastError());
+ CleanUp(hFile,szWritableFile);
+ Fail("");
+
+ }
+ }
+
+ if(!FlushFileBuffers(hFile))
+ {
+ Trace("WriteFile: ERROR -> Call to FlushFileBuffers failed"
+ "error %ld \n",GetLastError());
+ CleanUp(hFile,szWritableFile);
+ Fail("");
+ }
+
+ /* test if the size changed properly. */
+ if(GetFileSize(hFile,NULL) != 4000000)
+ {
+ Trace("WriteFile: ERROR -> file size did not change properly"
+ " after writing 4000 000 chars to it ( size= %u )\n",
+ GetFileSize(hFile,NULL));
+ CleanUp(hFile,szWritableFile);
+ Fail("");
+
+ }
+
+ if (!CleanUp(hFile,szWritableFile))
+ {
+ Fail("");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/errorpathnotfound/CMakeLists.txt b/src/pal/tests/palsuite/file_io/errorpathnotfound/CMakeLists.txt
new file mode 100644
index 0000000000..a3847f8ca9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/errorpathnotfound/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+
diff --git a/src/pal/tests/palsuite/file_io/errorpathnotfound/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/errorpathnotfound/test1/CMakeLists.txt
new file mode 100644
index 0000000000..91b7db1f03
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/errorpathnotfound/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_errorpathnotfound_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_errorpathnotfound_test1 coreclrpal)
+
+target_link_libraries(paltest_errorpathnotfound_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/errorpathnotfound/test1/test1.c b/src/pal/tests/palsuite/file_io/errorpathnotfound/test1/test1.c
new file mode 100644
index 0000000000..eaf3db3a30
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/errorpathnotfound/test1/test1.c
@@ -0,0 +1,783 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+
+**
+
+** Source: test1.c
+
+**
+
+** Purpose: Test the return value of GetLastError() after calling
+
+** some file_io functions with an invalid path.
+
+**
+
+** Functions covered by this test are:
+
+** CopyFileA, CopyFileW, CreateFileA,CreateFileW,
+
+** DeleteFileA and DeleteFileW.
+
+**
+**
+
+
+
+**
+
+**===================================================================*/
+
+
+
+#include <palsuite.h>
+
+
+
+int __cdecl main(int argc, char *argv[])
+
+{
+
+
+
+ BOOL testPass = TRUE;
+
+ BOOL bRc = TRUE;
+
+ HANDLE hFile;
+
+
+
+ const char* sBadFilePath = "bad/badPath.tmp";
+
+ const char* sBadFileName = "badName.tmp";
+
+ const char* sDest = "dest.tmp";
+
+ const WCHAR wBadFilePath[] =
+
+ {'w','b','a','d','/','b','a',
+
+ 'd','.','t','m','p','\0'};
+
+ const WCHAR wBadFileName[] =
+
+ {'w','B','a','d','.','t','m','p','\0'};
+
+ const WCHAR wDest[] =
+
+ {'w','d','e','s','t','.','t','m','p','\0'};
+
+
+
+
+
+ if (0 != PAL_Initialize(argc,argv))
+
+ {
+
+ return FAIL;
+
+ }
+
+
+
+ /*...................Test CopyFileW.............................*/
+
+
+
+ /* test with an invalid path */
+
+ bRc = CopyFileW(wBadFilePath,wDest,TRUE);
+
+ if(!bRc)
+
+ {
+
+ if(GetLastError()!= ERROR_PATH_NOT_FOUND)
+
+ {
+
+ Trace("CopyFileW: calling GetLastError() after copying a file"
+
+ " with wrong path returned [%u] while it should return [%u]\n"
+
+ ,GetLastError(), ERROR_PATH_NOT_FOUND);
+
+ testPass = FALSE;
+
+ }
+
+ }
+
+ else
+
+ {
+
+ testPass = FALSE;
+
+ }
+
+
+
+ /* test with invalid file name */
+
+ bRc = CopyFileW(wBadFileName,wDest,TRUE);
+
+ if(!bRc)
+
+ {
+
+ if(GetLastError()!= ERROR_FILE_NOT_FOUND)
+
+ {
+
+ Trace("CopyFileW: calling GetLastError() after copying a file"
+
+ " with wrong name returned [%u] while it should return [%u]\n"
+
+ ,GetLastError(), ERROR_FILE_NOT_FOUND);
+
+ testPass = FALSE;
+
+ }
+
+
+
+ }
+
+ else
+
+ {
+
+ Trace("CopyFileW: managed to copy a file with wrong name\n");
+
+ testPass = FALSE;
+
+ }
+
+
+
+
+
+
+
+ /*..................CopyFileA...................................*/
+
+
+
+ /* test with an invalid path */
+
+ bRc = CopyFileA(sBadFilePath,sDest,TRUE);
+
+ if(! bRc)
+
+ {
+
+ if(GetLastError()!= ERROR_PATH_NOT_FOUND)
+
+ {
+
+ Trace("CopyFileA: calling GetLastError() after copying a file"
+
+ " with wrong path returned [%u] while it should return [%u]\n"
+
+ ,GetLastError(), ERROR_PATH_NOT_FOUND);
+
+ testPass = FALSE;
+
+ }
+
+ }
+
+ else
+
+ {
+
+ Trace("CopyFileA: managed to copy a file with wrong path\n");
+
+ testPass = FALSE;
+
+ }
+
+
+
+ /* test with an invalid file name */
+
+ bRc = CopyFileA(sBadFileName,sDest,TRUE);
+
+ if(! bRc)
+
+ {
+
+ if(GetLastError()!= ERROR_FILE_NOT_FOUND)
+
+ {
+
+ Trace("CopyFileA: calling GetLastError() after copying a file"
+
+ " with wrong name returned [%u] while it should return [%u]\n"
+
+ ,GetLastError(), ERROR_FILE_NOT_FOUND);
+
+ testPass = FALSE;
+
+ }
+
+ }
+
+ else
+
+ {
+
+ Trace("CopyFileA: managed to copy a file with wrong name\n");
+
+ testPass = FALSE;
+
+ }
+
+
+
+
+
+
+
+ /*............. Test CreateFileA..................................*/
+
+
+
+ /* test with an invalid file name */
+
+ hFile = CreateFileA(sBadFileName,
+
+ GENERIC_READ, /* open for reading */
+
+ FILE_SHARE_READ, /* share for reading */
+
+ NULL, /* no security */
+
+ OPEN_EXISTING, /* existing file only */
+
+ FILE_ATTRIBUTE_NORMAL, /* normal file */
+
+ NULL); /* no attr. template */
+
+
+
+ if (hFile == INVALID_HANDLE_VALUE)
+
+ {
+
+ if(GetLastError() != ERROR_FILE_NOT_FOUND)
+
+ {
+
+ Trace("CreateFileA: calling GetLastError() returned [%u] "
+
+ "while it should return [%u] for a bad File Name\n",
+
+ GetLastError(),ERROR_FILE_NOT_FOUND);
+
+ testPass = FALSE;
+
+ }
+
+
+
+ }
+
+ else
+
+ {
+
+ Trace("CreateFileA: managed to create a file with an incorrect "
+
+ "filename\n");
+
+ testPass = FALSE;
+
+
+
+ if(!CloseHandle(hFile))
+
+ {
+
+ Trace("CreateFileA: Call to CloseHandle failed with ErrorCode "
+
+ "[%u]\n", GetLastError());
+
+
+
+ }
+
+ if(!DeleteFile(sBadFileName))
+
+ {
+
+ Trace("CreateFileA: Call to DeleteFile failed with ErrorCode "
+
+ "[%u]\n", GetLastError());
+
+ }
+
+ }
+
+
+
+ /* test with an invalid path */
+
+ hFile = CreateFileA(sBadFilePath,
+
+ GENERIC_READ, /* open for reading */
+
+ FILE_SHARE_READ, /* share for reading */
+
+ NULL, /* no security */
+
+ OPEN_EXISTING, /* existing file only */
+
+ FILE_ATTRIBUTE_NORMAL, /* normal file */
+
+ NULL); /* no attr. template */
+
+
+
+ if (hFile == INVALID_HANDLE_VALUE)
+
+ {
+
+ if(GetLastError() != ERROR_PATH_NOT_FOUND)
+
+ {
+
+ Trace("CreateFileA: calling GetLastError() returned [%u] "
+
+ "while it should return [%u] for a bad file path name\n",
+
+ GetLastError(), ERROR_PATH_NOT_FOUND);
+
+ testPass = FALSE;
+
+ }
+
+
+
+ }
+
+ else
+
+ {
+
+ Trace("CreateFileA: managed to create a file with an incorrect "
+
+ "filename\n");
+
+ testPass = FALSE;
+
+ /*this should not happen*/
+
+ if(!CloseHandle(hFile))
+
+ {
+
+ Trace("CreateFileA: Call to CloseHandle Failed with ErrorCode "
+
+ "[%u]\n", GetLastError());
+
+
+
+ }
+
+ if(!DeleteFile(sBadFilePath))
+
+ {
+
+ Trace("CreateFileA: Call to DeleteFile Failed with ErrorCode "
+
+ "[%u]\n", GetLastError());
+
+ }
+
+ }
+
+
+
+
+
+
+
+
+
+ /*............. Test CreateFileW..................................*/
+
+
+
+ /* test with an invalid file name */
+
+ hFile = CreateFileW(wBadFileName,
+
+ GENERIC_READ, /* open for reading */
+
+ FILE_SHARE_READ, /* share for reading */
+
+ NULL, /* no security */
+
+ OPEN_EXISTING, /* existing file only */
+
+ FILE_ATTRIBUTE_NORMAL, /* normal file */
+
+ NULL); /* no attr. template */
+
+
+
+ if (hFile == INVALID_HANDLE_VALUE)
+
+ {
+
+ if(GetLastError() != ERROR_FILE_NOT_FOUND)
+
+ {
+
+ Trace("CreateFileW: calling GetLastError() returned [%u] "
+
+ "while it should return [%u] for a bad filename\n",
+
+ GetLastError(), ERROR_FILE_NOT_FOUND);
+
+ testPass = FALSE;
+
+ }
+
+
+
+ }
+
+ else
+
+ {
+
+ Trace("CreateFileW: managed to create a file with an incorrect "
+
+ "filename\n");
+
+ testPass = FALSE;
+
+
+
+ if(!CloseHandle(hFile))
+
+ {
+
+ Trace("CreateFileW: Call to CloseHandle Failed with ErrorCode "
+
+ "[%u]\n", GetLastError());
+
+
+
+ }
+
+
+
+ if(!DeleteFileW(wBadFileName))
+
+ {
+
+ Trace("CreateFileW: Call to DeleteFile Failed with ErrorCode "
+
+ "[%u]\n", GetLastError());
+
+ }
+
+ }
+
+
+
+
+
+
+
+ /* test with an invalid path */
+
+ hFile = CreateFileW(wBadFilePath,
+
+ GENERIC_READ, /* open for reading */
+
+ FILE_SHARE_READ, /* share for reading */
+
+ NULL, /* no security */
+
+ OPEN_EXISTING, /* existing file only */
+
+ FILE_ATTRIBUTE_NORMAL, /* normal file */
+
+ NULL); /* no attr. template */
+
+
+
+ if (hFile == INVALID_HANDLE_VALUE)
+
+ {
+
+
+
+ if(GetLastError() != ERROR_PATH_NOT_FOUND)
+
+ {
+
+ Trace("CreateFileW: calling GetLastError() returned [%u] "
+
+ "while it should return [%u] for a bad file path \n",
+
+ GetLastError(), ERROR_FILE_NOT_FOUND);
+
+ testPass = FALSE;
+
+ }
+
+
+
+ }
+
+ else
+
+ {
+
+ Trace("CreateFileW: managed to create a file with an incorrect "
+
+ "filename\n");
+
+ testPass = FALSE;
+
+
+
+ if(!CloseHandle(hFile))
+
+ {
+
+ Trace("CreateFileW: Call to CloseHandle Failed with ErrorCode "
+
+ "[%u]\n", GetLastError());
+
+
+
+ }
+
+ if(!DeleteFileW(wBadFilePath))
+
+ {
+
+ Trace("CreateFileW: Call to DeleteFile Failed with ErrorCode "
+
+ "[%u]\n", GetLastError());
+
+ }
+
+ }
+
+
+
+
+
+
+
+ /* ............. DeleteFileW..................................*/
+
+
+
+ /* test with an invalid path */
+
+ if(DeleteFileW(wBadFilePath))
+
+ {
+
+ Trace("DeleteFileW: Call to DeleteFileW to delete a file"
+
+ " that does not exist succeeded\n");
+
+ testPass = FALSE;
+
+
+
+ }
+
+ else
+
+ {
+
+ if(GetLastError() != ERROR_PATH_NOT_FOUND)
+
+ {
+
+ Trace("DeleteFileW: Call GetLastError()returned "
+
+ "[%u] while it should return ERROR_PATH_NOT_FOUND [%u]\n",
+
+ GetLastError(),ERROR_FILE_NOT_FOUND);
+
+ testPass = FALSE;
+
+
+
+ }
+
+
+
+ }
+
+
+
+ /* test with an invalid file name */
+
+ if(DeleteFileW(wBadFileName))
+
+ {
+
+ Trace("DeleteFileW: Call to DeleteFileW to delete a file"
+
+ " that does not exist succeeded\n");
+
+ testPass = FALSE;
+
+
+
+ }
+
+ else
+
+ {
+
+ if(GetLastError() != ERROR_FILE_NOT_FOUND)
+
+ {
+
+ Trace("DeleteFileW: Call GetLastError()returned [%u]"
+
+ " while it should return ERROR_FILE_NOT_FOUND [%u]\n",
+
+ GetLastError(),ERROR_FILE_NOT_FOUND);
+
+ testPass = FALSE;
+
+
+
+ }
+
+
+
+ }
+
+
+
+
+
+ /* ............. DeleteFileA..................................*/
+
+
+
+ /* test with an invalid path */
+
+ if(DeleteFileA(sBadFilePath))
+
+ {
+
+ Trace("DeleteFileA: Call to DeleteFileA to delete a file"
+
+ " that does not exist succeeded\n");
+
+ testPass = FALSE;
+
+
+
+ }
+
+ else
+
+ {
+
+ if(GetLastError() != ERROR_PATH_NOT_FOUND)
+
+ {
+
+ Trace("DeleteFileA: Call GetLastError() returned [%u]"
+
+ " while it should return ERROR_PATH_NOT_FOUND [%u]\n",
+
+ GetLastError(),ERROR_FILE_NOT_FOUND);
+
+ testPass = FALSE;
+
+
+
+ }
+
+
+
+ }
+
+
+
+ /* test with an invalid file name */
+
+ if(DeleteFileA(sBadFileName))
+
+ {
+
+ Trace("DeleteFileA: Call to DeleteFileA to delete a file"
+
+ " that does not exist succeeded\n");
+
+ testPass = FALSE;
+
+
+
+ }
+
+ else
+
+ {
+
+ if(GetLastError() != ERROR_FILE_NOT_FOUND)
+
+ {
+
+ Trace("DeleteFileA: Call GetLastError() returned [%u]"
+
+ " while it should return ERROR_FILE_NOT_FOUND [%u]\n",
+
+ GetLastError(),ERROR_FILE_NOT_FOUND);
+
+ testPass = FALSE;
+
+
+
+ }
+
+
+
+ }
+
+
+
+
+
+
+
+ if(! testPass)
+
+ {
+
+ Fail("");
+
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+
+}
+
+
+
diff --git a/src/pal/tests/palsuite/file_io/errorpathnotfound/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/errorpathnotfound/test1/testinfo.dat
new file mode 100644
index 0000000000..dc1ddc96f1
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/errorpathnotfound/test1/testinfo.dat
@@ -0,0 +1,31 @@
+# Licensed to the .NET Foundation under one or more agreements.
+
+# The .NET Foundation licenses this file to you under the MIT license.
+
+# See the LICENSE file in the project root for more information.
+
+
+
+
+Version = 1.0
+
+Section = file_io
+
+Function = some File_io functions
+
+Name = errorpathnotfound - checking GetLastError.
+
+Type = DEFAULT
+
+EXE1 = test1
+
+Description
+
+= Test the return value of GetLastError() after calling
+
+= some file_io functions with an invalid path.
+
+= Functions covered by this test are:
+
+= CopyFile, CreateFile and DeleteFile.
+
diff --git a/src/pal/tests/palsuite/file_io/errorpathnotfound/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/errorpathnotfound/test2/CMakeLists.txt
new file mode 100644
index 0000000000..7d525c21d5
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/errorpathnotfound/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_errorpathnotfound_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_errorpathnotfound_test2 coreclrpal)
+
+target_link_libraries(paltest_errorpathnotfound_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/errorpathnotfound/test2/test2.c b/src/pal/tests/palsuite/file_io/errorpathnotfound/test2/test2.c
new file mode 100644
index 0000000000..5c2ab86b99
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/errorpathnotfound/test2/test2.c
@@ -0,0 +1,785 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+
+**
+
+** Source: test2.c
+
+**
+
+** Purpose: Test the return value of GetLastError() after calling
+
+** some file_io functions with an invalid path.
+
+**
+
+** Functions covered by this test are:
+
+** MoveFileW, FindFirstFileA, FindFirstFileW,
+
+** GetFileAttributesA, GetFileAttributesW,
+
+** SetFileAttributesA, SetFileAttributesW.
+
+**
+**
+
+**
+
+
+
+**
+
+**===================================================================*/
+
+
+
+#include <palsuite.h>
+
+
+
+int __cdecl main(int argc, char *argv[])
+
+{
+
+
+
+ BOOL testPass = TRUE;
+
+ BOOL bRc = TRUE;
+
+ HANDLE hFile;
+
+ WIN32_FIND_DATA findFileData;
+
+ WIN32_FIND_DATAW wFindFileData;
+
+ DWORD fileAttrib;
+
+
+
+ const char* sBadFilePath = "bad/badPath.tmp";
+
+ const char* sBadFileName = "badName.tmp";
+
+
+
+ const WCHAR wBadFilePath[] =
+
+ {'w','b','a','d','/','b','a',
+
+ 'd','.','t','m','p','\0'};
+
+ const WCHAR wBadFileName[] =
+
+ {'w','B','a','d','.','t','m','p','\0'};
+
+ const WCHAR wDest[] =
+
+ {'w','d','e','s','t','.','t','m','p','\0'};
+
+
+
+
+
+ if (0 != PAL_Initialize(argc,argv))
+
+ {
+
+ return FAIL;
+
+ }
+
+
+
+ /*...................Test MoveFileW.............................*/
+
+
+
+ /* test with an invalid path */
+
+ bRc = MoveFileW(wBadFilePath,wDest);
+
+ if(!bRc)
+
+ {
+
+ if(GetLastError()!= ERROR_PATH_NOT_FOUND)
+
+ {
+
+ Trace("MoveFileW: calling GetLastError() after moving a file"
+
+ " with wrong path returned [%u] while it should return [%u]\n"
+
+ ,GetLastError(), ERROR_PATH_NOT_FOUND);
+
+ testPass = FALSE;
+
+ }
+
+ }
+
+ else
+
+ {
+
+ testPass = FALSE;
+
+ }
+
+
+
+ /* test with invalid file name */
+
+ bRc = MoveFileW(wBadFileName,wDest);
+
+ if(!bRc)
+
+ {
+
+ if(GetLastError()!= ERROR_FILE_NOT_FOUND)
+
+ {
+
+ Trace("MoveFileW: calling GetLastError() after moving a file"
+
+ " with wrong name returned [%u] while it should return [%u]\n"
+
+ ,GetLastError(), ERROR_FILE_NOT_FOUND);
+
+ testPass = FALSE;
+
+ }
+
+ }
+
+ else
+
+ {
+
+ Trace("MoveFileW: managed to move a file with wrong name\n");
+
+ testPass = FALSE;
+
+ }
+
+
+
+ /*............. Test FindFirstFileA..................................*/
+
+
+
+ /* test with an invalid file name */
+
+ hFile = FindFirstFileA(sBadFileName,&findFileData );
+
+
+
+ if (hFile == INVALID_HANDLE_VALUE)
+
+ {
+
+ if(GetLastError() != ERROR_FILE_NOT_FOUND)
+
+ {
+
+ Trace("FindFirstFileA: calling GetLastError() returned [%u] "
+
+ "while it should return [%u] for a bad File Name\n",
+
+ GetLastError(),ERROR_FILE_NOT_FOUND);
+
+ testPass = FALSE;
+
+ }
+
+
+
+ }
+
+ else
+
+ {
+
+ Trace("FindFirstFileA: managed to find a file with an incorrect "
+
+ "filename\n");
+
+ testPass = FALSE;
+
+
+
+ if(!FindClose(hFile))
+
+ {
+
+ Trace("FindFirstFileA: Call to FindClose failed with ErrorCode"
+
+ " [%u]\n", GetLastError());
+
+
+
+ }
+
+
+
+ }
+
+
+
+ /* test with an invalid path */
+
+ hFile = FindFirstFileA(sBadFilePath,&findFileData);
+
+
+
+ if (hFile == INVALID_HANDLE_VALUE)
+
+ {
+
+ if(GetLastError() != ERROR_PATH_NOT_FOUND)
+
+ {
+
+ Trace("FindFirstFileA: calling GetLastError() returned [%u] "
+
+ "while it should return [%u] for a bad file path name\n",
+
+ GetLastError(), ERROR_PATH_NOT_FOUND);
+
+ testPass = FALSE;
+
+ }
+
+
+
+ }
+
+ else
+
+ {
+
+ Trace("FindFirstFileA: managed to find a file with an incorrect"
+
+ " filename\n");
+
+ testPass = FALSE;
+
+ /*this should not happen*/
+
+ if(!FindClose(hFile))
+
+ {
+
+ Trace("FindFirstFileA: Call to FindClose Failed with ErrorCode"
+
+ " [%u]\n", GetLastError());
+
+
+
+ }
+
+
+
+ }
+
+
+
+
+
+
+
+ /*............. Test FindFirstFileW..................................*/
+
+
+
+ /* test with an invalid file name */
+
+ hFile = FindFirstFileW(wBadFileName,&wFindFileData );
+
+
+
+ if (hFile == INVALID_HANDLE_VALUE)
+
+ {
+
+ if(GetLastError() != ERROR_FILE_NOT_FOUND)
+
+ {
+
+ Trace("FindFirstFileW: calling GetLastError() returned [%u] "
+
+ "while it should return [%u] for a bad File Name\n",
+
+ GetLastError(),ERROR_FILE_NOT_FOUND);
+
+ testPass = FALSE;
+
+ }
+
+
+
+ }
+
+ else
+
+ {
+
+ Trace("FindFirstFileW: managed to find a file with an incorrect "
+
+ "filename\n");
+
+ testPass = FALSE;
+
+
+
+ if(!FindClose(hFile))
+
+ {
+
+ Trace("FindFirstFileW: Call to FindClose failed with ErrorCode"
+
+ " [%u]\n", GetLastError());
+
+
+
+ }
+
+
+
+ }
+
+
+
+ /* test with an invalid path */
+
+ hFile = FindFirstFileW(wBadFilePath,&wFindFileData);
+
+
+
+ if (hFile == INVALID_HANDLE_VALUE)
+
+ {
+
+ if(GetLastError() != ERROR_PATH_NOT_FOUND)
+
+ {
+
+ Trace("FindFirstFileW: calling GetLastError() returned [%u] "
+
+ "while it should return [%u] for a bad file path name\n",
+
+ GetLastError(), ERROR_PATH_NOT_FOUND);
+
+ testPass = FALSE;
+
+ }
+
+
+
+ }
+
+ else
+
+ {
+
+ Trace("FindFirstFileW: managed to find a file with an incorrect "
+
+ "filename\n");
+
+ testPass = FALSE;
+
+ /*this should not happen*/
+
+ if(!FindClose(hFile))
+
+ {
+
+ Trace("FindFirstFileW: Call to FindClose Failed with ErrorCode "
+
+ "[%u]\n", GetLastError());
+
+
+
+ }
+
+
+
+ }
+
+
+
+
+
+ /*...................Test GetFileAttributesW.............................*/
+
+
+
+ /* test with an invalid path */
+
+ fileAttrib = GetFileAttributesW(wBadFilePath);
+
+ if(fileAttrib == -1)
+
+ {
+
+ if(GetLastError()!= ERROR_PATH_NOT_FOUND)
+
+ {
+
+ Trace("GetFileAttributesW: calling GetLastError() after getting"
+
+ " the attributes of a file with wrong path returned [%u]"
+
+ " while it should return [%u]\n",
+
+ GetLastError(), ERROR_PATH_NOT_FOUND);
+
+ testPass = FALSE;
+
+ }
+
+ }
+
+ else
+
+ {
+
+ Trace("GetFileAttributesW: managed to get the attrib of a file"
+
+ " with wrong path\n");
+
+ testPass = FALSE;
+
+ }
+
+
+
+ /* test with invalid file name */
+
+ fileAttrib = GetFileAttributesW(wBadFileName);
+
+ if(fileAttrib == -1)
+
+ {
+
+ if(GetLastError()!= ERROR_FILE_NOT_FOUND)
+
+ {
+
+ Trace("GetFileAttributesW: calling GetLastError() after getting"
+
+ " the attributes of a file with wrong name returned [%u] "
+
+ "while it should return [%u]\n"
+
+ ,GetLastError(), ERROR_FILE_NOT_FOUND);
+
+ testPass = FALSE;
+
+ }
+
+ }
+
+ else
+
+ {
+
+ Trace("GetFileAttributesW: managed to get the attrib of a file"
+
+ " with wrong name\n");
+
+ testPass = FALSE;
+
+ }
+
+
+
+ /*...................Test GetFileAttributesA.............................*/
+
+
+
+ /* test with an invalid path */
+
+ fileAttrib = GetFileAttributesA(sBadFilePath);
+
+ if(fileAttrib == -1)
+
+ {
+
+ if(GetLastError()!= ERROR_PATH_NOT_FOUND)
+
+ {
+
+ Trace("GetFileAttributesA: calling GetLastError() after getting"
+
+ " the attributes of a file with wrong path returned [%u] while"
+
+ " it should return [%u]\n",
+
+ GetLastError(), ERROR_PATH_NOT_FOUND);
+
+ testPass = FALSE;
+
+ }
+
+ }
+
+ else
+
+ {
+
+ Trace("GetFileAttributesA: managed to get the attrib of a file"
+
+ " with wrong path\n");
+
+ testPass = FALSE;
+
+ }
+
+
+
+ /* test with invalid file name */
+
+ fileAttrib = GetFileAttributesA(sBadFileName);
+
+ if(fileAttrib == -1)
+
+ {
+
+ if(GetLastError()!= ERROR_FILE_NOT_FOUND)
+
+ {
+
+ Trace("GetFileAttributesA: calling GetLastError() after getting "
+
+ "the attributes of a file with wrong name returned [%u] "
+
+ "while it should return [%u]\n"
+
+ ,GetLastError(), ERROR_FILE_NOT_FOUND);
+
+ testPass = FALSE;
+
+ }
+
+
+
+ }
+
+ else
+
+ {
+
+ Trace("GetFileAttributesA: managed to get the attrib of a file with"
+
+ " wrong name\n");
+
+ testPass = FALSE;
+
+ }
+
+
+
+
+
+
+
+
+
+ /*...................Test SetFileAttributesW.............................*/
+
+
+
+ /* test with an invalid path */
+
+ bRc = SetFileAttributesW(wBadFilePath,FILE_ATTRIBUTE_NORMAL);
+
+ if(!bRc)
+
+ {
+
+ if(GetLastError()!= ERROR_PATH_NOT_FOUND)
+
+ {
+
+ Trace("SetFileAttributesW: calling GetLastError() after setting"
+
+ " the attributes of a file with wrong path returned [%u] "
+
+ "while it should return [%u]\n",
+
+ GetLastError(), ERROR_PATH_NOT_FOUND);
+
+ testPass = FALSE;
+
+ }
+
+ }
+
+ else
+
+ {
+
+ Trace("SetFileAttributesW: managed to get the attrib of a file"
+
+ " with wrong path\n");
+
+ testPass = FALSE;
+
+ }
+
+
+
+ /* test with invalid file name */
+
+ bRc = SetFileAttributesW(wBadFileName,FILE_ATTRIBUTE_NORMAL);
+
+ if(!bRc)
+
+ {
+
+ if(GetLastError()!= ERROR_FILE_NOT_FOUND)
+
+ {
+
+ Trace("SetFileAttributesW: calling GetLastError() after setting"
+
+ " the attributes of a file with wrong name returned [%u]"
+
+ " while it should return [%u]\n",
+
+ GetLastError(), ERROR_FILE_NOT_FOUND);
+
+ testPass = FALSE;
+
+ }
+
+
+
+ }
+
+ else
+
+ {
+
+ Trace("SetFileAttributesW: managed to get the attrib of a file with"
+
+ " wrong name\n");
+
+ testPass = FALSE;
+
+ }
+
+
+
+
+
+ /*...................Test SetFileAttributesA.............................*/
+
+
+
+ /* test with an invalid path */
+
+ bRc = SetFileAttributesA(sBadFilePath,FILE_ATTRIBUTE_NORMAL);
+
+ if(!bRc)
+
+ {
+
+ if(GetLastError()!= ERROR_PATH_NOT_FOUND)
+
+ {
+
+ Trace("SetFileAttributesA: calling GetLastError() after setting "
+
+ "the attributes of a file with wrong path returned [%u] "
+
+ "while it should return [%u]\n"
+
+ ,GetLastError(), ERROR_PATH_NOT_FOUND);
+
+ testPass = FALSE;
+
+ }
+
+ }
+
+ else
+
+ {
+
+ Trace("SetFileAttributesA: managed to get the attrib of a file "
+
+ "with wrong path\n");
+
+ testPass = FALSE;
+
+ }
+
+
+
+ /* test with invalid file name */
+
+ bRc = SetFileAttributesA(sBadFileName,FILE_ATTRIBUTE_NORMAL);
+
+ if(!bRc)
+
+ {
+
+ if(GetLastError()!= ERROR_FILE_NOT_FOUND)
+
+ {
+
+ Trace("SetFileAttributesA: calling GetLastError() after setting"
+
+ " the attributes of a file with wrong name returned [%u]"
+
+ " while it should return [%u]\n",
+
+ GetLastError(), ERROR_FILE_NOT_FOUND);
+
+ testPass = FALSE;
+
+ }
+
+
+
+ }
+
+ else
+
+ {
+
+ Trace("SetFileAttributesA: managed to get the attrib of a file with "
+
+ "wrong name\n");
+
+ testPass = FALSE;
+
+ }
+
+
+
+
+
+ if(! testPass)
+
+ {
+
+ Fail("");
+
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+
+}
+
+
+
diff --git a/src/pal/tests/palsuite/file_io/errorpathnotfound/test2/testinfo.dat b/src/pal/tests/palsuite/file_io/errorpathnotfound/test2/testinfo.dat
new file mode 100644
index 0000000000..c5a61b949a
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/errorpathnotfound/test2/testinfo.dat
@@ -0,0 +1,34 @@
+# Licensed to the .NET Foundation under one or more agreements.
+
+# The .NET Foundation licenses this file to you under the MIT license.
+
+# See the LICENSE file in the project root for more information.
+
+
+
+Version = 1.0
+
+Section = file_io
+
+Function = some File_io functions
+
+Name = errorpathnotfound - checking GetLastError.
+
+Type = DEFAULT
+
+EXE1 = test2
+
+Description
+
+= Test the return value of GetLastError() after calling
+
+= some file_io functions with an invalid path.
+
+= Functions covered by this test are:
+
+= MoveFileW, FindFirstFileA, FindFirstFileW,
+
+= GetFileAttributesA, GetFileAttributesW,
+
+= SetFileAttributesA, SetFileAttributesW.
+
diff --git a/src/pal/tests/palsuite/file_io/errorpathnotfound/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/errorpathnotfound/test3/CMakeLists.txt
new file mode 100644
index 0000000000..c7434f3dba
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/errorpathnotfound/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_errorpathnotfound_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_errorpathnotfound_test3 coreclrpal)
+
+target_link_libraries(paltest_errorpathnotfound_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/errorpathnotfound/test3/test3.c b/src/pal/tests/palsuite/file_io/errorpathnotfound/test3/test3.c
new file mode 100644
index 0000000000..414cbab176
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/errorpathnotfound/test3/test3.c
@@ -0,0 +1,244 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+
+**
+
+** Source: test3.c
+
+**
+
+** Purpose: Test the return value of GetLastError() after calling
+
+** some file_io functions with an invalid path.
+
+**
+
+** Functions covered by this test are:
+
+** CreateDirectoryA, CreateDirectoryW, RemoveDirectoryW,
+
+**
+**
+
+
+
+**
+
+**===================================================================*/
+
+
+
+#include <palsuite.h>
+
+
+
+int __cdecl main(int argc, char *argv[])
+
+{
+
+
+
+ BOOL testPass = TRUE;
+
+ BOOL bRc = TRUE;
+
+ DWORD errCode;
+
+
+
+ const char* sBadSubDirectory = "bad/badDir";
+
+
+
+ /* Needed for RemoveDirectoryW */
+
+ const WCHAR tempName[] = {'b','a','d','/',
+
+ 'b','a','d','D','i','r'};
+
+
+
+ const WCHAR wBadSubDirectory[] =
+
+ {'w','b','a','d','/','b','a',
+
+ 'd','D','i','r','\0'};
+
+
+
+ if (0 != PAL_Initialize(argc,argv))
+
+ {
+
+ return FAIL;
+
+ }
+
+
+
+ /* ---------------------CreateDirectoryA------------------------- */
+
+
+
+
+
+ /* Testing of CreateDirectoryA */
+
+ bRc = CreateDirectoryA(sBadSubDirectory,NULL);
+
+ if(!bRc)
+
+ {
+
+ errCode = GetLastError();
+
+ if(errCode != ERROR_PATH_NOT_FOUND)
+
+ {
+
+ Trace("CreateDirectoryA: calling GetLastError() after creating a "
+
+ "directory with invalid path returned [%u] while it should "
+
+ "return [%u]\n",errCode, ERROR_PATH_NOT_FOUND);
+
+ testPass = FALSE;
+
+ }
+
+ }
+
+ else
+
+ {
+
+ Trace("CreateDirectoryA: Created a directory with an invalid path.\n");
+
+ bRc = RemoveDirectoryW(tempName);
+
+ if(!bRc)
+
+ {
+
+ Trace("Failed to remove %s with error %u.\n",
+
+ sBadSubDirectory,GetLastError());
+
+ }
+
+ testPass = FALSE;
+
+ }
+
+
+
+ /* ---------------------CreateDirectoryW------------------------- */
+
+
+
+ /* Testing of CreateDirectoryW */
+
+ bRc = CreateDirectoryW(wBadSubDirectory,NULL);
+
+ if(!bRc)
+
+ {
+
+ errCode = GetLastError();
+
+ if(errCode != ERROR_PATH_NOT_FOUND)
+
+ {
+
+ Trace("CreateDirectoryW: calling GetLastError() after creating a "
+
+ "directory with invalid path returned [%u] while it should "
+
+ "return [%u]\n",errCode, ERROR_PATH_NOT_FOUND);
+
+ testPass = FALSE;
+
+ }
+
+ }
+
+ else
+
+ {
+
+ Trace("CreateDirectoryW: Created a directory with an invalid path.\n");
+
+ bRc = RemoveDirectoryW(wBadSubDirectory);
+
+ if(!bRc)
+
+ {
+
+ Trace("Failed to remove %S with error %u.\n",
+
+ wBadSubDirectory,GetLastError());
+
+ }
+
+ testPass = FALSE;
+
+ }
+
+
+
+ /* ---------------------RemoveDirectoryW------------------------ */
+
+
+
+ /* Testing of RemoveDirectoryW */
+
+ bRc = RemoveDirectoryW(wBadSubDirectory);
+
+ if(!bRc)
+
+ {
+
+ errCode = GetLastError();
+
+ if(errCode != ERROR_PATH_NOT_FOUND)
+
+ {
+
+ Trace("RemoveDirectoryW: calling GetLastError() after removing a "
+
+ "sub directory with invalid path returned [%u] while it should "
+
+ "return [%u]\n",errCode, ERROR_PATH_NOT_FOUND);
+
+ testPass = FALSE;
+
+ }
+
+ }
+
+ else
+
+ {
+
+ Trace("RemoveDirectoryW: Removed a directory that did not exist.\n");
+
+ }
+
+ int exitCode = testPass ? PASS : FAIL;
+ PAL_TerminateEx(exitCode);
+ return exitCode;
+
+
+
+
+
+
+
+
+
+
+}
+
diff --git a/src/pal/tests/palsuite/file_io/errorpathnotfound/test3/testinfo.dat b/src/pal/tests/palsuite/file_io/errorpathnotfound/test3/testinfo.dat
new file mode 100644
index 0000000000..7a9019f17b
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/errorpathnotfound/test3/testinfo.dat
@@ -0,0 +1,30 @@
+# Licensed to the .NET Foundation under one or more agreements.
+
+# The .NET Foundation licenses this file to you under the MIT license.
+
+# See the LICENSE file in the project root for more information.
+
+
+
+Version = 1.0
+
+Section = file_io
+
+Function = some File_io functions
+
+Name = errorpathnotfound - checking GetLastError.
+
+Type = DEFAULT
+
+EXE1 = test3
+
+Description
+
+= Test the return value of GetLastError() after calling
+
+= some file_io functions with an invalid path.
+
+= Functions covered by this test are:
+
+= CreateDirectory, RemoveDirectory
+
diff --git a/src/pal/tests/palsuite/file_io/errorpathnotfound/test4/CMakeLists.txt b/src/pal/tests/palsuite/file_io/errorpathnotfound/test4/CMakeLists.txt
new file mode 100644
index 0000000000..f8062fd127
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/errorpathnotfound/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_errorpathnotfound_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_errorpathnotfound_test4 coreclrpal)
+
+target_link_libraries(paltest_errorpathnotfound_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/errorpathnotfound/test4/test4.c b/src/pal/tests/palsuite/file_io/errorpathnotfound/test4/test4.c
new file mode 100644
index 0000000000..e1b68995b0
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/errorpathnotfound/test4/test4.c
@@ -0,0 +1,351 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+
+**
+
+** Source: test4.c
+
+**
+
+** Purpose: Test the return value of GetLastError() after calling
+
+** some file_io functions with an invalid path.
+
+**
+
+** Functions covered by this test are:
+
+** GetDiskFreeSpaceW, GetTempFileNameA
+
+** and GetTempFileNameW
+
+**
+**
+
+**
+
+
+
+**
+
+**===================================================================*/
+
+
+
+#include <palsuite.h>
+
+
+
+int __cdecl main(int argc, char *argv[])
+
+{
+
+
+
+ BOOL testPass = TRUE;
+
+ BOOL bRc = TRUE;
+
+ DWORD lastErr=-50;
+
+ DWORD dwSectorsPerCluster_02; /* sectors per cluster */
+
+ DWORD dwBytesPerSector_02; /* bytes per sector */
+
+ DWORD dwNumberOfFreeClusters; /* free clusters */
+
+ DWORD dwTotalNumberOfClusters; /* total clusters */
+
+
+
+ UINT uiError = 0;
+
+ char szReturnedName[256];
+
+ const UINT uUnique = 0;
+
+ const char* sDot = {"tmpr"};
+
+ const char* sPrefix = {"cfr"};
+
+
+
+ WCHAR wzReturnedName[256];
+
+ const WCHAR wDot[] = {'t','m','p','r','\0'};
+
+ const WCHAR wPrefix[] = {'c','f','r','\0'};
+
+
+
+
+
+ const WCHAR wBadFilePath[] =
+
+ {'w','b','a','d','/','b','a',
+
+ 'd','.','t','m','p','\0'};
+
+ const WCHAR wBadFileName[] =
+
+ {'w','B','a','d','.','t','m','p','\0'};
+
+
+
+
+
+
+
+ if (0 != PAL_Initialize(argc,argv))
+
+ {
+
+ return FAIL;
+
+ }
+
+
+
+ /* test .................. GetDiskFreeSpaceW .................. */
+
+
+
+ /* test with invalid file name */
+
+ bRc = GetDiskFreeSpaceW(wBadFileName,
+
+ &dwSectorsPerCluster_02,
+
+ &dwBytesPerSector_02,
+
+ &dwNumberOfFreeClusters,
+
+ &dwTotalNumberOfClusters);
+
+ if (bRc != TRUE)
+
+
+
+ {
+
+ lastErr=GetLastError();
+
+
+
+ if(lastErr != ERROR_FILE_NOT_FOUND)
+
+ {
+
+ Trace("GetDiskFreeSpaceW: calling GetLastError() returned [%u] "
+
+ "while it should return [%u] for a bad File Name\n",
+
+ lastErr,ERROR_FILE_NOT_FOUND);
+
+ testPass = FALSE;
+
+ }
+
+ }
+
+ else
+
+ {
+
+ Trace("GetDiskFreeSpaceW: GetDiskFreeSpaceW succeeded when given "
+
+ "a bad fileName\n");
+
+ testPass = FALSE;
+
+
+
+ }
+
+
+
+
+
+ /* test with invalid path name */
+
+ bRc = GetDiskFreeSpaceW(wBadFilePath,
+
+ &dwSectorsPerCluster_02,
+
+ &dwBytesPerSector_02,
+
+ &dwNumberOfFreeClusters,
+
+ &dwTotalNumberOfClusters);
+
+ if (bRc != TRUE)
+
+
+
+ {
+
+ lastErr=GetLastError();
+
+ if(lastErr != ERROR_PATH_NOT_FOUND)
+
+ {
+
+ Trace("GetDiskFreeSpaceW: calling GetLastError() returned [%u] "
+
+ "while it should return [%u] for a bad File Name\n",
+
+ lastErr,ERROR_PATH_NOT_FOUND);
+
+ testPass = FALSE;
+
+ }
+
+ }
+
+ else
+
+ {
+
+ Trace("GetDiskFreeSpaceW: GetDiskFreeSpaceW succeeded when given "
+
+ "a bad fileName\n");
+
+ testPass = FALSE;
+
+
+
+
+
+ }
+
+
+
+
+
+ /* test .................. GetTempFileNameA .................. */
+
+
+
+ /* test with invalid path name */
+
+ uiError = GetTempFileNameA(sDot, sPrefix, uUnique, szReturnedName);
+
+ if (uiError == 0)
+
+ {
+
+ lastErr=GetLastError();
+
+ if(lastErr != ERROR_DIRECTORY)
+
+ {
+
+
+
+ Trace("GetTempFileNameA: calling GetLastError() returned [%u] "
+
+ "while it should return [%u] for invalid path name\n",
+
+ lastErr,ERROR_DIRECTORY);
+
+ testPass = FALSE;
+
+ }
+
+ }
+
+ else
+
+ {
+
+ Trace("GetTempFileNameA: GetTempFileNameA succeeded when given "
+
+ "invalid path name\n");
+
+ testPass = FALSE;
+
+ }
+
+
+
+
+
+
+
+ /* test .................. GetTempFileNameW .................. */
+
+
+
+ /* test with invalid path name */
+
+ uiError = GetTempFileNameW(wDot, wPrefix, uUnique, wzReturnedName);
+
+ if (uiError == 0)
+
+ {
+
+ lastErr=GetLastError();
+
+ if(lastErr != ERROR_DIRECTORY)
+
+ {
+
+
+
+ Trace("GetTempFileNameW: calling GetLastError() returned [%u] "
+
+ "while it should return [%u] for an invalid path name\n",
+
+ lastErr,ERROR_DIRECTORY);
+
+ testPass = FALSE;
+
+ }
+
+ }
+
+ else
+
+ {
+
+ Trace("GetTempFileNameW: GetTempFileNameW succeeded when given"
+
+ " an invalid path name\n");
+
+ testPass = FALSE;
+
+ }
+
+
+
+ if(! testPass)
+
+ {
+
+ Fail("");
+
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PAL_Terminate();
+
+ return PASS;
+
+}
+
+
+
diff --git a/src/pal/tests/palsuite/file_io/errorpathnotfound/test4/testinfo.dat b/src/pal/tests/palsuite/file_io/errorpathnotfound/test4/testinfo.dat
new file mode 100644
index 0000000000..d7b707fca9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/errorpathnotfound/test4/testinfo.dat
@@ -0,0 +1,34 @@
+# Licensed to the .NET Foundation under one or more agreements.
+
+# The .NET Foundation licenses this file to you under the MIT license.
+
+# See the LICENSE file in the project root for more information.
+
+
+
+Version = 1.0
+
+Section = file_io
+
+Function = some File_io functions
+
+Name = errorpathnotfound - checking GetLastError.
+
+Type = DEFAULT
+
+EXE1 = test4
+
+Description
+
+= Test the return value of GetLastError() after calling
+
+= some file_io functions with an invalid path.
+
+= Functions covered by this test are:
+
+= MoveFIlew, FindFirstFileA, FindFirstFileW,
+
+= GetFileAttributesA, GetFileAttributesW,
+
+= SetFileAttributesA, SetFileAttributesW.
+
diff --git a/src/pal/tests/palsuite/file_io/gettemppatha/CMakeLists.txt b/src/pal/tests/palsuite/file_io/gettemppatha/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/gettemppatha/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/file_io/gettemppatha/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/gettemppatha/test1/CMakeLists.txt
new file mode 100644
index 0000000000..2aff599e74
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/gettemppatha/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ gettemppatha.c
+)
+
+add_executable(paltest_gettemppatha_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_gettemppatha_test1 coreclrpal)
+
+target_link_libraries(paltest_gettemppatha_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/file_io/gettemppatha/test1/gettemppatha.c b/src/pal/tests/palsuite/file_io/gettemppatha/test1/gettemppatha.c
new file mode 100644
index 0000000000..b0da528af8
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/gettemppatha/test1/gettemppatha.c
@@ -0,0 +1,103 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: gettemppatha.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the GetTempPathA function.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+static void SetTmpDir(CHAR path[])
+{
+ DWORD result = SetEnvironmentVariableA("TMPDIR", path);
+ if (!result)
+ {
+ Fail("ERROR -> SetEnvironmentVariableA failed with result %d and error code %d.\n",
+ result, GetLastError());
+ }
+}
+
+static void SetAndCompare(CHAR tmpDirPath[], CHAR expected[])
+{
+ DWORD dwBufferLength = _MAX_DIR;
+ CHAR path[dwBufferLength];
+
+ SetTmpDir(tmpDirPath);
+
+ DWORD dwResultLen = GetTempPathA(dwBufferLength, path);
+ if (dwResultLen <= 0)
+ {
+ Fail("ERROR: GetTempPathA returned %d with error code %d.\n", dwResultLen, GetLastError());
+ }
+ if (dwResultLen >= dwBufferLength)
+ {
+ Fail("ERROR: Buffer of length %d passed to GetTempPathA was too small to hold %d chars..\n", dwBufferLength, dwResultLen);
+ }
+ if (strcmp(expected, path) != 0)
+ {
+ Fail("ERROR: GetTempPathA expected to get '%s' but instead got '%s'.\n", expected, path);
+ }
+ if (expected[dwResultLen - 1] != '/')
+ {
+ Fail("ERROR: GetTempPathA returned '%s', which should have ended in '/'.\n", path);
+ }
+}
+
+static void SetAndCheckLength(CHAR tmpDirPath[], int bufferLength, int expectedResultLength)
+{
+ CHAR path[bufferLength];
+
+ SetTmpDir(tmpDirPath);
+ DWORD dwResultLen = GetTempPathA(bufferLength, path);
+
+ if (dwResultLen != expectedResultLength)
+ {
+ Fail("GetTempPathA(%d, %s) expected to return %d but returned %d.\n",
+ bufferLength, tmpDirPath?tmpDirPath:"NULL", expectedResultLength, dwResultLen);
+ }
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (0 != PAL_Initialize(argc,argv))
+ {
+ return FAIL;
+ }
+
+ SetAndCompare("/tmp", "/tmp/");
+ SetAndCompare("/tmp/", "/tmp/");
+ SetAndCompare("", "/tmp/");
+ SetAndCompare(NULL, "/tmp/");
+ SetAndCompare("/", "/");
+ SetAndCompare("/var/tmp", "/var/tmp/");
+ SetAndCompare("/var/tmp/", "/var/tmp/");
+ SetAndCompare("~", "~/");
+ SetAndCompare("~/", "~/");
+ SetAndCompare(".tmp", ".tmp/");
+ SetAndCompare("./tmp", "./tmp/");
+ SetAndCompare("/home/someuser/sometempdir", "/home/someuser/sometempdir/");
+ SetAndCompare(NULL, "/tmp/");
+
+ DWORD dwResultLen = GetTempPathA(0, NULL);
+ if (dwResultLen != 0 || GetLastError() != ERROR_INVALID_PARAMETER)
+ {
+ Fail("GetTempPath(NULL, ...) returned %d with error code %d but "
+ "should have failed with ERROR_INVALID_PARAMETER (%d).\n",
+ dwResultLen, GetLastError(), ERROR_INVALID_PARAMETER);
+ }
+
+ SetAndCheckLength("abc/", 5, 4);
+ SetAndCheckLength("abcd", 5, 6);
+ SetAndCheckLength("abcde", 5, 7);
+ SetAndCheckLength("abcdef/", 5, 9);
+ SetAndCheckLength(NULL, 5, 6);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/file_io/gettemppatha/test1/testinfo.dat b/src/pal/tests/palsuite/file_io/gettemppatha/test1/testinfo.dat
new file mode 100644
index 0000000000..71f8bef651
--- /dev/null
+++ b/src/pal/tests/palsuite/file_io/gettemppatha/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = GetTempPathA
+Name = Test for GetTempPathA (test 1)
+Type = DEFAULT
+EXE1 = gettemppatha
+Description
+= Calls GetTempPathA and verifies by passing the returned
+= value to CreateDirectoryA. If the returned path exists,
+= CreateDirectoryA will fail.
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CMakeLists.txt
new file mode 100644
index 0000000000..3fc399fe59
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CMakeLists.txt
@@ -0,0 +1,28 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(CreateFileMappingA)
+add_subdirectory(CreateFileMappingW)
+add_subdirectory(FreeLibrary)
+add_subdirectory(FreeLibraryAndExitThread)
+add_subdirectory(GetModuleFileNameA)
+add_subdirectory(GetModuleFileNameW)
+add_subdirectory(GetProcAddress)
+add_subdirectory(GetProcessHeap)
+add_subdirectory(HeapAlloc)
+add_subdirectory(HeapFree)
+add_subdirectory(HeapReAlloc)
+add_subdirectory(LocalAlloc)
+add_subdirectory(LocalFree)
+add_subdirectory(LockFile)
+add_subdirectory(MapViewOfFile)
+add_subdirectory(OpenFileMappingA)
+add_subdirectory(OpenFileMappingW)
+add_subdirectory(ReadProcessMemory)
+add_subdirectory(RtlMoveMemory)
+add_subdirectory(UnlockFile)
+add_subdirectory(UnmapViewOfFile)
+add_subdirectory(VirtualAlloc)
+add_subdirectory(VirtualFree)
+add_subdirectory(VirtualProtect)
+add_subdirectory(VirtualQuery)
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/CMakeLists.txt
new file mode 100644
index 0000000000..0223c4d9b5
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/CMakeLists.txt
@@ -0,0 +1,11 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+add_subdirectory(test7)
+add_subdirectory(test8)
+add_subdirectory(test9)
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/CMakeLists.txt
new file mode 100644
index 0000000000..36084bf446
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ CreateFileMapping.c
+)
+
+add_executable(paltest_createfilemappinga_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createfilemappinga_test1 coreclrpal)
+
+target_link_libraries(paltest_createfilemappinga_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/CreateFileMapping.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/CreateFileMapping.c
new file mode 100644
index 0000000000..91640bfd04
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/CreateFileMapping.c
@@ -0,0 +1,173 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: createfilemapping.c (test 1)
+**
+** Purpose: Positive test the CreateFileMapping API.
+** Call CreateFileMapping with access PAGE_READONLY.
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+const int MAPPINGSIZE = 2048;
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ HANDLE hFile;
+ char buf[] = "this is a test string";
+ char ch[2048];
+ char lpFileName[] = "test.tmp";
+ DWORD dwBytesWritten;
+ BOOL err;
+ int RetVal = PASS;
+
+ HANDLE hFileMapping;
+ LPVOID lpMapViewAddress;
+
+ /* Initialize the PAL environment.
+ */
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Create a file handle with CreateFile.
+ */
+ hFile = CreateFile( lpFileName,
+ GENERIC_WRITE|GENERIC_READ,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: %u :unable to create file \"%s\".\n",
+ GetLastError(),
+ lpFileName);
+ }
+
+ /* Initialize the buffers.
+ */
+ memset(ch, 0, MAPPINGSIZE);
+
+ /* Write to the File handle.
+ */
+ err = WriteFile(hFile,
+ buf,
+ strlen(buf),
+ &dwBytesWritten,
+ NULL);
+
+ if (err == FALSE)
+ {
+ Trace("ERROR: %u :unable to write to file handle "
+ "hFile=0x%lx\n",
+ GetLastError(),
+ hFile);
+ RetVal = FAIL;
+ goto CleanUpOne;
+ }
+
+ /* Flush to the hard-drive.
+ */
+ FlushFileBuffers(hFile);
+
+ /* Create a unnamed file-mapping object with file handle FileHandle
+ * and with PAGE_READWRITE protection.
+ */
+ hFileMapping = CreateFileMapping(
+ hFile,
+ NULL, /*not inherited*/
+ PAGE_READONLY, /*read and wite*/
+ 0, /*high-order size*/
+ 0, /*low-order size*/
+ NULL); /*unnamed object*/
+
+ if(NULL == hFileMapping)
+ {
+ Trace("ERROR:%u: Failed to create File Mapping.\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpOne;
+ }
+
+ /* maps a view of a file into the address space of the calling process.
+ */
+ lpMapViewAddress = MapViewOfFile(
+ hFileMapping,
+ FILE_MAP_READ, /* access code */
+ 0, /*high order offset*/
+ 0, /*low order offset*/
+ 0); /* number of bytes for map */
+
+ if(NULL == lpMapViewAddress)
+ {
+ Trace("ERROR:%u: Failed to call MapViewOfFile "
+ "API to map a view of file!\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpTwo;
+ }
+
+ /* Copy the MapViewOfFile to buffer, so we can
+ * compare with value read from file directly.
+ */
+ memcpy(ch, (LPCSTR)lpMapViewAddress, MAPPINGSIZE);
+ if (memcmp(ch, buf, strlen(buf))!= 0)
+ {
+ Trace("ERROR: MapViewOfFile not equal to file contents "
+ "retrieved \"%s\", expected \"%s\".\n",
+ ch, buf);
+ RetVal = FAIL;
+ goto CleanUpThree;
+ }
+
+CleanUpThree:
+
+ /* Unmap the view of file.
+ */
+ if ( UnmapViewOfFile(lpMapViewAddress) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n",
+ GetLastError(),
+ lpMapViewAddress);
+ RetVal = FAIL;
+ }
+
+CleanUpTwo:
+
+ /* Close Handle to opend file mapping.
+ */
+ if ( CloseHandle(hFileMapping) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ hFileMapping);
+ RetVal = FAIL;
+ }
+
+CleanUpOne:
+
+ /* Close Handle to create file mapping.
+ */
+ if ( CloseHandle(hFile) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ hFile);
+ RetVal = FAIL;
+ }
+
+ /* Terminate the PAL.
+ */
+ PAL_TerminateEx(RetVal);
+ return RetVal;
+}
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/testinfo.dat
new file mode 100644
index 0000000000..36ff3238c7
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = CreateFileMapping
+Name = CreateFileMappingA with PAGE_READONLY
+TYPE = DEFAULT
+EXE1 = createfilemapping
+Description
+=Test the CreateFileMapping to create a named file-mapping object
+=and with PAGE_READONLY protection
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/CMakeLists.txt
new file mode 100644
index 0000000000..374f8f0946
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ CreateFileMapping.c
+)
+
+add_executable(paltest_createfilemappinga_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createfilemappinga_test3 coreclrpal)
+
+target_link_libraries(paltest_createfilemappinga_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/CreateFileMapping.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/CreateFileMapping.c
new file mode 100644
index 0000000000..2a849d86b8
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/CreateFileMapping.c
@@ -0,0 +1,155 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: createfilemapping.c (test 3)
+**
+** Purpose: Positive test the CreateFileMapping API.
+** Call CreateFileMapping with access PAGE_READWRITE.
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+const int MAPPINGSIZE = 2048;
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ HANDLE hFile;
+ char buf[] = "this is a test string";
+ char ch[2048];
+ char lpFileName[] = "test.tmp";
+ HANDLE hFileMapping;
+ LPVOID lpMapViewAddress;
+ int RetVal = PASS;
+
+ /* Initialize the PAL environment.
+ */
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Create a file handle with CreateFile.
+ */
+ hFile = CreateFile( lpFileName,
+ GENERIC_WRITE|GENERIC_READ,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: %u :unable to create file \"%s\".\n",
+ GetLastError(),
+ lpFileName);
+ }
+
+ /* Initialize the buffers.
+ */
+ memset(ch, 0, MAPPINGSIZE);
+
+ /* Create a unnamed file-mapping object with file handle FileHandle
+ * and with PAGE_READWRITE protection.
+ */
+ hFileMapping = CreateFileMapping(
+ hFile,
+ NULL, /*not inherited*/
+ PAGE_READWRITE, /*read and wite*/
+ 0, /*high-order size*/
+ MAPPINGSIZE, /*low-order size*/
+ NULL); /*unnamed object*/
+
+ if(NULL == hFileMapping)
+ {
+ Trace("ERROR:%u: Failed to create File Mapping.\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpOne;
+ }
+
+ /* maps a view of a file into the address space of the calling process.
+ */
+ lpMapViewAddress = MapViewOfFile(
+ hFileMapping,
+ FILE_MAP_ALL_ACCESS, /* access code */
+ 0, /*high order offset*/
+ 0, /*low order offset*/
+ MAPPINGSIZE); /* number of bytes for map */
+
+ if(NULL == lpMapViewAddress)
+ {
+ Trace("ERROR:%u: Failed to call MapViewOfFile "
+ "API to map a view of file!\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpTwo;
+ }
+
+ /* Write to the Map view.
+ */
+ memcpy(lpMapViewAddress, buf, strlen(buf));
+
+ /* Read from the Map view.
+ */
+ memcpy(ch, (LPCSTR)lpMapViewAddress, MAPPINGSIZE);
+
+ /* Copy the MapViewOfFile to buffer, so we can
+ * compare with value read from file directly.
+ */
+ if (memcmp(ch, buf, strlen(buf))!= 0)
+ {
+ Trace("ERROR: MapViewOfFile not equal to file contents "
+ "retrieved \"%s\", expected \"%s\".\n",
+ ch, buf);
+ RetVal = FAIL;
+ goto CleanUpThree;
+ }
+
+CleanUpThree:
+
+ /* Unmap the view of file.
+ */
+ if ( UnmapViewOfFile(lpMapViewAddress) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n",
+ GetLastError(),
+ lpMapViewAddress);
+ RetVal = FAIL;
+ }
+
+CleanUpTwo:
+
+ /* Close Handle to opend file mapping.
+ */
+ if ( CloseHandle(hFileMapping) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ hFileMapping);
+ RetVal = FAIL;
+ }
+
+CleanUpOne:
+
+ /* Close Handle to create file mapping.
+ */
+ if ( CloseHandle(hFile) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ hFile);
+ RetVal = FAIL;
+ }
+
+ /* Terminate the PAL.
+ */
+ PAL_TerminateEx(RetVal);
+ return RetVal;
+}
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/testinfo.dat
new file mode 100644
index 0000000000..4689ee6a08
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = CreateFileMapping
+Name = CreateFileMappingA with PAGE_READWRITE
+TYPE = DEFAULT
+EXE1 = createfilemapping
+Description
+=Test the CreateFileMapping to create a unnamed file-mapping object
+=and with PAGE_READWRITE protection
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/CMakeLists.txt
new file mode 100644
index 0000000000..665b10a3f0
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ CreateFileMapping.c
+)
+
+add_executable(paltest_createfilemappinga_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createfilemappinga_test4 coreclrpal)
+
+target_link_libraries(paltest_createfilemappinga_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/CreateFileMapping.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/CreateFileMapping.c
new file mode 100644
index 0000000000..64caa88ca0
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/CreateFileMapping.c
@@ -0,0 +1,181 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: createfilemapping.c (test 4)
+**
+** Purpose: Positive test the CreateFileMapping API.
+** Call CreateFileMapping with access PAGE_WRITECOPY.
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+const int MAPPINGSIZE = 2048;
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ HANDLE hFile;
+ char buf[] = "this is a test string";
+ char ch[2048];
+ char lpFileName[] = "test.tmp";
+ HANDLE hFileMapping;
+ LPVOID lpMapViewAddress;
+ int RetVal = PASS;
+ int err;
+ DWORD dwBytesWritten;
+
+
+ /* Initialize the PAL environment.
+ */
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Create a file handle with CreateFile.
+ */
+ hFile = CreateFile( lpFileName,
+ GENERIC_WRITE|GENERIC_READ,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: %u :unable to create file \"%s\".\n",
+ GetLastError(),
+ lpFileName);
+ }
+
+ /* Write to the File handle.
+ */
+ err = WriteFile(hFile,
+ buf,
+ strlen(buf),
+ &dwBytesWritten,
+ NULL);
+
+ if (err == FALSE)
+ {
+ Trace("ERROR: %u :unable to write to file handle "
+ "hFile=0x%lx\n",
+ GetLastError(),
+ hFile);
+ RetVal = FAIL;
+ goto CleanUpOne;
+ }
+
+ /* Flush to the hard-drive.
+ */
+ FlushFileBuffers(hFile);
+
+ /* Initialize the buffers.
+ */
+ memset(ch, 0, MAPPINGSIZE);
+
+ /* Create a unnamed file-mapping object with file handle FileHandle
+ * and with PAGE_WRITECOPY protection.
+ */
+ hFileMapping = CreateFileMapping(
+ hFile,
+ NULL, /*not inherited*/
+ PAGE_WRITECOPY, /*write copy*/
+ 0, /*high-order size*/
+ 0, /*low-order size*/
+ NULL); /*unnamed object*/
+
+ if(NULL == hFileMapping)
+ {
+ Trace("ERROR:%u: Failed to create File Mapping.\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpOne;
+ }
+
+ /* maps a view of a file into the address space of the calling process.
+ */
+ lpMapViewAddress = MapViewOfFile(
+ hFileMapping,
+ FILE_MAP_COPY, /* access code */
+ 0, /* high order offset*/
+ 0, /* low order offset*/
+ 0); /* number of bytes for map */
+
+ if(NULL == lpMapViewAddress)
+ {
+ Trace("ERROR:%u: Failed to call MapViewOfFile "
+ "API to map a view of file!\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpTwo;
+ }
+
+ /* Write to the Map view.3
+ */
+ memcpy(lpMapViewAddress, buf, strlen(buf));
+
+ /* Read from the Map view.
+ */
+ memcpy(ch, (LPCSTR)lpMapViewAddress, MAPPINGSIZE);
+
+ /* Copy the MapViewOfFile to buffer, so we can
+ * compare with value read from file directly.
+ */
+ if (memcmp(ch, buf, strlen(buf))!= 0)
+ {
+ Trace("ERROR: MapViewOfFile not equal to file contents "
+ "retrieved \"%s\", expected \"%s\".\n",
+ ch, buf);
+ RetVal = FAIL;
+ goto CleanUpThree;
+ }
+
+CleanUpThree:
+
+ /* Unmap the view of file.
+ */
+ if ( UnmapViewOfFile(lpMapViewAddress) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n",
+ GetLastError(),
+ lpMapViewAddress);
+ RetVal = FAIL;
+ }
+
+CleanUpTwo:
+
+ /* Close Handle to opend file mapping.
+ */
+ if ( CloseHandle(hFileMapping) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ hFileMapping);
+ RetVal = FAIL;
+ }
+
+CleanUpOne:
+
+ /* Close Handle to create file mapping.
+ */
+ if ( CloseHandle(hFile) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ hFile);
+ RetVal = FAIL;
+ }
+
+ /* Terminate the PAL.
+ */
+ PAL_TerminateEx(RetVal);
+ return RetVal;
+}
+
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/testinfo.dat
new file mode 100644
index 0000000000..7d9dda1a96
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = CreateFileMapping
+Name = CreateFileMappingA with PAGE_WRITECOPY.
+TYPE = DEFAULT
+EXE1 = createfilemapping
+Description
+= Positive test the CreateFileMapping API.
+= Call CreateFileMapping with access PAGE_WRITECOPY.
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/CMakeLists.txt
new file mode 100644
index 0000000000..6f7f3c3635
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ CreateFileMapping.c
+)
+
+add_executable(paltest_createfilemappinga_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createfilemappinga_test5 coreclrpal)
+
+target_link_libraries(paltest_createfilemappinga_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/CreateFileMapping.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/CreateFileMapping.c
new file mode 100644
index 0000000000..c7f9918b08
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/CreateFileMapping.c
@@ -0,0 +1,193 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: createfilemapping.c (test 5)
+**
+** Purpose: Positive test the CreateFileMapping API.
+** Test CreateFileMapping to a "swap" handle with
+** access PAGE_READONLY.
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+const int MAPPINGSIZE = 2048;
+HANDLE SWAP_HANDLE = ((VOID *)(-1));
+
+int __cdecl main(int argc, char *argv[])
+{
+ char testString[] = "this is a test string";
+ char lpObjectName[] = "myMappingObject";
+ int RetVal = FAIL;
+ char results[2048];
+
+ HANDLE hFileMapRO;
+ HANDLE hFileMapRW;
+ LPVOID lpMapViewRO;
+ LPVOID lpMapViewRW;
+
+ /* Initialize the PAL environment.
+ */
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Initialize the buffers.
+ */
+ memset(results, 0, MAPPINGSIZE);
+
+ /* Create a named file-mapping object with file handle FileHandle
+ * and with PAGE_READWRITE protection.
+ */
+ hFileMapRW = CreateFileMapping(
+ SWAP_HANDLE,
+ NULL, /*not inherited*/
+ PAGE_READWRITE, /*read only*/
+ 0, /*high-order size*/
+ MAPPINGSIZE, /*low-order size*/
+ lpObjectName); /*named object*/
+
+ if(NULL == hFileMapRW)
+ {
+ Fail("ERROR:%u: Failed to create File Mapping.\n",
+ GetLastError());
+ }
+
+ /* maps a view of a file into the address space of the calling process.
+ */
+ lpMapViewRW = MapViewOfFile(
+ hFileMapRW,
+ FILE_MAP_ALL_ACCESS, /* access code */
+ 0, /* high order offset*/
+ 0, /* low order offset*/
+ MAPPINGSIZE); /* number of bytes for map */
+
+ if(NULL == lpMapViewRW)
+ {
+ Trace("ERROR:%u: Failed to call MapViewOfFile "
+ "API to map a view of file!\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpOne;
+ }
+
+
+ hFileMapRO = CreateFileMapping(
+ SWAP_HANDLE,
+ NULL, /*not inherited*/
+ PAGE_READONLY, /*read and write*/
+ 0, /*high-order size*/
+ MAPPINGSIZE, /*low-order size*/
+ lpObjectName); /*named object*/
+
+ if(NULL == hFileMapRO)
+ {
+ Trace("ERROR:%u: Failed to create File Mapping.\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpTwo;
+ }
+
+ /* maps a view of a file into the address space of the calling process.
+ */
+ lpMapViewRO = MapViewOfFile(
+ hFileMapRO,
+ FILE_MAP_READ, /* access code */
+ 0, /* high order offset*/
+ 0, /* low order offset*/
+ MAPPINGSIZE); /* number of bytes for map */
+
+ if(NULL == lpMapViewRO)
+ {
+ Trace("ERROR:%u: Failed to call MapViewOfFile "
+ "API to map a view of file!\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpThree;
+ }
+
+ /* Write the test string to the Map view.
+ */
+ memcpy(lpMapViewRW, testString, strlen(testString));
+
+ /* Read from the second Map view.
+ */
+ memcpy(results, (LPCSTR)lpMapViewRO, MAPPINGSIZE);
+
+ /* Verify the contents of the file mapping,
+ * by comparing what was written to what was read.
+ */
+ if (memcmp(results, testString, strlen(testString))!= 0)
+ {
+ Trace("ERROR: MapViewOfFile not equal to file contents "
+ "retrieved \"%s\", expected \"%s\".\n",
+ results,
+ testString);
+ RetVal = FAIL;
+ goto CleanUpFour;
+ }
+
+ /* Test was successful.
+ */
+ RetVal = PASS;
+
+CleanUpFour:
+
+ /* Unmap the view of file.
+ */
+ if ( UnmapViewOfFile(lpMapViewRO) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n",
+ GetLastError(),
+ lpMapViewRO);
+ RetVal = FAIL;
+ }
+
+CleanUpThree:
+
+ /* Close Handle to opend file mapping.
+ */
+ if ( CloseHandle(hFileMapRO) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ hFileMapRO);
+ RetVal = FAIL;
+ }
+
+
+CleanUpTwo:
+ /* Unmap the view of file.
+ */
+ if ( UnmapViewOfFile(lpMapViewRW) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n",
+ GetLastError(),
+ lpMapViewRW);
+ RetVal = FAIL;
+ }
+
+
+CleanUpOne:
+
+ /* Close Handle to opend file mapping.
+ */
+ if ( CloseHandle(hFileMapRW) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ hFileMapRW);
+ RetVal = FAIL;
+ }
+
+
+ /* Terminate the PAL.
+ */
+ PAL_TerminateEx(RetVal);
+ return RetVal;
+}
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/testinfo.dat
new file mode 100644
index 0000000000..137db9d82b
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = CreateFileMapping
+Name = CreateFileMappingA - with PAGE_READWRITE and INVALID_HANDLE_VALUE file handle
+TYPE = DEFAULT
+EXE1 = createfilemapping
+Description
+=Test the CreateFileMapping to create a unnamed file-mapping object
+=and with PAGE_READWRITE protection by passing INVALID_HANDLE_VALUE
+=file handle
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/CMakeLists.txt
new file mode 100644
index 0000000000..2f5d98b5e6
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ CreateFileMapping.c
+)
+
+add_executable(paltest_createfilemappinga_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createfilemappinga_test6 coreclrpal)
+
+target_link_libraries(paltest_createfilemappinga_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/CreateFileMapping.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/CreateFileMapping.c
new file mode 100644
index 0000000000..6445295de8
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/CreateFileMapping.c
@@ -0,0 +1,164 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: createfilemapping.c (test 6)
+**
+** Purpose: Positive test the CreateFileMapping API.
+** Test CreateFileMapping to a "swap" handle with
+** access PAGE_READWRITE.
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+const int MAPPINGSIZE = 2048;
+HANDLE SWAP_HANDLE = ((VOID *)(-1));
+
+int __cdecl main(int argc, char *argv[])
+{
+ char testString[] = "this is a test string";
+ char lpObjectName[] = "myMappingObject";
+ char results[2048];
+ int RetVal = PASS;
+
+ HANDLE hFileMapRW;
+ LPVOID lpMapViewRW;
+ LPVOID lpMapViewRW2;
+
+ /* Initialize the PAL environment.
+ */
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Initialize the buffers.
+ */
+ memset(results, 0, MAPPINGSIZE);
+
+ /* Create a named file-mapping object with file handle FileHandle
+ * and with PAGE_READWRITE protection.
+ */
+ hFileMapRW = CreateFileMapping(
+ SWAP_HANDLE,
+ NULL, /*not inherited*/
+ PAGE_READWRITE, /*read write*/
+ 0, /*high-order size*/
+ MAPPINGSIZE, /*low-order size*/
+ lpObjectName); /*unnamed object*/
+
+ if(NULL == hFileMapRW)
+ {
+ Fail("ERROR:%u: Failed to create File Mapping.\n",
+ GetLastError());
+ }
+
+ /* Create a map view of the READWRITE file mapping.
+ */
+ lpMapViewRW = MapViewOfFile(
+ hFileMapRW,
+ FILE_MAP_ALL_ACCESS,/* access code */
+ 0, /* high order offset*/
+ 0, /* low order offset*/
+ MAPPINGSIZE); /* number of bytes for map */
+
+ if(NULL == lpMapViewRW)
+ {
+ Trace("ERROR:%u: Failed to call MapViewOfFile "
+ "API to map a view of file!\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpOne;
+ }
+
+
+ /* maps a view of a file into the address space of the calling process.
+ */
+ lpMapViewRW2 = MapViewOfFile(
+ hFileMapRW,
+ FILE_MAP_ALL_ACCESS, /* access code */
+ 0, /* high order offset*/
+ 0, /* low order offset*/
+ MAPPINGSIZE); /* number of bytes for map */
+
+ if(NULL == lpMapViewRW2)
+ {
+ Trace("ERROR:%u: Failed to call MapViewOfFile "
+ "API to map a view of file!\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpTwo;
+ }
+
+ /* Write the test string to the Map view.
+ */
+ memcpy(lpMapViewRW, testString, strlen(testString));
+
+ /* Read from the second Map view.
+ */
+ memcpy(results, (LPCSTR)lpMapViewRW2, MAPPINGSIZE);
+
+ /* Verify the contents of the file mapping,
+ * by comparing what was written to what was read.
+ */
+ if (memcmp(results, testString, strlen(testString))!= 0)
+ {
+ Trace("ERROR: MapViewOfFile not equal to file contents "
+ "retrieved \"%s\", expected \"%s\".\n",
+ results,
+ testString);
+ RetVal = FAIL;
+ goto CleanUpThree;
+ }
+
+ /* Test successful.
+ */
+ RetVal = PASS;
+
+CleanUpThree:
+
+ /* Unmap the view of file.
+ */
+ if ( UnmapViewOfFile(lpMapViewRW2) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n",
+ GetLastError(),
+ lpMapViewRW2);
+ RetVal = FAIL;
+ }
+
+CleanUpTwo:
+
+ /* Unmap the view of file.
+ */
+ if ( UnmapViewOfFile(lpMapViewRW) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n",
+ GetLastError(),
+ lpMapViewRW);
+ RetVal = FAIL;
+ }
+
+
+CleanUpOne:
+
+ /* Close Handle to create file mapping.
+ */
+ if ( CloseHandle(hFileMapRW) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ hFileMapRW);
+ RetVal = FAIL;
+ }
+
+
+ /* Terminate the PAL.
+ */
+ PAL_TerminateEx(RetVal);
+ return RetVal;
+}
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/testinfo.dat
new file mode 100644
index 0000000000..d088c5d562
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = CreateFileMapping
+Name = CreateFileMappingA - with PAGE_READONLY
+TYPE = DEFAULT
+EXE1 = createfilemapping
+Description
+=Test the CreateFileMapping to create a named file-mapping object
+=and with PAGE_READONLY protection
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/CMakeLists.txt
new file mode 100644
index 0000000000..4fd24a63a1
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ createfilemapping.c
+)
+
+add_executable(paltest_createfilemappinga_test7
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createfilemappinga_test7 coreclrpal)
+
+target_link_libraries(paltest_createfilemappinga_test7
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/createfilemapping.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/createfilemapping.c
new file mode 100644
index 0000000000..7cef9ddcdc
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/createfilemapping.c
@@ -0,0 +1,164 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: createfilemapping.c (test 7)
+**
+** Purpose: Positive test the CreateFileMapping API.
+** Test CreateFileMapping to a "swap" handle with
+** access PAGE_READWRITE.
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+const int MAPPINGSIZE = 2048;
+HANDLE SWAP_HANDLE = ((VOID *)(-1));
+
+int __cdecl main(int argc, char *argv[])
+{
+ char testString[] = "this is a test string";
+ char lpObjectName[] = "myMappingObject";
+ char results[2048];
+ int RetVal = PASS;
+
+ HANDLE hFileMapRW;
+ LPVOID lpMapViewRW;
+ LPVOID lpMapViewRO;
+
+ /* Initialize the PAL environment.
+ */
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Initialize the buffers.
+ */
+ memset(results, 0, MAPPINGSIZE);
+
+ /* Create a named file-mapping object with file handle FileHandle
+ * and with PAGE_READWRITE protection.
+ */
+ hFileMapRW = CreateFileMapping(
+ SWAP_HANDLE,
+ NULL, /*not inherited*/
+ PAGE_READWRITE, /*read write*/
+ 0, /*high-order size*/
+ MAPPINGSIZE, /*low-order size*/
+ lpObjectName); /*unnamed object*/
+
+ if(NULL == hFileMapRW)
+ {
+ Fail("ERROR:%u: Failed to create File Mapping.\n",
+ GetLastError());
+ }
+
+ /* Create a map view to the READWRITE file mapping.
+ */
+ lpMapViewRW = MapViewOfFile(
+ hFileMapRW,
+ FILE_MAP_ALL_ACCESS,/* access code */
+ 0, /* high order offset*/
+ 0, /* low order offset*/
+ MAPPINGSIZE); /* number of bytes for map */
+
+ if(NULL == lpMapViewRW)
+ {
+ Trace("ERROR:%u: Failed to call MapViewOfFile "
+ "API to map a view of file!\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpOne;
+ }
+
+
+ /* Create a map view to the READWRITE file mapping.
+ */
+ lpMapViewRO = MapViewOfFile(
+ hFileMapRW,
+ FILE_MAP_READ, /* access code */
+ 0, /* high order offset*/
+ 0, /* low order offset*/
+ MAPPINGSIZE); /* number of bytes for map */
+
+ if(NULL == lpMapViewRO)
+ {
+ Trace("ERROR:%u: Failed to call MapViewOfFile "
+ "API to map a view of file!\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpTwo;
+ }
+
+ /* Write the test string to the Map view.
+ */
+ memcpy(lpMapViewRW, testString, strlen(testString));
+
+ /* Read from the second Map view.
+ */
+ memcpy(results, (LPCSTR)lpMapViewRO, MAPPINGSIZE);
+
+ /* Verify the contents of the file mapping,
+ * by comparing what was written to what was read.
+ */
+ if (memcmp(results, testString, strlen(testString))!= 0)
+ {
+ Trace("ERROR: MapViewOfFile not equal to file contents "
+ "retrieved \"%s\", expected \"%s\".\n",
+ results,
+ testString);
+ RetVal = FAIL;
+ goto CleanUpThree;
+ }
+
+ /* Test successful.
+ */
+ RetVal = PASS;
+
+CleanUpThree:
+
+ /* Unmap the view of file.
+ */
+ if ( UnmapViewOfFile(lpMapViewRO) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n",
+ GetLastError(),
+ lpMapViewRO);
+ RetVal = FAIL;
+ }
+
+CleanUpTwo:
+
+ /* Unmap the view of file.
+ */
+ if ( UnmapViewOfFile(lpMapViewRW) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n",
+ GetLastError(),
+ lpMapViewRW);
+ RetVal = FAIL;
+ }
+
+
+CleanUpOne:
+
+ /* Close Handle to create file mapping.
+ */
+ if ( CloseHandle(hFileMapRW) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ hFileMapRW);
+ RetVal = FAIL;
+ }
+
+
+ /* Terminate the PAL.
+ */
+ PAL_TerminateEx(RetVal);
+ return RetVal;
+}
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/testinfo.dat
new file mode 100644
index 0000000000..c03d98a91c
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = CreateFileMapping
+Name = CreateFileMappingA - with PAGE_COPYWRITE
+TYPE = DEFAULT
+EXE1 = createfilemapping
+Description
+=Test the CreateFileMapping to create a named file-mapping object
+=and with PAGE_READONLY protection
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/CMakeLists.txt
new file mode 100644
index 0000000000..ae3ee8ddf6
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ createfilemapping.c
+)
+
+add_executable(paltest_createfilemappinga_test8
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createfilemappinga_test8 coreclrpal)
+
+target_link_libraries(paltest_createfilemappinga_test8
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/createfilemapping.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/createfilemapping.c
new file mode 100644
index 0000000000..02b2fb5e61
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/createfilemapping.c
@@ -0,0 +1,79 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: createfilemapping.c (test 8)
+**
+** Purpose: Positive test the CreateFileMapping API.
+** Test the un-verifiable parameter combinations.
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+const int MAPPINGSIZE = 2048;
+HANDLE SWAP_HANDLE = ((VOID *)(-1));
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE hFileMap;
+
+ /* Initialize the PAL environment.
+ */
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Create a READONLY, "swap", un-named file mapping.
+ * This test is unverifiable since there is no hook back to the file map
+ * because it is un-named. As well, since it resides in "swap", and is
+ * initialized to zero, there is nothing to read.
+ */
+ hFileMap = CreateFileMapping(
+ SWAP_HANDLE,
+ NULL, /*not inherited*/
+ PAGE_READONLY, /*read only*/
+ 0, /*high-order size*/
+ MAPPINGSIZE, /*low-order size*/
+ NULL); /*un-named object*/
+
+ if(NULL == hFileMap)
+ {
+ Fail("ERROR:%u: Failed to create File Mapping.\n",
+ GetLastError());
+ }
+
+
+ /* Create a COPYWRITE, "swap", un-named file mapping.
+ * This test is unverifiable, here is a quote from MSDN:
+ *
+ * Copy on write access. If you create the map with PAGE_WRITECOPY and
+ * the view with FILE_MAP_COPY, you will receive a view to file. If you
+ * write to it, the pages are automatically swappable and the modifications
+ * you make will not go to the original data file.
+ *
+ */
+ hFileMap = CreateFileMapping(
+ SWAP_HANDLE,
+ NULL, /*not inherited*/
+ PAGE_WRITECOPY, /*read only*/
+ 0, /*high-order size*/
+ MAPPINGSIZE, /*low-order size*/
+ NULL); /*unnamed object*/
+
+ if(NULL == hFileMap)
+ {
+ Fail("ERROR:%u: Failed to create File Mapping.\n",
+ GetLastError());
+ }
+
+
+ /* Terminate the PAL.
+ */
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/testinfo.dat
new file mode 100644
index 0000000000..ebe138f659
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = CreateFileMapping
+Name = CreateFileMappingA - unnamed swap, READWRITE.
+TYPE = DEFAULT
+EXE1 = createfilemapping
+Description
+= Positive test the CreateFileMapping API.
+= Test an unnamed File Mapping to a "swap"
+= handle with access PAGE_READWRITE.
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/CMakeLists.txt
new file mode 100644
index 0000000000..a377632bed
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ createfilemapping.c
+)
+
+add_executable(paltest_createfilemappinga_test9
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createfilemappinga_test9 coreclrpal)
+
+target_link_libraries(paltest_createfilemappinga_test9
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/createfilemapping.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/createfilemapping.c
new file mode 100644
index 0000000000..9224c22b4b
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/createfilemapping.c
@@ -0,0 +1,150 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: createfilemapping.c (test 9)
+**
+** Purpose: Negative test the CreateFileMapping API.
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+const int MAPPINGSIZE = 2048;
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ HANDLE hFile;
+ char lpFileName[] = "test.tmp";
+
+ HANDLE hFileMapping;
+
+ /* Initialize the PAL environment.
+ */
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Create a file handle with CreateFile, as READONLY
+ */
+ hFile = CreateFile( lpFileName,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: %u :unable to create file \"%s\".\n",
+ GetLastError(),
+ lpFileName);
+ }
+
+ /* Attempt to create a unnamed file-mapping object to a READONLY file
+ * as READWRITE access.
+ */
+ hFileMapping = CreateFileMapping(
+ hFile,
+ NULL, /*not inherited*/
+ PAGE_READWRITE, /*read and write*/
+ 0, /*high-order size*/
+ MAPPINGSIZE, /*low-order size*/
+ NULL); /*unnamed object*/
+
+ if(NULL != hFileMapping)
+ {
+ Trace("ERROR: Able to create READWRITE mapping to a "
+ "READONLY file.\n" );
+ if( 0 == CloseHandle(hFile) )
+ {
+ Trace("Unexpected Error: Unable to close file handle\n");
+ }
+ Fail("");
+ }
+
+ /* Attempt to create a unnamed file-mapping object to a zero lenght
+ * file.
+ */
+ hFileMapping = CreateFileMapping(
+ hFile,
+ NULL, /*not inherited*/
+ PAGE_READWRITE, /*read and write*/
+ 0, /*high-order size*/
+ 0, /*low-order size*/
+ NULL); /*unnamed object*/
+
+ if( NULL != hFileMapping )
+ {
+ Trace("ERROR: Able to create READWRITE mapping to a "
+ "READONLY file.\n" );
+ if( 0 == CloseHandle(hFile) )
+ {
+ Trace("Unexpected Error: Unable to close file handle\n");
+ }
+ Fail("");
+ }
+ if(GetLastError() != ERROR_ACCESS_DENIED)
+ {
+ Trace("ERROR: Expected GetLastError() to return "
+ "ERROR_FILE_INVALID (%d), it returned %u.\n",
+ ERROR_FILE_INVALID,
+ GetLastError());
+ if( 0 == CloseHandle(hFile) )
+ {
+ Trace("Unexpected Error: Unable to close file handle\n");
+ }
+ Fail("");
+ }
+
+ /* Attempt to create a file mapping that is larger than
+ * the file.
+ */
+ hFileMapping = CreateFileMapping(
+ hFile,
+ NULL, /*not inherited*/
+ PAGE_READONLY, /*read only*/
+ 0, /*high-order size*/
+ MAPPINGSIZE, /*low-order size*/
+ NULL); /*unnamed object*/
+ if(NULL != hFileMapping)
+ {
+ Trace("ERROR: Able to create file mapping of size %d to "
+ "file of size 0.\n",
+ MAPPINGSIZE);
+ if( 0 == CloseHandle(hFile) )
+ {
+ Trace("Unexpected Error: Unable to close file handle\n");
+ }
+ Fail("");
+ }
+
+ if(GetLastError() != ERROR_NOT_ENOUGH_MEMORY )
+ {
+ Trace("ERROR: Expected GetLastError() to return "
+ "ERROR_NOT_ENOUGH_MEMORY (%d), it returned %u.\n",
+ ERROR_NOT_ENOUGH_MEMORY,
+ GetLastError());
+ if( 0 == CloseHandle(hFile) )
+ {
+ Trace("Unexpected Error: Unable to close file handle\n");
+ }
+ Fail("");
+ }
+
+ if( 0 == CloseHandle(hFile) )
+ {
+ Fail("Unexpected Error: Unable to close file handle\n");
+ }
+
+ /* Terminate the PAL.
+ */
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/testinfo.dat
new file mode 100644
index 0000000000..11cbedc8c5
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = CreateFileMapping
+Name = CreateFileMappingA negative testing
+TYPE = DEFAULT
+EXE1 = createfilemapping
+Description
+= Negative test the CreateFileMapping API.
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CMakeLists.txt
new file mode 100644
index 0000000000..85f5c90e2c
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CMakeLists.txt
@@ -0,0 +1,16 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(CreateFileMapping_neg1)
+add_subdirectory(test1)
+
+# TODO: make this test compile
+# add_subdirectory(test2)
+
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+add_subdirectory(test7)
+add_subdirectory(test8)
+add_subdirectory(test9)
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/CMakeLists.txt
new file mode 100644
index 0000000000..a4ad343ea0
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ CreateFileMapping_neg.c
+)
+
+add_executable(paltest_createfilemappingw_createfilemapping_neg1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createfilemappingw_createfilemapping_neg1 coreclrpal)
+
+target_link_libraries(paltest_createfilemappingw_createfilemapping_neg1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/CreateFileMapping_neg.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/CreateFileMapping_neg.c
new file mode 100644
index 0000000000..8cf79b3c57
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/CreateFileMapping_neg.c
@@ -0,0 +1,93 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: createfilemapping_neg.c
+**
+** Purpose: Negative test the CreateFileMapping API.
+** Call CreateFileMapping to create a unnamed
+** file-mapping object with PAGE_READONLY
+** protection and try to map a zero length file
+** in UNICODE
+**
+**
+**============================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ HANDLE FileHandle;
+ HANDLE FileMappingHandle;
+ int err;
+ WCHAR *lpFileName = NULL;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ //conver string to a unicode one
+ lpFileName = convert("temp.txt");
+
+
+ //create a file and return the file handle
+ FileHandle = CreateFile(lpFileName,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_ARCHIVE,
+ NULL);
+
+ //free this memory
+ free(lpFileName);
+
+ if(INVALID_HANDLE_VALUE == FileHandle)
+ {
+ Fail("Failed to call CreateFile to create a file\n");
+ }
+
+ //create a unnamed file-mapping object with file handle FileHandle
+ //and with PAGE_READONLY protection
+ //try to map a file which is zero length.
+ FileMappingHandle = CreateFileMapping(
+ FileHandle, //File Handle
+ NULL, //not inherited
+ PAGE_READONLY, //access protection
+ 0, //high-order of object size
+ 0, //low-orger of object size
+ NULL); //unnamed object
+
+
+ if(NULL != FileMappingHandle || ERROR_FILE_INVALID != GetLastError())
+ {//no error occurred
+ Trace("\nFailed to call CreateFileMapping API for a negative test!\n");
+ err = CloseHandle(FileHandle);
+ if(0 == err)
+ {
+ Fail("\nFailed to call CloseHandle API\n");
+ }
+ err = CloseHandle(FileMappingHandle);
+ if(0 == err)
+ {
+ Fail("\nFailed to call CloseHandle API\n");
+ }
+ Fail("");
+ }
+
+ //close the file handle
+ err = CloseHandle(FileHandle);
+ if(0 == err)
+ {
+ Fail("\nFailed to call CloseHandle API\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/testinfo.dat
new file mode 100644
index 0000000000..a09487d4b9
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = CreateFileMapping
+Name = Negative test for CreateFileMappingW - with a zero length file
+TYPE = DEFAULT
+EXE1 = createfilemapping_neg
+Description
+=Test the CreateFileMapping to try to map a zero length file
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..0c569ec9b6
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ CreateFileMappingW.c
+)
+
+add_executable(paltest_createfilemappingw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createfilemappingw_test1 coreclrpal)
+
+target_link_libraries(paltest_createfilemappingw_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/CreateFileMappingW.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/CreateFileMappingW.c
new file mode 100644
index 0000000000..4263a3ad29
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/CreateFileMappingW.c
@@ -0,0 +1,174 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: createfilemappingw.c (test 1)
+**
+** Purpose: Positive test the CreateFileMappingW API.
+** Call CreateFileMappingW with access PAGE_READONLY.
+**
+**
+**============================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+const int MAPPINGSIZE = 2048;
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ HANDLE hFile;
+ char buf[] = "this is a test string";
+ char ch[2048];
+ WCHAR lpFileName[] = {'t','e','s','t','.','t','m','p','\0'};
+ DWORD dwBytesWritten;
+ BOOL err;
+ int RetVal = PASS;
+
+ HANDLE hFileMapping;
+ LPVOID lpMapViewAddress;
+
+ /* Initialize the PAL environment.
+ */
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Create a file handle with CreateFile.
+ */
+ hFile = CreateFile( lpFileName,
+ GENERIC_WRITE|GENERIC_READ,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: %u :unable to create file \"%s\".\n",
+ GetLastError(),
+ lpFileName);
+ }
+
+ /* Initialize the buffers.
+ */
+ memset(ch, 0, MAPPINGSIZE);
+
+ /* Write to the File handle.
+ */
+ err = WriteFile(hFile,
+ buf,
+ strlen(buf),
+ &dwBytesWritten,
+ NULL);
+
+ if (err == FALSE)
+ {
+ Trace("ERROR: %u :unable to write to file handle "
+ "hFile=0x%lx\n",
+ GetLastError(),
+ hFile);
+ RetVal = FAIL;
+ goto CleanUpOne;
+ }
+
+ /* Flush to the hard-drive.
+ */
+ FlushFileBuffers(hFile);
+
+ /* Create a unnamed file-mapping object with file handle FileHandle
+ * and with PAGE_READWRITE protection.
+ */
+ hFileMapping = CreateFileMapping(
+ hFile,
+ NULL, /*not inherited*/
+ PAGE_READONLY, /*read and wite*/
+ 0, /*high-order size*/
+ 0, /*low-order size*/
+ NULL); /*unnamed object*/
+
+ if(NULL == hFileMapping)
+ {
+ Trace("ERROR:%u: Failed to create File Mapping.\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpOne;
+ }
+
+ /* maps a view of a file into the address space of the calling process.
+ */
+ lpMapViewAddress = MapViewOfFile(
+ hFileMapping,
+ FILE_MAP_READ, /* access code */
+ 0, /*high order offset*/
+ 0, /*low order offset*/
+ 0); /* number of bytes for map */
+
+ if(NULL == lpMapViewAddress)
+ {
+ Trace("ERROR:%u: Failed to call MapViewOfFile "
+ "API to map a view of file!\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpTwo;
+ }
+
+ /* Copy the MapViewOfFile to buffer, so we can
+ * compare with value read from file directly.
+ */
+ memcpy(ch, (LPCSTR)lpMapViewAddress, MAPPINGSIZE);
+ if (memcmp(ch, buf, strlen(buf))!= 0)
+ {
+ Trace("ERROR: MapViewOfFile not equal to file contents "
+ "retrieved \"%s\", expected \"%s\".\n",
+ ch, buf);
+ RetVal = FAIL;
+ goto CleanUpThree;
+ }
+
+CleanUpThree:
+
+ /* Unmap the view of file.
+ */
+ if ( UnmapViewOfFile(lpMapViewAddress) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n",
+ GetLastError(),
+ lpMapViewAddress);
+ RetVal = FAIL;
+ }
+
+CleanUpTwo:
+
+ /* Close Handle to opend file mapping.
+ */
+ if ( CloseHandle(hFileMapping) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ hFileMapping);
+ RetVal = FAIL;
+ }
+
+CleanUpOne:
+
+ /* Close Handle to create file mapping.
+ */
+ if ( CloseHandle(hFile) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ hFile);
+ RetVal = FAIL;
+ }
+
+ /* Terminate the PAL.
+ */
+ PAL_TerminateEx(RetVal);
+ return RetVal;
+}
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/testinfo.dat
new file mode 100644
index 0000000000..464679a456
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = CreateFileMappingW
+Name = CreateFileMappingW with PAGE_READONLY
+TYPE = DEFAULT
+EXE1 = createfilemappingw
+Description
+=Test the CreateFileMappingW to create a unnamed file-mapping object
+=and with PAGE_READONLY protection
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test2/CMakeLists.txt
new file mode 100644
index 0000000000..992645f48c
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ CreateFileMappingW.c
+)
+
+add_executable(paltest_createfilemappingw_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createfilemappingw_test2 coreclrpal)
+
+target_link_libraries(paltest_createfilemappingw_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test2/CreateFileMappingW.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test2/CreateFileMappingW.c
new file mode 100644
index 0000000000..11ff967dfd
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test2/CreateFileMappingW.c
@@ -0,0 +1,124 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: createfilemappingw.c
+**
+** Purpose: Positive test the CreateFileMapping API.
+** Call CreateFileMapping to create a unnamed
+** file-mapping object with PAGE_READONLY
+** protection and SEC_IMAGE attribute in UNICODE
+**
+**
+**============================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ HANDLE FileHandle;
+ HANDLE FileMappingHandle;
+ int err;
+ WCHAR *wpFileName = NULL;
+ char executableFileName[256]="";
+
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+#if WIN32
+ sprintf(executableFileName,"%s","executable.exe");
+#else
+ sprintf(executableFileName,"%s","executable");
+#endif
+
+ //conver string to a unicode one
+ wpFileName = convert(executableFileName);
+
+
+ //create a file and return the file handle
+ FileHandle = CreateFile(wpFileName,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_ARCHIVE,
+ NULL);
+
+ //free this memory
+ free(wpFileName);
+
+ if(INVALID_HANDLE_VALUE == FileHandle)
+ {
+ Fail("Failed to call CreateFile to create a file\n");
+ }
+
+ //create a unnamed file-mapping object with file handle FileHandle
+ //and with PAGE_READONLY protection
+ FileMappingHandle = CreateFileMapping(
+ FileHandle, //File Handle
+ NULL, //not inherited
+ PAGE_READONLY|SEC_IMAGE, //access protection and section attribute
+ 0, //high-order of object size
+ 0, //low-orger of object size
+ NULL); //unnamed object
+
+
+ if(NULL == FileMappingHandle)
+ {
+ Trace("\nFailed to call CreateFileMapping to create a mapping object!\n");
+ err = CloseHandle(FileHandle);
+ if(0 == err)
+ {
+ Fail("\nFailed to call CloseHandle API\n");
+ }
+ Fail("");
+ }
+ if(GetLastError() == ERROR_ALREADY_EXISTS)
+ {
+ Trace("\nFile mapping object already exists!\n");
+ err = CloseHandle(FileHandle);
+ if(0 == err)
+ {
+ Trace("\nFailed to call CloseHandle API to close a file handle\n");
+ err = CloseHandle(FileMappingHandle);
+ if(0 == err)
+ {
+ Fail("\nFailed to call CloseHandle API to close a mapping object handle\n");
+ }
+ Fail("");
+ }
+ err = CloseHandle(FileMappingHandle);
+ if(0 == err)
+ {
+ Fail("\nFailed to call CloseHandle API to close a mapping object handle\n");
+ }
+ Fail("");
+ }
+ err = CloseHandle(FileMappingHandle);
+ if(0 == err)
+ {
+ Trace("\nFailed to call CloseHandle API to close a mapping object handle\n");
+ err = CloseHandle(FileHandle);
+ if(0 == err)
+ {
+ Fail("\nFailed to call CloseHandle API to close a file handle\n");
+ }
+ Fail("");
+ }
+ err = CloseHandle(FileHandle);
+ if(0 == err)
+ {
+ Fail("\nFailed to call CloseHandle API to close a file handle\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/CMakeLists.txt
new file mode 100644
index 0000000000..87832ffd9b
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ CreateFileMappingW.c
+)
+
+add_executable(paltest_createfilemappingw_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createfilemappingw_test3 coreclrpal)
+
+target_link_libraries(paltest_createfilemappingw_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/CreateFileMappingW.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/CreateFileMappingW.c
new file mode 100644
index 0000000000..1cbeff94a7
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/CreateFileMappingW.c
@@ -0,0 +1,156 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: createfilemappingw.c (test 3)
+**
+** Purpose: Positive test the CreateFileMappingW API.
+** Call CreateFileMapping with access PAGE_READWRITE.
+**
+**
+**============================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+const int MAPPINGSIZE = 2048;
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ HANDLE hFile;
+ char buf[] = "this is a test string";
+ char ch[2048];
+ WCHAR lpFileName[] = {'t','e','s','t','.','t','m','p','\0'};
+ HANDLE hFileMapping;
+ LPVOID lpMapViewAddress;
+ int RetVal = PASS;
+
+ /* Initialize the PAL environment.
+ */
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Create a file handle with CreateFile.
+ */
+ hFile = CreateFile( lpFileName,
+ GENERIC_WRITE|GENERIC_READ,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: %u :unable to create file \"%s\".\n",
+ GetLastError(),
+ lpFileName);
+ }
+
+ /* Initialize the buffers.
+ */
+ memset(ch, 0, MAPPINGSIZE);
+
+ /* Create a unnamed file-mapping object with file handle FileHandle
+ * and with PAGE_READWRITE protection.
+ */
+ hFileMapping = CreateFileMapping(
+ hFile,
+ NULL, /*not inherited*/
+ PAGE_READWRITE, /*read and wite*/
+ 0, /*high-order size*/
+ MAPPINGSIZE, /*low-order size*/
+ NULL); /*unnamed object*/
+
+ if(NULL == hFileMapping)
+ {
+ Trace("ERROR:%u: Failed to create File Mapping.\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpOne;
+ }
+
+ /* maps a view of a file into the address space of the calling process.
+ */
+ lpMapViewAddress = MapViewOfFile(
+ hFileMapping,
+ FILE_MAP_ALL_ACCESS, /* access code */
+ 0, /*high order offset*/
+ 0, /*low order offset*/
+ MAPPINGSIZE); /* number of bytes for map */
+
+ if(NULL == lpMapViewAddress)
+ {
+ Trace("ERROR:%u: Failed to call MapViewOfFile "
+ "API to map a view of file!\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpTwo;
+ }
+
+ /* Write to the Map view.
+ */
+ memcpy(lpMapViewAddress, buf, strlen(buf));
+
+ /* Read from the Map view.
+ */
+ memcpy(ch, (LPCSTR)lpMapViewAddress, MAPPINGSIZE);
+
+ /* Copy the MapViewOfFile to buffer, so we can
+ * compare with value read from file directly.
+ */
+ if (memcmp(ch, buf, strlen(buf))!= 0)
+ {
+ Trace("ERROR: MapViewOfFile not equal to file contents "
+ "retrieved \"%s\", expected \"%s\".\n",
+ ch, buf);
+ RetVal = FAIL;
+ goto CleanUpThree;
+ }
+
+CleanUpThree:
+
+ /* Unmap the view of file.
+ */
+ if ( UnmapViewOfFile(lpMapViewAddress) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n",
+ GetLastError(),
+ lpMapViewAddress);
+ RetVal = FAIL;
+ }
+
+CleanUpTwo:
+
+ /* Close Handle to opend file mapping.
+ */
+ if ( CloseHandle(hFileMapping) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ hFileMapping);
+ RetVal = FAIL;
+ }
+
+CleanUpOne:
+
+ /* Close Handle to create file mapping.
+ */
+ if ( CloseHandle(hFile) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ hFile);
+ RetVal = FAIL;
+ }
+
+ /* Terminate the PAL.
+ */
+ PAL_TerminateEx(RetVal);
+ return RetVal;
+}
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/testinfo.dat
new file mode 100644
index 0000000000..1077316618
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = CreateFileMappingW
+Name = CreateFileMappingW with PAGE_READWRITE
+TYPE = DEFAULT
+EXE1 = createfilemappingw
+Description
+=Test the CreateFileMappingW to create a unnamed file-mapping object
+=and with PAGE_READWRITE protection
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/CMakeLists.txt
new file mode 100644
index 0000000000..f8a5c9041f
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ CreateFileMappingW.c
+)
+
+add_executable(paltest_createfilemappingw_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createfilemappingw_test4 coreclrpal)
+
+target_link_libraries(paltest_createfilemappingw_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/CreateFileMappingW.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/CreateFileMappingW.c
new file mode 100644
index 0000000000..265a317b2f
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/CreateFileMappingW.c
@@ -0,0 +1,182 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: createfilemappingw.c (test 4)
+**
+** Purpose: Positive test the CreateFileMappingW API.
+** Call CreateFileMappingW with access PAGE_WRITECOPY.
+**
+**
+**============================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+const int MAPPINGSIZE = 2048;
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ HANDLE hFile;
+ char buf[] = "this is a test string";
+ char ch[2048];
+ WCHAR lpFileName[] = {'t','e','s','t','.','t','m','p','\0'};
+ HANDLE hFileMapping;
+ LPVOID lpMapViewAddress;
+ int RetVal = PASS;
+ int err;
+ DWORD dwBytesWritten;
+
+
+ /* Initialize the PAL environment.
+ */
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Create a file handle with CreateFile.
+ */
+ hFile = CreateFile( lpFileName,
+ GENERIC_WRITE|GENERIC_READ,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: %u :unable to create file \"%s\".\n",
+ GetLastError(),
+ lpFileName);
+ }
+
+ /* Write to the File handle.
+ */
+ err = WriteFile(hFile,
+ buf,
+ strlen(buf),
+ &dwBytesWritten,
+ NULL);
+
+ if (err == FALSE)
+ {
+ Trace("ERROR: %u :unable to write to file handle "
+ "hFile=0x%lx\n",
+ GetLastError(),
+ hFile);
+ RetVal = FAIL;
+ goto CleanUpOne;
+ }
+
+ /* Flush to the hard-drive.
+ */
+ FlushFileBuffers(hFile);
+
+ /* Initialize the buffers.
+ */
+ memset(ch, 0, MAPPINGSIZE);
+
+ /* Create a unnamed file-mapping object with file handle FileHandle
+ * and with PAGE_WRITECOPY protection.
+ */
+ hFileMapping = CreateFileMapping(
+ hFile,
+ NULL, /*not inherited*/
+ PAGE_WRITECOPY, /*write copy*/
+ 0, /*high-order size*/
+ 0, /*low-order size*/
+ NULL); /*unnamed object*/
+
+ if(NULL == hFileMapping)
+ {
+ Trace("ERROR:%u: Failed to create File Mapping.\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpOne;
+ }
+
+ /* maps a view of a file into the address space of the calling process.
+ */
+ lpMapViewAddress = MapViewOfFile(
+ hFileMapping,
+ FILE_MAP_COPY, /* access code */
+ 0, /* high order offset*/
+ 0, /* low order offset*/
+ 0); /* number of bytes for map */
+
+ if(NULL == lpMapViewAddress)
+ {
+ Trace("ERROR:%u: Failed to call MapViewOfFile "
+ "API to map a view of file!\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpTwo;
+ }
+
+ /* Write to the Map view.3
+ */
+ memcpy(lpMapViewAddress, buf, strlen(buf));
+
+ /* Read from the Map view.
+ */
+ memcpy(ch, (LPCSTR)lpMapViewAddress, MAPPINGSIZE);
+
+ /* Copy the MapViewOfFile to buffer, so we can
+ * compare with value read from file directly.
+ */
+ if (memcmp(ch, buf, strlen(buf))!= 0)
+ {
+ Trace("ERROR: MapViewOfFile not equal to file contents "
+ "retrieved \"%s\", expected \"%s\".\n",
+ ch, buf);
+ RetVal = FAIL;
+ goto CleanUpThree;
+ }
+
+CleanUpThree:
+
+ /* Unmap the view of file.
+ */
+ if ( UnmapViewOfFile(lpMapViewAddress) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n",
+ GetLastError(),
+ lpMapViewAddress);
+ RetVal = FAIL;
+ }
+
+CleanUpTwo:
+
+ /* Close Handle to opend file mapping.
+ */
+ if ( CloseHandle(hFileMapping) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ hFileMapping);
+ RetVal = FAIL;
+ }
+
+CleanUpOne:
+
+ /* Close Handle to create file mapping.
+ */
+ if ( CloseHandle(hFile) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ hFile);
+ RetVal = FAIL;
+ }
+
+ /* Terminate the PAL.
+ */
+ PAL_TerminateEx(RetVal);
+ return RetVal;
+}
+
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/testinfo.dat
new file mode 100644
index 0000000000..472b857eff
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = CreateFileMappingW
+Name = CreateFileMappingW with PAGE_WRITECOPY.
+TYPE = DEFAULT
+EXE1 = createfilemappingw
+Description
+=Test the CreateFileMapping to create a unnamed file-mapping object
+=and with PAGE_WRITE protection
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/CMakeLists.txt
new file mode 100644
index 0000000000..8391fbd721
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ CreateFileMappingW.c
+)
+
+add_executable(paltest_createfilemappingw_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createfilemappingw_test5 coreclrpal)
+
+target_link_libraries(paltest_createfilemappingw_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/CreateFileMappingW.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/CreateFileMappingW.c
new file mode 100644
index 0000000000..21bf7c6d76
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/CreateFileMappingW.c
@@ -0,0 +1,194 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: createfilemappingw.c (test 5)
+**
+** Purpose: Positive test the CreateFileMappingW API.
+** Test CreateFileMappingW to a "swap" handle with
+** access PAGE_READONLY.
+**
+**
+**============================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+const int MAPPINGSIZE = 2048;
+HANDLE SWAP_HANDLE = ((VOID *)(-1));
+
+int __cdecl main(int argc, char *argv[])
+{
+ char testString[] = "this is a test string";
+ WCHAR lpObjectName[] = {'m','y','O','b','j','e','c','t','\0'};
+ int RetVal = FAIL;
+ char results[2048];
+
+ HANDLE hFileMapRO;
+ HANDLE hFileMapRW;
+ LPVOID lpMapViewRO;
+ LPVOID lpMapViewRW;
+
+ /* Initialize the PAL environment.
+ */
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Initialize the buffers.
+ */
+ memset(results, 0, MAPPINGSIZE);
+
+ /* Create a named file-mapping object with file handle FileHandle
+ * and with PAGE_READWRITE protection.
+ */
+ hFileMapRW = CreateFileMapping(
+ SWAP_HANDLE,
+ NULL, /*not inherited*/
+ PAGE_READWRITE, /*read only*/
+ 0, /*high-order size*/
+ MAPPINGSIZE, /*low-order size*/
+ lpObjectName); /*named object*/
+
+ if(NULL == hFileMapRW)
+ {
+ Fail("ERROR:%u: Failed to create File Mapping.\n",
+ GetLastError());
+ }
+
+ /* maps a view of a file into the address space of the calling process.
+ */
+ lpMapViewRW = MapViewOfFile(
+ hFileMapRW,
+ FILE_MAP_ALL_ACCESS, /* access code */
+ 0, /* high order offset*/
+ 0, /* low order offset*/
+ MAPPINGSIZE); /* number of bytes for map */
+
+ if(NULL == lpMapViewRW)
+ {
+ Trace("ERROR:%u: Failed to call MapViewOfFile "
+ "API to map a view of file!\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpOne;
+ }
+
+
+ hFileMapRO = CreateFileMapping(
+ SWAP_HANDLE,
+ NULL, /*not inherited*/
+ PAGE_READONLY, /*read and write*/
+ 0, /*high-order size*/
+ MAPPINGSIZE, /*low-order size*/
+ lpObjectName); /*named object*/
+
+ if(NULL == hFileMapRO)
+ {
+ Trace("ERROR:%u: Failed to create File Mapping.\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpTwo;
+ }
+
+ /* maps a view of a file into the address space of the calling process.
+ */
+ lpMapViewRO = MapViewOfFile(
+ hFileMapRO,
+ FILE_MAP_READ, /* access code */
+ 0, /* high order offset*/
+ 0, /* low order offset*/
+ MAPPINGSIZE); /* number of bytes for map */
+
+ if(NULL == lpMapViewRO)
+ {
+ Trace("ERROR:%u: Failed to call MapViewOfFile "
+ "API to map a view of file!\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpThree;
+ }
+
+ /* Write the test string to the Map view.
+ */
+ memcpy(lpMapViewRW, testString, strlen(testString));
+
+ /* Read from the second Map view.
+ */
+ memcpy(results, (LPCSTR)lpMapViewRO, MAPPINGSIZE);
+
+ /* Verify the contents of the file mapping,
+ * by comparing what was written to what was read.
+ */
+ if (memcmp(results, testString, strlen(testString))!= 0)
+ {
+ Trace("ERROR: MapViewOfFile not equal to file contents "
+ "retrieved \"%s\", expected \"%s\".\n",
+ results,
+ testString);
+ RetVal = FAIL;
+ goto CleanUpFour;
+ }
+
+ /* Test was successful.
+ */
+ RetVal = PASS;
+
+CleanUpFour:
+
+ /* Unmap the view of file.
+ */
+ if ( UnmapViewOfFile(lpMapViewRO) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n",
+ GetLastError(),
+ lpMapViewRO);
+ RetVal = FAIL;
+ }
+
+CleanUpThree:
+
+ /* Close Handle to opend file mapping.
+ */
+ if ( CloseHandle(hFileMapRO) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ hFileMapRO);
+ RetVal = FAIL;
+ }
+
+
+CleanUpTwo:
+ /* Unmap the view of file.
+ */
+ if ( UnmapViewOfFile(lpMapViewRW) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n",
+ GetLastError(),
+ lpMapViewRW);
+ RetVal = FAIL;
+ }
+
+
+CleanUpOne:
+
+ /* Close Handle to opend file mapping.
+ */
+ if ( CloseHandle(hFileMapRW) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ hFileMapRW);
+ RetVal = FAIL;
+ }
+
+
+ /* Terminate the PAL.
+ */
+ PAL_TerminateEx(RetVal);
+ return RetVal;
+}
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/testinfo.dat
new file mode 100644
index 0000000000..87e16d3d79
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = CreateFileMappingW
+Name = CreateFileMappingW - PAGE_READWRITE
+TYPE = DEFAULT
+EXE1 = createfilemappingw
+Description
+= Positive test the CreateFileMappingW API.
+= Test CreateFileMappingW to create a named
+= "swap" handle with access PAGE_READONLY.
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/CMakeLists.txt
new file mode 100644
index 0000000000..abb62ad950
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ CreateFileMappingW.c
+)
+
+add_executable(paltest_createfilemappingw_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createfilemappingw_test6 coreclrpal)
+
+target_link_libraries(paltest_createfilemappingw_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/CreateFileMappingW.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/CreateFileMappingW.c
new file mode 100644
index 0000000000..acf3ac6dff
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/CreateFileMappingW.c
@@ -0,0 +1,165 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: createfilemappingw.c (test 6)
+**
+** Purpose: Positive test the CreateFileMappingW API.
+** Test CreateFileMappingW to a "swap" handle with
+** access PAGE_READWRITE.
+**
+**
+**============================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+const int MAPPINGSIZE = 2048;
+HANDLE SWAP_HANDLE = ((VOID *)(-1));
+
+int __cdecl main(int argc, char *argv[])
+{
+ char testString[] = "this is a test string";
+ WCHAR lpObjectName[] = {'m','y','O','b','j','e','c','t','\0'};
+ char results[2048];
+ int RetVal = PASS;
+
+ HANDLE hFileMapRW;
+ LPVOID lpMapViewRW;
+ LPVOID lpMapViewRW2;
+
+ /* Initialize the PAL environment.
+ */
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Initialize the buffers.
+ */
+ memset(results, 0, MAPPINGSIZE);
+
+ /* Create a named file-mapping object with file handle FileHandle
+ * and with PAGE_READWRITE protection.
+ */
+ hFileMapRW = CreateFileMapping(
+ SWAP_HANDLE,
+ NULL, /*not inherited*/
+ PAGE_READWRITE, /*read write*/
+ 0, /*high-order size*/
+ MAPPINGSIZE, /*low-order size*/
+ lpObjectName); /*named object*/
+
+ if(NULL == hFileMapRW)
+ {
+ Fail("ERROR:%u: Failed to create File Mapping.\n",
+ GetLastError());
+ }
+
+ /* Create a map view of the READWRITE file mapping.
+ */
+ lpMapViewRW = MapViewOfFile(
+ hFileMapRW,
+ FILE_MAP_ALL_ACCESS,/* access code */
+ 0, /* high order offset*/
+ 0, /* low order offset*/
+ MAPPINGSIZE); /* number of bytes for map */
+
+ if(NULL == lpMapViewRW)
+ {
+ Trace("ERROR:%u: Failed to call MapViewOfFile "
+ "API to map a view of file!\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpOne;
+ }
+
+
+ /* maps a view of a file into the address space of the calling process.
+ */
+ lpMapViewRW2 = MapViewOfFile(
+ hFileMapRW,
+ FILE_MAP_ALL_ACCESS, /* access code */
+ 0, /* high order offset*/
+ 0, /* low order offset*/
+ MAPPINGSIZE); /* number of bytes for map */
+
+ if(NULL == lpMapViewRW2)
+ {
+ Trace("ERROR:%u: Failed to call MapViewOfFile "
+ "API to map a view of file!\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpTwo;
+ }
+
+ /* Write the test string to the Map view.
+ */
+ memcpy(lpMapViewRW, testString, strlen(testString));
+
+ /* Read from the second Map view.
+ */
+ memcpy(results, (LPCSTR)lpMapViewRW2, MAPPINGSIZE);
+
+ /* Verify the contents of the file mapping,
+ * by comparing what was written to what was read.
+ */
+ if (memcmp(results, testString, strlen(testString))!= 0)
+ {
+ Trace("ERROR: MapViewOfFile not equal to file contents "
+ "retrieved \"%s\", expected \"%s\".\n",
+ results,
+ testString);
+ RetVal = FAIL;
+ goto CleanUpThree;
+ }
+
+ /* Test successful.
+ */
+ RetVal = PASS;
+
+CleanUpThree:
+
+ /* Unmap the view of file.
+ */
+ if ( UnmapViewOfFile(lpMapViewRW2) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n",
+ GetLastError(),
+ lpMapViewRW2);
+ RetVal = FAIL;
+ }
+
+CleanUpTwo:
+
+ /* Unmap the view of file.
+ */
+ if ( UnmapViewOfFile(lpMapViewRW) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n",
+ GetLastError(),
+ lpMapViewRW);
+ RetVal = FAIL;
+ }
+
+
+CleanUpOne:
+
+ /* Close Handle to create file mapping.
+ */
+ if ( CloseHandle(hFileMapRW) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ hFileMapRW);
+ RetVal = FAIL;
+ }
+
+
+ /* Terminate the PAL.
+ */
+ PAL_TerminateEx(RetVal);
+ return RetVal;
+}
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/testinfo.dat
new file mode 100644
index 0000000000..7afae68f16
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = CreateFileMapping
+Name = CreateFileMappingA - with PAGE_READONLY
+TYPE = DEFAULT
+EXE1 = createfilemappingw
+Description
+= Positive test the CreateFileMappingW API.
+= Test CreateFileMappingW to create a named
+= "swap" handle with access PAGE_READWRITE.
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/CMakeLists.txt
new file mode 100644
index 0000000000..b40cfeae96
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ createfilemapping.c
+)
+
+add_executable(paltest_createfilemappingw_test7
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createfilemappingw_test7 coreclrpal)
+
+target_link_libraries(paltest_createfilemappingw_test7
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/createfilemapping.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/createfilemapping.c
new file mode 100644
index 0000000000..e49b9f688d
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/createfilemapping.c
@@ -0,0 +1,165 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: createfilemappingw.c (test 7)
+**
+** Purpose: Positive test the CreateFileMappingW API.
+** Test CreateFileMappingW to a "swap" handle with
+** access PAGE_READWRITE.
+**
+**
+**============================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+const int MAPPINGSIZE = 2048;
+HANDLE SWAP_HANDLE = ((VOID *)(-1));
+
+int __cdecl main(int argc, char *argv[])
+{
+ char testString[] = "this is a test string";
+ WCHAR lpObjectName[] = {'m','y','O','b','j','e','c','t','\0'};
+ char results[2048];
+ int RetVal = PASS;
+
+ HANDLE hFileMapRW;
+ LPVOID lpMapViewRW;
+ LPVOID lpMapViewRO;
+
+ /* Initialize the PAL environment.
+ */
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Initialize the buffers.
+ */
+ memset(results, 0, MAPPINGSIZE);
+
+ /* Create a named file-mapping object with file handle FileHandle
+ * and with PAGE_READWRITE protection.
+ */
+ hFileMapRW = CreateFileMapping(
+ SWAP_HANDLE,
+ NULL, /*not inherited*/
+ PAGE_READWRITE, /*read write*/
+ 0, /*high-order size*/
+ MAPPINGSIZE, /*low-order size*/
+ lpObjectName); /*unnamed object*/
+
+ if(NULL == hFileMapRW)
+ {
+ Fail("ERROR:%u: Failed to create File Mapping.\n",
+ GetLastError());
+ }
+
+ /* Create a map view to the READWRITE file mapping.
+ */
+ lpMapViewRW = MapViewOfFile(
+ hFileMapRW,
+ FILE_MAP_ALL_ACCESS,/* access code */
+ 0, /* high order offset*/
+ 0, /* low order offset*/
+ MAPPINGSIZE); /* number of bytes for map */
+
+ if(NULL == lpMapViewRW)
+ {
+ Trace("ERROR:%u: Failed to call MapViewOfFile "
+ "API to map a view of file!\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpOne;
+ }
+
+
+ /* Create a map view to the READWRITE file mapping.
+ */
+ lpMapViewRO = MapViewOfFile(
+ hFileMapRW,
+ FILE_MAP_READ, /* access code */
+ 0, /* high order offset*/
+ 0, /* low order offset*/
+ MAPPINGSIZE); /* number of bytes for map */
+
+ if(NULL == lpMapViewRO)
+ {
+ Trace("ERROR:%u: Failed to call MapViewOfFile "
+ "API to map a view of file!\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpTwo;
+ }
+
+ /* Write the test string to the Map view.
+ */
+ memcpy(lpMapViewRW, testString, strlen(testString));
+
+ /* Read from the second Map view.
+ */
+ memcpy(results, (LPCSTR)lpMapViewRO, MAPPINGSIZE);
+
+ /* Verify the contents of the file mapping,
+ * by comparing what was written to what was read.
+ */
+ if (memcmp(results, testString, strlen(testString))!= 0)
+ {
+ Trace("ERROR: MapViewOfFile not equal to file contents "
+ "retrieved \"%s\", expected \"%s\".\n",
+ results,
+ testString);
+ RetVal = FAIL;
+ goto CleanUpThree;
+ }
+
+ /* Test successful.
+ */
+ RetVal = PASS;
+
+CleanUpThree:
+
+ /* Unmap the view of file.
+ */
+ if ( UnmapViewOfFile(lpMapViewRO) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n",
+ GetLastError(),
+ lpMapViewRO);
+ RetVal = FAIL;
+ }
+
+CleanUpTwo:
+
+ /* Unmap the view of file.
+ */
+ if ( UnmapViewOfFile(lpMapViewRW) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n",
+ GetLastError(),
+ lpMapViewRW);
+ RetVal = FAIL;
+ }
+
+
+CleanUpOne:
+
+ /* Close Handle to create file mapping.
+ */
+ if ( CloseHandle(hFileMapRW) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ hFileMapRW);
+ RetVal = FAIL;
+ }
+
+
+ /* Terminate the PAL.
+ */
+ PAL_TerminateEx(RetVal);
+ return RetVal;
+}
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/testinfo.dat
new file mode 100644
index 0000000000..a68a665d74
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = CreateFileMappingW
+Name = CreateFileMappingW - PAGE_COPYWRITE
+TYPE = DEFAULT
+EXE1 = createfilemapping
+Description
+= Positive test the CreateFileMappingW API.
+= Test CreateFileMappingW to create a named
+= "swap" handle with access PAGE_READWRITE
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/CMakeLists.txt
new file mode 100644
index 0000000000..96658c163a
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ createfilemapping.c
+)
+
+add_executable(paltest_createfilemappingw_test8
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createfilemappingw_test8 coreclrpal)
+
+target_link_libraries(paltest_createfilemappingw_test8
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/createfilemapping.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/createfilemapping.c
new file mode 100644
index 0000000000..1ff137d8d3
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/createfilemapping.c
@@ -0,0 +1,82 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: createfilemappingw.c (test 8)
+**
+** Purpose: Positive test the CreateFileMappingW API.
+** Test the un-verifiable parameter combinations.
+**
+**
+**============================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+const int MAPPINGSIZE = 2048;
+HANDLE SWAP_HANDLE = ((VOID *)(-1));
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR lpObjectName[] = {'m','y','O','b','j','e','c','t','\0'};
+
+ HANDLE hFileMap;
+
+ /* Initialize the PAL environment.
+ */
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Create a READONLY, "swap", un-named file mapping.
+ * This test is unverifiable since there is no hook back to the file map
+ * because it is un-named. As well, since it resides in "swap", and is
+ * initialized to zero, there is nothing to read.
+ */
+ hFileMap = CreateFileMapping(
+ SWAP_HANDLE,
+ NULL, /*not inherited*/
+ PAGE_READONLY, /*read only*/
+ 0, /*high-order size*/
+ MAPPINGSIZE, /*low-order size*/
+ NULL); /*un-named object*/
+
+ if(NULL == hFileMap)
+ {
+ Fail("ERROR:%u: Failed to create File Mapping.\n",
+ GetLastError());
+ }
+
+
+ /* Create a COPYWRITE, "swap", un-named file mapping.
+ * This test is unverifiable, here is a quote from MSDN:
+ *
+ * Copy on write access. If you create the map with PAGE_WRITECOPY and
+ * the view with FILE_MAP_COPY, you will receive a view to file. If you
+ * write to it, the pages are automatically swappable and the modifications
+ * you make will not go to the original data file.
+ *
+ */
+ hFileMap = CreateFileMapping(
+ SWAP_HANDLE,
+ NULL, /*not inherited*/
+ PAGE_WRITECOPY, /*write copy*/
+ 0, /*high-order size*/
+ MAPPINGSIZE, /*low-order size*/
+ NULL); /*unnamed object*/
+
+ if(NULL == hFileMap)
+ {
+ Fail("ERROR:%u: Failed to create File Mapping.\n",
+ GetLastError());
+ }
+
+
+ /* Terminate the PAL.
+ */
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/testinfo.dat
new file mode 100644
index 0000000000..475d827af4
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = CreateFileMappingW - Special cases
+Name = CreateFileMappingW
+TYPE = DEFAULT
+EXE1 = createfilemapping
+Description
+= Positive test the CreateFileMappingW API.
+= Test the un-verifiable parameter combinations.
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/CMakeLists.txt
new file mode 100644
index 0000000000..5a55e27b33
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ createfilemapping.c
+)
+
+add_executable(paltest_createfilemappingw_test9
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createfilemappingw_test9 coreclrpal)
+
+target_link_libraries(paltest_createfilemappingw_test9
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/createfilemapping.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/createfilemapping.c
new file mode 100644
index 0000000000..16ae74c126
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/createfilemapping.c
@@ -0,0 +1,151 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: createfilemapping.c (test 9)
+**
+** Purpose: Negative test the CreateFileMappingW API.
+**
+**
+**============================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+const int MAPPINGSIZE = 2048;
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ HANDLE hFile;
+ WCHAR lpFileName[] = {'t','e','s','t','.','t','m','p','\0'};
+
+ HANDLE hFileMapping;
+
+ /* Initialize the PAL environment.
+ */
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Create a file handle with CreateFile, as READONLY
+ */
+ hFile = CreateFile( lpFileName,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: %u :unable to create file \"%s\".\n",
+ GetLastError(),
+ lpFileName);
+ }
+
+ /* Attempt to create a unnamed file-mapping object to a READONLY file
+ * as READWRITE access.
+ */
+ hFileMapping = CreateFileMapping(
+ hFile,
+ NULL, /*not inherited*/
+ PAGE_READWRITE, /*read and write*/
+ 0, /*high-order size*/
+ MAPPINGSIZE, /*low-order size*/
+ NULL); /*unnamed object*/
+
+ if(NULL != hFileMapping)
+ {
+ Trace("ERROR: Able to create READWRITE mapping to a "
+ "READONLY file.\n" );
+ if( 0 == CloseHandle(hFile) )
+ {
+ Trace("Unexpected Error: Unable to close file handle\n");
+ }
+ Fail("");
+ }
+
+ /* Attempt to create a unnamed file-mapping object to a zero lenght
+ * file.
+ */
+ hFileMapping = CreateFileMapping(
+ hFile,
+ NULL, /*not inherited*/
+ PAGE_READWRITE, /*read and write*/
+ 0, /*high-order size*/
+ 0, /*low-order size*/
+ NULL); /*unnamed object*/
+
+ if( NULL != hFileMapping )
+ {
+ Trace("ERROR: Able to create READWRITE mapping to a "
+ "READONLY file.\n" );
+ if( 0 == CloseHandle(hFile) )
+ {
+ Trace("Unexpected Error: Unable to close file handle\n");
+ }
+ Fail("");
+ }
+ if(GetLastError() != ERROR_ACCESS_DENIED)
+ {
+ Trace("ERROR: Expected GetLastError() to return "
+ "ERROR_FILE_INVALID (%d), it returned %u.\n",
+ ERROR_FILE_INVALID,
+ GetLastError());
+ if( 0 == CloseHandle(hFile) )
+ {
+ Trace("Unexpected Error: Unable to close file handle\n");
+ }
+ Fail("");
+ }
+
+ /* Attempt to create a file mapping that is larger than
+ * the file.
+ */
+ hFileMapping = CreateFileMapping(
+ hFile,
+ NULL, /*not inherited*/
+ PAGE_READONLY, /*read only*/
+ 0, /*high-order size*/
+ MAPPINGSIZE, /*low-order size*/
+ NULL); /*unnamed object*/
+ if(NULL != hFileMapping)
+ {
+ Trace("ERROR: Able to create file mapping of size %d to "
+ "file of size 0.\n",
+ MAPPINGSIZE);
+ if( 0 == CloseHandle(hFile) )
+ {
+ Trace("Unexpected Error: Unable to close file handle\n");
+ }
+ Fail("");
+ }
+
+ if(GetLastError() != ERROR_NOT_ENOUGH_MEMORY )
+ {
+ Trace("ERROR: Expected GetLastError() to return "
+ "ERROR_NOT_ENOUGH_MEMORY (%d), it returned %u.\n",
+ ERROR_NOT_ENOUGH_MEMORY,
+ GetLastError());
+ if( 0 == CloseHandle(hFile) )
+ {
+ Trace("Unexpected Error: Unable to close file handle\n");
+ }
+ Fail("");
+ }
+
+ if( 0 == CloseHandle(hFile) )
+ {
+ Fail("Unexpected Error: Unable to close file handle\n");
+ }
+
+ /* Terminate the PAL.
+ */
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/testinfo.dat
new file mode 100644
index 0000000000..2a7ecdbab7
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = CreateFileMappingW
+Name = CreateFileMappingW negative testing
+TYPE = DEFAULT
+EXE1 = createfilemapping
+Description
+= Negative test the CreateFileMapping API.
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/CMakeLists.txt
new file mode 100644
index 0000000000..3807621e3f
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/CMakeLists.txt
@@ -0,0 +1,20 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ dlltest.c
+ FreeLibrary.c
+)
+
+add_executable(paltest_freelibrary_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_freelibrary_test1 coreclrpal)
+
+target_link_libraries(paltest_freelibrary_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/FreeLibrary.c b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/FreeLibrary.c
new file mode 100644
index 0000000000..a06a231586
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/FreeLibrary.c
@@ -0,0 +1,128 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source:
+**
+** Purpose: Positive test the FreeLibrary API.
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+/*char LibraryName[] = "dlltest";*/
+/* SHLEXT is defined only for Unix variants */
+
+#if defined(SHLEXT)
+#define LibraryName "dlltest"SHLEXT
+#else
+#define LibraryName "dlltest"
+#endif
+
+
+
+
+BOOL PALAPI TestDll(HMODULE, int);
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE hLib;
+
+ /* Initialize the PAL. */
+ if ((PAL_Initialize(argc, argv)) != 0)
+ {
+ return (FAIL);
+ }
+
+ /*Load library (DLL). */
+ hLib = LoadLibrary(LibraryName);
+
+ if(hLib == NULL)
+ {
+ Fail("ERROR:%u:Unable to load library %s\n",
+ GetLastError(),
+ LibraryName);
+ }
+
+ /* Test access to DLL. */
+ if(!TestDll(hLib, PASS))
+ {
+ Trace("ERROR: TestDll function returned FALSE "
+ "expected TRUE\n.");
+ FreeLibrary(hLib);
+ Fail("");
+ }
+
+ /* Call the FreeLibrary API. */
+ if (!FreeLibrary(hLib))
+ {
+ Fail("ERROR:%u: Unable to free library \"%s\"\n",
+ GetLastError(),
+ LibraryName);
+ }
+
+ /* Test access to the free'd DLL. */
+ if(!TestDll(hLib, FAIL))
+ {
+ Fail("ERROR: TestDll function returned FALSE "
+ "expected TRUE\n.");
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
+BOOL PALAPI TestDll(HMODULE hLib, int testResult)
+{
+ int RetVal;
+#if WIN32
+ char FunctName[] = "_DllTest@0";
+#else
+ char FunctName[] = "DllTest";
+#endif
+ FARPROC DllAddr;
+
+ /* Attempt to grab the proc address of the dll function.
+ * This one should succeed.*/
+ if(testResult == PASS)
+ {
+ DllAddr = GetProcAddress(hLib, FunctName);
+ if(DllAddr == NULL)
+ {
+ Trace("ERROR: Unable to load function \"%s\" library \"%s\"\n",
+ FunctName,
+ LibraryName);
+ return (FALSE);
+ }
+ /* Run the function in the DLL,
+ * to ensure that the DLL was loaded properly.*/
+ RetVal = DllAddr();
+ if (RetVal != 1)
+ {
+ Trace("ERROR: Unable to receive correct information from DLL! "
+ ":expected \"1\", returned \"%d\"\n",
+ RetVal);
+ return (FALSE);
+ }
+ }
+
+ /* Attempt to grab the proc address of the dll function.
+ * This one should fail.*/
+ if(testResult == FAIL)
+ {
+ DllAddr = GetProcAddress(hLib, FunctName);
+ if(DllAddr != NULL)
+ {
+ Trace("ERROR: Able to load function \"%s\" from free'd"
+ " library \"%s\"\n",
+ FunctName,
+ LibraryName);
+ return (FALSE);
+ }
+ }
+ return (TRUE);
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/dlltest.c b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/dlltest.c
new file mode 100644
index 0000000000..44f1b5a903
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/dlltest.c
@@ -0,0 +1,32 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: dlltest.c (FreeLibrary test dll)
+**
+** Purpose: This file will be used to create the shared library
+** that will be used in the FreeLibraryAndExitThread
+** test. A very simple shared library, with one function
+** "DllTest" which merely returns 1.
+**
+**
+**===================================================================*/
+#include "pal.h"
+
+#if WIN32
+__declspec(dllexport)
+#endif
+
+int __stdcall DllTest()
+{
+ return 1;
+}
+
+#ifdef WIN32
+int __stdcall _DllMainCRTStartup(void *hinstDLL, int reason, void * lpvReserved)
+{
+ return 1;
+}
+#endif
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/testinfo.dat
new file mode 100644
index 0000000000..a09d21428f
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = FreeLibrary
+Name = Positive test for FreeLibrary API
+TYPE = DEFAULT
+EXE1 = freelibrary
+LIB1 = dlltest
+Description
+=Test the FreeLibrary to decrement the reference
+=count of the loaded DLL
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/CMakeLists.txt
new file mode 100644
index 0000000000..00b1eca8e3
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_freelibrary_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_freelibrary_test2 coreclrpal)
+
+target_link_libraries(paltest_freelibrary_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/test2.c b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/test2.c
new file mode 100644
index 0000000000..b43f74d6bc
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/test2.c
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test2.c (FreeLibrary)
+**
+** Purpose: Tests the PAL implementation of the FreeLibrary function.
+** This is a negative test that will pass an invalid and a
+** null handle to FreeLibrary.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char* argv[])
+{
+ HANDLE hLib;
+
+ /* Initialize the PAL.
+ */
+ if ((PAL_Initialize(argc, argv)) != 0)
+ {
+ return (FAIL);
+ }
+
+ /* Attempt to pass FreeLibrary an invalid handle.
+ */
+ hLib = INVALID_HANDLE_VALUE;
+ if (FreeLibrary(hLib))
+ {
+ Fail("ERROR: Able to free library handle = \"0x%lx\".\n",
+ hLib);
+ }
+
+ /* Attempt to pass FreeLibrary a NULL handle.
+ */
+ hLib = NULL;
+ if (FreeLibrary(hLib))
+ {
+ Fail("ERROR: Able to free library handle = \"NULL\".\n");
+ }
+
+
+ /* Terminate the PAL.
+ */
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/testinfo.dat
new file mode 100644
index 0000000000..521fa6eaea
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = FreeLibrary
+Name = Negative test for FreeLibrary
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Tests the PAL implementation of the FreeLibrary function.
+= This is a negative test that will pass an invalid and a
+= null handle to FreeLibrary.
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/CMakeLists.txt
new file mode 100644
index 0000000000..cec083583a
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/CMakeLists.txt
@@ -0,0 +1,20 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ dlltest.c
+ test1.c
+)
+
+add_executable(paltest_freelibraryandexitthread_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_freelibraryandexitthread_test1 coreclrpal)
+
+target_link_libraries(paltest_freelibraryandexitthread_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/dlltest.c b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/dlltest.c
new file mode 100644
index 0000000000..954c624d19
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/dlltest.c
@@ -0,0 +1,32 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: dlltest.c (FreeLibraryAndExitThread test dll)
+**
+** Purpose: This file will be used to create the shared library
+** that will be used in the FreeLibraryAndExitThread
+** test. A very simple shared library, with one function
+** "DllTest" which merely returns 1.
+**
+**
+**===================================================================*/
+#include "pal.h"
+
+#if WIN32
+__declspec(dllexport)
+#endif
+
+int _stdcall DllTest()
+{
+ return 1;
+}
+
+#if WIN32
+int __stdcall _DllMainCRTStartup(void *hinstDLL, int reason, void * lpvReserved)
+{
+ return 1;
+}
+#endif
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/test1.c b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/test1.c
new file mode 100644
index 0000000000..6aacfc83b4
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/test1.c
@@ -0,0 +1,183 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c (FreeLibraryAndExitThread)
+**
+** Purpose: Tests the PAL implementation of the FreeLibraryAndExitThread
+** function. FreeLibraryAndExitThread when run will exit the
+** process that it is called within, therefore we create a
+** thread to run the API. Then test for the existance of the
+** thread and access to the library.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+/*Define platform specific information*/
+
+/* SHLEXT is defined only for Unix variants */
+#if defined(SHLEXT)
+#define LibraryName "dlltest"SHLEXT
+#else
+#define LibraryName "dlltest"
+#endif
+
+#define TIMEOUT 60000
+
+BOOL PALAPI StartThreadTest();
+DWORD PALAPI CreateTestThread(LPVOID);
+BOOL PALAPI TestDll(HMODULE, int);
+
+int __cdecl main(int argc, char* argv[])
+{
+ /*Initialize the PAL*/
+ if ((PAL_Initialize(argc, argv)) != 0)
+ {
+ return (FAIL);
+ }
+
+ if (!StartThreadTest())
+ {
+ Fail("ERROR: FreeLibraryAndExitThread test failed.\n");
+ }
+
+ /*Terminate the PAL*/
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
+BOOL PALAPI StartThreadTest()
+{
+ HMODULE hLib;
+ HANDLE hThread;
+ DWORD dwThreadId;
+ LPTHREAD_START_ROUTINE lpStartAddress = &CreateTestThread;
+ LPVOID lpParameter = lpStartAddress;
+ DWORD rc = -1;
+ /*Load library (DLL).*/
+ hLib = LoadLibrary(LibraryName);
+ if(hLib == NULL)
+ {
+ Trace("ERROR: Unable to load library %s\n", LibraryName);
+
+ return (FALSE);
+ }
+
+ /*Start the test thread*/
+ hThread = CreateThread(NULL,
+ (DWORD)0,
+ lpParameter,
+ hLib,
+ (DWORD)NULL,
+ &dwThreadId);
+ if(hThread == NULL)
+ {
+ Trace("ERROR:%u: Unable to create thread.\n",
+ GetLastError());
+
+ FreeLibrary(hLib);
+ return (FALSE);
+ }
+
+ /*Wait on thread.*/
+ rc = WaitForSingleObject(hThread, TIMEOUT);
+ if( rc != WAIT_OBJECT_0 )
+ {
+ Trace("ERROR:%u: hThread=0x%4.4lx not exited by "
+ "FreeLibraryAndExitThread, RC[%d]\n",
+ GetLastError(),
+ hThread, rc);
+
+// There is a possibility that the other thread might
+// still be using the library VSW:337893
+// FreeLibrary(hLib);
+ CloseHandle(hThread);
+ return (FALSE);
+ }
+
+ /*Test access to DLL.*/
+ if(!TestDll(hLib, 0))
+ {
+ Trace("ERROR: TestDll function returned FALSE "
+ "expected TRUE\n.");
+
+ CloseHandle(hThread);
+ return (FALSE);
+ }
+
+ FreeLibrary(hLib);
+ /*Clean-up thread.*/
+ CloseHandle(hThread);
+
+ return (TRUE);
+}
+
+BOOL PALAPI TestDll(HMODULE hLib, int testResult)
+{
+ int RetVal;
+ char FunctName[] = "DllTest";
+ FARPROC DllAddr;
+
+ /* Attempt to grab the proc address of the dll function.
+ * This one should succeed.*/
+ if(testResult == 1)
+ {
+ DllAddr = GetProcAddress(hLib, FunctName);
+ if(DllAddr == NULL)
+ {
+ Trace("ERROR: Unable to load function \"%s\" library \"%s\"\n",
+ FunctName,
+ LibraryName);
+ return (FALSE);
+ }
+ /* Run the function in the DLL,
+ * to ensure that the DLL was loaded properly.*/
+ RetVal = DllAddr();
+ if (RetVal != 1)
+ {
+ Trace("ERROR: Unable to receive correct information from DLL! "
+ ":expected \"1\", returned \"%d\"\n",
+ RetVal);
+ return (FALSE);
+ }
+ }
+
+ /* Attempt to grab the proc address of the dll function.
+ * This one should fail.*/
+ if(testResult == 0)
+ {
+ DllAddr = GetProcAddress(hLib, FunctName);
+ if(DllAddr != NULL)
+ {
+ Trace("ERROR: Able to load function \"%s\" from free'd"
+ " library \"%s\"\n",
+ FunctName,
+ LibraryName);
+ return (FALSE);
+ }
+ }
+ return (TRUE);
+}
+
+DWORD PALAPI CreateTestThread(LPVOID lpParam)
+{
+ /* Test access to DLL.*/
+ TestDll(lpParam, 1);
+
+ /*Free library and exit thread.*/
+ FreeLibraryAndExitThread(lpParam, (DWORD)0);
+
+ /* NOT REACHED */
+
+ /*Infinite loop, we should not get here.*/
+ while(1);
+
+ return (DWORD)0;
+}
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/testinfo.dat
new file mode 100644
index 0000000000..455829c0d5
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = FreeLibraryAndExitThread
+Name = Positive test for FreeLibraryAndExitThread
+TYPE = DEFAULT
+EXE1 = test1
+LIB1 = dlltest
+Description
+= Tests the PAL implementation of the FreeLibraryAndExitThread
+= function. When run, FreeLibraryAndExitThread will exit the
+= process that it is called within, therefore we create a
+= thread to run the API. Then we test for the existance of the
+= thread and access to the library.
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/CMakeLists.txt
new file mode 100644
index 0000000000..a1128c62b8
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetModuleFileNameA.c
+)
+
+add_executable(paltest_getmodulefilenamea_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getmodulefilenamea_test1 coreclrpal)
+
+target_link_libraries(paltest_getmodulefilenamea_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/GetModuleFileNameA.c b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/GetModuleFileNameA.c
new file mode 100644
index 0000000000..d05f0ac6a9
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/GetModuleFileNameA.c
@@ -0,0 +1,92 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: getmodulefilenamea.c
+**
+** Purpose: Positive test the GetModuleFileName API.
+** Call GetModuleFileName to retrieve the specified
+** module full path and file name
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+
+#define MODULENAMEBUFFERSIZE 1024
+
+/* SHLEXT is defined only for Unix variants */
+
+#if defined(SHLEXT)
+#define ModuleName "librotor_pal"SHLEXT
+#define Delimiter "/"
+#else
+#define ModuleName "rotor_pal.dll"
+#define Delimiter "\\"
+#endif
+
+int __cdecl main(int argc, char *argv[])
+{
+ HMODULE ModuleHandle;
+ int err;
+ DWORD ModuleNameLength;
+ char ModuleFileNameBuf[MODULENAMEBUFFERSIZE]="";
+ char* TempBuf = NULL;
+ char* LastBuf = NULL;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+
+ //load a module
+ ModuleHandle = LoadLibrary(ModuleName);
+ if(!ModuleHandle)
+ {
+ Fail("Failed to call LoadLibrary API!\n");
+ }
+
+
+ //retrieve the specified module full path and file name
+ ModuleNameLength = GetModuleFileName(
+ ModuleHandle,//specified module handle
+ ModuleFileNameBuf,//buffer for module file name
+ MODULENAMEBUFFERSIZE);
+
+ //strip out all full path
+ TempBuf = strtok(ModuleFileNameBuf,Delimiter);
+ LastBuf = TempBuf;
+ while(NULL != TempBuf)
+ {
+ LastBuf = TempBuf;
+ TempBuf = strtok(NULL,Delimiter);
+ }
+
+
+ if(0 == ModuleNameLength || strcmp(ModuleName,LastBuf))
+ {
+ Trace("\nFailed to all GetModuleFileName API!\n");
+ err = FreeLibrary(ModuleHandle);
+ if(0 == err)
+ {
+ Fail("\nFailed to all FreeLibrary API!\n");
+ }
+ Fail("");
+ }
+
+ //decrement the reference count of the loaded dll
+ err = FreeLibrary(ModuleHandle);
+ if(0 == err)
+ {
+ Fail("\nFailed to all FreeLibrary API!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/testinfo.dat
new file mode 100644
index 0000000000..8075e840ce
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = GetModuleFileNameA
+Name = Positive test for GetModuleFileNameA API
+TYPE = DEFAULT
+EXE1 = getmodulefilenamea
+Description
+=Test the GetModuleFileNameA to retrieve the specified module
+=full path and file name
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/CMakeLists.txt
new file mode 100644
index 0000000000..c35e9acc5e
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetModuleFileNameA.c
+)
+
+add_executable(paltest_getmodulefilenamea_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getmodulefilenamea_test2 coreclrpal)
+
+target_link_libraries(paltest_getmodulefilenamea_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/GetModuleFileNameA.c b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/GetModuleFileNameA.c
new file mode 100644
index 0000000000..e8aed6d30e
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/GetModuleFileNameA.c
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: getmodulefilenamea.c
+**
+** Purpose: Positive test the GetModuleFileNameA API.
+** Call GetModuleFileName to retrieve current process
+** full path and file name by passing a NULL module handle
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+
+#define MODULENAMEBUFFERSIZE 1024
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ DWORD ModuleNameLength;
+ char ModuleFileNameBuf[MODULENAMEBUFFERSIZE]="";
+ int err;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+
+ //retrieve the current process full path and file name
+ //by passing a NULL module handle
+ ModuleNameLength = GetModuleFileName(
+ NULL, //a NULL handle
+ ModuleFileNameBuf,//buffer for module file name
+ MODULENAMEBUFFERSIZE);
+
+ if(0 == ModuleNameLength)
+ {
+ Fail("\nFailed to all GetModuleFileName API!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/testinfo.dat
new file mode 100644
index 0000000000..45fdca6ae7
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = GetModuleFileNameA
+Name = Positive test for GetModuleFileNameA API
+TYPE = DEFAULT
+EXE1 = getmodulefilenamea
+Description
+=Test the GetModuleFileNameA to retrieve current process full
+=full path and file name by passing a NULL module handle
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..c702d07908
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetModuleFileNameW.c
+)
+
+add_executable(paltest_getmodulefilenamew_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getmodulefilenamew_test1 coreclrpal)
+
+target_link_libraries(paltest_getmodulefilenamew_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/GetModuleFileNameW.c b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/GetModuleFileNameW.c
new file mode 100644
index 0000000000..4c1c3b00ab
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/GetModuleFileNameW.c
@@ -0,0 +1,112 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: getmodulefilenamew.c
+**
+** Purpose: Test the GetModuleFileNameW to retrieve the specified module
+** full path and file name in UNICODE.
+**
+**
+**============================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+#define MODULENAMEBUFFERSIZE 1024
+
+/* SHLEXT is defined only for Unix variants */
+
+#if defined(SHLEXT)
+#define ModuleName "librotor_pal"SHLEXT
+#define Delimiter "/"
+#else
+#define ModuleName "rotor_pal.dll"
+#define Delimiter "\\"
+#endif
+
+int __cdecl main(int argc, char *argv[])
+{
+ HMODULE ModuleHandle;
+ int err;
+ WCHAR *lpModuleName;
+ DWORD ModuleNameLength;
+ WCHAR *ModuleFileNameBuf;
+ char* TempBuf = NULL;
+ char* LastBuf = NULL;
+ char NewModuleFileNameBuf[MODULENAMEBUFFERSIZE+200] = "";
+
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ ModuleFileNameBuf = malloc(MODULENAMEBUFFERSIZE*sizeof(WCHAR));
+
+ //convert a normal string to a wide one
+ lpModuleName = convert(ModuleName);
+
+ //load a module
+ ModuleHandle = LoadLibrary(lpModuleName);
+
+ //free the memory
+ free(lpModuleName);
+
+ if(!ModuleHandle)
+ {
+ Fail("Failed to call LoadLibrary API!\n");
+ }
+
+
+ //retrieve the specified module full path and file name
+ ModuleNameLength = GetModuleFileName(
+ ModuleHandle,//specified module handle
+ ModuleFileNameBuf,//buffer for module file name
+ MODULENAMEBUFFERSIZE);
+
+
+
+ //convert a wide full path name to a normal one
+ strcpy(NewModuleFileNameBuf,convertC(ModuleFileNameBuf));
+
+ //strip out all full path
+ TempBuf = strtok(NewModuleFileNameBuf,Delimiter);
+ LastBuf = TempBuf;
+ while(NULL != TempBuf)
+ {
+ LastBuf = TempBuf;
+ TempBuf = strtok(NULL,Delimiter);
+ }
+
+
+ //free the memory
+ free(ModuleFileNameBuf);
+
+ if(0 == ModuleNameLength || strcmp(ModuleName,LastBuf))
+ {
+ Trace("\nFailed to all GetModuleFileName API!\n");
+ err = FreeLibrary(ModuleHandle);
+ if(0 == err)
+ {
+ Fail("\nFailed to all FreeLibrary API!\n");
+ }
+ Fail("");
+ }
+
+
+
+ //decrement the reference count of the loaded dll
+ err = FreeLibrary(ModuleHandle);
+ if(0 == err)
+ {
+ Fail("\nFailed to all FreeLibrary API!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/testinfo.dat
new file mode 100644
index 0000000000..c8d94b73b4
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = GetModuleFileNameW
+Name = Positive test for GetModuleFileNameW API
+TYPE = DEFAULT
+EXE1 = getmodulefilenamew
+Description
+=Test the GetModuleFileNameW to retrieve the specified module
+=full path and file name in UNICODE
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/CMakeLists.txt
new file mode 100644
index 0000000000..857feb330d
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetModuleFileNameW.c
+)
+
+add_executable(paltest_getmodulefilenamew_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getmodulefilenamew_test2 coreclrpal)
+
+target_link_libraries(paltest_getmodulefilenamew_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/GetModuleFileNameW.c b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/GetModuleFileNameW.c
new file mode 100644
index 0000000000..6009a9d298
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/GetModuleFileNameW.c
@@ -0,0 +1,57 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: getmodulefilenamew.c
+**
+** Purpose: Positive test the GetModuleFileName API.
+** Call GetModuleFileName to retrieve current process
+** full path and file name by passing a NULL module handle
+** in UNICODE
+**
+**
+**============================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+#define MODULENAMEBUFFERSIZE 1024
+
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ DWORD ModuleNameLength;
+ WCHAR *ModuleFileNameBuf;
+ int err;
+
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ ModuleFileNameBuf = malloc(MODULENAMEBUFFERSIZE*sizeof(WCHAR));
+
+ //retrieve the current process full path and file name
+ //by passing a NULL module handle
+ ModuleNameLength = GetModuleFileName(
+ NULL, //a NULL handle
+ ModuleFileNameBuf,//buffer for module file name
+ MODULENAMEBUFFERSIZE);
+
+ //free the memory
+ free(ModuleFileNameBuf);
+
+ if(0 == ModuleNameLength)
+ {
+ Fail("\nFailed to all GetModuleFileName API!\n");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/testinfo.dat
new file mode 100644
index 0000000000..8b8740149c
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = GetModuleFileNameW
+Name = Positive test for GetModuleFileNameW API
+TYPE = DEFAULT
+EXE1 = getmodulefilenamew
+Description
+=Test the GetModuleFileNameW to retrieve current process full
+=full path and file name by passing a NULL module handle in UNICODE
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/CMakeLists.txt
new file mode 100644
index 0000000000..541ef8b98e
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/CMakeLists.txt
@@ -0,0 +1,20 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+ testlib.c
+)
+
+add_executable(paltest_getprocaddress_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getprocaddress_test1 coreclrpal)
+
+target_link_libraries(paltest_getprocaddress_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/test1.c b/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/test1.c
new file mode 100644
index 0000000000..f0b76c615f
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/test1.c
@@ -0,0 +1,111 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c (filemapping_memmgt\getprocaddress\test1)
+**
+** Purpose: Positive test the GetProcAddress API.
+** The first test calls GetProcAddress to retrieve the
+** address of SimpleFunction inside testlib by its name,
+** then calls the function and checks that it worked.
+**
+**
+**===========================================================================*/
+#include <palsuite.h>
+
+typedef int (__stdcall *SIMPLEFUNCTION)(int);
+
+/* SHLEXT is defined only for Unix variants */
+#if defined(SHLEXT)
+#define lpModuleName "testlib"SHLEXT
+#else
+#define lpModuleName "testlib.dll"
+#endif
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ HMODULE hModule;
+ SIMPLEFUNCTION procAddressByName;
+
+#if WIN32
+ const char *FunctionName = "_SimpleFunction@4";
+#else
+ const char *FunctionName = "SimpleFunction";
+#endif
+
+ /* Initialize the PAL environment. */
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /* load a module */
+ hModule = LoadLibrary(lpModuleName);
+ if(!hModule)
+ {
+ Fail("Unexpected error: "
+ "LoadLibrary(%s) failed.\n",
+ lpModuleName);
+ }
+
+ /*
+ * Test 1
+ *
+ * Get the address of a function
+ */
+ procAddressByName = (SIMPLEFUNCTION) GetProcAddress(hModule,FunctionName);
+ if(!procAddressByName)
+ {
+ Trace("ERROR: Unable to get address of SimpleFunction by its name. "
+ "GetProcAddress returned NULL with error %d\n",
+ GetLastError());
+
+ /* Cleanup */
+ err = FreeLibrary(hModule);
+ if(0 == err)
+ {
+ Fail("Unexpected error: Failed to FreeLibrary %s\n",
+ lpModuleName);
+ }
+ Fail("");
+ }
+
+ /* Call the function to see that it really worked */
+ /* Simple function adds 1 to the argument passed */
+ if( 2 != ((procAddressByName)(1)))
+ {
+ Trace("ERROR: Problem calling the function by its address.\n");
+
+ /* Cleanup */
+ err = FreeLibrary(hModule);
+ if(0 == err)
+ {
+ Fail("Unexpected error: Failed to FreeLibrary %s\n",
+ lpModuleName);
+ }
+ Fail("");
+ }
+
+ /* Cleanup */
+ err = FreeLibrary(hModule);
+ if(0 == err)
+ {
+ Fail("Unexpected error: Failed to FreeLibrary %s\n",
+ lpModuleName);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/testinfo.dat
new file mode 100644
index 0000000000..31b262e31e
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/testinfo.dat
@@ -0,0 +1,19 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = filemapping_memmgt
+Function = getprocaddress
+Name = Positive test for GetProcAddress API
+TYPE = DEFAULT
+EXE1 = test1
+LIB1 = testlib
+Description
+=Positive test the GetProcAddress API.
+=The first test calls GetProcAddress to retrieve the
+=address of strcpy by its name, then calls the function and
+=checks that it worked. The second part of the test
+=calls GetProcAddress to retrieve the address of
+=strcpy by its ordinal, then calls the function and
+=checks that it worked.
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/testlib.c b/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/testlib.c
new file mode 100644
index 0000000000..e8fe48e05d
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/testlib.c
@@ -0,0 +1,33 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: testlib.c (filemapping_memmgt\getprocaddress\test1)
+**
+** Purpose: Create a simple library containing one function
+** to test GetProcAddress
+**
+**
+**===========================================================================*/
+#include "pal.h"
+
+#if WIN32
+__declspec(dllexport)
+#endif
+
+/**
+ * Simple function that returns i+1
+ */
+int __stdcall SimpleFunction(int i)
+{
+ return i+1;
+}
+
+#if WIN32
+int __stdcall _DllMainCRTStartup(void *hinstDLL, int reason, void *lpvReserved)
+{
+ return 1;
+}
+#endif
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/CMakeLists.txt
new file mode 100644
index 0000000000..60a5ba1a6e
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/CMakeLists.txt
@@ -0,0 +1,20 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+ testlib.c
+)
+
+add_executable(paltest_getprocaddress_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getprocaddress_test2 coreclrpal)
+
+target_link_libraries(paltest_getprocaddress_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/test2.c b/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/test2.c
new file mode 100644
index 0000000000..9107728423
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/test2.c
@@ -0,0 +1,152 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test2.c (filemapping_memmgt\getprocaddress\test2)
+**
+** Purpose: This test tries to call GetProcAddress with
+** a NULL handle, with a NULL function name, with an empty
+** function name, with an invalid name and with an
+** invalid ordinal value.
+**
+**
+**===========================================================================*/
+#include <palsuite.h>
+
+
+/* SHLEXT is defined only for Unix variants */
+#if defined(SHLEXT)
+#define lpModuleName "testlib"SHLEXT
+#else
+#define lpModuleName "testlib.dll"
+#endif
+
+
+/**
+ * main
+ */
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ HMODULE hModule;
+ FARPROC procAddress;
+
+ /* Initialize the PAL environment. */
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* load a module */
+ hModule = LoadLibrary(lpModuleName);
+ if(!hModule)
+ {
+ Fail("Unexpected error: "
+ "LoadLibrary(%s) failed.\n",
+ lpModuleName);
+ }
+
+ /*
+ * Test 1
+ *
+ * Call GetProcAddress with a NULL handle
+ */
+ procAddress = GetProcAddress(NULL,"SimpleFunction");
+ if(procAddress != NULL)
+ {
+ Trace("ERROR: GetProcAddress with a NULL handle "
+ "returned a non-NULL value when it should have "
+ "returned a NULL value with an error\n");
+
+ /* Cleanup */
+ err = FreeLibrary(hModule);
+ if(0 == err)
+ {
+ Fail("Unexpected error: Failed to FreeLibrary %s\n",
+ lpModuleName);
+ }
+ Fail("");
+ }
+
+ /**
+ * Test 2
+ *
+ * Call GetProcAddress with a NULL function name
+ */
+
+ procAddress = GetProcAddress(hModule,NULL);
+ if(procAddress != NULL)
+ {
+ Trace("ERROR: GetProcAddress with a NULL function name "
+ "returned a non-NULL value when it should have "
+ "returned a NULL value with an error\n");
+
+ /* Cleanup */
+ err = FreeLibrary(hModule);
+ if(0 == err)
+ {
+ Fail("Unexpected error: Failed to FreeLibrary %s\n",
+ lpModuleName);
+ }
+ Fail("");
+ }
+
+ /**
+ * Test 3
+ *
+ * Call GetProcAddress with an empty function name string
+ */
+
+ procAddress = GetProcAddress(hModule,"");
+ if(procAddress != NULL)
+ {
+ Trace("ERROR: GetProcAddress with an empty function name "
+ "returned a non-NULL value when it should have "
+ "returned a NULL value with an error\n");
+
+ /* Cleanup */
+ err = FreeLibrary(hModule);
+ if(0 == err)
+ {
+ Fail("Unexpected error: Failed to FreeLibrary %s\n",
+ lpModuleName);
+ }
+ Fail("");
+ }
+
+ /**
+ * Test 4
+ *
+ * Call GetProcAddress with an invalid name
+ */
+
+ procAddress = GetProcAddress(hModule,"Simple Function");
+ if(procAddress != NULL)
+ {
+ Trace("ERROR: GetProcAddress with an invalid function name "
+ "returned a non-NULL value when it should have "
+ "returned a NULL value with an error\n");
+
+ /* Cleanup */
+ err = FreeLibrary(hModule);
+ if(0 == err)
+ {
+ Fail("Unexpected error: Failed to FreeLibrary %s\n",
+ lpModuleName);
+ }
+ Fail("");
+ }
+
+ /* cleanup */
+ err = FreeLibrary(hModule);
+ if(0 == err)
+ {
+ Fail("Unexpected error: Failed to FreeLibrary %s\n",
+ lpModuleName);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/testinfo.dat
new file mode 100644
index 0000000000..8bf50ad812
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/testinfo.dat
@@ -0,0 +1,18 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = filemapping_memmgt
+Function = getprocaddress
+Name = Negative test for GetProcAddress API
+TYPE = DEFAULT
+EXE1 = test2
+LIB1 = testlib
+Description
+=This test tries to call GetProcAddress with
+=a NULL handle, with a NULL function name, with an empty
+=function name, with an invalid name and with an
+=nvalid ordinal value.
+
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/testlib.c b/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/testlib.c
new file mode 100644
index 0000000000..23e58e871e
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/testlib.c
@@ -0,0 +1,33 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: testlib.c (filemapping_memmgt\getprocaddress\test2)
+**
+** Purpose: Create a simple library containing one function
+** to test GetProcAddress
+**
+**
+**===========================================================================*/
+#include "pal.h"
+
+#if WIN32
+__declspec(dllexport)
+#endif
+
+/**
+ * Simple function that returns i+1
+ */
+int __stdcall SimpleFunction(int i)
+{
+ return i+1;
+}
+
+#if WIN32
+int __stdcall _DllMainCRTStartup(void *hinstDLL, int reason, void *lpvReserved)
+{
+ return 1;
+}
+#endif
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetProcessHeap/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/GetProcessHeap/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/GetProcessHeap/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetProcessHeap/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/GetProcessHeap/test1/CMakeLists.txt
new file mode 100644
index 0000000000..18871abf00
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/GetProcessHeap/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetProcessHeap.c
+)
+
+add_executable(paltest_getprocessheap_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getprocessheap_test1 coreclrpal)
+
+target_link_libraries(paltest_getprocessheap_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetProcessHeap/test1/GetProcessHeap.c b/src/pal/tests/palsuite/filemapping_memmgt/GetProcessHeap/test1/GetProcessHeap.c
new file mode 100644
index 0000000000..bec6b5c616
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/GetProcessHeap/test1/GetProcessHeap.c
@@ -0,0 +1,39 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: getprocheap.c
+**
+** Purpose: Positive test the GetProcessHeap API.
+** Call GetProcessHeap to retrieve the handle of
+** calling process heap
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ HANDLE ProcessHeapHandle;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ //Retrieve the calling process heap handle
+ ProcessHeapHandle = GetProcessHeap();
+
+ if(!ProcessHeapHandle)
+ {
+ Fail("\nFailed to call GetProcessHeap API!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetProcessHeap/test1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/GetProcessHeap/test1/testinfo.dat
new file mode 100644
index 0000000000..cec3dd12d7
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/GetProcessHeap/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = GetProcessHeap
+Name = Positive test for GetProcessHeap API retrieve the handle of calling process heap
+TYPE = DEFAULT
+EXE1 = getprocessheap
+Description
+=Test the GetProcessHeap to retrieve the handle of the calling process heap
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/CMakeLists.txt
new file mode 100644
index 0000000000..1962ade358
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test1/CMakeLists.txt
new file mode 100644
index 0000000000..3a64a0c58a
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ HeapAlloc.c
+)
+
+add_executable(paltest_heapalloc_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_heapalloc_test1 coreclrpal)
+
+target_link_libraries(paltest_heapalloc_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test1/HeapAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test1/HeapAlloc.c
new file mode 100644
index 0000000000..04de274e80
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test1/HeapAlloc.c
@@ -0,0 +1,100 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: heapalloc.c
+**
+** Purpose: Positive test the HeapAlloc API.
+** Call HeapAlloc by pssing zero as control flag
+** Call HeapAlloc by passing HEAP_ZERO_MEMORY as control flag
+** Call HeapAlloc to allocate one byte heap memory
+** Call HeapAlloc to allocate maximum available heap memory
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+#define HEAPSIZE 64
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ HANDLE ProcessHeapHandle;
+ LPVOID lpHeap;
+
+ /* Initialize the PAL environment */
+ err = PAL_Initialize(argc, argv);
+ if(0 != 0)
+ {
+ ExitProcess(FAIL);
+ }
+
+ /* Retrieve the calling process heap handle */
+ ProcessHeapHandle = GetProcessHeap();
+
+ if(!ProcessHeapHandle)
+ {
+ Fail("\nFailed to call GetProcessHeap API!\n");
+ }
+
+ /* allocate a heap memory in specified size */
+ lpHeap = HeapAlloc(ProcessHeapHandle, /* HeapHandle */
+ 0, /* control flag */
+ HEAPSIZE); /* /specify the heap size */
+ if(NULL == lpHeap)
+ {
+ Fail("Failed to call HeapAlloc API!\n");
+ }
+
+ /* free the heap memory */
+ err = HeapFree(ProcessHeapHandle,
+ 0,
+ lpHeap);
+ if(0 == err)
+ {
+ Fail("Failed to call HeapFree API!\n");
+ }
+
+
+ /* allocate a heap memory in 1 byte size */
+ lpHeap = HeapAlloc(ProcessHeapHandle, /* HeapHandle */
+ 0, /* control flag */
+ 1); /* specify the heap size*/
+ if(NULL == lpHeap)
+ {
+ Fail("Failed to call HeapAlloc API to allocate one byte heap memory!\n");
+ }
+
+ /* free the heap memory */
+ err = HeapFree(ProcessHeapHandle,
+ 0,
+ lpHeap);
+ if(0 == err)
+ {
+ Fail("Failed to call HeapFree API!\n");
+ }
+
+ /* allocate a heap memory and initialize it to zero */
+ lpHeap = HeapAlloc(ProcessHeapHandle,/* HeapHandle */
+ HEAP_ZERO_MEMORY,/* control flag */
+ HEAPSIZE); /* specify the heap size */
+ if(NULL == lpHeap)
+ {
+ Fail("Failed to call HeapAlloc API with HEAP_ZERO_MEMORY control flag!\n");
+ }
+
+ /* free the heap memory */
+ err = HeapFree(ProcessHeapHandle,
+ 0,
+ lpHeap);
+ if(0 == err)
+ {
+ Fail("Failed to call HeapFree API!\n");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test1/testinfo.dat
new file mode 100644
index 0000000000..9b6064349d
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = HeapAlloc
+Name = Positive test for HeapAlloc API
+TYPE = DEFAULT
+EXE1 = heapalloc
+Description
+=Test the HeapAlloc by passing zero as the control flag
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test2/CMakeLists.txt
new file mode 100644
index 0000000000..5253110d8d
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ HeapAlloc.c
+)
+
+add_executable(paltest_heapalloc_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_heapalloc_test2 coreclrpal)
+
+target_link_libraries(paltest_heapalloc_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test2/HeapAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test2/HeapAlloc.c
new file mode 100644
index 0000000000..5f4ff90498
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test2/HeapAlloc.c
@@ -0,0 +1,59 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: heapalloc.c
+**
+** Purpose: Positive test the HeapAlloc API.
+** Call HeapAlloc with HEAP_ZERO_MEMORY control flag
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+#define HEAPSIZE 64
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ HANDLE ProcessHeapHandle;
+ LPVOID lpHeap;
+
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ //Retrieve the calling process heap handle
+ ProcessHeapHandle = GetProcessHeap();
+
+ if(!ProcessHeapHandle)
+ {
+ Fail("\nFailed to call GetProcessHeap API!\n");
+ }
+
+ lpHeap = HeapAlloc(ProcessHeapHandle,//HeapHandle
+ HEAP_ZERO_MEMORY,//control flag
+ HEAPSIZE); //specify the heap size
+ if(NULL == lpHeap)
+ {
+ Fail("Failed to call HeapAlloc API!\n");
+ }
+
+ //free the heap memory
+ err = HeapFree(ProcessHeapHandle,
+ 0,
+ lpHeap);
+ if(0 == err)
+ {
+ Fail("Failed to call HeapFree API!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test2/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test2/testinfo.dat
new file mode 100644
index 0000000000..5c6e77d2cc
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test2/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = HeapAlloc
+Name = Positive test for HeapAlloc API
+TYPE = DEFAULT
+EXE1 = heapalloc
+Description
+=Test the HeapAlloc with HEAP_ZERO_MEMORY control flag
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test3/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test3/CMakeLists.txt
new file mode 100644
index 0000000000..f0b89461d2
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ HeapAlloc.c
+)
+
+add_executable(paltest_heapalloc_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_heapalloc_test3 coreclrpal)
+
+target_link_libraries(paltest_heapalloc_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test3/HeapAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test3/HeapAlloc.c
new file mode 100644
index 0000000000..4a74fe8194
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test3/HeapAlloc.c
@@ -0,0 +1,62 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: heapalloc.c
+**
+** Purpose: Positive test the HeapAlloc API.
+** Call HeapAlloc asking for zero bytes
+** with HEAP_ZERO_MEMORY control flag
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+#define HEAPSIZE 0
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ HANDLE ProcessHeapHandle;
+ LPVOID lpHeap;
+
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ //Retrieve the calling process heap handle
+ ProcessHeapHandle = GetProcessHeap();
+
+ if(!ProcessHeapHandle)
+ {
+ Fail("\nFailed to call GetProcessHeap API!\n");
+ }
+
+ lpHeap = HeapAlloc(ProcessHeapHandle,//HeapHandle
+ HEAP_ZERO_MEMORY,//control flag
+ HEAPSIZE); //specify the heap size
+
+ //lpHeap should be non-NULL pointer
+ if(NULL == lpHeap)
+ {
+ Fail("Failed to call HeapAlloc API, when number of bytes to be allocated is zero!\n");
+ }
+
+ //free the heap memory
+ err = HeapFree(ProcessHeapHandle,
+ 0,
+ lpHeap);
+ if(0 == err)
+ {
+ Fail("Failed to call HeapFree API!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test3/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test3/testinfo.dat
new file mode 100644
index 0000000000..c7d67d3b4f
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test3/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = HeapAlloc
+Name = Positive test for HeapAlloc API
+TYPE = DEFAULT
+EXE1 = heapalloc
+Description
+=Test the HeapAlloc asking for zero bytes with HEAP_ZERO_MEMORY control flag
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapFree/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/HeapFree/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapFree/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapFree/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/HeapFree/test1/CMakeLists.txt
new file mode 100644
index 0000000000..898047a9ad
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapFree/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ HeapFree.c
+)
+
+add_executable(paltest_heapfree_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_heapfree_test1 coreclrpal)
+
+target_link_libraries(paltest_heapfree_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapFree/test1/HeapFree.c b/src/pal/tests/palsuite/filemapping_memmgt/HeapFree/test1/HeapFree.c
new file mode 100644
index 0000000000..37b6b3bf60
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapFree/test1/HeapFree.c
@@ -0,0 +1,62 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: heapfree.c
+**
+** Purpose: Positive test the HeapFree API.
+** Call HeapFree to free a memory block
+** and try to free an invalid memory block
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+#define HEAPSIZE 64
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ HANDLE ProcessHeapHandle;
+ LPVOID lpHeap;
+
+
+ /* Initialize the PAL environment */
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Retrieve the calling process heap handle */
+ ProcessHeapHandle = GetProcessHeap();
+
+ if(!ProcessHeapHandle)
+ {
+ Fail("\nFailed to call GetProcessHeap API!\n");
+ }
+
+
+ lpHeap = HeapAlloc(ProcessHeapHandle,/* HeapHandle */
+ HEAP_ZERO_MEMORY,/* control flag */
+ HEAPSIZE); /* specify the heap size */
+ if(NULL == lpHeap)
+ {
+ Fail("Failed to call HeapAlloc API!\n");
+ }
+
+
+ /* free a allocate heap memory */
+ err = HeapFree(ProcessHeapHandle,
+ 0,
+ lpHeap);
+
+ if(0 == err)
+ {
+ Fail("Failed to call HeapFree API!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapFree/test1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/HeapFree/test1/testinfo.dat
new file mode 100644
index 0000000000..c6f18167e3
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapFree/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = HeapFree
+Name = Positive test for HeapFree API to free an allocated heap block
+TYPE = DEFAULT
+EXE1 = heapfree
+Description
+=Test the HeapFree to free a memory block
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/CMakeLists.txt
new file mode 100644
index 0000000000..8083faf655
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/CMakeLists.txt
@@ -0,0 +1,8 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test1/CMakeLists.txt
new file mode 100644
index 0000000000..1decb02c73
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_heaprealloc_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_heaprealloc_test1 coreclrpal)
+
+target_link_libraries(paltest_heaprealloc_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test1/test1.c b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test1/test1.c
new file mode 100644
index 0000000000..497d208eca
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test1/test1.c
@@ -0,0 +1,72 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test1.c
+**
+** Purpose: Allocate some memory. Then reallocate that memory. Ensure the
+** return values are correct, and also that data placed in the allocated
+** memory carries over to the reallocated block.
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ HANDLE TheHeap;
+ char* TheMemory;
+ char* ReAllocMemory;
+ int i;
+
+ if(PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ TheHeap = GetProcessHeap();
+
+ if(TheHeap == NULL)
+ {
+ Fail("ERROR: GetProcessHeap() returned NULL when it was called. "
+ "GetLastError() returned %d.",GetLastError());
+ }
+
+ /* Allocate 100 bytes on the heap */
+ if((TheMemory = HeapAlloc(TheHeap, 0, 100)) == NULL)
+ {
+ Fail("ERROR: HeapAlloc returned NULL when it was called. "
+ "GetLastError() returned %d.",GetLastError());
+ }
+
+ /* Set each byte of that memory block to 'x' */
+ memset(TheMemory, 'X', 100);
+
+ /* Reallocate the memory */
+ ReAllocMemory = HeapReAlloc(TheHeap, 0, TheMemory, 100);
+
+ if(ReAllocMemory == NULL)
+ {
+ Fail("ERROR: HeapReAlloc failed to reallocate the 100 bytes of "
+ "heap memory. GetLastError returns %d.",GetLastError());
+ }
+
+ /* Check that each byte of the memory Reallocated is 'x' */
+
+ for(i=0; i<100; ++i)
+ {
+ if(ReAllocMemory[i] != 'X')
+ {
+ Fail("ERROR: Byte number %d of the reallocated memory block "
+ "is not set to 'X' as it should be.",i);
+ }
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test1/testinfo.dat
new file mode 100644
index 0000000000..ad3a3ffc73
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = HeapReAlloc
+Name = Positive test for HeapReAlloc to check normal behaviour
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Allocate some memory. Then reallocate that memory. Ensure the
+= return values are correct, and also that data placed in the allocated
+= memory carries over to the reallocated block.
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test2/CMakeLists.txt
new file mode 100644
index 0000000000..6f5510387a
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_heaprealloc_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_heaprealloc_test2 coreclrpal)
+
+target_link_libraries(paltest_heaprealloc_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test2/test2.c b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test2/test2.c
new file mode 100644
index 0000000000..13e789f901
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test2/test2.c
@@ -0,0 +1,79 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test2.c
+**
+** Purpose: Allocate some memory. Then reallocate that memory into less
+** space than the original amount. Ensure the
+** return values are correct, and also that data placed in the allocated
+** memory carries over to the reallocated block.
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ HANDLE TheHeap;
+ char* TheMemory;
+ char* ReAllocMemory;
+ int i;
+
+ if(PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ TheHeap = GetProcessHeap();
+
+ if(TheHeap == NULL)
+ {
+ Fail("ERROR: GetProcessHeap() returned NULL when it was called. "
+ "GetLastError() returned %d.",GetLastError());
+ }
+
+ /* Allocate 200 bytes on the heap */
+ if((TheMemory = HeapAlloc(TheHeap, 0, 200)) == NULL)
+ {
+ Fail("ERROR: HeapAlloc returned NULL when it was called. "
+ "GetLastError() returned %d.",GetLastError());
+ }
+
+ /* Set the first 100 bytes to 'X' */
+ memset(TheMemory, 'X', 100);
+
+ /* Set the second 100 bytes to 'Z' */
+ memset(TheMemory+100, 'Z', 100);
+
+ /* Reallocate the memory to 100 bytes */
+ ReAllocMemory = HeapReAlloc(TheHeap, 0, TheMemory, 100);
+
+ if(ReAllocMemory == NULL)
+ {
+ Fail("ERROR: HeapReAlloc failed to reallocate the 100 bytes of "
+ "heap memory. GetLastError returns %d.",GetLastError());
+ }
+
+ /* Check that each of the first 100 bytes hasn't lost any data.
+ Anything beyond the first 100 might still be valid, but we can't
+ gaurentee it.
+ */
+
+ for(i=0; i<100; ++i)
+ {
+ /* Note: Cast to char* so the function knows the size is 1 */
+ if(ReAllocMemory[i] != 'X')
+ {
+ Fail("ERROR: Byte number %d of the reallocated memory block "
+ "is not set to 'X' as it should be.",i);
+ }
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test2/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test2/testinfo.dat
new file mode 100644
index 0000000000..95a12aafd5
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test2/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = HeapReAlloc
+Name = Positive test for HeapReAlloc to reallocate into a smaller space
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Allocate some memory. Then reallocate that memory into less
+= space than the origional amount. Ensure the
+= return values are correct, and also that data placed in the allocated
+= memory carries over to the reallocated block.
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test3/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test3/CMakeLists.txt
new file mode 100644
index 0000000000..7ad836706a
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_heaprealloc_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_heaprealloc_test3 coreclrpal)
+
+target_link_libraries(paltest_heaprealloc_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test3/test3.c b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test3/test3.c
new file mode 100644
index 0000000000..dea9de348d
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test3/test3.c
@@ -0,0 +1,78 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test3.c
+**
+** Purpose: Allocate some memory. Then reallocate that memory into a
+** bigger space on the heap. Check that the first portion of the data is
+** unchanged. Then set the new portion to a value, to ensure that it is
+** properly writable memory.
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ HANDLE TheHeap;
+ char* TheMemory;
+ char* ReAllocMemory;
+ int i;
+
+ if(PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ TheHeap = GetProcessHeap();
+
+ if(TheHeap == NULL)
+ {
+ Fail("ERROR: GetProcessHeap() returned NULL when it was called. "
+ "GetLastError() returned %d.",GetLastError());
+ }
+
+ /* Allocate 100 bytes on the heap */
+ if((TheMemory = HeapAlloc(TheHeap, 0, 100)) == NULL)
+ {
+ Fail("ERROR: HeapAlloc returned NULL when it was called. "
+ "GetLastError() returned %d.",GetLastError());
+ }
+
+ /* Set the first 100 bytes to 'X' */
+ memset(TheMemory, 'X', 100);
+
+ /* Reallocate the memory to 200 bytes */
+ ReAllocMemory = HeapReAlloc(TheHeap, 0, TheMemory, 200);
+
+ if(ReAllocMemory == NULL)
+ {
+ Fail("ERROR: HeapReAlloc failed to reallocate the 100 bytes of "
+ "heap memory. GetLastError returns %d.",GetLastError());
+ }
+
+ /* Check that each of the first 100 bytes hasn't lost any data. */
+ for(i=0; i<100; ++i)
+ {
+
+ if(ReAllocMemory[i] != 'X')
+ {
+ Fail("ERROR: Byte number %d of the reallocated memory block "
+ "is not set to 'X' as it should be.",i);
+ }
+ }
+
+ /* Beyond the first 100 bytes is valid free memory. We'll set all this
+ memory to a value -- though, even if HeapReAlloc didn't work, it might
+ still be possible to memset this memory without raising an exception.
+ */
+ memset(ReAllocMemory+100, 'Z', 100);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test3/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test3/testinfo.dat
new file mode 100644
index 0000000000..ed6da87c33
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test3/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = HeapReAlloc
+Name = Positive test for HeapReAlloc to reallocate into a larger space
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Allocate some memory. Then reallocate that memory into a
+= bigger space on the heap. Check that the first portion of the data is
+= unchanged. Then set the new portion to a value, to ensure that it is
+= properly writable memory.
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test4/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test4/CMakeLists.txt
new file mode 100644
index 0000000000..024a4ef840
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_heaprealloc_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_heaprealloc_test4 coreclrpal)
+
+target_link_libraries(paltest_heaprealloc_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test4/test4.c b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test4/test4.c
new file mode 100644
index 0000000000..cebf904501
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test4/test4.c
@@ -0,0 +1,80 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test4.c
+**
+** Purpose: Call HeapReAlloc with a NULL pointer to memory. It should
+** return NULL.
+**
+**
+**============================================================*/
+
+/* Note: When attempted with a NULL Handle, this test crashes under win32.
+ As such, the behaviour isn't tested here.
+*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ HANDLE TheHeap;
+ LPVOID TheMemory = NULL;
+
+ if(PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ TheHeap = GetProcessHeap();
+
+ if(TheHeap == NULL)
+ {
+ Fail("ERROR: GetProcessHeap() returned NULL when it was called. "
+ "GetLastError() returned %d.",GetLastError());
+ }
+
+ /* Allocate 100 bytes on the heap */
+ if(HeapAlloc(TheHeap, 0, 100) == NULL)
+ {
+ Fail("ERROR: HeapAlloc returned NULL when it was called. "
+ "GetLastError() returned %d.",GetLastError());
+ }
+
+ /* Call HeapReAlloc with a NULL memory pointer. It should fail */
+
+ if(HeapReAlloc(TheHeap, 0, TheMemory, 100) != NULL)
+ {
+ Fail("ERROR: HeapReAlloc was passed an invalid memory pointer. "
+ "It should have failed and returned NULL upon failure.");
+ }
+
+ if(GetLastError() != 0)
+ {
+ Fail("ERROR: GetLastError should be zero after passing a NULL "
+ "memory pointer to HeapReAlloc.\n");
+ }
+
+ /* Call HeapReAlloc with a size of 0 bytes on a NULL memory pointer.
+ It should still fail.
+ */
+
+ if(HeapReAlloc(TheHeap, 0, TheMemory, 0) != NULL)
+ {
+ Fail("ERROR: HeapReAlloc was passed an invalid memory pointer and "
+ "the amount of memory to reallocate was 0. "
+ "It should have failed and returned NULL upon failure.");
+ }
+
+ if(GetLastError() != 0)
+ {
+ Fail("ERROR: GetLastError should be zero after passing a NULL "
+ "memory pointer to HeapReAlloc.\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test4/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test4/testinfo.dat
new file mode 100644
index 0000000000..cfa5f5ceed
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test4/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = HeapReAlloc
+Name = Negative test for HeapReAlloc
+TYPE = DEFAULT
+EXE1 = test4
+Description
+= Call HeapReAlloc with a NULL pointer to memory. It should
+= return NULL.
+
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test5/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test5/CMakeLists.txt
new file mode 100644
index 0000000000..3ab3ec16e8
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test5.c
+)
+
+add_executable(paltest_heaprealloc_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_heaprealloc_test5 coreclrpal)
+
+target_link_libraries(paltest_heaprealloc_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test5/test5.c b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test5/test5.c
new file mode 100644
index 0000000000..230e65e492
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test5/test5.c
@@ -0,0 +1,69 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test5.c
+**
+** Purpose: Allocate some memory. Then call HeapRealloc with 0 as the
+** amount of memory to reallocate. This should work, essentially freeing
+** the memory (though we can't verfiy this)
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ HANDLE TheHeap;
+ char* TheMemory;
+ char* ReAllocMemory;
+ char* ReAllocMemory2;
+
+ if(PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ TheHeap = GetProcessHeap();
+
+ if(TheHeap == NULL)
+ {
+ Fail("ERROR: GetProcessHeap() returned NULL when it was called. "
+ "GetLastError() returned %d.",GetLastError());
+ }
+
+ /* Allocate 100 bytes on the heap */
+ if((TheMemory = HeapAlloc(TheHeap, 0, 100)) == NULL)
+ {
+ Fail("ERROR: HeapAlloc returned NULL when it was called. "
+ "GetLastError() returned %d.",GetLastError());
+ }
+
+ /* Set each byte of that memory block to 'x' */
+ memset(TheMemory, 'X', 100);
+
+ /* Reallocate the memory into 0 bytes */
+ ReAllocMemory = HeapReAlloc(TheHeap, 0, TheMemory, 0);
+
+ if(ReAllocMemory == NULL)
+ {
+ Fail("ERROR: HeapReAlloc failed to reallocate the 100 bytes of "
+ "heap memory. GetLastError returns %d.",GetLastError());
+ }
+
+ /* Reallocate the memory we just put into 0 bytes, into 100 bytes. */
+ ReAllocMemory2 = HeapReAlloc(TheHeap, 0, ReAllocMemory, 100);
+
+ if(ReAllocMemory2 == NULL)
+ {
+ Fail("ERROR: HeapReAlloc failed to reallocate the 0 bytes of "
+ "heap memory into 100. GetLastError returns %d.",GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test5/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test5/testinfo.dat
new file mode 100644
index 0000000000..e36b9035c5
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test5/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = HeapReAlloc
+Name = Positive test for HeapReAlloc to check behaviour with byte size 0
+TYPE = DEFAULT
+EXE1 = test5
+Description
+= Allocate some memory. Then call HeapRealloc with 0 as the
+= amount of memory to reallocate. This should work, essentially freeing
+= the memory (though we can't verfiy this)
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/CMakeLists.txt
new file mode 100644
index 0000000000..c96e00a170
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ LocalAlloc.c
+)
+
+add_executable(paltest_localalloc_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_localalloc_test1 coreclrpal)
+
+target_link_libraries(paltest_localalloc_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/LocalAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/LocalAlloc.c
new file mode 100644
index 0000000000..17afbc6020
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/LocalAlloc.c
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: LocalAlloc.c
+**
+** Purpose: Positive test the LocalAlloc API.
+** Call LocalAlloc with zero as the allocation attribute
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ HLOCAL LocalHeap;
+ HLOCAL FreeHeap;
+ int err;
+ const SIZE_T heapSize = 64;
+
+ /*Initialize the PAL environment*/
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+ /*Allocate the specified number of bytes from the heap*/
+ /*with allocation attribute: zero which is required by PAL Doc*/
+ LocalHeap = LocalAlloc(0, heapSize);
+ if(!LocalHeap)
+ {
+ Fail("\nFailed to call LocalAlloc API, "
+ "error code=%u\n", GetLastError());
+ }
+
+ /*Free the allocated local heap memory*/
+ FreeHeap = LocalFree(LocalHeap);
+ if(FreeHeap)
+ {
+ Fail("Failed to call LocalFree API, "
+ "error code=%u\n", GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/testinfo.dat
new file mode 100644
index 0000000000..056d9ceb21
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = LocalAlloc
+Name = Positive test LocalAlloc API to Allocate the specified number of bytes from the heap
+TYPE = DEFAULT
+EXE1 = localalloc
+Description
+=Test the LocalAlloc with zero ad allocation attribute
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/CMakeLists.txt
new file mode 100644
index 0000000000..47ad76ebe6
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ LocalFree.c
+)
+
+add_executable(paltest_localfree_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_localfree_test1 coreclrpal)
+
+target_link_libraries(paltest_localfree_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/LocalFree.c b/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/LocalFree.c
new file mode 100644
index 0000000000..d9c062e761
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/LocalFree.c
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: LocalFree.c
+**
+** Purpose: Positive test the LocalFree API.
+** Call LocalFree to free a specified local memory object
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ HLOCAL LocalHeap;
+ HLOCAL FreeHeap;
+ int err;
+ const SIZE_T heapSize = 64;
+
+ /*Initialize the PAL environment*/
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+ /*Allocate the specified number of bytes from the heap*/
+ /*with zero ad the allocation attribute*/
+ LocalHeap = LocalAlloc(0, heapSize);
+ if(!LocalHeap)
+ {
+ Fail("\nFailed to call LocalAlloc API, "
+ "error code=%u\n", GetLastError());
+ }
+
+ /*Free the allocated local heap memory*/
+ FreeHeap = LocalFree(LocalHeap);
+ if(FreeHeap)
+ {
+ Fail("Failed to call LocalFree API, "
+ "error code=%u\n", GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/testinfo.dat
new file mode 100644
index 0000000000..2c0611bdec
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = LocalFree
+Name = Positive test LocalFree API to free a specified local memory object
+TYPE = DEFAULT
+EXE1 = localfree
+Description
+=Test the LocalFree to free a specified local memory object
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/CMakeLists.txt
new file mode 100644
index 0000000000..ac7a11a05f
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ LocalFree.c
+)
+
+add_executable(paltest_localfree_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_localfree_test2 coreclrpal)
+
+target_link_libraries(paltest_localfree_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/LocalFree.c b/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/LocalFree.c
new file mode 100644
index 0000000000..4d4567dc3f
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/LocalFree.c
@@ -0,0 +1,39 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: LocalFree.c
+**
+** Purpose: Positive test the LocalFree API.
+** call LocalFree by passing NULL as local memory
+** object handle
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ HLOCAL FreeHeap;
+ int err;
+
+ /*Initialize the PAL environment*/
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+ /*call LocalFree by passing NULL as local memory object handle*/
+ FreeHeap = LocalFree(NULL);
+ if(FreeHeap)
+ {
+ Fail("Failed to call LocalFree API, "
+ "error code=%u\n", GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/testinfo.dat
new file mode 100644
index 0000000000..1455fe93b7
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = LocalFree
+Name = Positive test LocalFree API by passing NULL as local memory object handle
+TYPE = DEFAULT
+EXE1 = localfree
+Description
+=Test the LocalFree by passing NULL
+=as a local memory object handle
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/CMakeLists.txt
new file mode 100644
index 0000000000..19ee487a6a
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/CMakeLists.txt
@@ -0,0 +1,10 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+add_subdirectory(test7)
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/LockFile.h b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/LockFile.h
new file mode 100644
index 0000000000..2862b6c524
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/LockFile.h
@@ -0,0 +1,152 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: LockFile.h
+**
+** Purpose: This header file has a RunHelper method which will be used to
+** start a child proccess in many LockFile testcases. The CreateAndLockFile
+** method Creates a file and calls LockFile upon it. And the two Signal
+** methods are used for IPC.
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+
+int RunHelper(char* Helper)
+{
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+ DWORD RetCode;
+
+ ZeroMemory( &si, sizeof(si) );
+ si.cb = sizeof(si);
+ ZeroMemory( &pi, sizeof(pi) );
+
+ if(!CreateProcess( NULL,Helper,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi))
+ {
+ Fail("ERROR: CreateProcess failed to load executable '%s'.",Helper);
+ }
+
+ if(WaitForSingleObject( pi.hProcess, INFINITE ) == WAIT_FAILED)
+ {
+ Fail("ERROR: WaitForSingleObject returned WAIT_FAILED when it was "
+ "called.");
+ }
+
+ /* Get the return value from the helper process */
+ if (GetExitCodeProcess(pi.hProcess, &RetCode) == 0)
+ {
+ Fail("ERROR: GetExitCodeProccess failed when attempting to retrieve "
+ "the exit code of the child process.");
+ }
+
+ if(CloseHandle( pi.hProcess ) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the process.");
+ }
+
+ if(CloseHandle( pi.hThread ) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the thread.");
+ }
+
+ return RetCode;
+}
+
+HANDLE CreateAndLockFile(HANDLE TheFile, char* FileName, char* WriteBuffer,
+ DWORD LockStart, DWORD LockLength)
+{
+ DWORD BytesWritten;
+
+ TheFile = CreateFile(FileName,
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (TheFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Could not open file '%s' with CreateFile. "
+ "GetLastError() returned %d.",FileName,GetLastError());
+ }
+
+ if(WriteFile(TheFile, WriteBuffer,
+ strlen(WriteBuffer),&BytesWritten, NULL) == 0)
+ {
+ Fail("ERROR: WriteFile has failed. It returned 0 when we "
+ "attempted to write to the file '%s'. GetLastError() "
+ "returned %d.",FileName,GetLastError());
+ }
+
+ if(FlushFileBuffers(TheFile) == 0)
+ {
+ Fail("ERROR: FlushFileBuffers returned failure. GetLastError() "
+ "returned %d.",GetLastError());
+ }
+
+ if(LockFile(TheFile, LockStart, 0, LockLength, 0) == 0)
+ {
+ Fail("ERROR: LockFile failed. GetLastError returns %d.",
+ GetLastError());
+ }
+
+ return TheFile;
+}
+
+void SignalAndBusyWait(HANDLE TheFile)
+{
+ int size;
+ DWORD BytesWritten;
+
+ size = GetFileSize(TheFile,NULL)+1;
+
+ if(SetFilePointer(TheFile, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER)
+ {
+ Fail("ERROR: SetFilePointer was unable to set the pointer to the "
+ "end of the file. GetLastError() returned %d.",GetLastError());
+ }
+
+ if(WriteFile(TheFile, "x", 1,&BytesWritten, NULL) == 0)
+ {
+ Fail("ERROR: WriteFile was unable to write to the WaitFile. "
+ "GetLastError() returned %d.",GetLastError());
+ }
+
+ if(FlushFileBuffers(TheFile) == 0)
+ {
+ Fail("ERROR: FlushFileBuffers failed when flushing the WaitFile. "
+ "GetLastError() returned %d.");
+ }
+
+ while(GetFileSize(TheFile,NULL) == size) { Sleep(100); }
+}
+
+void SignalFinish(HANDLE TheFile)
+{
+ DWORD BytesWritten;
+
+ if(SetFilePointer(TheFile, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER)
+ {
+ Fail("ERROR: SetFilePointer was unable to set the pointer to the "
+ "end of the WaitFile. GetLastError() returned %d.",
+ GetLastError());
+ }
+
+ if(WriteFile(TheFile, "x", 1,&BytesWritten, NULL) == 0)
+ {
+ Fail("ERROR: WriteFile was unable to write to the WaitFile. "
+ "GetLastError returned %d.",GetLastError());
+ }
+
+ if(FlushFileBuffers(TheFile) == 0)
+ {
+ Fail("ERROR: FlushFileBuffers failed when flushing the WaitFile. "
+ "GetLastError() returned %d.");
+ }
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test1/CMakeLists.txt
new file mode 100644
index 0000000000..0af09480ef
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test1/CMakeLists.txt
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(TESTSOURCES
+ test1.c
+)
+
+add_executable(paltest_lockfile_test1
+ ${TESTSOURCES}
+)
+
+add_dependencies(paltest_lockfile_test1 coreclrpal)
+
+target_link_libraries(paltest_lockfile_test1
+ pthread
+ m
+ coreclrpal
+)
+
+
+set(HELPERSOURCES
+ helper.c
+)
+
+add_executable(paltest_lockfile_test1_helper
+ ${HELPERSOURCES}
+)
+
+add_dependencies(paltest_lockfile_test1_helper coreclrpal)
+
+target_link_libraries(paltest_lockfile_test1_helper
+ pthread
+ m
+ coreclrpal
+) \ No newline at end of file
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test1/helper.c b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test1/helper.c
new file mode 100644
index 0000000000..05b4b8451a
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test1/helper.c
@@ -0,0 +1,86 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: helper.c
+**
+** Purpose: A child process which will attempt to read and write to files
+** which were locked in the parent.
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+
+#define BUF_SIZE 128
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE TheFile;
+ int result = 0;
+ char DataBuffer[BUF_SIZE];
+ DWORD BytesRead, BytesWritten;
+ char fileName[] = "testfile.tmp";
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Open the same file that the parent has opened and locked */
+ TheFile = CreateFile(fileName,
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (TheFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Could not open file '%s' with CreateFile.",fileName);
+ }
+
+ /* Attempt to Read 5 bytes from this file. Since it is locked, this
+ should fail.
+ */
+
+ if(ReadFile(TheFile, DataBuffer, 5, &BytesRead, NULL) != 0)
+ {
+ Trace("ERROR: ReadFile should have failed! It was called on "
+ "a locked file. But, it returned non-zero indicating success.");
+ result = 1;
+ }
+
+ /* Attempt to Write 5 bytes to this file. Since it is locked this should
+ fail.
+ */
+
+ memset(DataBuffer,'X',BUF_SIZE);
+
+ if(WriteFile(TheFile, DataBuffer, 5,&BytesWritten, NULL) != 0)
+ {
+ Trace("ERROR: WriteFile should have failed! It was called on "
+ "a locked file. But, it returned non-zero indicating success.");
+ result = 1;
+ }
+
+ /* Check to ensure that the number of Bytes read/written is still 0,
+ since nothing should have been read or written.
+ */
+
+ if(BytesRead != 0 || BytesWritten !=0)
+ {
+ Trace("ERROR: The number of bytes read is %d and written is %d. "
+ "These should both be 0, as the file was locked.",
+ BytesRead,BytesWritten);
+ result = 1;
+ }
+
+ PAL_TerminateEx(result);
+ return result;
+}
+
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test1/test1.c b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test1/test1.c
new file mode 100644
index 0000000000..cee223ef81
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test1/test1.c
@@ -0,0 +1,140 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test1.c
+**
+** Purpose: Open a file, and lock it from start to EOF. Then create a
+** new process, which will attempt to Read and Write from the file. Check
+** to ensure both of these operations fail.
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+#include "../LockFile.h"
+
+#define HELPER "helper"
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ HANDLE TheFile;
+ DWORD FileStart = 0;
+ DWORD FileEnd = 0;
+ const char lpBuffer[] = "This is a test file.";
+ DWORD bytesWritten;
+ BOOL bRc = TRUE;
+ char fileName[] = "testfile.tmp";
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Important to have sharing enabled, or there is no need for the lock. */
+ TheFile = CreateFile(fileName,
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (TheFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Could not open file '%s' with CreateFile.",fileName);
+ }
+
+ bRc = WriteFile(TheFile,
+ lpBuffer,
+ (DWORD)sizeof(lpBuffer),
+ &bytesWritten,
+ NULL);
+
+ if(!bRc)
+ {
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+
+ Fail("ERROR: Could not write to file '%s' with WriteFile.",fileName);
+ }
+ else if(bytesWritten != (DWORD)sizeof(lpBuffer))
+ {
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+
+ Fail("ERROR: Could not write the correct number of bytes to the "
+ "file '%s' with WriteFile.",fileName);
+ }
+
+ /* Find the value for the End of the file */
+ FileEnd = SetFilePointer(TheFile,0,NULL,FILE_END);
+
+ if(FileEnd == INVALID_SET_FILE_POINTER)
+ {
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+
+ Fail("ERROR: Could not set the file pointer to the end of the file "
+ "using SetFilePointer. It returned INVALID_SET_FILE_POINTER.");
+ }
+
+ /* Lock the file from Start to EOF */
+
+ if(LockFile(TheFile, FileStart, 0, FileEnd, 0) == 0)
+ {
+ Trace("ERROR: LockFile failed. GetLastError returns %d.",
+ GetLastError());
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+ Fail("");
+ }
+
+ /* Launch another process, which will attempt to read and write from
+ the locked file.
+
+ If the helper program returns 1, then the test fails. More
+ specific errors are given by the Helper file itself.
+ */
+ if(RunHelper(HELPER))
+ {
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+
+ Fail("ERROR: The Helper program determined that the file was not "
+ "locked properly by LockFile.");
+ }
+
+ if(UnlockFile(TheFile, FileStart, 0, FileEnd, 0) == 0)
+ {
+ Trace("ERROR: UnlockFile failed. GetLastError returns %d.",
+ GetLastError());
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+ Fail("");
+ }
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test1/testinfo.dat
new file mode 100644
index 0000000000..cbe4d94d40
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = LockFile
+Name = Positive test for LockFile API
+TYPE = DEFAULT
+EXE1 = test1
+EXE2 = helper
+Description
+= Open a file, and lock it from start to EOF. Then create a
+= new process, which will attempt to Read and Write from the file. Check
+= to ensure both of these operations fail.
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test2/CMakeLists.txt
new file mode 100644
index 0000000000..157c517e62
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_lockfile_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_lockfile_test2 coreclrpal)
+
+target_link_libraries(paltest_lockfile_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test2/test2.c b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test2/test2.c
new file mode 100644
index 0000000000..8aef130ef4
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test2/test2.c
@@ -0,0 +1,94 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test2.c
+**
+** Purpose: Open a file, and lock it from start to EOF. Check to ensure
+** the current process can still read and write from/to the file.
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+#include "../LockFile.h"
+
+#define FILENAME "testfile.txt"
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ HANDLE TheFile = NULL;
+ DWORD FileStart = 0;
+ DWORD FileEnd = 0;
+ DWORD BytesWritten = 0;
+ DWORD BytesRead = 0;
+ char WriteBuffer[] = "This is some test data.";
+ char DataBuffer[128];
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Call the helper function to Create a file, write 'WriteBuffer' to
+ the file, and lock the file.
+ */
+
+ FileEnd = strlen(WriteBuffer);
+ TheFile = CreateAndLockFile(TheFile, FILENAME, WriteBuffer,
+ FileStart, FileEnd);
+
+ /* Move the file pointer to the start of the file */
+ if(SetFilePointer(TheFile, 0, NULL, FILE_BEGIN) != 0)
+ {
+ Fail("ERROR: SetFilePointer failed to move the file pointer back "
+ "to the start of the file.");
+ }
+
+ /* Attempt to Read 5 bytes from this file. Since the lock does not
+ affect the calling process, this should succeed.
+ */
+
+ if(ReadFile(TheFile, DataBuffer, 5, &BytesRead, NULL) == 0)
+ {
+ Fail("ERROR: ReadFile has failed. Attempted to read in 5 bytes from "
+ "the file '%s' after it had LockFile called upon it, but within "
+ "the same process.",FILENAME);
+ }
+
+ if(strncmp(DataBuffer, WriteBuffer, 5) != 0)
+ {
+ Fail("ERROR: The data read in from ReadFile is not what should have "
+ "been written in the file. '%s' ",DataBuffer);
+ }
+
+ /* Attempt to Write 5 bytes to this file. Since the lock does not affect
+ the calling process, this should succeed.
+ */
+
+ memset(WriteBuffer, 'X', strlen(WriteBuffer));
+
+ if(WriteFile(TheFile, WriteBuffer, 5,&BytesWritten, NULL) == 0)
+ {
+ Fail("ERROR: WriteFile has failed. Attempted to write 5 bytes to "
+ "the file '%s' after it had LockFile called upon it, but within "
+ "the same process.",FILENAME);
+ }
+
+ if(UnlockFile(TheFile, FileStart, 0, FileEnd, 0) == 0)
+ {
+ Fail("ERROR: UnlockFile failed. GetLastError returns %d.",
+ GetLastError());
+ }
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test2/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test2/testinfo.dat
new file mode 100644
index 0000000000..c84e7c0a0a
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = LockFile
+Name = Positive test for LockFile API
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Open a file, and lock it from start to EOF. Check to ensure
+= the current process can still read and write from/to the file.
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test3/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test3/CMakeLists.txt
new file mode 100644
index 0000000000..69516de69b
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test3/CMakeLists.txt
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(TESTSOURCES
+ test3.c
+)
+
+add_executable(paltest_lockfile_test3
+ ${TESTSOURCES}
+)
+
+add_dependencies(paltest_lockfile_test3 coreclrpal)
+
+target_link_libraries(paltest_lockfile_test3
+ pthread
+ m
+ coreclrpal
+)
+
+
+set(HELPERSOURCES
+ helper.c
+)
+
+add_executable(paltest_lockfile_test3_helper
+ ${HELPERSOURCES}
+)
+
+add_dependencies(paltest_lockfile_test3_helper coreclrpal)
+
+target_link_libraries(paltest_lockfile_test3_helper
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test3/helper.c b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test3/helper.c
new file mode 100644
index 0000000000..079417fce8
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test3/helper.c
@@ -0,0 +1,102 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: helper.c
+**
+** Purpose: A child process which will attempt to read and write to files
+** which were locked in the parent.
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+
+#define FILENAME "testfile.txt"
+#define BUF_SIZE 128
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE TheFile;
+ int result = 0;
+ char DataBuffer[BUF_SIZE];
+ DWORD BytesRead, BytesWritten;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Open the same file that the parent has opened and locked */
+ TheFile = CreateFile(FILENAME,
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (TheFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Could not open file '%s' with CreateFile. "
+ "GetLastError() returns %d.",FILENAME,GetLastError());
+ }
+
+ /* Attempt to Read the first 3 bytes from this file.
+ Since it is unlocked, this should work properly.
+ */
+
+ if(ReadFile(TheFile, DataBuffer, 3, &BytesRead, NULL) == 0)
+ {
+ Trace("ERROR: ReadFile should have succeeded in reading the first "
+ "three bytes of the file, as these bytes were not locked. "
+ "GetLastError() returned %d.",GetLastError());
+ result = 1;
+ }
+
+ /* Now, read the next 10 bytes, which should be locked. Ensure that
+ ReadFile fails.
+ */
+
+ if(ReadFile(TheFile, DataBuffer,10, &BytesRead, NULL) != 0)
+ {
+ Trace("ERROR: ReadFile should have failed when attempting to read in "
+ "bytes between StartOfFile+3 and EndOfFile-3.");
+ result = 1;
+ }
+
+ /* Attempt to Write 10 bytes to this file. Since it is locked this should
+ fail.
+ */
+
+ memset(DataBuffer,'X',BUF_SIZE);
+
+ if(WriteFile(TheFile, DataBuffer, 10,&BytesWritten, NULL) != 0)
+ {
+ Trace("ERROR: WriteFile should have failed when attempting to write "
+ "bytes between StartOfFile+3 and EOF-3.");
+ result = 1;
+ }
+
+
+ /* Move the FilePointer to the EOF-3, where the lock ends */
+ if(SetFilePointer(TheFile,-3,NULL,FILE_END) == INVALID_SET_FILE_POINTER)
+ {
+ Fail("ERROR: Could not set the file pointer to the EOF-3 "
+ "using SetFilePointer. It returned INVALID_SET_FILE_POINTER.");
+ }
+
+ /* Attempt to write to those 3 unlocked bytes on the end of the file */
+ if(WriteFile(TheFile, DataBuffer, 3,&BytesWritten, NULL) == 0)
+ {
+ Trace("ERROR: WriteFile should have succeeded when attempting "
+ "to write the last three bytes of the file, as they were not "
+ "locked. GetLastError() returned %d.",GetLastError());
+ result = 1;
+ }
+
+ PAL_TerminateEx(result);
+ return result;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test3/test3.c b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test3/test3.c
new file mode 100644
index 0000000000..78662c5685
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test3/test3.c
@@ -0,0 +1,71 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test3.c
+**
+** Purpose: Open a file, lock a region in the middle. Create a new process
+** and attempt to read and write directly before and after that region, which
+** should succeed. Also, check to see that reading/writing in the locked
+** region fails.
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+#include "../LockFile.h"
+
+#define HELPER "helper"
+#define FILENAME "testfile.txt"
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ HANDLE TheFile = NULL;
+ DWORD FileStart = 0;
+ DWORD FileEnd = 0;
+ char* WriteBuffer = "12345678901234567890123456";
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Call the helper function to Create a file, write 'WriteBuffer' to
+ the file, and lock the file.
+ */
+
+ FileEnd = strlen(WriteBuffer);
+ TheFile = CreateAndLockFile(TheFile,FILENAME, WriteBuffer,
+ FileStart+3, FileEnd-6);
+
+
+ /* Launch another process, which will attempt to read and write from
+ the locked file.
+
+ If the helper program returns 1, then the test fails. More
+ specific errors are given by the Helper file itself.
+ */
+ if(RunHelper(HELPER))
+ {
+ Fail("ERROR: The Helper program determined that the file was not "
+ "locked properly by LockFile.");
+ }
+
+ if(UnlockFile(TheFile, FileStart+3, 0, FileEnd-6, 0) == 0)
+ {
+ Fail("ERROR: UnlockFile failed. GetLastError returns %d.",
+ GetLastError());
+ }
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file. "
+ "GetLastError() returned %d.",GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test3/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test3/testinfo.dat
new file mode 100644
index 0000000000..b64ec5ed03
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test3/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = LockFile
+Name = Positive test for LockFile API
+TYPE = DEFAULT
+EXE1 = test3
+EXE2 = helper
+Description
+= Open a file, lock a region in the middle. Create a new process
+= and attempt to read and write directly before and after that region, which
+= should succeed. Also, check to see that reading/writing in the locked
+= region fails.
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test4/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test4/CMakeLists.txt
new file mode 100644
index 0000000000..fb8f6745d4
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_lockfile_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_lockfile_test4 coreclrpal)
+
+target_link_libraries(paltest_lockfile_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test4/test4.c b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test4/test4.c
new file mode 100644
index 0000000000..f5cd359fb5
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test4/test4.c
@@ -0,0 +1,231 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test4.c
+**
+** Purpose:
+** - Attempt to call LockFile on a file without GENERIC_READ or
+** GENERIC_WRITE (this should fail)
+** - Attempt to overlap two locks, this should fail.
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+
+char fileName[] = "testfile.tmp";
+
+void OverlapTest()
+{
+ HANDLE TheFile = NULL;
+ DWORD FileStart = 0;
+ const char lpBuffer[] = "This is a test file.";
+ DWORD bytesWritten;
+ BOOL bRc = TRUE;
+
+ TheFile = CreateFile(fileName,
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (TheFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Could not open file '%s' with CreateFile. "
+ "GetLastError() returned %d.",fileName,GetLastError());
+ }
+
+ bRc = WriteFile(TheFile,
+ lpBuffer,
+ (DWORD)sizeof(lpBuffer),
+ &bytesWritten,
+ NULL);
+
+ if(!bRc)
+ {
+ Trace("ERROR: Could not write to file '%s' with WriteFile.",fileName);
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+ Fail("");
+
+ }
+ else if(bytesWritten != (DWORD)sizeof(lpBuffer))
+ {
+ Trace("ERROR: Could not write the correct number of bytes to the "
+ "file '%s' with WriteFile.",fileName);
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+ Fail("");
+ }
+
+ /* Lock the First 5 bytes of the File */
+
+ if(LockFile(TheFile, FileStart, 0, 5, 0) == 0)
+ {
+ Trace("ERROR: LockFile failed in Overlap test. "
+ "GetLastError returns %d.",
+ GetLastError());
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+ Fail("");
+ }
+
+ /* Lock from Byte 2 until 7 -- this overlaps and should return failure. */
+ if(LockFile(TheFile,FileStart+2, 0, 5, 0) != 0)
+ {
+ Trace("ERROR: LockFile returned success when it was overlapped on "
+ "an already locked region of the file.");
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+ Fail("");
+ }
+
+ /* Unlock the file */
+ if(UnlockFile(TheFile, FileStart, 0, 5, 0) == 0)
+ {
+ Trace("ERROR: UnlockFile failed in Overlap test. GetLastError "
+ "returns %d.",GetLastError());
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+ Fail("");
+ }
+
+ /* Close the File */
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file in the Overlap "
+ "test. GetLastError() returned %d.",GetLastError());
+ }
+}
+
+void FlagsTest(DWORD TheFlags, int ExpectedResult)
+{
+ HANDLE TheFile = NULL;
+ DWORD FileStart = 0;
+ int result;
+
+ TheFile = CreateFile(fileName,
+ TheFlags,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (TheFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Could not open file '%s' with CreateFile. "
+ "GetLastError() returned %d.",fileName,GetLastError());
+ }
+
+ /* Lock the First 5 bytes of the File. The result of this depends
+ upon which flags were set with the CreateFile.
+ */
+
+ result = LockFile(TheFile, FileStart, 0, 5, 0);
+
+ /* If the expected result is 1, check to ensure the result is non-zero,
+ as non-zero is returned on success
+ */
+ if(ExpectedResult == 1)
+ {
+ if(result == 0)
+ {
+ Trace("ERROR: LockFile returned zero when the expected result "
+ "was non-zero. It was passed the flag value %d.",
+ TheFlags);
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+ Fail("");
+ }
+ }
+ /* If the expected result is 0, check to ensure the result is 0 */
+ else
+ {
+ if(result != 0)
+ {
+ Trace("ERROR: LockFile returned %d when the expected result "
+ "was zero. It was passed the flag value %d.",
+ result, TheFlags);
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+ Fail("");
+ }
+ }
+
+ /* Only unlock the file if we expect it to be successfully locked */
+ if(ExpectedResult)
+ {
+ if(UnlockFile(TheFile,FileStart,0, 5, 0) == 0)
+ {
+ Fail("ERROR: UnlockFile failed in the Flags Test. GetLastError() "
+ "returned %d.",GetLastError());
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+ Fail("");
+ }
+ }
+
+ /* Close the File */
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file in the Flags "
+ "test. GetLastError() returned %d.",GetLastError());
+ }
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* This test opens a file, then calls lock twice, overlapping the
+ regions and checking to ensure that this causes an error.
+ */
+ OverlapTest();
+
+ /* Test that LockFile fails if no flags are set */
+ FlagsTest(0,0);
+
+ /* Test that LockFile passes if only GENERIC_READ is set */
+ FlagsTest(GENERIC_READ,1);
+
+ /* Test that LockFile passes if only GENERIC_WRITE is set */
+ FlagsTest(GENERIC_WRITE,1);
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test4/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test4/testinfo.dat
new file mode 100644
index 0000000000..0600260d82
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test4/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = LockFile
+Name = Negative test for LockFile API
+TYPE = DEFAULT
+EXE1 = test4
+Description
+= - Attempt to call LockFile on a file without GENERIC_READ or
+= GENERIC_WRITE (this should fail)
+= - Attempt to overlap two locks, this should fail.
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test5/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test5/CMakeLists.txt
new file mode 100644
index 0000000000..cc4548a6f0
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test5/CMakeLists.txt
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(TESTSOURCES
+ test5.c
+)
+
+add_executable(paltest_lockfile_test5
+ ${TESTSOURCES}
+)
+
+add_dependencies(paltest_lockfile_test5 coreclrpal)
+
+target_link_libraries(paltest_lockfile_test5
+ pthread
+ m
+ coreclrpal
+)
+
+
+set(HELPERSOURCES
+ helper.c
+)
+
+add_executable(paltest_lockfile_test5_helper
+ ${HELPERSOURCES}
+)
+
+add_dependencies(paltest_lockfile_test5_helper coreclrpal)
+
+target_link_libraries(paltest_lockfile_test5_helper
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test5/helper.c b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test5/helper.c
new file mode 100644
index 0000000000..1fc9b1a9a5
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test5/helper.c
@@ -0,0 +1,122 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: helper.c
+**
+** Purpose: A child process which will attempt to read and write to files
+** which were locked in the parent. It will also lock another region of the
+** same file.
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+#include "../LockFile.h"
+
+#define FILENAME "testfile.txt"
+#define WAITFILENAME "waitfile"
+#define BUF_SIZE 128
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE TheFile, WaitFile;
+ int result = 0;
+ char DataBuffer[BUF_SIZE];
+ DWORD BytesRead;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Open the same file that the parent has opened and locked */
+ TheFile = CreateFile(FILENAME,
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (TheFile == INVALID_HANDLE_VALUE)
+ {
+ Trace("ERROR: Could not open file '%s' with CreateFile.",FILENAME);
+ result = 1;
+ }
+
+ /* Open up the WaitFile that we're using for IPC */
+ WaitFile = CreateFile(WAITFILENAME,
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (WaitFile == INVALID_HANDLE_VALUE)
+ {
+ Trace("ERROR: Could not open file '%s' with CreateFile. "
+ "GetLastError() returned %d.",WAITFILENAME,GetLastError());
+ result = 1;
+ }
+
+ /* Lock the same file that the parent process locked, but the child
+ locks bytes 11 through 20
+ */
+
+ if(LockFile(TheFile, 11, 0, 10, 0) == 0)
+ {
+ Trace("ERROR: LockFile failed in the child proccess. "
+ "GetLastError returns %d.",
+ GetLastError());
+ result = 1;
+ }
+
+ /* Check to ensure the parent lock is respected */
+ if(ReadFile(TheFile, DataBuffer, 10, &BytesRead, NULL) != 0)
+ {
+ Trace("ERROR: ReadFile returned success when it should "
+ "have failed. Attempted to read the first 10 bytes "
+ "of a file which was locked by the parent process.");
+ result = 1;
+ }
+
+ /* Check to ensure the lock put on by this proccess doesn't restrict
+ access
+ */
+
+ if(SetFilePointer(TheFile, 11, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
+ {
+ Trace("ERROR: SetFilePointer was unable to move the file pointer to "
+ "the 11th byte in the file, within the child proccess. "
+ "GetLastError() returned %d.",GetLastError());
+ result = 1;
+ }
+
+ if(ReadFile(TheFile, DataBuffer, 10, &BytesRead, NULL) == 0)
+ {
+ Trace("ERROR: ReadFile failed when attempting to read a section of "
+ "the file which was locked by the current process. It should "
+ "have been able to read this. GetLastError() returned %d.",
+ GetLastError());
+ result = 1;
+ }
+
+ // Sleep for a bit to give the parent a chance to block before we do.
+ Sleep(1000);
+
+ /* Switch back to the parent, so it can check the child's locks */
+ SignalAndBusyWait(WaitFile);
+
+ if(UnlockFile(TheFile, 11, 0, 10, 0) == 0)
+ {
+ Fail("ERROR: Failed to Unlock bytes 11-20 in the file. "
+ "GetLastError returned %d.",GetLastError());
+ }
+
+ PAL_TerminateEx(result);
+ return result;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test5/test5.c b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test5/test5.c
new file mode 100644
index 0000000000..a02a3c5a49
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test5/test5.c
@@ -0,0 +1,161 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test5.c
+**
+** Purpose:
+** Have two processes obtain a lock on a single file, but in different
+** regions of the file. Use Read/Write to ensure the locks are respected.
+** This requires some IPC, which is done here with a crude busy wait on a
+** file (waiting for the file size to change) to avoid too many more
+** dependencies.
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+#include "../LockFile.h"
+
+#define HELPER "helper"
+#define FILENAME "testfile.txt"
+#define WAITFILENAME "waitfile"
+#define BUF_SIZE 128
+
+int RunTest(char* Helper, HANDLE TheFile, HANDLE WaitFile)
+{
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+ DWORD ChildRetCode = 0;
+ DWORD ParentRetCode = 0;
+ DWORD BytesRead;
+ char DataBuffer[BUF_SIZE];
+
+
+ ZeroMemory( &si, sizeof(si) );
+ si.cb = sizeof(si);
+ ZeroMemory( &pi, sizeof(pi) );
+
+ /* Load up the helper Process, and then Wait until it signals that it
+ is finished locking.
+ */
+ if(!CreateProcess( NULL,Helper,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi))
+ {
+ Fail("ERROR: CreateProcess failed to load executable '%s'.",Helper);
+ }
+
+ SignalAndBusyWait(WaitFile);
+
+ /* Now the child proccess has locked another section of the file, from
+ bytes 11 through 20. Let's check that the parent lock is still ignored
+ by the parent proccess and that the child's lock is respected.
+ */
+
+ if(ReadFile(TheFile, DataBuffer, 10, &BytesRead, NULL) == 0)
+ {
+ Trace("ERROR: ReadFile failed when attempting to read a section of "
+ "the file which was locked by the current process. It should "
+ "have been able to read this. GetLastError() returned %d.",
+ GetLastError());
+ ParentRetCode = 1;
+ }
+
+ SetFilePointer(TheFile, 11, 0, FILE_BEGIN);
+
+ if(ReadFile(TheFile, DataBuffer, 10, &BytesRead, NULL) != 0)
+ {
+ Trace("ERROR: ReadFile returned success when it should "
+ "have failed. Attempted to read 10 bytes of the file which "
+ "were locked by the child.");
+ ParentRetCode = 1;
+ }
+
+ /* We're finished testing. Let the child proccess know so it can clean
+ up, and the parent will wait until it is done.
+ */
+ SignalFinish(WaitFile);
+ WaitForSingleObject(pi.hProcess,INFINITE);
+
+ /* Get the return value from the helper process */
+ if (GetExitCodeProcess(pi.hProcess, &ChildRetCode) == 0)
+ {
+ Fail("ERROR: GetExitCodeProccess failed when attempting to retrieve "
+ "the exit code of the child process.");
+ }
+
+ if(CloseHandle( pi.hProcess ) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the process.");
+ }
+
+ if(CloseHandle( pi.hThread ) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the thread.");
+ }
+
+ return (ChildRetCode || ParentRetCode);
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE TheFile = NULL;
+ HANDLE WaitFile = NULL;
+ char* WriteBuffer = "12345678901234567890123456";
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Open up the file we'll be using for some crude IPC */
+ WaitFile = CreateFile(WAITFILENAME,
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (WaitFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Could not open file '%s' with CreateFile. "
+ "GetLastError() returned %d.",WAITFILENAME,GetLastError());
+ }
+
+ /* Call the helper function to Create a file, write 'WriteBuffer' to
+ the file, and lock the file from bytes 0 to 10.
+ */
+ TheFile = CreateAndLockFile(TheFile, FILENAME, WriteBuffer,
+ 0, 10);
+
+ /* Run the test. Better errors are displayed by Trace throughout. */
+ if(RunTest(HELPER, TheFile, WaitFile))
+ {
+ Fail("ERROR: Attempting to have two processes lock different "
+ "sections of the same file has failed.");
+ }
+
+ /* Unlock the first 10 bytes which were locked by the parent proccess */
+ if(UnlockFile(TheFile, 0, 0, 10, 0) == 0)
+ {
+ Fail("ERROR: Failed to Unlock the first 10 bytes of the file. "
+ "GetLastError returned %d.",GetLastError());
+ }
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file used for "
+ "testing the locks. GetLastError() returns %d.",GetLastError());
+ }
+
+ if(CloseHandle(WaitFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the wait file. "
+ "GetLastError() returns %d.",GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test5/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test5/testinfo.dat
new file mode 100644
index 0000000000..f020933cd9
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test5/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = LockFile
+Name = Positive test for LockFile API
+TYPE = DEFAULT
+EXE1 = test5
+EXE2 = helper
+Description
+= Have two processes obtain a lock on a single file, but in different
+= regions of the file. Use Read/Write to ensure the locks are respected.
+= This requires some IPC, which is done here with a crude busy wait on a
+= file (waiting for the file size to change) to avoid too many more
+= dependencies.
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test6/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test6/CMakeLists.txt
new file mode 100644
index 0000000000..5049977582
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test6/CMakeLists.txt
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(TESTSOURCES
+ test6.c
+)
+
+add_executable(paltest_lockfile_test6
+ ${TESTSOURCES}
+)
+
+add_dependencies(paltest_lockfile_test6 coreclrpal)
+
+target_link_libraries(paltest_lockfile_test6
+ pthread
+ m
+ coreclrpal
+)
+
+
+set(HELPERSOURCES
+ helper.c
+)
+
+add_executable(paltest_lockfile_test6_helper
+ ${HELPERSOURCES}
+)
+
+add_dependencies(paltest_lockfile_test6_helper coreclrpal)
+
+target_link_libraries(paltest_lockfile_test6_helper
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test6/helper.c b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test6/helper.c
new file mode 100644
index 0000000000..98112fc4a5
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test6/helper.c
@@ -0,0 +1,71 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: helper.c
+**
+** Purpose: A child process which will attempt to append to the end of
+** a locked file.
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+
+#define FILENAME "testfile.txt"
+#define BUF_SIZE 128
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE TheFile;
+ int result = 0;
+ char DataBuffer[BUF_SIZE];
+ DWORD BytesWritten;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Open the same file that the parent has opened and locked */
+ TheFile = CreateFile(FILENAME,
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (TheFile == INVALID_HANDLE_VALUE)
+ {
+ Trace("ERROR: Could not open file '%s' with CreateFile. "
+ "GetLastError() returns %d.",FILENAME,GetLastError());
+ result = -1;
+ }
+
+
+ /* Move the FilePointer to the EOF */
+ if(SetFilePointer(TheFile,0,NULL,FILE_END) == INVALID_SET_FILE_POINTER)
+ {
+ Trace("ERROR: Could not set the file pointer to the EOF "
+ "using SetFilePointer. It returned INVALID_SET_FILE_POINTER.");
+ result = -1;
+ }
+
+ memset(DataBuffer, 'X', BUF_SIZE);
+
+ /* Return the result of WriteFile -- we want to check in the parent that
+ this was successful. Note: WriteFile doesn't get run if something
+ failed during the setup, in that case -1 is returned.
+ */
+
+ if(result != -1)
+ {
+ result = WriteFile(TheFile, DataBuffer, 3,&BytesWritten, NULL);
+ }
+
+ PAL_TerminateEx(result);
+ return result;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test6/test6.c b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test6/test6.c
new file mode 100644
index 0000000000..ba01b9710a
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test6/test6.c
@@ -0,0 +1,146 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test6.c
+**
+** Purpose:
+** Append to a file which is locked until the end of the file, and
+** append to a file which is locked past the end of the file. (The first
+** should succeed, while the second should fail)
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+#include "../LockFile.h"
+
+#define HELPER "helper"
+#define FILENAME "testfile.txt"
+
+/* This test checks that you can append to a file which is locked from Start
+ to EOF.
+*/
+void Test1()
+{
+ HANDLE TheFile = NULL;
+ DWORD FileStart = 0;
+ DWORD FileEnd = 0;
+ int result;
+ char* WriteBuffer = "12345678901234567890123456";
+
+ /* Call the helper function to Create a file, write 'WriteBuffer' to
+ the file, and lock the file.
+ */
+
+ FileEnd = strlen(WriteBuffer);
+ TheFile = CreateAndLockFile(TheFile,FILENAME, WriteBuffer,
+ FileStart, FileEnd);
+
+
+ /*
+ Launch another proccess which will attempt to append to the
+ end of the file. Note: This returns -1 if the setup failed in some way.
+ */
+
+ result = RunHelper(HELPER);
+
+ if(result == -1)
+ {
+ Fail("ERROR: The Helper program failed in setting up the "
+ "test, so it could never be run.");
+ }
+ else if(result == 0)
+ {
+ Fail("ERROR: Failed to append to the file which was Locked from "
+ "start until EOF. Should have been able to append to this "
+ "file still. GetLastError() is %d.",GetLastError());
+ }
+
+ if(UnlockFile(TheFile, FileStart, 0, FileEnd, 0) == 0)
+ {
+ Fail("ERROR: UnlockFile failed. GetLastError returns %d.",
+ GetLastError());
+ }
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file. "
+ "GetLastError() returned %d.",GetLastError());
+ }
+
+}
+
+/* This test checks that you can't append to a file which is locked beyond
+ EOF.
+*/
+void Test2()
+{
+ HANDLE TheFile = NULL;
+ DWORD FileStart = 0;
+ DWORD FileEnd = 0;
+ int result;
+ char* WriteBuffer = "12345678901234567890123456";
+
+ /* Call the helper function to Create a file, write 'WriteBuffer' to
+ the file, and lock the file.
+ */
+
+ FileEnd = strlen(WriteBuffer);
+ TheFile = CreateAndLockFile(TheFile,FILENAME, WriteBuffer,
+ FileStart, FileEnd+20);
+
+
+ /*
+ Launch another proccess which will attempt to append to the
+ end of the file.
+ */
+
+ result = RunHelper(HELPER);
+
+ if(result == -1)
+ {
+ Fail("ERROR: The Helper program failed in setting up the "
+ "test, so it could never be run.");
+ }
+ else if(result > 0)
+ {
+ Fail("ERROR: The Helper program successfully appended to the "
+ "end of the file, even though it was locked beyond EOF. This "
+ "should have failed.");
+ }
+
+ if(UnlockFile(TheFile, FileStart, 0, FileEnd+20, 0) == 0)
+ {
+ Fail("ERROR: UnlockFile failed. GetLastError returns %d.",
+ GetLastError());
+ }
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file. "
+ "GetLastError() returned %d.",GetLastError());
+ }
+
+}
+
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Test a file which is locked until EOF to see if you can append */
+ Test1();
+
+ /* Test a file which is locked past EOF to ensure you can't append */
+ Test2();
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test6/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test6/testinfo.dat
new file mode 100644
index 0000000000..871a9a2756
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test6/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = LockFile
+Name = Positive test for LockFile API
+TYPE = DEFAULT
+EXE1 = test6
+EXE2 = helper
+Description
+= Append to a file which is locked until the end of the file, and
+= append to a file which is locked past the end of the file. (The first
+= should succeed, while the second should fail)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test7/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test7/CMakeLists.txt
new file mode 100644
index 0000000000..e8434cc787
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test7/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test7.c
+)
+
+add_executable(paltest_lockfile_test7
+ ${SOURCES}
+)
+
+add_dependencies(paltest_lockfile_test7 coreclrpal)
+
+target_link_libraries(paltest_lockfile_test7
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test7/test7.c b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test7/test7.c
new file mode 100644
index 0000000000..c572a6e653
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test7/test7.c
@@ -0,0 +1,135 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test7.c
+**
+** Purpose: Try locking an invalid HANDLE and a NULL Handle.
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+#include "../LockFile.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ HANDLE TheFile = NULL;
+ DWORD FileEnd = 0;
+ const char lpBuffer[] = "This is a test file.";
+ DWORD bytesWritten;
+ BOOL bRc = TRUE;
+ char fileName[] = "testfile.tmp";
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ TheFile = CreateFile(fileName,
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (TheFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Could not open file '%s' with CreateFile. "
+ "GetLastError() returned %d.",fileName,GetLastError());
+ }
+
+ bRc = WriteFile(
+ TheFile, // handle to file
+ lpBuffer, // data buffer
+ (DWORD)sizeof(lpBuffer), // number of bytes to write
+ &bytesWritten, // number of bytes written
+ NULL // overlapped buffer
+ );
+
+ if(!bRc)
+ {
+ Trace("ERROR: Could not write to file '%s' with WriteFile.",fileName);
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+ Fail("");
+
+ }
+ else if(bytesWritten != (DWORD)sizeof(lpBuffer))
+ {
+ Trace("ERROR: Could not write the correct number of bytes to the "
+ "file '%s' with WriteFile.",fileName);
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+ Fail("");
+ }
+
+ /* Attempt to lock a region of this file beyond EOF, to ensure this
+ doesn't cause an error.
+ */
+ FileEnd = SetFilePointer(TheFile, 0, NULL, FILE_END);
+
+ if(LockFile(TheFile, FileEnd+10, 0, 10, 0) == 0)
+ {
+ Trace("ERROR: LockFile failed when attempting to lock a region "
+ "beyond the EOF. GetLastError() returned %d.",GetLastError());
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+ Fail("");
+ }
+
+ if(UnlockFile(TheFile, FileEnd+10, 0, 10, 0) == 0)
+ {
+ Trace("ERROR: UnlockFile failed when attempting to unlock the region "
+ "which was locked beyond the EOF. GetLastError returned %d.",
+ GetLastError());
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+ Fail("");
+ }
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: Failed to call CloseHandle. GetLastError "
+ "returned %d.",GetLastError());
+ }
+
+ /* Attempt to call Lockfile on an HANDLE which has been closed. This
+ should fail.
+ */
+ if(LockFile(TheFile, 0, 0, 5, 0) != 0)
+ {
+ Fail("ERROR: Attempted to Lock an invalid handle and the function "
+ "returned success.");
+ }
+
+ /* Attempt to call Lockfile by passing it NULL for a handle. This should
+ fail.
+ */
+
+ if(LockFile(NULL, 0, 0, 5, 0) != 0)
+ {
+ Fail("ERROR: Attempted to Lock a NULL handle and the function "
+ "returned success.");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test7/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test7/testinfo.dat
new file mode 100644
index 0000000000..74e7f00306
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test7/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = LockFile
+Name = Positive test for LockFile API
+TYPE = DEFAULT
+EXE1 = test7
+Description
+= Ensure that LockFile succeeds when the lock begins beyond
+= EOF. Try locking an invalid HANDLE and a NULL Handle.
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/CMakeLists.txt
new file mode 100644
index 0000000000..7c20179353
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/CMakeLists.txt
@@ -0,0 +1,9 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/CMakeLists.txt
new file mode 100644
index 0000000000..ef9838d41e
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ MapViewOfFile.c
+)
+
+add_executable(paltest_mapviewoffile_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_mapviewoffile_test1 coreclrpal)
+
+target_link_libraries(paltest_mapviewoffile_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/MapViewOfFile.c b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/MapViewOfFile.c
new file mode 100644
index 0000000000..6177e0decf
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/MapViewOfFile.c
@@ -0,0 +1,226 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: MapViewOfFile.c
+**
+**
+** Purpose: Positive test the MapViewOfFile API.
+** Call MapViewOfFile with access FILE_MAP_READ.
+**
+**
+**============================================================*/
+#include <palsuite.h>
+#define MAPPINGSIZE 8192
+int __cdecl main(int argc, char *argv[])
+{
+
+ HANDLE hFile = INVALID_HANDLE_VALUE;
+ LPSTR buf = NULL;
+ CHAR ch[MAPPINGSIZE];
+ CHAR lpFileName[] = "test.tmp";
+ DWORD dwBytesWritten = 0;
+ DWORD dwInitialSize = 0;
+ DWORD dwFinalSize = 0;
+ BOOL bRetVal = FALSE;
+
+ HANDLE hFileMapping = 0;
+ LPVOID lpMapViewAddress = NULL;
+
+ /* Initialize the PAL environment.
+ */
+ if( 0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Create a file handle with CreateFile.
+ */
+ hFile = CreateFile( lpFileName,
+ GENERIC_WRITE|GENERIC_READ,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING,
+ NULL);
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail( "ERROR: %u :unable to create file \"%s\".\n",
+ GetLastError(), lpFileName);
+ }
+
+ /* Get the initial size of file, for latter tests.
+ */
+ dwInitialSize = GetFileSize (hFile, NULL);
+ if ( INVALID_FILE_SIZE == dwInitialSize )
+ {
+ Fail("ERROR:%u: The created file \"%s\" has an invalid "
+ "file size.\n",GetLastError(),lpFileName);
+ }
+
+ /*
+ * An application must meet certain requirements when working
+ * with files opened with FILE_FLAG_NO_BUFFERING:
+ * File access must begin at byte offsets within the file that
+ * are integer multiples of the volume's sector size. To determine a
+ * volume's sector size, call the GetDiskFreeSpace function.
+ *
+ * File access must be for numbers of bytes that are integer
+ * multiples of the volume's sector size. For example, if the
+ * sector size is 512 bytes, an application can request reads and
+ * writes of 512, 1024, or 2048 bytes, but not of 335, 981, or 7171 bytes.
+ *
+ * Buffer addresses for read and write operations must be sector
+ * aligned (aligned on addresses in memory that are integer multiples
+ * of the volume's sector size). One way to sector align buffers is to use the
+ * VirtualAlloc function to allocate the buffers. This function allocates memory
+ * that is aligned on addresses that are integer multiples of the system's page size.
+ * Because both page and volume sector sizes are powers of 2, memory aligned by multiples
+ * of the system's page size is also aligned by multiples of the volume's sector size.
+ */
+ buf = (LPSTR)VirtualAlloc( NULL, /* Let the system decide the location. */
+ MAPPINGSIZE / 2, /* One page, the smallest you can request */
+ MEM_COMMIT, /* Reserve and commit in one pass */
+ PAGE_READWRITE ); /* Allow reading and writting. */
+
+ if ( NULL == buf )
+ {
+ Trace( "VirtualAlloc failed! LastError=%d\n", GetLastError() );
+ CloseHandle( hFile );
+ Fail("");
+ }
+
+
+ /*
+ * Write to the File handle.
+ * The reminder will be padded with zeros.
+ */
+ strncpy( buf,
+ "thats not a test string....THIS is a test string",
+ MAPPINGSIZE / 2 );
+
+ bRetVal = WriteFile(hFile,
+ buf,
+ MAPPINGSIZE / 2,
+ &dwBytesWritten,
+ NULL);
+
+ if ( FALSE == bRetVal )
+ {
+ Trace( "ERROR: %u :unable to write to file handle hFile=0x%lx\n",
+ GetLastError(), hFile);
+ CloseHandle(hFile);
+ VirtualFree( buf, 0, MEM_RELEASE );
+ Fail("");
+ }
+
+ /* Create a unnamed file-mapping object with file handle FileHandle
+ * and with PAGE_READWRITE protection.
+ */
+ hFileMapping = CreateFileMapping( hFile,
+ NULL, /*not inherited*/
+ PAGE_READWRITE, /*read and wite*/
+ 0, /*high-order of object size*/
+ MAPPINGSIZE, /*low-orger of object size*/
+ NULL); /*unnamed object*/
+
+ if( NULL == hFileMapping )
+ {
+ Trace("ERROR:%u: Failed to create File Mapping.\n", GetLastError());
+ CloseHandle(hFile);
+ VirtualFree( buf, 0, MEM_RELEASE );
+ Fail("");
+ }
+
+ /* maps a view of a file into the address space of the calling process.
+ */
+ lpMapViewAddress = MapViewOfFile( hFileMapping,
+ FILE_MAP_READ, /* access code */
+ 0, /*high order offset*/
+ 0, /*low order offset*/
+ MAPPINGSIZE); /* number of bytes for map */
+
+ if( NULL == lpMapViewAddress )
+ {
+ Trace( "ERROR:%u: Failed to call MapViewOfFile API to map"
+ " a view of file!\n", GetLastError());
+ CloseHandle(hFile);
+ CloseHandle(hFileMapping);
+ VirtualFree( buf, 0, MEM_RELEASE );
+ Fail("");
+ }
+
+ /* Verify that the size of the file has increased to
+ * accomidate the MapView.
+ */
+ dwFinalSize = GetFileSize (hFile, NULL);
+ if ( (dwFinalSize <= dwInitialSize) && (dwFinalSize != MAPPINGSIZE))
+ {
+
+ CloseHandle(hFile);
+ CloseHandle(hFileMapping);
+ VirtualFree( buf, 0, MEM_RELEASE );
+ UnmapViewOfFile(lpMapViewAddress);
+
+ Fail( "ERROR: Size of the file was expected to "
+ "increase from \"%d\", to \"%d\".\n ",
+ dwInitialSize,
+ dwFinalSize);
+ }
+
+ /* Copy the MapViewOfFile to buffer, so we can
+ * compare with value read from file directly.
+ */
+ memcpy(ch, (LPCSTR)lpMapViewAddress, MAPPINGSIZE);
+ if (memcmp(ch, buf, strlen(buf)) != 0)
+ {
+ CloseHandle(hFile);
+ CloseHandle(hFileMapping);
+ UnmapViewOfFile(lpMapViewAddress) ;
+ VirtualFree( buf, 0, MEM_RELEASE );
+
+ Fail( "ERROR: MapViewOfFile not equal to file contents "
+ "retrieved \"%s\", expected \"%s\".\n",
+ ch,
+ buf);
+ }
+
+ /* Unmap the view of file.
+ */
+ if( FALSE == UnmapViewOfFile(lpMapViewAddress) )
+ {
+ Trace( "\nFailed to call UnmapViewOfFile API to unmap the "
+ "view of a file, error code=%u\n", GetLastError());
+ CloseHandle(hFile);
+ CloseHandle(hFileMapping);
+ VirtualFree( buf, 0, MEM_RELEASE );
+ Fail("");
+ }
+
+ /* Close handle to create file.
+ */
+ if( FALSE == CloseHandle(hFile) )
+ {
+ Trace( "ERROR:%u:Failed to call CloseHandle API to close a file handle.",
+ GetLastError());
+ CloseHandle(hFileMapping);
+ VirtualFree( buf, 0, MEM_RELEASE );
+ Fail("");
+ }
+
+ if( FALSE == CloseHandle(hFileMapping) )
+ {
+ Trace( "ERROR:%u:Failed to call CloseHandle API to close a "
+ "filemapping handle.",GetLastError());
+ VirtualFree( buf, 0, MEM_RELEASE );
+ Fail("");
+ }
+
+ VirtualFree( buf, 0, MEM_RELEASE );
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/testinfo.dat
new file mode 100644
index 0000000000..f1d8451efb
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = MapViewOfFile
+Name = Positive test MapViewOfFile API with access FILE_MAP_READ
+TYPE = DEFAULT
+EXE1 = mapviewoffile
+Description
+=Test the MapViewOfFile with access FILE_MAP_READ
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/CMakeLists.txt
new file mode 100644
index 0000000000..18a9d105b1
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ MapViewOfFile.c
+)
+
+add_executable(paltest_mapviewoffile_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_mapviewoffile_test2 coreclrpal)
+
+target_link_libraries(paltest_mapviewoffile_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/MapViewOfFile.c b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/MapViewOfFile.c
new file mode 100644
index 0000000000..c08f585c0e
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/MapViewOfFile.c
@@ -0,0 +1,203 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: MapViewOfFile.c
+**
+** Purpose: Positive test the MapViewOfFile API.
+** Call MapViewOfFile with access FILE_MAP_WRITE.
+**
+** Depends: CreateFile,
+** GetFileSize,
+** memset,
+** CreateFileMapping,
+** CloseHandle,
+** memcpy,
+** ReadFile,
+** memcmp,
+** UnMapViewOfFile.
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ HANDLE hFile;
+ HANDLE hFileMapping;
+ LPVOID lpMapViewAddress;
+ char buf[] = "this is a test string";
+ const int MAPPINGSIZE = 2048;
+ char ch[2048];
+ char readString[2048];
+ char lpFileName[] = "test.tmp";
+ DWORD dwBytesRead;
+ DWORD dwInitialSize = 0;
+ DWORD dwFinalSize = 0;
+ BOOL bRetVal;
+
+ /* Initialize the PAL environment.
+ */
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Create a file handle with CreateFile.
+ */
+ hFile = CreateFile( lpFileName,
+ GENERIC_WRITE|GENERIC_READ,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: %u :unable to create file \"%s\".\n",
+ GetLastError(),
+ lpFileName);
+ }
+
+ /* Get the initial size of file, for latter tests.
+ */
+ dwInitialSize = GetFileSize (hFile, NULL);
+ if ( dwInitialSize == INVALID_FILE_SIZE )
+ {
+ Fail("ERROR:%u: The created file \"%s\" has an invalid "
+ "file size.\n",
+ GetLastError(),
+ lpFileName);
+ }
+
+ /* Initialize the buffers.
+ */
+ memset(ch, 0, MAPPINGSIZE);
+ memset(readString, 0, MAPPINGSIZE);
+
+ /* Create a unnamed file-mapping object with file handle FileHandle
+ * and with PAGE_READWRITE protection.
+ */
+ hFileMapping = CreateFileMapping(
+ hFile,
+ NULL, /*not inherited*/
+ PAGE_READWRITE, /*read and wite*/
+ 0, /*high-order of object size*/
+ MAPPINGSIZE, /*low-orger of object size*/
+ NULL); /*unnamed object*/
+
+ if(NULL == hFileMapping)
+ {
+ Trace("ERROR:%u: Failed to create File Mapping.\n",
+ GetLastError());
+ CloseHandle(hFile);
+ Fail("");
+ }
+
+ /* maps a view of a file into the address space of the calling process.
+ */
+ lpMapViewAddress = MapViewOfFile(
+ hFileMapping,
+ FILE_MAP_WRITE, /* access code */
+ 0, /*high order offset*/
+ 0, /*low order offset*/
+ MAPPINGSIZE); /* number of bytes for map */
+
+ if(NULL == lpMapViewAddress)
+ {
+ Trace("ERROR:%u: Failed to call MapViewOfFile API to map a view"
+ " of file!\n",
+ GetLastError());
+ CloseHandle(hFile);
+ CloseHandle(hFileMapping);
+ Fail("");
+ }
+
+ /* Verify that the size of the file has increased to
+ * accomidate the MapView.
+ */
+ dwFinalSize = GetFileSize (hFile, NULL);
+ if ( (dwFinalSize <= dwInitialSize) && (dwFinalSize != MAPPINGSIZE))
+ {
+ CloseHandle(hFile);
+ CloseHandle(hFileMapping);
+ Fail("ERROR: Size of the file was expected to "
+ "increase from \"%d\", to \"%d\".\n ",
+ dwInitialSize,
+ MAPPINGSIZE);
+ }
+
+ /* Write to the MapView and copy the MapViewOfFile
+ * to buffer, so we can compare with value read from
+ * file directly.
+ */
+ memcpy(lpMapViewAddress, buf, strlen(buf));
+
+ /* Read from the File handle.
+ */
+ bRetVal = ReadFile(hFile,
+ readString,
+ strlen(buf),
+ &dwBytesRead,
+ NULL);
+
+ if (bRetVal == FALSE)
+ {
+ Trace("ERROR: %u :unable to read from file handle "
+ "hFile=0x%lx\n",
+ GetLastError(),
+ hFile);
+ CloseHandle(hFile);
+ CloseHandle(hFileMapping);
+ Fail("");
+ }
+
+ if (memcmp(buf, readString, strlen(readString)) != 0)
+ {
+ CloseHandle(hFile);
+ CloseHandle(hFileMapping);
+ Fail("ERROR: Read string from file \"%s\", is "
+ "not equal to string written through MapView "
+ "\"%s\".\n",
+ readString,
+ ch);
+ }
+
+ /* Unmap the view of file.
+ */
+ if(UnmapViewOfFile(lpMapViewAddress) == FALSE)
+ {
+ Trace("ERROR: Failed to call UnmapViewOfFile API to"
+ " unmap the view of a file, error code=%u\n",
+ GetLastError());
+ CloseHandle(hFile);
+ CloseHandle(hFileMapping);
+ Fail("");
+ }
+
+ /* Close handle to create file.
+ */
+ if(CloseHandle(hFile) == FALSE)
+ {
+ Trace("ERROR:%u:Failed to call CloseHandle API "
+ "to close a file handle.",
+ GetLastError());
+ CloseHandle(hFileMapping);
+ Fail("");
+ }
+
+ if(CloseHandle(hFileMapping) == FALSE)
+ {
+ Fail("ERROR:%u:Failed to call CloseHandle API "
+ "to close a file mapping handle.",
+ GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/testinfo.dat
new file mode 100644
index 0000000000..13b3f52cf1
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = MapViewOfFile
+Name = Positive test for MapViewOfFile API with access FILE_MAP_WRITE
+TYPE = DEFAULT
+EXE1 = mapviewoffile
+Description
+=Test the MapViewOfFile with access FILE_MAP_WRITE
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/CMakeLists.txt
new file mode 100644
index 0000000000..76bd3276a4
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ MapViewOfFile.c
+)
+
+add_executable(paltest_mapviewoffile_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_mapviewoffile_test3 coreclrpal)
+
+target_link_libraries(paltest_mapviewoffile_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/MapViewOfFile.c b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/MapViewOfFile.c
new file mode 100644
index 0000000000..63bee768f9
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/MapViewOfFile.c
@@ -0,0 +1,209 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: MapViewOfFile.c
+**
+** Purpose: Positive test the MapViewOfFile API.
+** Call MapViewOfFile with access FILE_MAP_ALL_ACCESS.
+**
+** Depends: CreateFile,
+** GetFileSize,
+** memset,
+** memcpy,
+** memcmp,
+** ReadFile,
+** UnMapViewOfFile,
+** CreateFileMapping,
+** CloseHandle.
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ HANDLE hFile;
+ HANDLE hFileMapping;
+ LPVOID lpMapViewAddress;
+ char buf[] = "this is a test string";
+ const int MAPPINGSIZE = 2048;
+ char ch[2048];
+ char readString[2048];
+ char lpFileName[] = "test.tmp";
+ DWORD dwBytesRead;
+ DWORD dwInitialSize = 0;
+ DWORD dwFinalSize = 0;
+ BOOL bRetVal;
+
+ /* Initialize the PAL environment.
+ */
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Create a file handle with CreateFile.
+ */
+ hFile = CreateFile( lpFileName,
+ GENERIC_WRITE|GENERIC_READ,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: %u :unable to create file \"%s\".\n",
+ GetLastError(),
+ lpFileName);
+ }
+
+ /* Get the initial size of file, for latter tests.
+ */
+ dwInitialSize = GetFileSize (hFile, NULL);
+ if ( dwInitialSize == INVALID_FILE_SIZE )
+ {
+ Trace("ERROR:%u: The created file \"%s\" has an invalid "
+ "file size.\n",
+ GetLastError(),
+ lpFileName);
+ CloseHandle(hFile);
+ Fail("");
+ }
+
+ /* Initialize the buffers.
+ */
+ memset(ch, 0, MAPPINGSIZE);
+ memset(readString, 0, MAPPINGSIZE);
+
+ /* Create a unnamed file-mapping object with file handle FileHandle
+ * and with PAGE_READWRITE protection.
+ */
+ hFileMapping = CreateFileMapping(
+ hFile,
+ NULL, /*not inherited*/
+ PAGE_READWRITE, /*read and wite*/
+ 0, /*high-order of object size*/
+ MAPPINGSIZE, /*low-orger of object size*/
+ NULL); /*unnamed object*/
+
+ if(NULL == hFileMapping)
+ {
+ Trace("ERROR:%u: Failed to create File Mapping.\n",
+ GetLastError());
+ CloseHandle(hFile);
+ Fail("");
+ }
+
+ /* maps a view of a file into the address space of the calling process.
+ */
+ lpMapViewAddress = MapViewOfFile(
+ hFileMapping,
+ FILE_MAP_ALL_ACCESS, /*access code*/
+ 0, /*high order offset*/
+ 0, /*low order offset*/
+ MAPPINGSIZE); /* number of bytes for map */
+
+ if(NULL == lpMapViewAddress)
+ {
+ Trace("ERROR:%u: Failed to call MapViewOfFile API to map a view"
+ " of file!\n",
+ GetLastError());
+ CloseHandle(hFile);
+ CloseHandle(hFileMapping);
+ Fail("");
+ }
+
+ /* Verify that the size of the file has increased to
+ * accomidate the MapView.
+ */
+ dwFinalSize = GetFileSize (hFile, NULL);
+ if ( (dwFinalSize <= dwInitialSize) && (dwFinalSize != MAPPINGSIZE))
+ {
+ CloseHandle(hFile);
+ CloseHandle(hFileMapping);
+ Fail("ERROR: Size of the file was expected to "
+ "increase from \"%d\", to \"%d\".\n ",
+ dwInitialSize,
+ MAPPINGSIZE);
+ }
+
+ /* Write to the MapView and copy the MapViewOfFile
+ * to buffer, so we can compare with value read from
+ * file directly.
+ */
+
+ memcpy(lpMapViewAddress, buf, strlen(buf));
+ memcpy(ch, (LPCSTR)lpMapViewAddress, MAPPINGSIZE);
+
+ /* Read from the File handle.
+ */
+ bRetVal = ReadFile(hFile,
+ readString,
+ strlen(buf),
+ &dwBytesRead,
+ NULL);
+
+ if (bRetVal == FALSE)
+ {
+ Trace("ERROR: %u :unable to read from file handle "
+ "hFile=0x%lx\n",
+ GetLastError(),
+ hFile);
+ CloseHandle(hFile);
+ CloseHandle(hFileMapping);
+ Fail("");
+ }
+
+ if (memcmp(ch, readString, strlen(readString)) != 0)
+ {
+ CloseHandle(hFile);
+ CloseHandle(hFileMapping);
+ Fail("ERROR: Read string from file \"%s\", is "
+ "not equal to string written through MapView "
+ "\"%s\".\n",
+ readString,
+ ch);
+ }
+
+ /* Unmap the view of file.
+ */
+ if(UnmapViewOfFile(lpMapViewAddress) == FALSE)
+ {
+ Trace("ERROR: Failed to call UnmapViewOfFile API to"
+ " unmap the view of a file, error code=%u\n",
+ GetLastError());
+ CloseHandle(hFile);
+ CloseHandle(hFileMapping);
+ Fail("");
+ }
+
+ /* Close handle to create file.
+ */
+ if(CloseHandle(hFile) == FALSE)
+ {
+ Trace("ERROR:%u:Failed to call CloseHandle API "
+ "to close a file handle.",
+ GetLastError());
+ CloseHandle(hFileMapping);
+ Fail("");
+ }
+
+ /* Close handle to file mapping.
+ */
+ if(CloseHandle(hFileMapping) == FALSE)
+ {
+ Fail("ERROR:%u:Failed to call CloseHandle API "
+ "to close a file handle.",
+ GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/testinfo.dat
new file mode 100644
index 0000000000..f76333e7ea
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = MapViewOfFile
+Name = Positive test MapViewOfFile API with access FILE_MAP_ALL_ACCESS
+TYPE = DEFAULT
+EXE1 = mapviewoffile
+Description
+=Test the MapViewOfFile with access FILE_MAP_ALL_ACCESS
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/CMakeLists.txt
new file mode 100644
index 0000000000..52381c510f
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ mapviewoffile.c
+)
+
+add_executable(paltest_mapviewoffile_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_mapviewoffile_test4 coreclrpal)
+
+target_link_libraries(paltest_mapviewoffile_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/mapviewoffile.c b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/mapviewoffile.c
new file mode 100644
index 0000000000..7f3252144b
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/mapviewoffile.c
@@ -0,0 +1,166 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: MapViewOfFile.c
+**
+** Purpose: Negative test the MapViewOfFile API.
+** Call MapViewOfFile with all access modes, except
+** read-only, on a read only map.
+**
+** Depends: CreateFile,
+** CreateFileMapping,
+** CloseHandle,
+** UnMapViewOfFile.
+**
+
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ HANDLE hFile;
+ BOOL err;
+ HANDLE hFileMapping;
+ LPVOID lpMapViewAddress;
+ DWORD dwBytesWritten;
+ const int MAPPINGSIZE = 2048;
+ char buf[] = "this is a test string";
+ char lpFileName[] = "test.tmp";
+
+ /* Initialize the PAL environment.
+ */
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Create a file handle with CreateFile.
+ */
+ hFile = CreateFile( lpFileName,
+ GENERIC_WRITE|GENERIC_READ,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: %u :unable to create file \"%s\".\n",
+ GetLastError(),
+ lpFileName);
+ }
+
+ /* Write to the File handle.
+ */
+ err = WriteFile(hFile,
+ buf,
+ strlen(buf),
+ &dwBytesWritten,
+ NULL);
+
+ if ( !FlushFileBuffers( hFile ) )
+ {
+ CloseHandle(hFile);
+ Fail("ERROR: Unable to flush the buffers\n");
+ }
+
+ if (err == FALSE)
+ {
+ Trace("ERROR: %u :unable to write to file handle "
+ "hFile=0x%lx\n",
+ GetLastError(),
+ hFile);
+ CloseHandle(hFile);
+ Fail("");
+ }
+
+ /* Create a unnamed file-mapping object with file handle FileHandle
+ * and with PAGE_READWRITE protection.
+ */
+ hFileMapping = CreateFileMapping(
+ hFile,
+ NULL, /*not inherited*/
+ PAGE_READONLY, /*read and wite*/
+ 0, /*high-order of object size*/
+ 0, /*low-orger of object size*/
+ NULL); /*unnamed object*/
+
+ if(NULL == hFileMapping)
+ {
+ Trace("ERROR:%u: Failed to create File Mapping.\n",
+ GetLastError());
+ CloseHandle(hFile);
+ Fail("");
+ }
+
+ /* map a writeable view of a file to a read-only file map.
+ */
+ lpMapViewAddress = MapViewOfFile(
+ hFileMapping,
+ FILE_MAP_WRITE, /* access code */
+ 0, /* high order offset */
+ 0, /* low order offset */
+ MAPPINGSIZE); /* number of bytes for map */
+
+ if(NULL != lpMapViewAddress)
+ {
+ Trace("ERROR:%u: Able to create a writeable MapViewOfFile"
+ " to a read-only file.\n",
+ GetLastError());
+ CloseHandle(hFile);
+ CloseHandle(hFileMapping);
+ UnmapViewOfFile(lpMapViewAddress);
+ Fail("");
+ }
+
+ /* map an all access view of a file to a read-only file map.
+ */
+ lpMapViewAddress = MapViewOfFile(
+ hFileMapping,
+ FILE_MAP_ALL_ACCESS, /* access code */
+ 0, /* high order offset */
+ 0, /* low order offset */
+ MAPPINGSIZE); /* number of bytes for map */
+
+ if(NULL != lpMapViewAddress)
+ {
+ Trace("ERROR:%u: Able to create an all access MapViewOfFile"
+ " to a read-only file.\n",
+ GetLastError());
+ CloseHandle(hFile);
+ CloseHandle(hFileMapping);
+ UnmapViewOfFile(lpMapViewAddress);
+ Fail("");
+ }
+
+ /* map an copy view of a file to a read-only file map.
+ */
+ lpMapViewAddress = MapViewOfFile(
+ hFileMapping,
+ FILE_MAP_COPY, /* access code */
+ 0, /* high order offset */
+ 0, /* low order offset */
+ MAPPINGSIZE); /* number of bytes for map */
+
+ if(NULL != lpMapViewAddress)
+ {
+ Trace("ERROR:%u: Able to create a copy access MapViewOfFile "
+ "to a read-only file.\n",
+ GetLastError());
+ CloseHandle(hFile);
+ CloseHandle(hFileMapping);
+ Fail("");
+ }
+
+ /* Clean-up and Teminate. */
+ CloseHandle(hFile);
+ CloseHandle(hFileMapping);
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/testinfo.dat
new file mode 100644
index 0000000000..37655eda5b
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = MapViewOfFile
+Name = Negative test MapViewOfFile API
+TYPE = DEFAULT
+EXE1 = mapviewoffile
+Description
+= Negative test the MapViewOfFile API.
+= Call MapViewOfFile with all access modes,
+= except read-only, on a read only map.
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/CMakeLists.txt
new file mode 100644
index 0000000000..f98a4b7779
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ mapviewoffile.c
+)
+
+add_executable(paltest_mapviewoffile_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_mapviewoffile_test5 coreclrpal)
+
+target_link_libraries(paltest_mapviewoffile_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/mapviewoffile.c b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/mapviewoffile.c
new file mode 100644
index 0000000000..219b3fa12a
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/mapviewoffile.c
@@ -0,0 +1,131 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: MapViewOfFile.c
+**
+** Purpose: Negative test the MapViewOfFile API.
+** Passing invalid values for the hFileMappingObject.
+**
+** Depends: CreatePipe,
+** CreateFile,
+** CreateFileMapping,
+** CloseHandle.
+**
+
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ const int MAPPINGSIZE = 2048;
+ HANDLE hFileMapping;
+ LPVOID lpMapViewAddress;
+ HANDLE hReadPipe = NULL;
+ HANDLE hWritePipe = NULL;
+ BOOL bRetVal;
+
+ SECURITY_ATTRIBUTES lpPipeAttributes;
+
+ /* Initialize the PAL environment.
+ */
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /* Attempt to create a MapViewOfFile with a NULL handle.
+ */
+ hFileMapping = NULL;
+
+ lpMapViewAddress = MapViewOfFile(
+ hFileMapping,
+ FILE_MAP_WRITE, /* access code */
+ 0, /* high order offset */
+ 0, /* low order offset */
+ MAPPINGSIZE); /* number of bytes for map */
+
+ if((NULL != lpMapViewAddress) &&
+ (GetLastError() != ERROR_INVALID_HANDLE))
+ {
+ Trace("ERROR:%u: Able to create a MapViewOfFile with "
+ "hFileMapping=0x%lx.\n",
+ GetLastError());
+ UnmapViewOfFile(lpMapViewAddress);
+ Fail("");
+ }
+
+ /* Attempt to create a MapViewOfFile with an invalid handle.
+ */
+ hFileMapping = INVALID_HANDLE_VALUE;
+
+ lpMapViewAddress = MapViewOfFile(
+ hFileMapping,
+ FILE_MAP_WRITE, /* access code */
+ 0, /* high order offset */
+ 0, /* low order offset */
+ MAPPINGSIZE); /* number of bytes for map */
+
+ if((NULL != lpMapViewAddress) &&
+ (GetLastError() != ERROR_INVALID_HANDLE))
+ {
+ Trace("ERROR:%u: Able to create a MapViewOfFile with "
+ "hFileMapping=0x%lx.\n",
+ GetLastError());
+ UnmapViewOfFile(lpMapViewAddress);
+ Fail("");
+ }
+
+ /* Setup SECURITY_ATTRIBUTES structure for CreatePipe.
+ */
+ lpPipeAttributes.nLength = sizeof(lpPipeAttributes);
+ lpPipeAttributes.lpSecurityDescriptor = NULL;
+ lpPipeAttributes.bInheritHandle = TRUE;
+
+ /* Create a Pipe.
+ */
+ bRetVal = CreatePipe(&hReadPipe, /* read handle*/
+ &hWritePipe, /* write handle */
+ &lpPipeAttributes,/* security attributes*/
+ 0); /* pipe size*/
+ if (bRetVal == FALSE)
+ {
+ Fail("ERROR: %ld :Unable to create pipe\n",
+ GetLastError());
+ }
+
+ /* Attempt creating a MapViewOfFile with a Pipe Handle.
+ */
+ lpMapViewAddress = MapViewOfFile(
+ hReadPipe,
+ FILE_MAP_WRITE, /* access code */
+ 0, /* high order offset */
+ 0, /* low order offset */
+ MAPPINGSIZE); /* number of bytes for map */
+
+ if((NULL != lpMapViewAddress) &&
+ (GetLastError() != ERROR_INVALID_HANDLE))
+ {
+ Trace("ERROR:%u: Able to create a MapViewOfFile with "
+ "hFileMapping=0x%lx.\n",
+ GetLastError());
+ CloseHandle(hReadPipe);
+ CloseHandle(hWritePipe);
+ UnmapViewOfFile(lpMapViewAddress);
+ Fail("");
+ }
+
+ /* Clean-up and Terminate the PAL.
+ */
+ CloseHandle(hReadPipe);
+ CloseHandle(hWritePipe);
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/testinfo.dat
new file mode 100644
index 0000000000..e3ecb32772
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = MapViewOfFile
+Name = Negative test for MapViewOfFile API.
+TYPE = DEFAULT
+EXE1 = mapviewoffile
+Description
+= Negative test the MapViewOfFile API.
+= Passing invalid values for the hFileMappingObject.
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test6/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test6/CMakeLists.txt
new file mode 100644
index 0000000000..dad03aaf80
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ mapviewoffile.c
+)
+
+add_executable(paltest_mapviewoffile_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_mapviewoffile_test6 coreclrpal)
+
+target_link_libraries(paltest_mapviewoffile_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test6/mapviewoffile.c b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test6/mapviewoffile.c
new file mode 100644
index 0000000000..f7d7302a4c
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test6/mapviewoffile.c
@@ -0,0 +1,85 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: MapViewOfFile.c
+**
+** Purpose: Positivve test the MapViewOfFile API.
+** Mapping a pagefile allocation into memory
+**
+** Depends: CreateFileMappingW,
+** UnmapViewOfFile
+** CloseHandle.
+**
+
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ const int MAPPINGSIZE = 2048;
+ HANDLE hFileMapping;
+ LPVOID lpMapViewAddress;
+ char *p;
+ int i;
+
+ /* Initialize the PAL environment.
+ */
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ hFileMapping = CreateFileMappingW(INVALID_HANDLE_VALUE,
+ NULL,
+ PAGE_READWRITE,
+ 0,
+ MAPPINGSIZE,
+ NULL);
+
+ if (hFileMapping == NULL) {
+ Trace("ERROR:%u: CreateFileMappingW() failed\n", GetLastError());
+ Fail("");
+ }
+
+
+ lpMapViewAddress = MapViewOfFile(
+ hFileMapping,
+ FILE_MAP_WRITE, /* access code */
+ 0, /* high order offset */
+ 0, /* low order offset */
+ MAPPINGSIZE); /* number of bytes for map */
+
+ if(NULL == lpMapViewAddress)
+ {
+ Trace("ERROR:%u: MapViewOfFile() failed.\n",
+ GetLastError());
+ CloseHandle(hFileMapping);
+ Fail("");
+ }
+
+ p = (char *)lpMapViewAddress;
+ for (i=0; i<MAPPINGSIZE; ++i) {
+ /* Confirm that the memory is zero-initialized */
+ if (p[i] != 0)
+ {
+ Fail("MapViewOfFile() of pagefile didn't return 0-filled data "
+ "(Offset %d has value 0x%x)\n", i, p[i]);
+ }
+ /* Confirm that it is writable */
+ *(char *)lpMapViewAddress = 0xcc;
+ }
+
+ /* Clean-up and Terminate the PAL.
+ */
+ CloseHandle(hFileMapping);
+ UnmapViewOfFile(lpMapViewAddress);
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test6/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test6/testinfo.dat
new file mode 100644
index 0000000000..020827d2fe
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test6/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = MapViewOfFile
+Name = Positive test for MapViewOfFile API.
+TYPE = DEFAULT
+EXE1 = mapviewoffile
+Description
+= Positive test the MapViewOfFile API.
+= Mapping in a section of anonymous pagefile
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/CMakeLists.txt
new file mode 100644
index 0000000000..1962ade358
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test1/CMakeLists.txt
new file mode 100644
index 0000000000..b286924864
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ OpenFileMappingA.c
+)
+
+add_executable(paltest_openfilemappinga_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_openfilemappinga_test1 coreclrpal)
+
+target_link_libraries(paltest_openfilemappinga_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test1/OpenFileMappingA.c b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test1/OpenFileMappingA.c
new file mode 100644
index 0000000000..9087285112
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test1/OpenFileMappingA.c
@@ -0,0 +1,157 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: openfilemappinga.c (test 1)
+**
+** Purpose: Positive test the OpenFileMapping API.
+** Call OpenFileMapping to open a named file-mapping
+** object with FILE_MAP_ALL_ACCESS access
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE FileMappingHandle;
+ HANDLE OpenFileMappingHandle;
+ HANDLE lpMapViewAddress;
+ const int LOWORDERSIZE = 1024;
+ char buf[] = "this is a test";
+ char MapObject[] = "myMappingObject";
+ char ch[1024];
+ int err;
+ int RetVal = PASS;
+
+ /* Initialize the PAL environment.
+ */
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+
+ /* Create a named file-mapping object with
+ * file handle FileHandle.
+ */
+ FileMappingHandle = CreateFileMapping(
+ INVALID_HANDLE_VALUE,
+ NULL, /* not inherited */
+ PAGE_READWRITE, /* read and write */
+ 0, /* high-order size */
+ LOWORDERSIZE, /* low-order size */
+ MapObject); /* named object */
+
+ if(NULL == FileMappingHandle)
+ {
+ Fail("ERROR:%u:Failed to call CreateFileMapping to "
+ "create a mapping object.\n",
+ GetLastError());
+ }
+ if(GetLastError() == ERROR_ALREADY_EXISTS)
+ {
+ Trace("ERROR:File mapping object already exists\n");
+ RetVal = FAIL;
+ goto CleanUpOne;
+ }
+
+ /* Open a named file-mapping object with
+ * FILE_MAP_ALL_ACCESS access.
+ */
+ OpenFileMappingHandle = OpenFileMapping(
+ FILE_MAP_ALL_ACCESS,
+ TRUE,
+ MapObject );
+
+ if(NULL == OpenFileMappingHandle)
+ {
+ Trace("ERROR:%u:Failed to Call OpenFileMapping API!\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpOne;
+ }
+
+ /* Test the opened map view.
+ */
+ lpMapViewAddress = MapViewOfFile(
+ OpenFileMappingHandle,
+ FILE_MAP_ALL_ACCESS, /* access code */
+ 0, /* high order offset */
+ 0, /* low order offset */
+ LOWORDERSIZE); /* number of bytes for map */
+
+ if(NULL == lpMapViewAddress)
+ {
+ Trace("ERROR:%u: Failed to call MapViewOfFile "
+ "API to map a view of file!\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpTwo;
+ }
+
+ /* Write to the Map View.
+ */
+ memcpy(lpMapViewAddress, buf, strlen(buf));
+
+ /* Read from the Map View.
+ */
+ memcpy(ch, (LPCSTR)lpMapViewAddress, LOWORDERSIZE);
+
+ /* Compare what was written to the Map View,
+ * to what was read.
+ */
+ if (memcmp(ch, buf, strlen(buf))!= 0)
+ {
+ Trace("ERROR: MapViewOfFile not equal to file contents "
+ "retrieved \"%s\", expected \"%s\".\n",
+ ch, buf);
+ RetVal = FAIL;
+ goto CleanUpThree;
+
+ }
+
+CleanUpThree:
+
+ /* Unmap the view of file.
+ */
+ if ( UnmapViewOfFile(lpMapViewAddress) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n",
+ GetLastError(),
+ lpMapViewAddress);
+ RetVal = FAIL;
+ }
+
+CleanUpTwo:
+
+ /* Close Handle to opend file mapping.
+ */
+ if ( CloseHandle(OpenFileMappingHandle) == 0 )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ OpenFileMappingHandle);
+ RetVal = FAIL;
+ }
+
+CleanUpOne:
+
+ /* Close Handle to create file mapping.
+ */
+ if ( CloseHandle(FileMappingHandle) == 0 )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ FileMappingHandle);
+ RetVal = FAIL;
+ }
+
+
+ /* Terminat the PAL.*/
+ PAL_TerminateEx(RetVal);
+ return RetVal;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test1/testinfo.dat
new file mode 100644
index 0000000000..010f2fe279
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = OpenFileMappingA
+Name = Positive test for OpenFileMappingA API with FILE_MAP_ALL_ACCESS access
+TYPE = DEFAULT
+EXE1 = openfilemappinga
+Description
+=Test the OpenFileMappingA with FILE_MAP_ALL_ACCESS access
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/CMakeLists.txt
new file mode 100644
index 0000000000..3a0eff04a7
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ OpenFileMappingA.c
+)
+
+add_executable(paltest_openfilemappinga_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_openfilemappinga_test2 coreclrpal)
+
+target_link_libraries(paltest_openfilemappinga_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/OpenFileMappingA.c b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/OpenFileMappingA.c
new file mode 100644
index 0000000000..5e41a92024
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/OpenFileMappingA.c
@@ -0,0 +1,214 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: openfilemappinga.c (test 2)
+**
+** Purpose: Positive test the OpenFileMapping API.
+** Call OpenFileMapping to open a named file-mapping
+** object with FILE_MAP_WRITE access
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE FileMappingHandle;
+ HANDLE OpenFileMappingHandle;
+ HANDLE lpMapViewAddress;
+ HANDLE OpenFileMappingHandle2;
+ HANDLE lpMapViewAddress2;
+ const int LOWORDERSIZE = 1024;
+ char MapObject[] = "myMappingObject";
+ char buf[] = "this is a test";
+ char ch[1024];
+ int RetVal = PASS;
+
+
+ /* Initialize the PAL environment.
+ */
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Create a named file-mapping object with file handle FileHandle.
+ */
+ FileMappingHandle = CreateFileMapping(
+ INVALID_HANDLE_VALUE,
+ NULL, /* not inherited */
+ PAGE_READWRITE, /* read and write */
+ 0, /* high-order size */
+ LOWORDERSIZE, /* low-order size */
+ MapObject); /* named object */
+
+
+ if(NULL == FileMappingHandle)
+ {
+ Fail("\nFailed to call CreateFileMapping to create "
+ "a mapping object!\n");
+ }
+ if(GetLastError() == ERROR_ALREADY_EXISTS)
+ {
+ Trace("\nFile mapping object already exists!\n");
+ RetVal = FAIL;
+ goto CleanUpOne;
+ }
+
+ /* Open a named file-mapping object with FILE_MAP_WRITE access.
+ */
+ OpenFileMappingHandle = OpenFileMapping(
+ FILE_MAP_WRITE,
+ FALSE,
+ MapObject);
+
+ if(NULL == OpenFileMappingHandle)
+ {
+ Trace("\nFailed to Call OpenFileMapping API!\n");
+ RetVal = FAIL;
+ goto CleanUpOne;
+ }
+
+ /* Open a named file-mapping object with
+ * FILE_MAP_ALL_ACCESS access, to verify
+ * the FILE_MAP_WRITE access map.
+ */
+ OpenFileMappingHandle2 = OpenFileMapping(
+ FILE_MAP_ALL_ACCESS,
+ FALSE,
+ MapObject);
+
+ if(NULL == OpenFileMappingHandle2)
+ {
+ Trace("\nFailed to Call OpenFileMapping API!\n");
+ RetVal = FAIL;
+ goto CleanUpTwo;
+ }
+
+ /* Create map view of the open mapping that has
+ * FILE_MAP_WRITE access.
+ */
+ lpMapViewAddress = MapViewOfFile(
+ OpenFileMappingHandle,
+ FILE_MAP_WRITE, /* access code */
+ 0, /* high order offset */
+ 0, /* low order offset */
+ LOWORDERSIZE); /* number of bytes for map */
+
+ if(NULL == lpMapViewAddress)
+ {
+ Trace("ERROR:%u: Failed to call MapViewOfFile "
+ "API to map a view of file!\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpThree;
+ }
+
+ /* Create map view of the open mapping that has
+ * FILE_MAP_ALL_ACCESS access.
+ */
+ lpMapViewAddress2 = MapViewOfFile(
+ OpenFileMappingHandle2,
+ FILE_MAP_ALL_ACCESS, /* access code */
+ 0, /* high order offset */
+ 0, /* low order offset */
+ LOWORDERSIZE); /* number of bytes for map */
+
+ if(NULL == lpMapViewAddress2)
+ {
+ Trace("ERROR:%u: Failed to call MapViewOfFile "
+ "API to map a view of file!\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpFour;
+ }
+
+ /* Write to the Map View.
+ */
+ memcpy(lpMapViewAddress, buf, strlen(buf));
+
+ /* Read from the Map View.
+ */
+ memcpy(ch, (LPCSTR)lpMapViewAddress, LOWORDERSIZE);
+
+ /* Compare what was written to the Map View,
+ * to what was read.
+ */
+ if (memcmp(ch, buf, strlen(buf))!= 0)
+ {
+ Fail("ERROR: MapViewOfFile not equal to file contents "
+ "retrieved \"%s\", expected \"%s\".\n",
+ ch, buf);
+ RetVal = FAIL;
+ goto CleanUpFive;
+ }
+
+CleanUpFive:
+
+ /* Unmap the view of file.
+ */
+ if ( UnmapViewOfFile(lpMapViewAddress2) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n",
+ GetLastError(),
+ lpMapViewAddress2);
+ RetVal = FAIL;
+ }
+
+CleanUpFour:
+
+ /* Unmap the view of file.
+ */
+ if ( UnmapViewOfFile(lpMapViewAddress) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n",
+ GetLastError(),
+ lpMapViewAddress);
+ RetVal = FAIL;
+ }
+
+CleanUpThree:
+
+ /* Close Handle to opened file mapping.
+ */
+ if ( CloseHandle(OpenFileMappingHandle2) == 0 )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ OpenFileMappingHandle2);
+ RetVal = FAIL;
+ }
+
+CleanUpTwo:
+
+ /* Close Handle to opened file mapping.
+ */
+ if ( CloseHandle(OpenFileMappingHandle) == 0 )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ OpenFileMappingHandle);
+ RetVal = FAIL;
+ }
+
+CleanUpOne:
+
+ /* Close Handle to create file mapping.
+ */
+ if ( CloseHandle(FileMappingHandle) == 0 )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ FileMappingHandle);
+ RetVal = FAIL;
+ }
+
+
+ /* Terminate the PAL.
+ */
+ PAL_TerminateEx(RetVal);
+ return RetVal;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/testinfo.dat
new file mode 100644
index 0000000000..2a02128b68
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = OpenFileMappingA
+Name = Positive test for OpenFileMappingA API with FILE_MAP_WRITE access
+TYPE = DEFAULT
+EXE1 = openfilemappinga
+Description
+=Test the OpenFileMappingA with FILE_MAP_WRITE access
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/CMakeLists.txt
new file mode 100644
index 0000000000..599a09ffc7
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ OpenFileMappingA.c
+)
+
+add_executable(paltest_openfilemappinga_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_openfilemappinga_test3 coreclrpal)
+
+target_link_libraries(paltest_openfilemappinga_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/OpenFileMappingA.c b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/OpenFileMappingA.c
new file mode 100644
index 0000000000..b01a3e8c0b
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/OpenFileMappingA.c
@@ -0,0 +1,217 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: openfilemappinga.c
+**
+** Purpose: Positive test the OpenFileMapping API.
+** Call OpenFileMapping to open a named file-mapping
+** object with FILE_MAP_READ access
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ HANDLE FileMappingHandle;
+ HANDLE OpenFileMappingHandle;
+ HANDLE OpenFileMappingHandle2;
+ HANDLE lpMapViewAddress;
+ HANDLE lpMapViewAddress2;
+ const int LOWORDERSIZE = 1024;
+ char buf[] = "this is a test";
+ char MapObject[] = "myMappingObject";
+ char ch[1024];
+ int RetVal = PASS;
+
+ /* Initialize the PAL environment.
+ */
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Create a named file-mapping object with file handle FileHandle.
+ */
+ FileMappingHandle = CreateFileMapping(
+ INVALID_HANDLE_VALUE,
+ NULL, /* Not inherited */
+ PAGE_READWRITE, /* Read only */
+ 0, /* High-order size */
+ LOWORDERSIZE, /* Must be none 0 */
+ MapObject); /* Named object */
+
+
+ if(NULL == FileMappingHandle)
+ {
+ Fail("ERROR:%u:Failed to call CreateFileMapping to create "
+ "mapping object = \"%s\".\n",
+ GetLastError(),
+ MapObject);
+ }
+ if(GetLastError() == ERROR_ALREADY_EXISTS)
+ {
+ Trace("ERROR:File mapping object \"%s\" already exists!\n",
+ MapObject);
+ RetVal = FAIL;
+ goto CleanUpOne;
+ }
+
+ /* Open a named file-mapping object with
+ * FILE_MAP_READ access.
+ */
+ OpenFileMappingHandle = OpenFileMapping(
+ FILE_MAP_READ,
+ 0,
+ MapObject);
+
+ if(NULL == OpenFileMappingHandle)
+ {
+ Trace("ERROR:%u: Failed to Call OpenFileMapping API.\n");
+ RetVal = FAIL;
+ goto CleanUpOne;
+ }
+
+ /* Open a named file-mapping object with
+ * FILE_MAP_ALL_ACCESS access, to verify the
+ * READ-ONLY Map view.
+ */
+ OpenFileMappingHandle2 = OpenFileMapping(
+ FILE_MAP_ALL_ACCESS,
+ 0,
+ MapObject);
+
+ if(NULL == OpenFileMappingHandle2)
+ {
+ Trace("Failed to Call OpenFileMapping API!\n");
+ RetVal = FAIL;
+ goto CleanUpTwo;
+ }
+
+ /* Test the opened map view.
+ */
+ lpMapViewAddress = MapViewOfFile(
+ OpenFileMappingHandle,
+ FILE_MAP_READ, /* access code */
+ 0, /* high order offset */
+ 0, /* low order offset */
+ LOWORDERSIZE); /* number of bytes for map */
+
+ if(NULL == lpMapViewAddress)
+ {
+ Trace("ERROR:%u: Failed to call MapViewOfFile "
+ "API to map a view of file!\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpThree;
+ }
+
+ /* Open the second Map view to verify the writing
+ * of the READ-ONLY Map view.
+ */
+ lpMapViewAddress2 = MapViewOfFile(
+ OpenFileMappingHandle2,
+ FILE_MAP_ALL_ACCESS, /* access code */
+ 0, /* high order offset */
+ 0, /* low order offset */
+ LOWORDERSIZE); /* number of bytes for map */
+
+ if(NULL == lpMapViewAddress2)
+ {
+ Trace("ERROR:%u: Failed to call MapViewOfFile "
+ "API to map a view of file!\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpFour;
+ }
+
+ /* Write to the ALL_ACCESS Map View.
+ */
+ memcpy(lpMapViewAddress2, buf, strlen(buf));
+
+ /* Read from the READ-ONLY Map View.
+ */
+ memcpy(ch, (LPCSTR)lpMapViewAddress, LOWORDERSIZE);
+
+ /* Compare what was written to the Map View,
+ * to what was read.
+ */
+ if (memcmp(ch, buf, strlen(buf))!= 0)
+ {
+ Trace("ERROR: MapViewOfFile not equal to file contents "
+ "retrieved \"%s\", expected \"%s\".\n",
+ ch, buf);
+ RetVal = FAIL;
+ goto CleanUpFive;
+ }
+
+CleanUpFive:
+
+ /* Unmap the view of file.
+ */
+ if ( UnmapViewOfFile(lpMapViewAddress2) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n",
+ GetLastError(),
+ lpMapViewAddress2);
+ RetVal = FAIL;
+ }
+
+CleanUpFour:
+
+ /* Unmap the view of file.
+ */
+ if ( UnmapViewOfFile(lpMapViewAddress) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n",
+ GetLastError(),
+ lpMapViewAddress);
+ RetVal = FAIL;
+ }
+
+CleanUpThree:
+
+ /* Close Handle to opened file mapping.
+ */
+ if ( CloseHandle(OpenFileMappingHandle2) == 0 )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ OpenFileMappingHandle2);
+ RetVal = FAIL;
+ }
+
+CleanUpTwo:
+
+ /* Close Handle to opened file mapping.
+ */
+ if ( CloseHandle(OpenFileMappingHandle) == 0 )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ OpenFileMappingHandle);
+ RetVal = FAIL;
+ }
+
+CleanUpOne:
+
+ /* Close Handle to create file mapping.
+ */
+ if ( CloseHandle(FileMappingHandle) == 0 )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ FileMappingHandle);
+ RetVal = FAIL;
+ }
+
+ /* Terminate the PAL.
+ */
+ PAL_TerminateEx(RetVal);
+ return RetVal;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/testinfo.dat
new file mode 100644
index 0000000000..4aff853f91
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = OpenFileMappingA
+Name = Positive test for OpenFileMappingA API with FILE_MAP_READ access
+TYPE = DEFAULT
+EXE1 = openfilemappinga
+Description
+=Test the OpenFileMappingA with FILE_MAP_READ access
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/CMakeLists.txt
new file mode 100644
index 0000000000..1962ade358
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..04e9e47ef0
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ OpenFileMappingW.c
+)
+
+add_executable(paltest_openfilemappingw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_openfilemappingw_test1 coreclrpal)
+
+target_link_libraries(paltest_openfilemappingw_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/OpenFileMappingW.c b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/OpenFileMappingW.c
new file mode 100644
index 0000000000..079af4a5c0
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/OpenFileMappingW.c
@@ -0,0 +1,155 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: openfilemappingw.c (test 1)
+**
+** Purpose: Positive test the OpenFileMapping API.
+** Call OpenFileMapping to open a named file-mapping
+** object with FILE_MAP_ALL_ACCESS access
+**
+**
+**============================================================*/
+
+#define UNICODE
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ HANDLE lpMapViewAddress;
+ char buf[] = "this is a test";
+ char ch[1024];
+
+ HANDLE FileMappingHandle;
+ HANDLE OpenFileMappingHandle;
+ const int LOWORDERSIZE = 1024;
+ int RetVal = PASS;
+ WCHAR wpMappingFileObject[] = {'m','y','O','b','j','e','c','t','\0'};
+
+ /* Initialize the PAL environment.
+ */
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Create a unnamed file-mapping object with file handle FileHandle.
+ */
+ FileMappingHandle = CreateFileMapping(
+ INVALID_HANDLE_VALUE,
+ NULL, /* Not inherited*/
+ PAGE_READWRITE, /* Read and write*/
+ 0, /* High-order size*/
+ LOWORDERSIZE, /* Low-order size*/
+ wpMappingFileObject);/* Named object*/
+
+
+ if(NULL == FileMappingHandle)
+ {
+ Fail("\nFailed to call CreateFileMapping to create a "
+ "mapping object!\n");
+ }
+ if(GetLastError() == ERROR_ALREADY_EXISTS)
+ {
+ Trace("\nFile mapping object already exists!\n");
+ RetVal = FAIL;
+ goto CleanUpOne;
+ }
+
+ /* Open a named file-mapping object with FILE_MAP_ALL_ACCESS access.
+ */
+ OpenFileMappingHandle = OpenFileMapping(
+ FILE_MAP_ALL_ACCESS,
+ FALSE,
+ wpMappingFileObject);
+
+ if(NULL == OpenFileMappingHandle)
+ {
+ Trace("\nFailed to Call OpenFileMapping API!\n");
+ RetVal = FAIL;
+ goto CleanUpOne;
+ }
+
+ /* Test the opened map view.
+ */
+ lpMapViewAddress = MapViewOfFile(
+ OpenFileMappingHandle,
+ FILE_MAP_ALL_ACCESS, /* access code */
+ 0, /* high order offset */
+ 0, /* low order offset */
+ LOWORDERSIZE); /* number of bytes for map */
+
+ if(NULL == lpMapViewAddress)
+ {
+ Trace("ERROR:%u: Failed to call MapViewOfFile "
+ "API to map a view of file!\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpTwo;
+ }
+
+ /* Write to the Map View.
+ */
+ memcpy(lpMapViewAddress, buf, strlen(buf));
+
+ /* Read from the Map View.
+ */
+ memcpy(ch, (LPCSTR)lpMapViewAddress, LOWORDERSIZE);
+
+ /* Compare what was written to the Map View,
+ * to what was read.
+ */
+ if (memcmp(ch, buf, strlen(buf))!= 0)
+ {
+ Trace("ERROR: MapViewOfFile not equal to file contents "
+ "retrieved \"%s\", expected \"%s\".\n",
+ ch, buf);
+ RetVal = FAIL;
+ goto CleanUpThree;
+ }
+
+CleanUpThree:
+
+ /* Unmap the view of file.
+ */
+ if ( UnmapViewOfFile(lpMapViewAddress) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n",
+ GetLastError(),
+ lpMapViewAddress);
+ RetVal = FAIL;
+ }
+
+CleanUpTwo:
+
+ /* Close Handle to opend file mapping.
+ */
+ if ( CloseHandle(OpenFileMappingHandle) == 0 )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ OpenFileMappingHandle);
+ RetVal = FAIL;
+ }
+
+CleanUpOne:
+
+ /* Close Handle to create file mapping.
+ */
+ if ( CloseHandle(FileMappingHandle) == 0 )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ FileMappingHandle);
+ RetVal = FAIL;
+ }
+
+ /* Terminate the PAL.
+ */
+ PAL_TerminateEx(RetVal);
+ return RetVal;
+}
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/testinfo.dat
new file mode 100644
index 0000000000..e67f4775f4
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = OpenFileMappingW
+Name = Positive test for OpenFileMappingW API
+TYPE = DEFAULT
+EXE1 = openfilemappingw
+Description
+=Test the OpenFileMappingW with FILE_MAP_ALL_ACCESS access
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/CMakeLists.txt
new file mode 100644
index 0000000000..22e960b788
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ OpenFileMappingW.c
+)
+
+add_executable(paltest_openfilemappingw_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_openfilemappingw_test2 coreclrpal)
+
+target_link_libraries(paltest_openfilemappingw_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/OpenFileMappingW.c b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/OpenFileMappingW.c
new file mode 100644
index 0000000000..e6a69651fa
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/OpenFileMappingW.c
@@ -0,0 +1,217 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: openfilemappingw.c (test 2)
+**
+** Purpose: Positive test the OpenFileMapping API.
+** Call OpenFileMapping to open a named file-mapping
+** object with FILE_MAP_WRITE access
+**
+**
+**============================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE FileMappingHandle;
+ HANDLE OpenFileMappingHandle;
+ HANDLE lpMapViewAddress;
+ HANDLE OpenFileMappingHandle2;
+ HANDLE lpMapViewAddress2;
+ const int LOWORDERSIZE = 1024;
+ WCHAR MapObject[] = {'m','y','O','b','j','e','c','t','\0'};
+ char buf[] = "this is a test";
+ char ch[1024];
+ int RetVal = PASS;
+
+
+ /* Initialize the PAL environment.
+ */
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Create a named file-mapping object with file handle FileHandle.
+ */
+ FileMappingHandle = CreateFileMapping(
+ INVALID_HANDLE_VALUE,
+ NULL, /* not inherited */
+ PAGE_READWRITE, /* read and wite */
+ 0, /* high-order size */
+ LOWORDERSIZE, /* low-order size */
+ MapObject); /* named object */
+
+ if(NULL == FileMappingHandle)
+ {
+ Fail("\nFailed to call CreateFileMapping to "
+ "create a mapping object!\n");
+ }
+ if(GetLastError() == ERROR_ALREADY_EXISTS)
+ {
+ Trace("\nFile mapping object already exists!\n");
+ RetVal = FAIL;
+ goto CleanUpOne;
+ }
+
+ /* Open a named file-mapping object with FILE_MAP_WRITE access.
+ */
+ OpenFileMappingHandle = OpenFileMapping(
+ FILE_MAP_WRITE,
+ FALSE,
+ MapObject);
+
+ if(NULL == OpenFileMappingHandle)
+ {
+ Trace("\nFailed to Call OpenFileMappingW API!\n");
+ RetVal = FAIL;
+ goto CleanUpOne;
+ }
+
+ /* Open a named file-mapping object with
+ * FILE_MAP_ALL_ACCESS access, to verify
+ * the FILE_MAP_WRITE access map.
+ */
+ OpenFileMappingHandle2 = OpenFileMapping(
+ FILE_MAP_ALL_ACCESS,
+ FALSE,
+ MapObject);
+
+ if(NULL == OpenFileMappingHandle2)
+ {
+ Trace("\nFailed to Call OpenFileMappingW API!\n");
+ RetVal = FAIL;
+ goto CleanUpTwo;
+ }
+
+ /* Create map view of the open mapping that has
+ * FILE_MAP_WRITE access.
+ */
+ lpMapViewAddress = MapViewOfFile(
+ OpenFileMappingHandle,
+ FILE_MAP_WRITE, /* access code */
+ 0, /* high order offset */
+ 0, /* low order offset */
+ LOWORDERSIZE); /* number of bytes for map */
+
+ if(NULL == lpMapViewAddress)
+ {
+ Trace("ERROR:%u: Failed to call MapViewOfFile "
+ "API to map a view of file!\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpThree;
+ }
+
+ /* Create map view of the open mapping that has
+ * FILE_MAP_ALL_ACCESS access.
+ */
+
+ lpMapViewAddress2 = MapViewOfFile(
+ OpenFileMappingHandle2,
+ FILE_MAP_ALL_ACCESS, /* access code */
+ 0, /* high order offset */
+ 0, /* low order offset */
+ LOWORDERSIZE); /* number of bytes for map */
+
+ if(NULL == lpMapViewAddress2)
+ {
+ Trace("ERROR:%u: Failed to call MapViewOfFile "
+ "API to map a view of file!\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpFour;
+ }
+
+ /* Write to the Map View.
+ */
+ memcpy(lpMapViewAddress, buf, strlen(buf));
+
+ /* Read from the Map View.
+ */
+ memcpy(ch, (LPCSTR)lpMapViewAddress, LOWORDERSIZE);
+
+ /* Compare what was written to the Map View,
+ * to what was read.
+ */
+ if (memcmp(ch, buf, strlen(buf))!= 0)
+ {
+
+ Trace("ERROR: MapViewOfFile not equal to file contents "
+ "retrieved \"%s\", expected \"%s\".\n",
+ ch, buf);
+ RetVal = FAIL;
+ goto CleanUpFive;
+ }
+
+
+CleanUpFive:
+
+ /* Unmap the view of file.
+ */
+ if ( UnmapViewOfFile(lpMapViewAddress2) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n",
+ GetLastError(),
+ lpMapViewAddress2);
+ RetVal = FAIL;
+ }
+
+CleanUpFour:
+
+ /* Unmap the view of file.
+ */
+ if ( UnmapViewOfFile(lpMapViewAddress) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n",
+ GetLastError(),
+ lpMapViewAddress);
+ RetVal = FAIL;
+ }
+
+CleanUpThree:
+
+ /* Close Handle to opened file mapping.
+ */
+ if ( CloseHandle(OpenFileMappingHandle2) == 0 )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ OpenFileMappingHandle2);
+ RetVal = FAIL;
+ }
+
+CleanUpTwo:
+
+ /* Close Handle to opened file mapping.
+ */
+ if ( CloseHandle(OpenFileMappingHandle) == 0 )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ OpenFileMappingHandle);
+ RetVal = FAIL;
+ }
+
+CleanUpOne:
+
+ /* Close Handle to create file mapping.
+ */
+ if ( CloseHandle(FileMappingHandle) == 0 )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ FileMappingHandle);
+ RetVal = FAIL;
+ }
+
+ /* Terminate the PAL.
+ */
+ PAL_TerminateEx(RetVal);
+ return RetVal;
+}
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/testinfo.dat
new file mode 100644
index 0000000000..d481560a0d
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = OpenFileMappingW
+Name = Positive test for OpenFileMappingW API
+TYPE = DEFAULT
+EXE1 = openfilemappingw
+Description
+=Test the OpenFileMappingW with FILE_MAP_WRITE access
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/CMakeLists.txt
new file mode 100644
index 0000000000..5a54368110
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ OpenFileMappingW.c
+)
+
+add_executable(paltest_openfilemappingw_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_openfilemappingw_test3 coreclrpal)
+
+target_link_libraries(paltest_openfilemappingw_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/OpenFileMappingW.c b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/OpenFileMappingW.c
new file mode 100644
index 0000000000..9c83491f6b
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/OpenFileMappingW.c
@@ -0,0 +1,210 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: openfilemappingw.c (test 3)
+**
+** Purpose: Positive test the OpenFileMappingW API.
+** Call OpenFileMappingW to open a named file-mapping
+** object with FILE_MAP_READ access
+**
+**
+**============================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ char buf[] = "this is a test";
+ char ch[1024];
+ HANDLE FileMappingHandle;
+ HANDLE OpenFileMappingHandle;
+ HANDLE OpenFileMappingHandle2;
+ HANDLE lpMapViewAddress;
+ HANDLE lpMapViewAddress2;
+ const int LOWORDERSIZE = 1024;
+ int RetVal = PASS;
+ WCHAR wpMappingFileObject[] = {'m','y','O','b','j','e','c','t','\0'};
+
+
+ /* Initialize the PAL environment.
+ */
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Create a unnamed file-mapping object with file handle FileHandle.
+ */
+ FileMappingHandle = CreateFileMapping(
+ INVALID_HANDLE_VALUE,
+ NULL, /* not inherited */
+ PAGE_READWRITE, /* read and wite */
+ 0, /* high-order size */
+ LOWORDERSIZE, /* must be non-zero */
+ wpMappingFileObject);/* named object */
+
+ if(NULL == FileMappingHandle)
+ {
+ Fail("\nFailed to call CreateFileMapping to create mapping object!\n");
+ }
+ if(GetLastError() == ERROR_ALREADY_EXISTS)
+ {
+ Trace("\nFile mapping object already exists!\n");
+ RetVal = FAIL;
+ goto CleanUpOne;
+ }
+
+ /* Open a named file-mapping object with FILE_MAP_ALL_ACCESS access.
+ */
+ OpenFileMappingHandle = OpenFileMapping(
+ FILE_MAP_READ,
+ FALSE,
+ wpMappingFileObject);
+
+ if(NULL == OpenFileMappingHandle)
+ {
+ Trace("\nFailed to Call OpenFileMapping API!\n");
+ RetVal = FAIL;
+ goto CleanUpOne;
+ }
+
+ /* Open a file mapping with FILE_MAP_ALL_ACCESS access,
+ * to verify the FILE_MAP_READ.
+ */
+ OpenFileMappingHandle2 = OpenFileMapping(
+ FILE_MAP_ALL_ACCESS,
+ FALSE,
+ wpMappingFileObject);
+
+ if(NULL == OpenFileMappingHandle2)
+ {
+ Trace("\nFailed to Call OpenFileMapping API!\n");
+ RetVal = FAIL;
+ goto CleanUpTwo;
+ }
+
+ /* Test the opened map view.
+ */
+ lpMapViewAddress = MapViewOfFile(
+ OpenFileMappingHandle,
+ FILE_MAP_READ, /* access code */
+ 0, /* high order offset */
+ 0, /* low order offset */
+ LOWORDERSIZE); /* number of bytes for map */
+
+ if(NULL == lpMapViewAddress)
+ {
+ Trace("ERROR:%u: Failed to call MapViewOfFile "
+ "API to map a view of file!\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpThree;
+ }
+
+ /* Open a map view with FILE_MAP_ALL_ACCESS to verify,
+ * the FILE_MAP_READ view.
+ */
+ lpMapViewAddress2 = MapViewOfFile(
+ OpenFileMappingHandle2,
+ FILE_MAP_ALL_ACCESS, /* access code */
+ 0, /* high order offset */
+ 0, /* low order offset */
+ LOWORDERSIZE); /* number of bytes for map */
+
+ if(NULL == lpMapViewAddress2)
+ {
+ Trace("2ERROR:%u: Failed to call MapViewOfFile "
+ "API to map a view of file!\n",
+ GetLastError());
+ RetVal = FAIL;
+ goto CleanUpFour;
+ }
+
+ /* Write to the Map View.
+ */
+ memcpy(lpMapViewAddress2, buf, strlen(buf));
+ /* Read from the Map View.
+ */
+ memcpy(ch, (LPCSTR)lpMapViewAddress, LOWORDERSIZE);
+
+ /* Compare what was written to the Map View,
+ * to what was read.
+ */
+ if (memcmp(ch, buf, strlen(buf))!= 0)
+ {
+ Trace("ERROR: MapViewOfFile not equal to file contents "
+ "retrieved \"%s\", expected \"%s\".\n",
+ ch,
+ buf);
+ RetVal = FAIL;
+ goto CleanUpFive;
+ }
+
+CleanUpFive:
+
+ /* Unmap the view of file.
+ */
+ if ( UnmapViewOfFile(lpMapViewAddress2) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n",
+ GetLastError(),
+ lpMapViewAddress2);
+ RetVal = FAIL;
+ }
+
+CleanUpFour:
+
+ /* Unmap the view of file.
+ */
+ if ( UnmapViewOfFile(lpMapViewAddress) == FALSE )
+ {
+ Trace("ERROR:%u: Failed to UnmapViewOfFile of \"%0x%lx\".\n",
+ GetLastError(),
+ lpMapViewAddress);
+ RetVal = FAIL;
+ }
+
+CleanUpThree:
+
+ /* Close Handle to opened file mapping.
+ */
+ if ( CloseHandle(OpenFileMappingHandle2) == 0 )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ OpenFileMappingHandle2);
+ RetVal = FAIL;
+ }
+
+CleanUpTwo:
+
+ /* Close Handle to opened file mapping.
+ */
+ if ( CloseHandle(OpenFileMappingHandle) == 0 )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ OpenFileMappingHandle);
+ RetVal = FAIL;
+ }
+
+CleanUpOne:
+
+ /* Close Handle to create file mapping.
+ */
+ if ( CloseHandle(FileMappingHandle) == 0 )
+ {
+ Trace("ERROR:%u: Failed to CloseHandle \"0x%lx\".\n",
+ GetLastError(),
+ FileMappingHandle);
+ RetVal = FAIL;
+ }
+
+ /* Terminate the PAL.
+ */
+ PAL_TerminateEx(RetVal);
+ return RetVal;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/testinfo.dat
new file mode 100644
index 0000000000..b4ac69ec36
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = OpenFileMappingW
+Name = Positive test for OpenFileMappingW API with FILE_MAP_READ access
+TYPE = DEFAULT
+EXE1 = openfilemappingw
+Description
+=Test the OpenFileMappingW with FILE_MAP_READ access
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/CMakeLists.txt
new file mode 100644
index 0000000000..d2ae61f923
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(ReadProcessMemory_neg1)
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/CMakeLists.txt
new file mode 100644
index 0000000000..400c9219f6
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ ReadProcessMemory_neg.c
+)
+
+add_executable(paltest_readprocessmemory_readprocessmemory_neg1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_readprocessmemory_readprocessmemory_neg1 coreclrpal)
+
+target_link_libraries(paltest_readprocessmemory_readprocessmemory_neg1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/ReadProcessMemory_neg.c b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/ReadProcessMemory_neg.c
new file mode 100644
index 0000000000..aecd5ad576
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/ReadProcessMemory_neg.c
@@ -0,0 +1,127 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: ReadProcessMemory_neg.c
+**
+** Purpose: Negative test the ReadProcessMemory API.
+** Call ReadProcessMemory to read unreadabel memory area
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+#define REGIONSIZE 1024
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ BOOL bResult;
+ HANDLE ProcessHandle;
+ DWORD ProcessID;
+ LPVOID lpProcessAddress = NULL;
+ char ProcessBuffer[REGIONSIZE];
+ ULONG_PTR size = 0;
+
+
+ /*Initialize the PAL environment*/
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+ /*retrieve the current process ID*/
+ ProcessID = GetCurrentProcessId();
+
+ /*retrieve the current process handle*/
+ ProcessHandle = OpenProcess(
+ PROCESS_ALL_ACCESS,
+ FALSE, /*not inherited*/
+ ProcessID);
+
+ if(NULL == ProcessHandle)
+ {
+ Fail("\nFailed to call OpenProcess API to retrieve "
+ "current process handle error code=%u\n",
+ GetLastError());
+ }
+
+
+
+ /*allocate the virtual memory*/
+ lpProcessAddress = VirtualAlloc(
+ NULL, /*system determine where to allocate the region*/
+ REGIONSIZE, /*specify the size*/
+ MEM_RESERVE, /*allocation type*/
+ PAGE_READONLY); /*access protection*/
+
+ if(NULL == lpProcessAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API to allocate "
+ "virtual memory, error code=%u\n", GetLastError());
+ }
+
+ /*zero the memory*/
+ memset(ProcessBuffer, 0, REGIONSIZE);
+ /*try to retrieve the unreadable memory area*/
+ bResult = ReadProcessMemory(
+ ProcessHandle, /*current process handle*/
+ lpProcessAddress, /*base of memory area*/
+ (LPVOID)ProcessBuffer,
+ REGIONSIZE, /*buffer length in bytes*/
+ &size);
+
+
+ /*check the return value*/
+ if(0 != bResult)
+ {
+ Trace("\nFailed to call ReadProcessMemory API for a negative test, "
+ "Try to read an unreadable memory area will cause fail "
+ "but it successes\n");
+
+ err = CloseHandle(ProcessHandle);
+ if(0 == err)
+ {
+ Trace("\nFailed to call CloseHandle API, error code=%u\n",
+ GetLastError());
+ }
+
+ /*decommit the specified region*/
+ err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Trace("\nFailed to call VirtualFree API, error code=%u\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ err = CloseHandle(ProcessHandle);
+ if(0 == err)
+ {
+ Trace("\nFailed to call CloseHandle API, error code = %u\n",
+ GetLastError());
+
+ err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Trace("\nFailed to call VirtualFree API, error code=%u\n",
+ GetLastError());
+ }
+
+ Fail("");
+ }
+ /*decommit the specified region*/
+ err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API, error code=%u\n",
+ GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/testinfo.dat
new file mode 100644
index 0000000000..08c8f3291d
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = ReadProcessMemory
+Name = Negative test ReadProcessMemory API to read unreadable memory area
+TYPE = DEFAULT
+EXE1 = readprocessmemory_neg
+Description
+=Test the ReadProcessMemory to read unreadable memory area
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/CMakeLists.txt
new file mode 100644
index 0000000000..8c21f01562
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ ReadProcessMemory.c
+)
+
+add_executable(paltest_readprocessmemory_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_readprocessmemory_test1 coreclrpal)
+
+target_link_libraries(paltest_readprocessmemory_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/ReadProcessMemory.c b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/ReadProcessMemory.c
new file mode 100644
index 0000000000..c9475f13f1
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/ReadProcessMemory.c
@@ -0,0 +1,126 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: ReadProcessMemory.c
+**
+** Purpose: Positive test the ReadProcessMemory API.
+** Call ReadProcessMemory to read memory contents
+** inside current process.
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+#define REGIONSIZE 1024
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ BOOL bResult;
+ HANDLE ProcessHandle;
+ DWORD ProcessID;
+ LPVOID lpProcessAddress = NULL;
+ char ProcessBuffer[REGIONSIZE];
+ ULONG_PTR size = 0;
+
+
+ /*Initialize the PAL environment*/
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+ /*retrieve the current process ID*/
+ ProcessID = GetCurrentProcessId();
+
+ /*retrieve the current process handle*/
+ ProcessHandle = OpenProcess(
+ PROCESS_VM_READ,/*access flag*/
+ FALSE, /*not inherited*/
+ ProcessID);
+
+ if(NULL == ProcessHandle)
+ {
+ Fail("\nFailed to call OpenProcess API to retrieve "
+ "current process handle error code=%u\n",
+ GetLastError());
+ }
+
+ /*allocate the virtual memory*/
+ lpProcessAddress = VirtualAlloc(
+ NULL, /*system determine where to allocate the region*/
+ REGIONSIZE, /*specify the size*/
+ MEM_COMMIT, /*allocation type*/
+ PAGE_READONLY); /*access protection*/
+
+ if(NULL == lpProcessAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API to allocate "
+ "virtual memory, error code=%u!\n", GetLastError());
+ }
+
+ /*zero the memory*/
+ memset(ProcessBuffer, 0, REGIONSIZE);
+
+ /*retrieve the memory contents*/
+ bResult = ReadProcessMemory(
+ ProcessHandle, /*current process handle*/
+ lpProcessAddress, /*base of memory area*/
+ (LPVOID)ProcessBuffer,
+ REGIONSIZE, /*buffer length in bytes*/
+ &size);
+
+ if(!bResult || REGIONSIZE != size)
+ {
+ Trace("\nFailed to call ReadProcessMemory API "
+ "to retrieve the memory contents, error code=%u\n",
+ GetLastError());
+
+ err = CloseHandle(ProcessHandle);
+ if(0 == err)
+ {
+ Trace("\nFailed to call CloseHandle API, error code=%u\n",
+ GetLastError());
+ }
+
+ /*decommit the specified region*/
+ err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Trace("\nFailed to call VirtualFree API, error code=%u\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ err = CloseHandle(ProcessHandle);
+ if(0 == err)
+ {
+ Trace("\nFailed to call CloseHandle API, error code = %u\n",
+ GetLastError());
+
+ err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Trace("\nFailed to call VirtualFree API, error code=%u\n",
+ GetLastError());
+ }
+
+ Fail("");
+ }
+
+ /*decommit the specified region*/
+ err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API, error code=%u\n",
+ GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/testinfo.dat
new file mode 100644
index 0000000000..c56920d206
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = ReadProcessMemory
+Name = Positive test for ReadProcessMemory API to read memory contents
+TYPE = DEFAULT
+EXE1 = readprocessmemory
+Description
+=Test the ReadProcessMemory to read the memory contents
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/CMakeLists.txt
new file mode 100644
index 0000000000..9e0de95a0a
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/CMakeLists.txt
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(TESTSOURCES
+ test2.c
+)
+
+add_executable(paltest_readprocessmemory_test2
+ ${TESTSOURCES}
+)
+
+add_dependencies(paltest_readprocessmemory_test2 coreclrpal)
+
+target_link_libraries(paltest_readprocessmemory_test2
+ pthread
+ m
+ coreclrpal
+)
+
+
+set(HELPERSOURCES
+ helper.c
+)
+
+add_executable(paltest_readprocessmemory_test2_helper
+ ${HELPERSOURCES}
+)
+
+add_dependencies(paltest_readprocessmemory_test2_helper coreclrpal)
+
+target_link_libraries(paltest_readprocessmemory_test2_helper
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/commonconsts.h b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/commonconsts.h
new file mode 100644
index 0000000000..433d820f0f
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/commonconsts.h
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: commonconsts.h
+**
+**
+**============================================================*/
+
+#ifndef _COMMONCONSTS_H_
+#define _COMMONCONSTS_H_
+
+#include <pal.h>
+#define REGIONSIZE 1024
+
+const int TIMEOUT = 40000;
+
+const WCHAR szcToHelperEvName[] = { 'T', 'o', '\0' };
+const WCHAR szcFromHelperEvName[] = { 'F', 'r', 'o', 'm', '\0' };
+
+const char initialValue = '-';
+const char nextValue = '|';
+const char guardValue = '*';
+const char *commsFileName = "AddrNLen.dat";
+
+
+/* PEDANTIC and PEDANTIC0 is a helper macro that just grumps about any
+ * zero return codes in a generic way. with little typing */
+#define PEDANTIC(function, parameters) \
+{ \
+ if (! (function parameters) ) \
+ { \
+ Trace("%s: NonFatal failure of %s%s for reasons %u and %u\n", \
+ __FILE__, #function, #parameters, GetLastError(), errno); \
+ } \
+}
+#define PEDANTIC1(function, parameters) \
+{ \
+ if ( (function parameters) ) \
+ { \
+ Trace("%s: NonFatal failure of %s%s for reasons %u and %u\n", \
+ __FILE__, #function, #parameters, GetLastError(), errno); \
+ } \
+}
+
+#endif
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/helper.c b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/helper.c
new file mode 100644
index 0000000000..59e882fc1f
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/helper.c
@@ -0,0 +1,249 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: helper.c
+**
+** Purpose: This helper process sets up a several blocks of memory,
+** then uses a file to tell its parent process where that memory is
+** So it can do a WriteProcessMemory on it. When the parent process is done
+** we check here that it was written properly.
+**
+**
+**============================================================*/
+
+#include "commonconsts.h"
+
+#include <palsuite.h>
+
+#if defined(BIT64) && defined(PLATFORM_UNIX)
+#define LLFORMAT "%I64u"
+#else
+#define LLFORMAT "%u"
+#endif
+
+struct allhandles_t
+{
+ HANDLE hEvToHelper;
+ HANDLE hEvFromHelper;
+ char *valuesFileName;
+};
+
+
+/* function: wpmDoIt
+ *
+ * This is a general WriteProcessMemory testing function that sets up
+ * the RAM pointed to and tells the companion process on the other end
+ * of the handles in 'Comms' to attempt to alter 'lenDest' bytes at
+ * '*pDest'.
+ *
+ * '*pBuffer'[0..'lenBuffer'] is expected to be a guard region
+ * surrounding the '*pDest'[0..'lenDest'] region so that this function
+ * can verify that only the proper bytes were altered.
+ */
+
+int wpmDoIt(struct allhandles_t Comms,
+ char * pBuffer, unsigned int lenBuffer,
+ char * pDest, unsigned int lenDest,
+ const char* storageDescription)
+{
+ char *pCurr;
+ FILE *commsFile;
+ DWORD dwRet;
+
+ if (pBuffer > pDest || lenDest > lenBuffer)
+ {
+ Trace("WriteProcessMemory::DoIt() test implementation: "
+ "(pBuffer > pDest || lenDest > lenBuffer)\n");
+ return FALSE;
+ }
+
+ /* set up the storage */
+ memset(pBuffer, guardValue, lenBuffer);
+ memset(pDest, initialValue, lenDest);
+
+ /* tell the parent what RAM to adjust */
+ if(!(commsFile = fopen(Comms.valuesFileName, "w")))
+ {
+ Trace("WriteProcessMemory: fopen of '%S' failed (%u). \n",
+ Comms.valuesFileName, GetLastError());
+ return FALSE;
+ }
+ if (!fprintf(commsFile, LLFORMAT " " LLFORMAT " '%s'\n",
+ pDest, lenDest, storageDescription))
+ {
+ Trace("WriteProcessMemory: fprintf to '%S' failed (%u). \n",
+ Comms.valuesFileName, GetLastError());
+ return FALSE;
+ }
+ PEDANTIC1(fclose, (commsFile));
+
+ /* Tell the parent the data is ready for it to adjust */
+ PEDANTIC(ResetEvent, (Comms.hEvToHelper));
+ PEDANTIC(SetEvent, (Comms.hEvFromHelper));
+
+ dwRet = WaitForSingleObject(Comms.hEvToHelper, TIMEOUT); /* parent is done */
+ if (dwRet != WAIT_OBJECT_0)
+ {
+ Trace("helper WaitForSingleObjectTest: WaitForSingleObject "
+ "failed (%u)\n", GetLastError());
+ return FALSE;
+ }
+
+ /* check the stuff that SHOULD have changed */
+ for (pCurr = pDest; pCurr < (pDest + lenDest); pCurr++)
+ {
+ if ( *pCurr != nextValue)
+ {
+ Trace("When testing '%s': alteration test failed "
+ "at " LLFORMAT " offset " LLFORMAT " Found '%c' instead of '%c'\n.",
+ storageDescription, pDest, pCurr - pDest, *pCurr, nextValue);
+ Trace(" 'Altered' string: '%.*s'\n",lenBuffer, pBuffer);
+ return FALSE;
+ }
+ }
+ /* check the stuff that should NOT have changed */
+ for (pCurr = pBuffer; pCurr < pDest; pCurr++ )
+ {
+ if ( *pCurr != guardValue)
+ {
+ Trace("When testing '%s': leading guard zone test failed "
+ "at " LLFORMAT " offset " LLFORMAT ". Found '%c' instead of '%c'\n.",
+ storageDescription, pDest, pCurr - pBuffer, *pCurr, guardValue);
+ Trace(" 'Altered' string: '%.*s'\n",lenBuffer, pBuffer);
+ return FALSE;
+ }
+ }
+ for (pCurr = pDest + lenDest; pCurr < (pBuffer + lenBuffer); pCurr++ )
+ {
+ if ( *pCurr != guardValue)
+ {
+ Trace("When testing '%s': trailing guard zone test failed "
+ "at " LLFORMAT " offset " LLFORMAT ". Found '%c' instead of '%c'\n.",
+ storageDescription, pDest + lenDest, pCurr - pBuffer, *pCurr, guardValue);
+ Trace(" 'Altered' string: '%.*s'\n",lenBuffer, pBuffer);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ BOOL success = TRUE; /* assume success */
+ struct allhandles_t Comms = {0,0,0} ;
+
+ /* variables to track storage to alter */
+ char *pTarget = NULL;
+ unsigned int sizeTarget;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* hook up with the events created by the parent */
+ Comms.hEvToHelper = OpenEventW(EVENT_ALL_ACCESS, 0, szcToHelperEvName);
+ if (!Comms.hEvToHelper)
+ {
+ Fail("WriteProcessMemory: OpenEvent of '%S' failed (%u). "
+ "(the event should already exist!)\n",
+ szcToHelperEvName, GetLastError());
+ }
+ Comms.hEvFromHelper = OpenEventW(EVENT_ALL_ACCESS, 0, szcFromHelperEvName);
+ if (!Comms.hEvToHelper)
+ {
+ Trace("WriteProcessMemory: OpenEvent of '%S' failed (%u). "
+ "(the event should already exist!)\n",
+ szcFromHelperEvName, GetLastError());
+ success = FALSE;
+ goto EXIT;
+ }
+ Comms.valuesFileName = argv[1];
+
+ {
+ char autoAllocatedOnStack[51];
+
+ /* Get the parent process to write to the local stack */
+ success &= wpmDoIt(Comms, autoAllocatedOnStack,
+ sizeof(autoAllocatedOnStack),
+ autoAllocatedOnStack + sizeof(int),
+ sizeof(autoAllocatedOnStack) - 2 * sizeof(int),
+ "const size array on stack with int sized guards");
+ }
+
+ /* Get the parent process to write to stuff on the heap */
+ sizeTarget = 2 * sizeof(int) + 23 ; /* 23 is just a random prime > 16 */
+ if (!(pTarget = malloc(sizeTarget)))
+ {
+ Trace("WriteProcessMemory helper: unable to allocate '%s'->%d bytes of memory"
+ "(%u).\n",
+ argv[3], sizeTarget, GetLastError());
+ success = FALSE;
+ goto EXIT;
+
+ }
+ success &= wpmDoIt(Comms, pTarget, sizeTarget,
+ pTarget + sizeof(int),
+ sizeTarget - 2 * sizeof(int),
+ "array on heap with int sized guards");
+
+ /* just to be nice try something 16 - 2 * sizeof(int) bytes long */
+ {
+ char autoAllocatedOnStack[16];
+
+ /* Get the parent process to write to the local stack */
+ success &= wpmDoIt(Comms, autoAllocatedOnStack,
+ sizeof(autoAllocatedOnStack),
+ autoAllocatedOnStack + sizeof(int),
+ sizeof(autoAllocatedOnStack) - 2 * sizeof(int),
+ "another 16 byte array on stack with int sized guards inside");
+ }
+
+ /* NOTE: Don't try 0 bytes long. Win32 WriteProcessMemory claims
+ * it writes 8 bytes in that case! */
+
+ /* and 1 byte long... */
+ {
+ char autoAllocatedOnStack[1+ 2 * sizeof(int)];
+
+ /* Get the parent process to write to the local stack */
+ success &= wpmDoIt(Comms, autoAllocatedOnStack,
+ sizeof(autoAllocatedOnStack),
+ autoAllocatedOnStack + sizeof(int),
+ 1,
+ "no bytes with int sized guards outside on stack");
+ }
+
+
+EXIT:
+ /* Tell the parent that we are done */
+ if (!DeleteFile(Comms.valuesFileName))
+ {
+ Trace("helper: DeleteFile failed so parent (test1) is unlikely "
+ "to exit cleanly\n");
+ }
+ PEDANTIC(ResetEvent, (Comms.hEvToHelper));
+ if (!SetEvent(Comms.hEvFromHelper))
+ {
+ Trace("helper: SetEvent failed so parent (test1) is unlikely "
+ "to exit cleanly\n");
+ }
+
+ free(pTarget);
+ PEDANTIC(CloseHandle, (Comms.hEvToHelper));
+ PEDANTIC(CloseHandle, (Comms.hEvFromHelper));
+
+ if (!success)
+ {
+ Fail("");
+ }
+
+ PAL_Terminate();
+
+ return success ? PASS : FAIL;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/test2.c b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/test2.c
new file mode 100644
index 0000000000..eda40599ce
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/test2.c
@@ -0,0 +1,258 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test2.c
+**
+** Purpose: Create a child process and some events for communications with it.
+** When the child gets back to us with a memory location and a length,
+** Call WriteProcessMemory on this location and check to see that it
+** writes successfully. Then call ReadProcessMemory to check if the
+** contents read are same as those written
+**
+**
+**============================================================*/
+
+#define UNICODE
+
+#include "commonconsts.h"
+
+#include <palsuite.h>
+
+#if defined(BIT64) && defined(PLATFORM_UNIX)
+#define LLFORMAT "%I64u"
+#else
+#define LLFORMAT "%u"
+#endif
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ PROCESS_INFORMATION pi;
+ STARTUPINFO si;
+ HANDLE hEvToHelper;
+ HANDLE hEvFromHelper;
+ DWORD dwExitCode;
+
+ DWORD dwRet;
+ char cmdComposeBuf[MAX_PATH];
+ PWCHAR uniString;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Create the signals we need for cross process communication */
+ hEvToHelper = CreateEvent(NULL, TRUE, FALSE, szcToHelperEvName);
+ if (!hEvToHelper)
+ {
+ Fail("WriteProcessMemory: CreateEvent of '%S' failed. "
+ "GetLastError() returned %d.\n", szcToHelperEvName,
+ GetLastError());
+ }
+ if (GetLastError() == ERROR_ALREADY_EXISTS)
+ {
+ Fail("WriteProcessMemory: CreateEvent of '%S' failed. "
+ "(already exists!)\n", szcToHelperEvName);
+ }
+ hEvFromHelper = CreateEvent(NULL, TRUE, FALSE, szcFromHelperEvName);
+ if (!hEvToHelper)
+ {
+ Fail("WriteProcessMemory: CreateEvent of '%S' failed. "
+ "GetLastError() returned %d.\n", szcFromHelperEvName,
+ GetLastError());
+ }
+ if (GetLastError() == ERROR_ALREADY_EXISTS)
+ {
+ Fail("WriteProcessMemory: CreateEvent of '%S' failed. "
+ "(already exists!)\n", szcFromHelperEvName);
+ }
+ ResetEvent(hEvFromHelper);
+ ResetEvent(hEvToHelper);
+
+ if (!sprintf(cmdComposeBuf, "helper %s", commsFileName))
+ {
+ Fail("Could not convert command line\n");
+ }
+ uniString = convert(cmdComposeBuf);
+
+ ZeroMemory( &si, sizeof(si) );
+ si.cb = sizeof(si);
+ ZeroMemory( &pi, sizeof(pi) );
+
+ /* Create a new process. This is the process that will ask for
+ * memory munging */
+ if(!CreateProcess( NULL, uniString, NULL, NULL,
+ FALSE, 0, NULL, NULL, &si, &pi))
+ {
+ Trace("ERROR: CreateProcess failed to load executable '%S'. "
+ "GetLastError() returned %u.\n",
+ uniString, GetLastError());
+ free(uniString);
+ Fail("");
+ }
+ free(uniString);
+
+
+ while(1)
+ {
+ FILE *commsFile;
+ char* pSrcMemory;
+ char* pDestMemory;
+ SIZE_T Count;
+ SIZE_T wpmCount;
+ char incomingCMDBuffer[MAX_PATH + 1];
+
+ int err;
+ HANDLE readProcessHandle;
+ DWORD readProcessID;
+ char readProcessBuffer[REGIONSIZE]; // size 1024
+ BOOL bResult;
+ size_t size = 0;
+
+ readProcessID = pi.dwProcessId;
+
+ /* wait until the helper tells us that it has given us
+ * something to do */
+ dwRet = WaitForSingleObject(hEvFromHelper, TIMEOUT);
+ if (dwRet != WAIT_OBJECT_0)
+ {
+ Trace("test1 WaitForSingleObjectTest: WaitForSingleObject "
+ "failed (%u)\n", GetLastError());
+ break; /* no more work incoming */
+ }
+
+ /* get the parameters to test WriteProcessMemory with */
+ if (!(commsFile = fopen(commsFileName, "r")))
+ {
+ /* no file means there is no more work */
+ break;
+ }
+ if ( NULL == fgets(incomingCMDBuffer, MAX_PATH, commsFile))
+ {
+ Fail ("unable to read from communication file %s "
+ "for reasons %u & %u\n",
+ errno, GetLastError());
+ }
+ PEDANTIC1(fclose,(commsFile));
+ sscanf(incomingCMDBuffer, LLFORMAT " " LLFORMAT, &pDestMemory, &Count);
+ if (argc > 1)
+ {
+ Trace("Preparing to write to " LLFORMAT " bytes @ " LLFORMAT "('%s')\n",
+ Count, pDestMemory, incomingCMDBuffer);
+ }
+
+ /* compose some data to write to the client process */
+ if (!(pSrcMemory = malloc(Count)))
+ {
+ Trace("could not dynamically allocate memory to copy from "
+ "for reasons %u & %u\n",
+ errno, GetLastError());
+ goto doneIteration;
+ }
+ memset(pSrcMemory, nextValue, Count);
+ Trace("Preparing to write to " LLFORMAT " bytes @ " LLFORMAT " ('%s')[%u]\n",
+ Count, pDestMemory, incomingCMDBuffer, pSrcMemory);
+
+ /* do the work */
+ dwRet = WriteProcessMemory(pi.hProcess,
+ pDestMemory,
+ pSrcMemory,
+ Count,
+ &wpmCount);
+
+ if (!dwRet)
+ {
+ Trace("%s: Problem: on a write to "LLFORMAT " bytes @ " LLFORMAT " ('%s')\n",
+ argv[0], Count, pDestMemory, incomingCMDBuffer);
+ Trace("test1 WriteProcessMemory returned a (!=0) (GLE=%u)\n",
+ GetLastError());
+ }
+ if(Count != wpmCount)
+ {
+ Trace("%s: Problem: on a write to " LLFORMAT " bytes @ " LLFORMAT " ('%s')\n",
+ argv[0], Count, pDestMemory, incomingCMDBuffer);
+ Trace("The number of bytes written should have been "
+ LLFORMAT ", but was reported as " LLFORMAT " \n", Count, wpmCount);
+ }
+
+ readProcessHandle = OpenProcess(
+ PROCESS_VM_READ,
+ FALSE,
+ readProcessID);
+
+ if(NULL == readProcessHandle)
+ {
+ Fail("\nFailed to call OpenProcess API to retrieve "
+ "current process handle error code=%u\n",
+ GetLastError());
+ }
+
+ /*zero the memory*/
+ memset(readProcessBuffer, 0, size);
+
+ /*retrieve the memory contents*/
+ bResult = ReadProcessMemory(
+ readProcessHandle, /*current process handle*/
+ pDestMemory, /*base of memory area*/
+ (LPVOID)readProcessBuffer,
+ Count, /*buffer length in bytes*/
+ &size);
+
+
+ if( !bResult || (Count != size) )
+ {
+ Trace("\nFailed to call ReadProcessMemory API "
+ "to retrieve the memory contents, error code=%u; Bresult[%u] Count[" LLFORMAT "], Size[%d]\n",
+ GetLastError(), bResult, Count, size);
+
+ err = CloseHandle(readProcessHandle);
+
+ if(0 == err)
+ {
+ Trace("\nFailed to call CloseHandle API, error code=%u\n",
+ GetLastError());
+ }
+ dwExitCode = FAIL;
+ }
+
+ if( !memcmp (pDestMemory, readProcessBuffer, Count ) )
+ {
+ Trace("Difference in memory contents, expected [%s], but received [%s]\n", pDestMemory, readProcessBuffer);
+ dwExitCode = FAIL;
+ }
+
+ Trace("ReadProcessBuffer contains [%s]\n", readProcessBuffer);
+ err = CloseHandle(readProcessHandle);
+
+ free(pSrcMemory);
+
+ doneIteration:
+ PEDANTIC(ResetEvent, (hEvFromHelper));
+ PEDANTIC(SetEvent, (hEvToHelper));
+ }
+
+ /* wait for the child process to complete */
+ WaitForSingleObject ( pi.hProcess, TIMEOUT );
+ /* this may return a failure code on a success path */
+
+ /* check the exit code from the process */
+ if( ! GetExitCodeProcess( pi.hProcess, &dwExitCode ) )
+ {
+ Trace( "GetExitCodeProcess call failed with error code %u\n",
+ GetLastError() );
+ dwExitCode = FAIL;
+ }
+
+
+ PEDANTIC(CloseHandle, (hEvToHelper));
+ PEDANTIC(CloseHandle, (hEvFromHelper));
+ PEDANTIC(CloseHandle, (pi.hThread));
+ PEDANTIC(CloseHandle, (pi.hProcess));
+
+ PAL_TerminateEx(dwExitCode);
+ return dwExitCode;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/testinfo.dat
new file mode 100644
index 0000000000..58a9935a08
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/testinfo.dat
@@ -0,0 +1,18 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Debug
+Function = ReadProcessMemory
+Name = Check that writing/reading text to/from process memory succeeds.
+TYPE = DEFAULT
+EXE1 = test2
+EXE2 = helper
+Description
+= Create a child process and attempt to write to its memory
+= at the places and lengths it specifies via a data file.
+= the child verifies that all the specified memory was altered
+= with no overruns. Parent then tries to read memory from child
+= and does memory compare to ensure it read memory contents
+= correctly
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/CMakeLists.txt
new file mode 100644
index 0000000000..393074b4ee
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test1/CMakeLists.txt
new file mode 100644
index 0000000000..987c413d03
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_rtlmovememory_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_rtlmovememory_test1 coreclrpal)
+
+target_link_libraries(paltest_rtlmovememory_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test1/test1.c b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test1/test1.c
new file mode 100644
index 0000000000..7fc56510d8
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test1/test1.c
@@ -0,0 +1,56 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test1.c
+**
+** Purpose: Simple test -- have two 128 blocks of memory allocated. Then
+** move one block to the other and check to see that the data was not
+** corrupted.
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+
+enum Memory
+{
+ MEMORY_AMOUNT = 128
+};
+
+int __cdecl main(int argc, char *argv[])
+{
+ char NewAddress[MEMORY_AMOUNT];
+ char OldAddress[MEMORY_AMOUNT];
+ int i;
+ char temp;
+
+ if(PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Put some data into the block we'll be moving */
+ memset(OldAddress, 'X', MEMORY_AMOUNT);
+
+ /* Move the block to the NewAddress */
+ RtlMoveMemory(NewAddress, OldAddress, MEMORY_AMOUNT);
+
+ /* Check to ensure the data didn't get corrupted */
+ for(i=0; i<MEMORY_AMOUNT; ++i)
+ {
+ if(NewAddress[i] != 'X')
+ {
+ temp = NewAddress[i];
+ Fail("ERROR: When the memory was moved to a new location, the "
+ "data which was stored in it was somehow corrupted. "
+ "Character %d should have been 'X' but instead is %c.\n",
+ i, temp);
+ }
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test1/testinfo.dat
new file mode 100644
index 0000000000..645d46c968
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = RtlMoveMemory
+Name = Positive test for RtlMoveMemory API
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Simple test -- have two 128 blocks of memory allocated. Then
+= move one block to the other and check to see that the data was not
+= corrupted.
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test3/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test3/CMakeLists.txt
new file mode 100644
index 0000000000..14098a8dc1
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_rtlmovememory_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_rtlmovememory_test3 coreclrpal)
+
+target_link_libraries(paltest_rtlmovememory_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test3/test3.c b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test3/test3.c
new file mode 100644
index 0000000000..279c0c1199
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test3/test3.c
@@ -0,0 +1,72 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test3.c
+**
+** Purpose: Allocate 128 bytes of memory and store data in it. Move 10
+** other bytes of memory to that location. Check that the first 10 bytes
+** carried over their data and that the other 118 were unchanged.
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+
+enum Memory
+{
+ NEW_MEMORY_AMOUNT = 128,
+ OLD_MEMORY_AMOUNT = 10
+};
+
+int __cdecl main(int argc, char *argv[])
+{
+ char NewAddress[NEW_MEMORY_AMOUNT];
+ char OldAddress[OLD_MEMORY_AMOUNT];
+ int i;
+
+
+ if(PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Put some data into the block we'll be moving */
+ memset(OldAddress, 'X', OLD_MEMORY_AMOUNT);
+
+ /* Put some data into the block we're moving to */
+ memset(NewAddress, 'Z', NEW_MEMORY_AMOUNT);
+
+ /* Move the block to the NewAddress */
+ RtlMoveMemory(NewAddress, OldAddress, OLD_MEMORY_AMOUNT);
+
+ /* Check to ensure the moved data didn't get corrupted */
+ for(i=0; i<OLD_MEMORY_AMOUNT; ++i)
+ {
+ if(NewAddress[i] != 'X')
+ {
+ Fail("ERROR: When the memory was moved to a new location, the "
+ "data which was stored in it was somehow corrupted. "
+ "Character %d should have been 'X' but instead is %c.\n",
+ i, NewAddress[i]);
+ }
+ }
+
+ /* Check to ensure the memory which didn't move didn't get corrupted */
+ for(i=OLD_MEMORY_AMOUNT; i<NEW_MEMORY_AMOUNT; ++i)
+ {
+ if(NewAddress[i] != 'Z')
+ {
+ Fail("ERROR: When the memory was moved to a new location, the "
+ "data which was stored in it was somehow corrupted. "
+ "Character %d should have been 'Z' but instead is %c.\n",
+ i, NewAddress[i]);
+ }
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test3/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test3/testinfo.dat
new file mode 100644
index 0000000000..fb56f2e985
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test3/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = RtlMoveMemory
+Name = Positive test for RtlMoveMemory API, move a small block to large
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Allocate 128 bytes of memory and store data in it. Move 10
+= other bytes of memory to that location. Check that the first 10 bytes
+= carried over their data and that the other 118 were unchanged.
+
+
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test4/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test4/CMakeLists.txt
new file mode 100644
index 0000000000..00aec7e8f7
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_rtlmovememory_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_rtlmovememory_test4 coreclrpal)
+
+target_link_libraries(paltest_rtlmovememory_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test4/test4.c b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test4/test4.c
new file mode 100644
index 0000000000..b6e1ecd6f7
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test4/test4.c
@@ -0,0 +1,76 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test4.c
+**
+** Purpose: Test simple overlapping. Move the first 50 bytes of a
+** piece of memory to the latter 50 bytes. ie i -> i+50 Check to make sure
+** no data is lost.
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+
+enum Memory
+{
+ MEMORY_AMOUNT = 128
+};
+
+int __cdecl main(int argc, char *argv[])
+{
+ char* NewAddress;
+ char OldAddress[MEMORY_AMOUNT];
+ int i;
+
+ if(PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ NewAddress = OldAddress+50;
+
+ /* Put some data into the block we'll be moving
+ The first 50 byes will be 'X' and the rest set to 'Z'
+ */
+ memset(OldAddress, 'X', 50);
+ memset(NewAddress, 'Z', MEMORY_AMOUNT-50);
+
+ /* Move the first 50 bytes of OldAddress to OldAddress+50. This
+ is to test that the source and destination addresses can overlap.
+ */
+ RtlMoveMemory(NewAddress, OldAddress, 50);
+
+ /* Check to ensure the moved data didn't get corrupted
+ The first 50 bytes should be 'X'
+ */
+ for(i=0; i<50; ++i)
+ {
+ if(NewAddress[i] != 'X')
+ {
+ Fail("ERROR: When the memory was moved to a new location, the "
+ "data which was stored in it was somehow corrupted. "
+ "Character %d should have been 'X' but instead is %c.\n",
+ i, NewAddress[i]);
+ }
+ }
+
+ /* The rest of the memory should be 'Z' */
+ for(i=50; i<MEMORY_AMOUNT-50; ++i)
+ {
+ if(NewAddress[i] != 'Z')
+ {
+
+ Fail("ERROR: When the memory was moved to a new location, the "
+ "data which was stored in it was somehow corrupted. "
+ "Character %d should have been 'Z' but instead is %c.\n",
+ i, NewAddress[i]);
+ }
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test4/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test4/testinfo.dat
new file mode 100644
index 0000000000..56b82f2083
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test4/testinfo.dat
@@ -0,0 +1,18 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = RtlMoveMemory
+Name = Positive test for RtlMoveMemory API, test that overlapping works
+TYPE = DEFAULT
+EXE1 = test4
+Description
+= Test simple overlapping. Move the first 50 bytes of a
+= piece of memory to the latter 50 bytes. ie i -> i+50 Check to make sure
+= no data is lost.
+
+
+
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test5/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test5/CMakeLists.txt
new file mode 100644
index 0000000000..f2de78216e
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test5.c
+)
+
+add_executable(paltest_rtlmovememory_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_rtlmovememory_test5 coreclrpal)
+
+target_link_libraries(paltest_rtlmovememory_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test5/test5.c b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test5/test5.c
new file mode 100644
index 0000000000..affcb0abc9
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test5/test5.c
@@ -0,0 +1,63 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test5.c
+**
+** Purpose: Do more complex overlapping. Move a section of memory back so
+** that it actually ends up overlapping itself.
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+
+enum Memory
+{
+ MEMORY_AMOUNT = 128
+};
+
+int __cdecl main(int argc, char *argv[])
+{
+ char* NewAddress;
+ char* SectionToMove;
+ char TheMemory[MEMORY_AMOUNT];
+ int i;
+
+ if(PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ NewAddress = TheMemory;
+ SectionToMove = TheMemory+50;
+
+ /* Put some data into the first 50 bytes */
+ memset(TheMemory, 'X', 50);
+
+ /* Put some data into the rest of the memory */
+ memset(SectionToMove, 'Z', MEMORY_AMOUNT-50);
+
+ /* Move the section in the middle of TheMemory back to the start of
+ TheMemory -- but have it also overlap itself. (ie. the section
+ to be move is overlapping itself)
+ */
+ RtlMoveMemory(NewAddress, SectionToMove, MEMORY_AMOUNT-50);
+
+ /* Check to ensure the moved data didn't get corrupted */
+ for(i=0; i<MEMORY_AMOUNT-50; ++i)
+ {
+ if(NewAddress[i] != 'Z')
+ {
+ Fail("ERROR: When the memory was moved to a new location, the "
+ "data which was stored in it was somehow corrupted. "
+ "Character %d should have been 'Z' but instead is %c.\n",
+ i, NewAddress[i]);
+ }
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test5/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test5/testinfo.dat
new file mode 100644
index 0000000000..a4ba99a29d
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test5/testinfo.dat
@@ -0,0 +1,18 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = RtlMoveMemory
+Name = Positive test for RtlMoveMemory API, test that overlapping works
+TYPE = DEFAULT
+EXE1 = test5
+Description
+= Do more complex overlapping. Move a section of memory back so
+= that it actually ends up overlapping itself.
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/CMakeLists.txt
new file mode 100644
index 0000000000..a3847f8ca9
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/UnlockFile.h b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/UnlockFile.h
new file mode 100644
index 0000000000..8fce2695a7
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/UnlockFile.h
@@ -0,0 +1,112 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: UnLockFile.h
+**
+** Purpose: This header file has a RunHelper method which will be used to
+** start a child proccess in many LockFile testcases. The CreateAndLockFile
+** method Creates a file and calls LockFile upon it. And the two Signal
+** methods are used for IPC.
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+
+HANDLE CreateAndLockFile(HANDLE TheFile, char* FileName, char* WriteBuffer,
+ DWORD LockStart, DWORD LockLength)
+{
+ DWORD BytesWritten;
+
+ TheFile = CreateFile(FileName,
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (TheFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Could not open file '%s' with CreateFile. "
+ "GetLastError() returned %d.\n",FileName,GetLastError());
+ }
+
+ if(WriteFile(TheFile, WriteBuffer,
+ strlen(WriteBuffer),&BytesWritten, NULL) == 0)
+ {
+ Fail("ERROR: WriteFile has failed. It returned 0 when we "
+ "attempted to write to the file '%s'. GetLastError() "
+ "returned %d.\n",FileName,GetLastError());
+ }
+
+ if(FlushFileBuffers(TheFile) == 0)
+ {
+ Fail("ERROR: FlushFileBuffers returned failure. GetLastError() "
+ "returned %d.\n",GetLastError());
+ }
+
+ if(LockFile(TheFile, LockStart, 0, LockLength, 0) == 0)
+ {
+ Fail("ERROR: LockFile failed. GetLastError returns %d.\n",
+ GetLastError());
+ }
+
+ return TheFile;
+}
+
+void SignalAndBusyWait(HANDLE TheFile)
+{
+ int size;
+ DWORD BytesWritten;
+
+ size = GetFileSize(TheFile,NULL)+1;
+
+ if(SetFilePointer(TheFile, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER)
+ {
+ Fail("ERROR: SetFilePointer was unable to set the pointer to the "
+ "end of the file. GetLastError() returned %d.\n",GetLastError());
+ }
+
+ if(WriteFile(TheFile, "x", 1,&BytesWritten, NULL) == 0)
+ {
+ Fail("ERROR: WriteFile was unable to write to the WaitFile. "
+ "GetLastError() returned %d.\n",GetLastError());
+ }
+
+ if(FlushFileBuffers(TheFile) == 0)
+ {
+ Fail("ERROR: FlushFileBuffers failed when flushing the WaitFile. "
+ "GetLastError() returned %d.\n");
+ }
+
+ while(GetFileSize(TheFile,NULL) == size) {}
+}
+
+void SignalFinish(HANDLE TheFile)
+{
+ DWORD BytesWritten;
+
+ if(SetFilePointer(TheFile, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER)
+ {
+ Fail("ERROR: SetFilePointer was unable to set the pointer to the "
+ "end of the WaitFile. GetLastError() returned %d.\n",
+ GetLastError());
+ }
+
+ if(WriteFile(TheFile, "x", 1,&BytesWritten, NULL) == 0)
+ {
+ Fail("ERROR: WriteFile was unable to write to the WaitFile. "
+ "GetLastError returned %d.\n",GetLastError());
+ }
+
+ if(FlushFileBuffers(TheFile) == 0)
+ {
+ Fail("ERROR: FlushFileBuffers failed when flushing the WaitFile. "
+ "GetLastError() returned %d.\n");
+ }
+
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test1/CMakeLists.txt
new file mode 100644
index 0000000000..0e6d6fef4c
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test1/CMakeLists.txt
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(TESTSOURCES
+ test1.c
+)
+
+add_executable(paltest_unlockfile_test1
+ ${TESTSOURCES}
+)
+
+add_dependencies(paltest_unlockfile_test1 coreclrpal)
+
+target_link_libraries(paltest_unlockfile_test1
+ pthread
+ m
+ coreclrpal
+)
+
+
+set(HELPERSOURCES
+ helper.c
+)
+
+add_executable(paltest_unlockfile_test1_helper
+ ${HELPERSOURCES}
+)
+
+add_dependencies(paltest_unlockfile_test1_helper coreclrpal)
+
+target_link_libraries(paltest_unlockfile_test1_helper
+ pthread
+ m
+ coreclrpal
+) \ No newline at end of file
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test1/helper.c b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test1/helper.c
new file mode 100644
index 0000000000..c2ef5a6736
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test1/helper.c
@@ -0,0 +1,92 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: helper.c
+**
+** Purpose: A child process which will attempt to read from the
+** locked file to ensure it is locked. After it has been unlocked, it
+** will then read again to check that Unlock worked.
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+#include "../UnlockFile.h"
+
+#define FILENAME "testfile.txt"
+#define WAITFILENAME "waitfile"
+#define BUF_SIZE 128
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE TheFile, WaitFile;
+ int result = 0;
+ char DataBuffer[BUF_SIZE];
+ DWORD BytesRead;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Open the same file that the parent has opened and locked */
+ TheFile = CreateFile(FILENAME,
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (TheFile == INVALID_HANDLE_VALUE)
+ {
+ Trace("ERROR: Could not open file '%s' with CreateFile.\n",FILENAME);
+ result = 1;
+ }
+
+ /* Open up the WaitFile that we're using for IPC */
+ WaitFile = CreateFile(WAITFILENAME,
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (WaitFile == INVALID_HANDLE_VALUE)
+ {
+ Trace("ERROR: Could not open file '%s' with CreateFile. "
+ "GetLastError() returned %d.\n",WAITFILENAME,GetLastError());
+ result = 1;
+ }
+
+
+ /* Check to ensure the parent lock is respected */
+ if(ReadFile(TheFile, DataBuffer, 10, &BytesRead, NULL) != 0)
+ {
+ Trace("ERROR: ReadFile returned success when it should "
+ "have failed. Attempted to read the first 10 bytes "
+ "of a file which was locked by the parent process.\n");
+ result = 1;
+ }
+
+ // Sleep for a bit to give the parent a chance to block before we do.
+ Sleep(1000);
+
+ /* Switch back to the parent, so it can unlock the file */
+ SignalAndBusyWait(WaitFile);
+
+ if(ReadFile(TheFile, DataBuffer, 10, &BytesRead, NULL) == 0)
+ {
+ Trace("ERROR: ReadFile was unable to read from the file after it "
+ "had been unlocked. Attempted to read 10 bytes and ReadFile "
+ "returned 0. GetLastError() returned %d.\n",GetLastError());
+ result = 1;
+ }
+
+ PAL_TerminateEx(result);
+ return result;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test1/test1.c b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test1/test1.c
new file mode 100644
index 0000000000..14634c7f7a
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test1/test1.c
@@ -0,0 +1,154 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test1.c
+**
+** Purpose:
+** Have the parent Lock a file, then have the child check the lock, then
+** have the parent unlock the file, and the child check again.
+** This requires some IPC, which is done here with a crude busy wait on a
+** file (waiting for the file size to change) to avoid too many more
+** dependencies.
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+#include "../UnlockFile.h"
+
+#define HELPER "helper"
+#define FILENAME "testfile.txt"
+#define WAITFILENAME "waitfile"
+#define BUF_SIZE 128
+
+int RunTest(char* Helper, HANDLE TheFile, HANDLE WaitFile)
+{
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+ DWORD ChildRetCode = 0;
+ DWORD ParentRetCode = 0;
+ DWORD FileEnd;
+
+ ZeroMemory( &si, sizeof(si) );
+ si.cb = sizeof(si);
+ ZeroMemory( &pi, sizeof(pi) );
+
+ /* Load up the helper Process, and then Wait until it signals that it
+ is finished locking.
+ */
+ if(!CreateProcess( NULL, Helper, NULL,
+ NULL, FALSE, 0,
+ NULL, NULL, &si, &pi))
+ {
+ Fail("ERROR: CreateProcess failed to load executable '%s'.\n",Helper);
+ }
+
+ SignalAndBusyWait(WaitFile);
+
+ /* When the child proccess is finished verifying the lock, find the end
+ of the file and unlock the file.
+ */
+
+ FileEnd = SetFilePointer(TheFile, 0, NULL, FILE_END);
+
+ if(FileEnd == INVALID_SET_FILE_POINTER)
+ {
+ Trace("ERROR: SetFilePointer failed to set the file pointer to the "
+ "end of the file. GetLastError() returned %d.\n",
+ GetLastError());
+ ParentRetCode = 1;
+ }
+
+ if(UnlockFile(TheFile, 0, 0, FileEnd, 0) == 0)
+ {
+ Trace("ERROR: The call to UnlockFile returned 0 when attempting to "
+ "unlock the file within the parent. This should have "
+ "succeeded. GetLastError returned %d.\n",GetLastError());
+ ParentRetCode = 1;
+ }
+
+ /* Switch back to the child so that it can ensure the unlock worked
+ properly.
+ */
+
+ SignalFinish(WaitFile);
+ WaitForSingleObject(pi.hProcess,INFINITE);
+
+ /* Get the return value from the helper process */
+ if (GetExitCodeProcess(pi.hProcess, &ChildRetCode) == 0)
+ {
+ Fail("ERROR: GetExitCodeProccess failed when attempting to retrieve "
+ "the exit code of the child process.\n");
+ }
+
+ if(CloseHandle( pi.hProcess ) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the process.\n");
+ }
+
+ if(CloseHandle( pi.hThread ) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the thread.\n");
+ }
+
+ return (ChildRetCode || ParentRetCode);
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE TheFile = NULL;
+ HANDLE WaitFile = NULL;
+ char* WriteBuffer = "12345678901234567890123456";
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Open up the file we'll be using for some crude IPC */
+ WaitFile = CreateFile(WAITFILENAME,
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (WaitFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Could not open file '%s' with CreateFile. "
+ "GetLastError() returned %d.\n",WAITFILENAME,GetLastError());
+ }
+
+ /* Call the helper function to Create a file, write 'WriteBuffer' to
+ the file, and lock the file from start to end.
+ */
+ TheFile = CreateAndLockFile(TheFile, FILENAME, WriteBuffer,
+ 0, strlen(WriteBuffer));
+
+ /* Run the test. Better errors are displayed by Trace throughout. */
+ if(RunTest(HELPER, TheFile, WaitFile))
+ {
+ Fail("ERROR: Checking to ensure that Unlock successfully unlocked "
+ "a file failed.\n");
+ }
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file used for "
+ "testing the locks. GetLastError() returns %d.\n",
+ GetLastError());
+ }
+
+ if(CloseHandle(WaitFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the wait file. "
+ "GetLastError() returns %d.\n",GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test1/testinfo.dat
new file mode 100644
index 0000000000..4d0ad6afc9
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test1/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = UnlockFile
+Name = Positive test for UnlockFile API
+TYPE = DEFAULT
+EXE1 = test1
+EXE2 = helper
+Description
+= Have the parent Lock a file, then have the child check the lock, then
+= have the parent unlock the file, and the child check again.
+= This requires some IPC, which is done here with a crude busy wait on a
+= file (waiting for the file size to change) to avoid too many more
+= dependencies.
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test2/CMakeLists.txt
new file mode 100644
index 0000000000..142b2763cb
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_unlockfile_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_unlockfile_test2 coreclrpal)
+
+target_link_libraries(paltest_unlockfile_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test2/test2.c b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test2/test2.c
new file mode 100644
index 0000000000..22c2cce2fb
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test2/test2.c
@@ -0,0 +1,154 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test2.c
+**
+** Purpose: Open a file, and call Unlock on the file, even though it has yet
+** to be locked. Then lock a portion of the file, and attempt to call unlock
+** on a larger portion of the file. Also, try to unlock a smaller portion
+** than was locked.
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+#include "../UnlockFile.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE TheFile = NULL;
+ const char lpBuffer[] = "This is a test file.";
+ DWORD bytesWritten;
+ BOOL bRc = TRUE;
+ char fileName[] = "testfile.tmp";
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Open a file which is in the directory */
+ TheFile = CreateFile(fileName,
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (TheFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Could not open file '%s' with CreateFile. "
+ "GetLastError() returned %d.\n",fileName,GetLastError());
+ }
+
+ bRc = WriteFile(
+ TheFile, // handle to file
+ lpBuffer, // data buffer
+ (DWORD)sizeof(lpBuffer), // number of bytes to write
+ &bytesWritten, // number of bytes written
+ NULL // overlapped buffer
+ );
+
+ if(!bRc)
+ {
+ Trace("ERROR: Could not write to file '%s' with WriteFile.",fileName);
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+ Fail("");
+
+ }
+ else if(bytesWritten != (DWORD)sizeof(lpBuffer))
+ {
+ Trace("ERROR: Could not write the correct number of bytes to the "
+ "file '%s' with WriteFile.",fileName);
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+ Fail("");
+ }
+
+ /* Call unlock file on an unlocked file, this should return 0 */
+ if(UnlockFile(TheFile, 0, 0, 5, 0) != 0)
+ {
+ Trace("ERROR: Attempted to unlock a file which was not locked and "
+ "the UnlockFile call was successful.\n");
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+ Fail("");
+ }
+
+ /* Lock the file */
+ if(LockFile(TheFile, 0, 0, 5, 0) == 0)
+ {
+ Trace("ERROR: Failed to call LockFile on a valid file handle. "
+ "GetLastError returned %d.\n",GetLastError());
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+ Fail("");
+ }
+
+ /* Try to unlock more of the file than was locked by LockFile */
+ if(UnlockFile(TheFile, 0, 0, 10, 0) != 0)
+ {
+ Trace("ERROR: Attempted to unlock bytes 0 to 9, but only bytes "
+ "0 to 4 are locked. But, UnlockFile was successful, when it "
+ "should have failed.\n");
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+ Fail("");
+ }
+
+ /* Try to unlock less of the file than was locked by LockFile */
+ if(UnlockFile(TheFile, 0, 0, 3, 0) != 0)
+ {
+ Trace("ERROR: Attempted to unlock bytes 0 to 2, but the bytes 0 to "
+ "4 were locked by LockFile. Unlockfile should have failed "
+ "when attempting this operation.\n");
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+ Fail("");
+ }
+
+ /* Properly unlock the file */
+ if(UnlockFile(TheFile, 0, 0, 5, 0) == 0)
+ {
+ Trace("ERROR: UnlockFile failed to unlock bytes 0 to 4 of the file. "
+ "GetLastError returned %d.\n",GetLastError());
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+ Fail("");
+ }
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test2/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test2/testinfo.dat
new file mode 100644
index 0000000000..932a4a2b8a
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test2/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = UnlockFile
+Name = Positive test for UnlockFile API
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Open a file, and call Unlock on the file, even though it has yet
+= to be locked. Then lock a portion of the file, and attempt to call unlock
+= on a larger portion of the file. Also, try to unlock a smaller portion
+= than was locked.
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test3/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test3/CMakeLists.txt
new file mode 100644
index 0000000000..b4ec37c88c
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test3/CMakeLists.txt
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(TESTSOURCES
+ test3.c
+)
+
+add_executable(paltest_unlockfile_test3
+ ${TESTSOURCES}
+)
+
+add_dependencies(paltest_unlockfile_test3 coreclrpal)
+
+target_link_libraries(paltest_unlockfile_test3
+ pthread
+ m
+ coreclrpal
+)
+
+
+set(HELPERSOURCES
+ helper.c
+)
+
+add_executable(paltest_unlockfile_test3_helper
+ ${HELPERSOURCES}
+)
+
+add_dependencies(paltest_unlockfile_test3_helper coreclrpal)
+
+target_link_libraries(paltest_unlockfile_test3_helper
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test3/helper.c b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test3/helper.c
new file mode 100644
index 0000000000..650abf49ad
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test3/helper.c
@@ -0,0 +1,103 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: helper.c
+**
+** Purpose: A child process which will lock a portion of the file,
+** then try to unlock a portion of the file which was locked by the parent.
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+#include "../UnlockFile.h"
+
+#define FILENAME "testfile.txt"
+#define WAITFILENAME "waitfile"
+#define BUF_SIZE 128
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE TheFile, WaitFile;
+ int result = 0;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Open the same file that the parent has opened and locked */
+ TheFile = CreateFile(FILENAME,
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (TheFile == INVALID_HANDLE_VALUE)
+ {
+ Trace("ERROR: Could not open file '%s' with CreateFile.\n",FILENAME);
+ result = 1;
+ }
+
+ /* Open up the WaitFile that we're using for IPC */
+ WaitFile = CreateFile(WAITFILENAME,
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (WaitFile == INVALID_HANDLE_VALUE)
+ {
+ Trace("ERROR: Could not open file '%s' with CreateFile. "
+ "GetLastError() returned %d.\n",WAITFILENAME,GetLastError());
+ result = 1;
+ }
+
+ /* Lock a section of the file different from which was locked in the
+ parent proccess
+ */
+ if(LockFile(TheFile, 10, 0, 10, 0) == 0)
+ {
+ Trace("ERROR: The LockFile call within the child failed to lock "
+ "the file. GetLastError() returned %d.\n",GetLastError());
+ result = 1;
+ }
+
+ /* Attempt to unlock the portion of the file which was locked within the
+ parent process.
+ */
+ if(UnlockFile(TheFile, 0, 0, 10, 0) != 0)
+ {
+ Trace("ERROR: The UnlockFile call within the child succeeded in "
+ "calling UnlockFile on the portion of the file which was "
+ "locked by the parent.\n");
+ result = 1;
+ }
+
+ // Sleep for a bit to give the parent a chance to block before we do.
+ Sleep(1000);
+
+ /* Switch back to the parent, so it can check the child lock */
+ SignalAndBusyWait(WaitFile);
+
+ /* Finally, clean up the lock which was done within this proccess and
+ exit.
+ */
+ if(UnlockFile(TheFile, 10, 0, 10, 0) == 0)
+ {
+ Trace("ERROR: The UnlockFile call within the child failed to unlock "
+ "the portion of the file which was locked by the child. "
+ "GetLastError() returned %d.\n", GetLastError());
+ result = 1;
+ }
+
+ PAL_TerminateEx(result);
+ return result;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test3/test3.c b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test3/test3.c
new file mode 100644
index 0000000000..cf27aba0a3
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test3/test3.c
@@ -0,0 +1,142 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test3.c
+**
+** Purpose:
+** Lock a portion of the file with the parent. Then have the child lock
+** another portion. Have the child attempt to call Unlock on the parent's
+** locked data, and the parent do the same to the child. Ensure that the
+** locks are respected.
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+#include "../UnlockFile.h"
+
+#define HELPER "helper"
+#define FILENAME "testfile.txt"
+#define WAITFILENAME "waitfile"
+#define BUF_SIZE 128
+
+int RunTest(char* Helper, HANDLE TheFile, HANDLE WaitFile)
+{
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+ DWORD ChildRetCode = 0;
+ DWORD ParentRetCode = 0;
+
+ ZeroMemory( &si, sizeof(si) );
+ si.cb = sizeof(si);
+ ZeroMemory( &pi, sizeof(pi) );
+
+ /* Load up the helper Process, and then Wait until it signals that it
+ is finished locking.
+ */
+ if(!CreateProcess( NULL, Helper, NULL,
+ NULL, FALSE, 0,
+ NULL, NULL, &si, &pi))
+ {
+ Fail("ERROR: CreateProcess failed to load executable '%s'.\n",Helper);
+ }
+
+ SignalAndBusyWait(WaitFile);
+
+ /* When the child proccess is finished setting its lock and testing the
+ parent lock, then the parent can test the child's lock.
+ */
+
+ if(UnlockFile(TheFile, 10, 0, 10, 0) != 0)
+ {
+ Trace("ERROR: The parent proccess called Unlock on the child "
+ "proccesses lock, and the function returned non-zero, when "
+ "it should have failed.\n");
+ ParentRetCode = 1;
+ }
+
+ /* Switch back to the child so that it can unlock its portion and
+ cleanup.
+ */
+
+ SignalFinish(WaitFile);
+ WaitForSingleObject(pi.hProcess,INFINITE);
+
+ /* Get the return value from the helper process */
+ if (GetExitCodeProcess(pi.hProcess, &ChildRetCode) == 0)
+ {
+ Fail("ERROR: GetExitCodeProccess failed when attempting to retrieve "
+ "the exit code of the child process.\n");
+ }
+
+ if(CloseHandle( pi.hProcess ) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the process.\n");
+ }
+
+ if(CloseHandle( pi.hThread ) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the thread.\n");
+ }
+
+ return (ChildRetCode || ParentRetCode);
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE TheFile = NULL;
+ HANDLE WaitFile = NULL;
+ char* WriteBuffer = "12345678901234567890123456";
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Open up the file we'll be using for some crude IPC */
+ WaitFile = CreateFile(WAITFILENAME,
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (WaitFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Could not open file '%s' with CreateFile. "
+ "GetLastError() returned %d.\n",WAITFILENAME,GetLastError());
+ }
+
+ /* Call the helper function to Create a file, write 'WriteBuffer' to
+ the file, and lock the file from bytes 0-9.
+ */
+ TheFile = CreateAndLockFile(TheFile, FILENAME, WriteBuffer,
+ 0, 10);
+
+ /* Run the test. Better errors are displayed by Trace throughout. */
+ if(RunTest(HELPER, TheFile, WaitFile))
+ {
+ Fail("ERROR: The test to check that the Unlock will not work on "
+ "on locks set by other proccesses failed.\n");
+ }
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file used for "
+ "testing the locks. GetLastError() returns %d.\n",
+ GetLastError());
+ }
+
+ if(CloseHandle(WaitFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the wait file. "
+ "GetLastError() returns %d.\n",GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test3/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test3/testinfo.dat
new file mode 100644
index 0000000000..bf7ec5f809
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test3/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = UnlockFile
+Name = Positive test for UnlockFile API
+TYPE = DEFAULT
+EXE1 = test3
+EXE2 = helper
+Description
+= Lock a portion of the file with the parent. Then have the child lock
+= another portion. Have the child attempt to call Unlock on the parent's
+= locked data, and the parent do the same to the child. Ensure that the
+= locks are respected.
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test4/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test4/CMakeLists.txt
new file mode 100644
index 0000000000..d6bee307c2
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_unlockfile_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_unlockfile_test4 coreclrpal)
+
+target_link_libraries(paltest_unlockfile_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test4/test4.c b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test4/test4.c
new file mode 100644
index 0000000000..55abcd24bc
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test4/test4.c
@@ -0,0 +1,187 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test4.c
+**
+** Purpose: Pass an invalid handle to UnlockFile. Pass a null handle to
+** UnlockFile. Create a file and lock two consecuative regions and call
+** UnlockFile on the whole region (this should fail, see msdn)
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+#include "../UnlockFile.h"
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE TheFile = NULL;
+ const char lpBuffer[] = "This is a test file.";
+ DWORD bytesWritten;
+ BOOL bRc = TRUE;
+ char fileName[] = "testfile.tmp";
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Open a file which is in the directory */
+ TheFile = CreateFile(fileName,
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (TheFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Could not open file '%s' with CreateFile. "
+ "GetLastError() returned %d.\n",fileName,GetLastError());
+ }
+
+ bRc = WriteFile(
+ TheFile, // handle to file
+ lpBuffer, // data buffer
+ (DWORD)sizeof(lpBuffer), // number of bytes to write
+ &bytesWritten, // number of bytes written
+ NULL // overlapped buffer
+ );
+
+ if(!bRc)
+ {
+ Trace("ERROR: Could not write to file '%s' with WriteFile.",fileName);
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+ Fail("");
+
+ }
+ else if(bytesWritten != (DWORD)sizeof(lpBuffer))
+ {
+ Trace("ERROR: Could not write the correct number of bytes to the "
+ "file '%s' with WriteFile.",fileName);
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+ Fail("");
+ }
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.\n");
+ }
+
+
+ /* Test an invalid handle and a NULL handle */
+ if(UnlockFile(TheFile, 0, 0, 0, 0) != 0)
+ {
+ Fail("ERROR: Called UnlockFile on an invalid HANDLE and it "
+ "returned a success value.\n");
+ }
+
+ if(UnlockFile(NULL, 0, 0, 0, 0) != 0)
+ {
+ Fail("ERROR: Called UnlockFile with NULL passed for the HANDLE and "
+ "it returned a success value.\n");
+ }
+
+ /* Re-open the file */
+ TheFile = CreateFile(fileName,
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (TheFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: Could not open file '%s' with CreateFile. "
+ "GetLastError() returned %d.\n",fileName,GetLastError());
+ }
+
+ /* Lock two consecuative regions of this file */
+ if(LockFile(TheFile, 0, 0, 5, 0) == 0)
+ {
+ Trace("ERROR: LockFile failed attempting to lock bytes 0-4. "
+ "GetLastError() returned %d.\n",GetLastError());
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+ Fail("");
+ }
+
+ if(LockFile(TheFile, 5, 0, 5, 0) == 0)
+ {
+ Fail("ERROR: LockFile failed attempting to lock bytes 5-9. "
+ "GetLastError() returned %d.\n",GetLastError());
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+ Fail("");
+ }
+
+ /* Attempt to unlock the entire region which was locked with one
+ call to UnlockFile. This should fail.
+ */
+ if(UnlockFile(TheFile, 0, 0, 10, 0) != 0)
+ {
+ Fail("ERROR: Called UnlockFile on bytes 0-9 which were locked with "
+ "two seperate LockFile calls. This should have failed. "
+ "UnlockFile will not unlock consecuative locked regions.\n");
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+ Fail("");
+ }
+
+
+ /* Now, unlock the regions one at a time. */
+ if(UnlockFile(TheFile, 0, 0, 5, 0) == 0)
+ {
+ Fail("ERROR: UnlockFile failed when attempting to unlock bytes "
+ "0-4 of the file. GetLastError() returned %d.\n",GetLastError());
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+ Fail("");
+ }
+
+ if(UnlockFile(TheFile, 5, 0, 5, 0) == 0)
+ {
+ Fail("ERROR: UnlockFile failed when attempting to unlock bytes "
+ "5-9 of the file. GetLastError() returned %d.\n",GetLastError());
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.");
+ }
+ Fail("");
+ }
+
+ if(CloseHandle(TheFile) == 0)
+ {
+ Fail("ERROR: CloseHandle failed to close the file.\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test4/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test4/testinfo.dat
new file mode 100644
index 0000000000..4f3885b978
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test4/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = UnlockFile
+Name = Positive test for UnlockFile API
+TYPE = DEFAULT
+EXE1 = test4
+Description
+= Pass an invalid handle to UnlockFile. Pass a null handle to
+= UnlockFile. Create a file and lock two consecuative regions and call
+= UnlockFile on the whole region (this should fail, see msdn)
+
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/CMakeLists.txt
new file mode 100644
index 0000000000..5ebda77ba6
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ UnmapViewOfFile.c
+)
+
+add_executable(paltest_unmapviewoffile_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_unmapviewoffile_test1 coreclrpal)
+
+target_link_libraries(paltest_unmapviewoffile_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/UnmapViewOfFile.c b/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/UnmapViewOfFile.c
new file mode 100644
index 0000000000..a970ccc3b5
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/UnmapViewOfFile.c
@@ -0,0 +1,184 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: UnMapViewOfFile.c
+**
+** Purpose: Positive test the MapViewOfFile API.
+** Call MapViewOfFile with access FILE_MAP_ALL_ACCESS.
+**
+** Depends: CreateFile,
+** GetFileSize,
+** memset,
+** memcpy,
+** memcmp,
+** ReadFile,
+** UnMapViewOfFile,
+** CreateFileMapping,
+** CloseHandle.
+
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ const int MappingSize = 2048;
+ HANDLE hFile;
+ HANDLE hFileMapping;
+ LPVOID lpMapViewAddress;
+ char buf[] = "this is a test string";
+ char ch[2048];
+ char readString[2048];
+ char lpFileName[] = "test.tmp";
+ DWORD dwBytesRead;
+ BOOL bRetVal;
+
+ /* Initialize the PAL environment.
+ */
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Create a file handle with CreateFile.
+ */
+ hFile = CreateFile( lpFileName,
+ GENERIC_WRITE|GENERIC_READ,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: %u :unable to create file \"%s\".\n",
+ GetLastError(),
+ lpFileName);
+ }
+
+ /* Initialize the buffers.
+ */
+ memset(ch, 0, MappingSize);
+ memset(readString, 0, MappingSize);
+
+ /* Create a unnamed file-mapping object with file handle FileHandle
+ * and with PAGE_READWRITE protection.
+ */
+ hFileMapping = CreateFileMapping(
+ hFile,
+ NULL, /*not inherited*/
+ PAGE_READWRITE, /*read and wite*/
+ 0, /*high-order of object size*/
+ MappingSize, /*low-orger of object size*/
+ NULL); /*unnamed object*/
+
+ if(NULL == hFileMapping)
+ {
+ Trace("ERROR:%u: Failed to create File Mapping.\n",
+ GetLastError());
+ CloseHandle(hFile);
+ Fail("");
+ }
+
+ /* maps a view of a file into the address space of the calling process.
+ */
+ lpMapViewAddress = MapViewOfFile(
+ hFileMapping,
+ FILE_MAP_ALL_ACCESS, /* access code */
+ 0, /* high order offset */
+ 0, /* low order offset */
+ MappingSize); /* number of bytes for map */
+
+ if(NULL == lpMapViewAddress)
+ {
+ Trace("ERROR:%u: Failed to call MapViewOfFile API to map a view"
+ " of file!\n",
+ GetLastError());
+ CloseHandle(hFile);
+ CloseHandle(hFileMapping);
+ Fail("");
+ }
+
+ /* Write to the MapView and copy the MapViewOfFile
+ * to buffer, so we can compare with value read from
+ * file directly.
+ */
+
+ memcpy(lpMapViewAddress, buf, strlen(buf));
+ memcpy(ch, (LPCSTR)lpMapViewAddress, MappingSize);
+
+ /* Read from the File handle.
+ */
+ bRetVal = ReadFile(hFile,
+ readString,
+ strlen(buf),
+ &dwBytesRead,
+ NULL);
+
+ if (bRetVal == FALSE)
+ {
+ Trace("ERROR: %u :unable to read from file handle "
+ "hFile=0x%lx\n",
+ GetLastError(),
+ hFile);
+ CloseHandle(hFile);
+ CloseHandle(hFileMapping);
+ Fail("");
+ }
+
+ if (memcmp(ch, readString, strlen(readString)) != 0)
+ {
+ Trace("ERROR: Read string from file \"%s\", is "
+ "not equal to string written through MapView "
+ "\"%s\".\n",
+ readString,
+ ch);
+ CloseHandle(hFile);
+ CloseHandle(hFileMapping);
+ Fail("");
+ }
+
+ /* Unmap the view of file.
+ */
+ if(UnmapViewOfFile(lpMapViewAddress) == FALSE)
+ {
+ Trace("ERROR: Failed to call UnmapViewOfFile API to"
+ " unmap the view of a file, error code=%u\n",
+ GetLastError());
+ CloseHandle(hFile);
+ CloseHandle(hFileMapping);
+ Fail("");
+ }
+
+ /* Re-initialize the buffer.
+ */
+ memset(ch, 0, MappingSize);
+
+ /* Close handle to created file mapping.
+ */
+ if(CloseHandle(hFileMapping) == FALSE)
+ {
+ Trace("ERROR:%u:Failed to call CloseHandle API "
+ "to close a file mapping handle.",
+ GetLastError());
+ CloseHandle(hFile);
+ Fail("");
+ }
+
+ /* Close handle to create file.
+ */
+ if(CloseHandle(hFile) == FALSE)
+ {
+ Fail("ERROR:%u:Failed to call CloseHandle API "
+ "to close a file handle.",
+ GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/testinfo.dat
new file mode 100644
index 0000000000..8418015360
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = UnmapViewOfFile
+Name = Positive test UnmapViewOfFile API to unmap a view of file
+TYPE = DEFAULT
+EXE1 = unmapviewoffile
+LANG = cpp
+Description
+= Test the UnmapViewOfFile to unmap a view of file.
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/CMakeLists.txt
new file mode 100644
index 0000000000..5c12cf9825
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ unmapviewoffile.c
+)
+
+add_executable(paltest_unmapviewoffile_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_unmapviewoffile_test2 coreclrpal)
+
+target_link_libraries(paltest_unmapviewoffile_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/testinfo.dat
new file mode 100644
index 0000000000..29e847a82f
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = UnmapViewOfFile
+Name = Negative test UnmapViewOfFile API to unmap a view of file
+TYPE = DEFAULT
+EXE1 = unmapviewoffile
+Description
+= Test the UnmapViewOfFile to unmap a view of file
+= negative test by passing a NULL mapping address.
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/unmapviewoffile.c b/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/unmapviewoffile.c
new file mode 100644
index 0000000000..2ca185d234
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/unmapviewoffile.c
@@ -0,0 +1,42 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: UnmapViewOfFile.c (test 2)
+**
+** Purpose: Negative test the UnmapViewOfFile API.
+** Call UnmapViewOfFile to unmap a view of
+** NULL.
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+
+ /*Initialize the PAL environment*/
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+ /* Negative test the UnmapViewOfFile by passing a NULL*/
+ /* mapping address handle*/
+ err = UnmapViewOfFile(NULL);
+ if(0 != err)
+ {
+ Fail("ERROR: Able to call UnmapViewOfFile API "
+ "by passing a NULL mapping address.\n" );
+
+ }
+
+ /* Terminate the PAL.
+ */
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/CMakeLists.txt
new file mode 100644
index 0000000000..eafaa66856
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/CMakeLists.txt
@@ -0,0 +1,24 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test10)
+add_subdirectory(test11)
+add_subdirectory(test12)
+add_subdirectory(test13)
+add_subdirectory(test14)
+add_subdirectory(test15)
+add_subdirectory(test16)
+add_subdirectory(test17)
+add_subdirectory(test18)
+add_subdirectory(test19)
+add_subdirectory(test2)
+add_subdirectory(test20)
+add_subdirectory(test21)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+add_subdirectory(test7)
+add_subdirectory(test8)
+add_subdirectory(test9)
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/CMakeLists.txt
new file mode 100644
index 0000000000..90ba41bd79
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ VirtualAlloc.c
+)
+
+add_executable(paltest_virtualalloc_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_virtualalloc_test1 coreclrpal)
+
+target_link_libraries(paltest_virtualalloc_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/VirtualAlloc.c
new file mode 100644
index 0000000000..26ee942ba1
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/VirtualAlloc.c
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: virtualalloc.c
+**
+** Purpose: Positive test the VirtualAlloc API.
+** Call VirtualAlloc with MEM_COMMIT allocation type
+** and PAGE_READONLY access protection
+
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ LPVOID lpVirtualAddress;
+
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ //Allocate the physical storage in memory or in the paging file on disk
+ lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region
+ 1024, //specify the size
+ MEM_COMMIT, //allocation type
+ PAGE_READONLY); //access protection
+ if(NULL == lpVirtualAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API!\n");
+ }
+
+ //decommit the specified region
+ err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/testinfo.dat
new file mode 100644
index 0000000000..5b8311a05d
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = VirtualAlloc
+Name = Positive test for VirtualAlloc API
+TYPE = DEFAULT
+EXE1 = virtualalloc
+Description
+=Test the VirtualAlloc with MEM_COMMIT allocation type
+=and PAGE_READONLY access protection
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/CMakeLists.txt
new file mode 100644
index 0000000000..51b0e1d92e
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ VirtualAlloc.c
+)
+
+add_executable(paltest_virtualalloc_test10
+ ${SOURCES}
+)
+
+add_dependencies(paltest_virtualalloc_test10 coreclrpal)
+
+target_link_libraries(paltest_virtualalloc_test10
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/VirtualAlloc.c
new file mode 100644
index 0000000000..ac06b9b5c8
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/VirtualAlloc.c
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: virtualalloc.c
+**
+** Purpose: Positive test the VirtualAlloc API.
+** Call VirtualAlloc with MEM_RESERVE allocation type
+** and PAGE_EXECUTE_READ access protection
+
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ LPVOID lpVirtualAddress;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ //Allocate the physical storage in memory or in the paging file on disk
+ lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region
+ 1024, //specify the size
+ MEM_RESERVE, //allocation type
+ PAGE_EXECUTE_READ); //access protection
+ if(NULL == lpVirtualAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API!\n");
+ }
+
+ //decommit the specified region
+ err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/testinfo.dat
new file mode 100644
index 0000000000..960f2265d5
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = VirtualAlloc
+Name = Positive test for VirtualAlloc API
+TYPE = DEFAULT
+EXE1 = virtualalloc
+Description
+=Test the VirtualAlloc with MEM_RESERVE allocation type
+=and PAGE_EXECUTE_READ access protection
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/CMakeLists.txt
new file mode 100644
index 0000000000..adff47087b
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ VirtualAlloc.c
+)
+
+add_executable(paltest_virtualalloc_test11
+ ${SOURCES}
+)
+
+add_dependencies(paltest_virtualalloc_test11 coreclrpal)
+
+target_link_libraries(paltest_virtualalloc_test11
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/VirtualAlloc.c
new file mode 100644
index 0000000000..a3df39b634
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/VirtualAlloc.c
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: virtualalloc.c
+**
+** Purpose: Positive test the VirtualAlloc API.
+** Call VirtualAlloc with MEM_RESERVE allocation type
+** and PAGE_READONLY access protection
+**
+
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ LPVOID lpVirtualAddress;
+
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+ //Allocate the physical storage in memory or in the paging file on disk
+ lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region
+ 1024, //specify the size
+ MEM_RESERVE, //allocation type
+ PAGE_EXECUTE_READWRITE); //access protection
+ if(NULL == lpVirtualAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API!\n");
+ }
+
+ //decommit the specified region
+ err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/testinfo.dat
new file mode 100644
index 0000000000..5d9f0ad880
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = VirtualAlloc
+Name = Positive test for VirtualAlloc API
+TYPE = DEFAULT
+EXE1 = virtualalloc
+Description
+=Test the VirtualAlloc with MEM_RESERVE allocation type
+=and PAGE_EXECUTE_READWRITE access protection
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/CMakeLists.txt
new file mode 100644
index 0000000000..26f303573e
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ VirtualAlloc.c
+)
+
+add_executable(paltest_virtualalloc_test12
+ ${SOURCES}
+)
+
+add_dependencies(paltest_virtualalloc_test12 coreclrpal)
+
+target_link_libraries(paltest_virtualalloc_test12
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/VirtualAlloc.c
new file mode 100644
index 0000000000..8b3508635f
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/VirtualAlloc.c
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: virtualalloc.c
+**
+** Purpose: Positive test the VirtualAlloc API.
+** Call VirtualAlloc with MEM_RESERVE allocation type
+** and PAGE_NOACCESS access protection
+
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ LPVOID lpVirtualAddress;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ //Allocate the physical storage in memory or in the paging file on disk
+ lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region
+ 1024, //specify the size
+ MEM_RESERVE, //allocation type
+ PAGE_NOACCESS); //access protection
+ if(NULL == lpVirtualAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API!\n");
+ }
+
+ //decommit the specified region
+ err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/testinfo.dat
new file mode 100644
index 0000000000..ac2b91c0dc
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = VirtualAlloc
+Name = Positive test for VirtualAlloc API
+TYPE = DEFAULT
+EXE1 = virtualalloc
+Description
+=Test the VirtualAlloc with MEM_COMMIT allocation type
+=and PAGE_NOACCESS access protection
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/CMakeLists.txt
new file mode 100644
index 0000000000..f85cbdc694
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ VirtualAlloc.c
+)
+
+add_executable(paltest_virtualalloc_test13
+ ${SOURCES}
+)
+
+add_dependencies(paltest_virtualalloc_test13 coreclrpal)
+
+target_link_libraries(paltest_virtualalloc_test13
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/VirtualAlloc.c
new file mode 100644
index 0000000000..d2109c0339
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/VirtualAlloc.c
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: virtualalloc.c
+**
+** Purpose: Positive test the VirtualAlloc API.
+** Call VirtualAlloc with MEM_COMMIT|MEM_TOP_DOWN allocation type
+** and PAGE_READONLY access protection
+
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ LPVOID lpVirtualAddress;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ //Allocate the physical storage in memory or in the paging file on disk
+ lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region
+ 1024, //specify the size
+ MEM_COMMIT|MEM_TOP_DOWN, //allocation type
+ PAGE_READONLY); //access protection
+ if(NULL == lpVirtualAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API!\n");
+ }
+
+ //decommit the specified region
+ err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/testinfo.dat
new file mode 100644
index 0000000000..a571e9f8d2
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = VirtualAlloc
+Name = Positive test for VirtualAlloc API
+TYPE = DEFAULT
+EXE1 = virtualalloc
+Description
+=Test the VirtualAlloc with MEM_COMMIT|MEM_TOP_DOWN allocation type
+=and PAGE_READONLY access protection
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/CMakeLists.txt
new file mode 100644
index 0000000000..41ed0ca208
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ VirtualAlloc.c
+)
+
+add_executable(paltest_virtualalloc_test14
+ ${SOURCES}
+)
+
+add_dependencies(paltest_virtualalloc_test14 coreclrpal)
+
+target_link_libraries(paltest_virtualalloc_test14
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/VirtualAlloc.c
new file mode 100644
index 0000000000..49bd21875e
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/VirtualAlloc.c
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: virtualalloc.c
+**
+** Purpose: Positive test the VirtualAlloc API.
+** Call VirtualAlloc with MEM_COMMIT|MEM_TOP_DOWN allocation type
+** and PAGE_READWRITE access protection
+
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ LPVOID lpVirtualAddress;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ //Allocate the physical storage in memory or in the paging file on disk
+ lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region
+ 1024, //specify the size
+ MEM_COMMIT|MEM_TOP_DOWN, //allocation type
+ PAGE_READWRITE); //access protection
+ if(NULL == lpVirtualAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API!\n");
+ }
+
+ //decommit the specified region
+ err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/testinfo.dat
new file mode 100644
index 0000000000..60decb8461
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = VirtualAlloc
+Name = Positive test for VirtualAlloc API
+TYPE = DEFAULT
+EXE1 = virtualalloc
+Description
+=Test the VirtualAlloc with MEM_COMMIT|MEM_TOP_DOWN allocation type
+=and PAGE_READWRITE access protection
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/CMakeLists.txt
new file mode 100644
index 0000000000..87b29108b2
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ VirtualAlloc.c
+)
+
+add_executable(paltest_virtualalloc_test15
+ ${SOURCES}
+)
+
+add_dependencies(paltest_virtualalloc_test15 coreclrpal)
+
+target_link_libraries(paltest_virtualalloc_test15
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/VirtualAlloc.c
new file mode 100644
index 0000000000..3cf1502f26
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/VirtualAlloc.c
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: virtualalloc.c
+**
+** Purpose: Positive test the VirtualAlloc API.
+** Call VirtualAlloc with MEM_COMMIT|MEM_TOP_DOWN allocation type
+** and PAGE_EXECUTE access protection
+
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ LPVOID lpVirtualAddress;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ //Allocate the physical storage in memory or in the paging file on disk
+ lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region
+ 1024, //specify the size
+ MEM_COMMIT|MEM_TOP_DOWN, //allocation type
+ PAGE_EXECUTE); //access protection
+ if(NULL == lpVirtualAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API!\n");
+ }
+
+ //decommit the specified region
+ err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/testinfo.dat
new file mode 100644
index 0000000000..2d9845ded6
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = VirtualAlloc
+Name = Positive test for VirtualAlloc API
+TYPE = DEFAULT
+EXE1 = virtualalloc
+Description
+=Test the VirtualAlloc with MEM_COMMIT|MEM_TOP_DOWN allocation type
+=and PAGE_EXECUTE access protection
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/CMakeLists.txt
new file mode 100644
index 0000000000..90e3f3bdb2
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ VirtualAlloc.c
+)
+
+add_executable(paltest_virtualalloc_test16
+ ${SOURCES}
+)
+
+add_dependencies(paltest_virtualalloc_test16 coreclrpal)
+
+target_link_libraries(paltest_virtualalloc_test16
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/VirtualAlloc.c
new file mode 100644
index 0000000000..ce61b9aa39
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/VirtualAlloc.c
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: virtualalloc.c
+**
+** Purpose: Positive test the VirtualAlloc API.
+** Call VirtualAlloc with MEM_COMMIT|MEM_TOP_DOWN allocation type
+** and PAGE_EXECUTE_READ access protection
+
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ LPVOID lpVirtualAddress;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ //Allocate the physical storage in memory or in the paging file on disk
+ lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region
+ 1024, //specify the size
+ MEM_COMMIT|MEM_TOP_DOWN, //allocation type
+ PAGE_EXECUTE_READ); //access protection
+ if(NULL == lpVirtualAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API!\n");
+ }
+
+ //decommit the specified region
+ err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/testinfo.dat
new file mode 100644
index 0000000000..1389f1f92e
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = VirtualAlloc
+Name = Positive test for VirtualAlloc API
+TYPE = DEFAULT
+EXE1 = virtualalloc
+Description
+=Test the VirtualAlloc with MEM_COMMIT|MEM_TOP_DOWN allocation type
+=and PAGE_EXECUTE_READ access protection
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/CMakeLists.txt
new file mode 100644
index 0000000000..461b48ccc0
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ VirtualAlloc.c
+)
+
+add_executable(paltest_virtualalloc_test17
+ ${SOURCES}
+)
+
+add_dependencies(paltest_virtualalloc_test17 coreclrpal)
+
+target_link_libraries(paltest_virtualalloc_test17
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/VirtualAlloc.c
new file mode 100644
index 0000000000..eb609f14e4
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/VirtualAlloc.c
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: virtualalloc.c
+**
+** Purpose: Positive test the VirtualAlloc API.
+** Call VirtualAlloc with MEM_COMMIT|MEM_TOP_DOWN allocation type
+** and PAGE_READONLY access protection
+**
+
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ LPVOID lpVirtualAddress;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ //Allocate the physical storage in memory or in the paging file on disk
+ lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region
+ 1024, //specify the size
+ MEM_COMMIT|MEM_TOP_DOWN, //allocation type
+ PAGE_EXECUTE_READWRITE); //access protection
+ if(NULL == lpVirtualAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API!\n");
+ }
+
+ //decommit the specified region
+ err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/testinfo.dat
new file mode 100644
index 0000000000..49ced63836
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = VirtualAlloc
+Name = Positive test for VirtualAlloc API
+TYPE = DEFAULT
+EXE1 = virtualalloc
+Description
+=Test the VirtualAlloc with MEM_COMMIT|MEM_TOP_DOWN allocation type
+=and PAGE_EXECUTE_READWRITE access protection
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/CMakeLists.txt
new file mode 100644
index 0000000000..69823be14b
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ VirtualAlloc.c
+)
+
+add_executable(paltest_virtualalloc_test18
+ ${SOURCES}
+)
+
+add_dependencies(paltest_virtualalloc_test18 coreclrpal)
+
+target_link_libraries(paltest_virtualalloc_test18
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/VirtualAlloc.c
new file mode 100644
index 0000000000..e46da851db
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/VirtualAlloc.c
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: virtualalloc.c
+**
+** Purpose: Positive test the VirtualAlloc API.
+** Call VirtualAlloc with MEM_COMMIT|MEM_TOP_DOWN allocation type
+** and PAGE_NOACCESS access protection
+
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ LPVOID lpVirtualAddress;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+
+ //Allocate the physical storage in memory or in the paging file on disk
+ lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region
+ 1024, //specify the size
+ MEM_COMMIT|MEM_TOP_DOWN, //allocation type
+ PAGE_NOACCESS); //access protection
+ if(NULL == lpVirtualAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API!\n");
+ }
+
+ //decommit the specified region
+ err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/testinfo.dat
new file mode 100644
index 0000000000..1fd4ac6f14
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = VirtualAlloc
+Name = Positive test for VirtualAlloc API
+TYPE = DEFAULT
+EXE1 = virtualalloc
+Description
+=Test the VirtualAlloc with MEM_COMMIT|MEM_TOP_DOWN allocation type
+=and PAGE_NOACCESS access protection
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/CMakeLists.txt
new file mode 100644
index 0000000000..fa65b4fa46
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ VirtualAlloc.c
+)
+
+add_executable(paltest_virtualalloc_test19
+ ${SOURCES}
+)
+
+add_dependencies(paltest_virtualalloc_test19 coreclrpal)
+
+target_link_libraries(paltest_virtualalloc_test19
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/VirtualAlloc.c
new file mode 100644
index 0000000000..5cbe48b15e
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/VirtualAlloc.c
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: virtualalloc.c
+**
+** Purpose: Positive test the VirtualAlloc API.
+** Call VirtualAlloc to reserve and commit
+** simultaneously with MEM_COMMIT|MEM_RESERVE|MEM_TOP_DOWN
+** allocation type and PAGE_READONLY access
+** protection
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ LPVOID lpVirtualAddress;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ //reserve and commit simultaneously by using MEM_COMMIT|MEM_RESERVE
+ lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region
+ 1024, //specify the size
+ MEM_COMMIT|MEM_RESERVE|MEM_TOP_DOWN, //allocation type
+ PAGE_READONLY); //access protection
+ if(NULL == lpVirtualAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API!\n");
+ }
+
+ //decommit the specified region
+ err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/testinfo.dat
new file mode 100644
index 0000000000..6e427da15a
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = VirtualAlloc
+Name = Positive test for VirtualAlloc API
+TYPE = DEFAULT
+EXE1 = virtualalloc
+Description
+=Test the VirtualAlloc to reserve and commit
+=simultaneously by using MEM_COMMIT|MEM_RESERVE|MEM_TOP_DOWN
+=allocation type and PAGE_READONLY access protection
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/CMakeLists.txt
new file mode 100644
index 0000000000..1753b1edc5
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ VirtualAlloc.c
+)
+
+add_executable(paltest_virtualalloc_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_virtualalloc_test2 coreclrpal)
+
+target_link_libraries(paltest_virtualalloc_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/VirtualAlloc.c
new file mode 100644
index 0000000000..99cf76a523
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/VirtualAlloc.c
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: virtualalloc.c
+**
+** Purpose: Positive test the VirtualAlloc API.
+** Call VirtualAlloc with MEM_COMMIT allocation type
+** and PAGE_READWRITE access protection
+
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ LPVOID lpVirtualAddress;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ //Allocate the physical storage in memory or in the paging file on disk
+ lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region
+ 1024, //specify the size
+ MEM_COMMIT, //allocation type
+ PAGE_READWRITE); //access protection
+ if(NULL == lpVirtualAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API!\n");
+ }
+
+ //decommit the specified region
+ err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/testinfo.dat
new file mode 100644
index 0000000000..c7d8b6783d
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = VirtualAlloc
+Name = Positive test for VirtualAlloc API
+TYPE = DEFAULT
+EXE1 = virtualalloc
+Description
+=Test the VirtualAlloc with MEM_COMMIT allocation type
+=and PAGE_READWRITE access protection
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/CMakeLists.txt
new file mode 100644
index 0000000000..2c55071149
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ virtualalloc.c
+)
+
+add_executable(paltest_virtualalloc_test20
+ ${SOURCES}
+)
+
+add_dependencies(paltest_virtualalloc_test20 coreclrpal)
+
+target_link_libraries(paltest_virtualalloc_test20
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/testinfo.dat
new file mode 100644
index 0000000000..6010a18c8a
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = VirtualAlloc
+Name = Positive test for VirtualAlloc API
+TYPE = DEFAULT
+EXE1 = virtualalloc
+Description
+=Test VirtualAlloc to ensure that re-committed memory is not changed.
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/virtualalloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/virtualalloc.c
new file mode 100644
index 0000000000..7aec3c7f55
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/virtualalloc.c
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: virtualalloc.c
+**
+** Purpose: Positive test the VirtualAlloc API.
+** Ensure that memory re-committed through VirtualAlloc
+** is not changed.
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ int *ptr;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ ptr = (int *) VirtualAlloc(NULL, 4096, MEM_COMMIT | MEM_RESERVE,
+ PAGE_READWRITE);
+ if (ptr == NULL)
+ {
+ Fail("First VirtualAlloc failed!\n");
+ }
+
+ *ptr = 123;
+
+ ptr = (int *) VirtualAlloc(ptr, 4096, MEM_COMMIT, PAGE_READWRITE);
+ if (ptr == NULL)
+ {
+ Fail("Second VirtualAlloc failed!\n");
+ }
+ if (*ptr != 123)
+ {
+ Fail("VirtualAlloc modified (probably zeroed) re-committed memory!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/CMakeLists.txt
new file mode 100644
index 0000000000..f97c32af75
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ virtualalloc.c
+)
+
+add_executable(paltest_virtualalloc_test21
+ ${SOURCES}
+)
+
+add_dependencies(paltest_virtualalloc_test21 coreclrpal)
+
+target_link_libraries(paltest_virtualalloc_test21
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/testinfo.dat
new file mode 100644
index 0000000000..c32d352d19
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = VirtualAlloc
+Name = Positive test for VirtualAlloc API
+TYPE = DEFAULT
+EXE1 = virtualalloc
+Description
+=Test VirtualAlloc to ensure that freed memory that is committed again is zeroed.
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/virtualalloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/virtualalloc.c
new file mode 100644
index 0000000000..065a2ff5c8
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/virtualalloc.c
@@ -0,0 +1,54 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: virtualalloc.c
+**
+** Purpose: Positive test the VirtualAlloc API.
+** Ensure that memory committed through VirtualAlloc,
+** then freed, then committed again is zeroed.
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ int *ptr;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ ptr = (int *) VirtualAlloc(NULL, 4096, MEM_COMMIT | MEM_RESERVE,
+ PAGE_READWRITE);
+ if (ptr == NULL)
+ {
+ Fail("First VirtualAlloc failed!\n");
+ }
+ *ptr = 123;
+
+ if (!VirtualFree(ptr, 4096, MEM_DECOMMIT))
+ {
+ Fail("VirtualFree failed!\n");
+ }
+
+ ptr = (int *) VirtualAlloc(ptr, 4096, MEM_COMMIT, PAGE_READWRITE);
+ if (ptr == NULL)
+ {
+ Fail("Second VirtualAlloc failed!\n");
+ }
+ if (*ptr != 0)
+ {
+ Fail("VirtualAlloc failed to zero its memory!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/CMakeLists.txt
new file mode 100644
index 0000000000..035594bd79
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ VirtualAlloc.c
+)
+
+add_executable(paltest_virtualalloc_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_virtualalloc_test3 coreclrpal)
+
+target_link_libraries(paltest_virtualalloc_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/VirtualAlloc.c
new file mode 100644
index 0000000000..5c57ec337f
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/VirtualAlloc.c
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: virtualalloc.c
+**
+** Purpose: Positive test the VirtualAlloc API.
+** Call VirtualAlloc with MEM_COMMIT allocation type
+** and PAGE_EXECUTE access protection
+
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ LPVOID lpVirtualAddress;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ //Allocate the physical storage in memory or in the paging file on disk
+ lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region
+ 1024, //specify the size
+ MEM_COMMIT, //allocation type
+ PAGE_EXECUTE); //access protection
+ if(NULL == lpVirtualAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API!\n");
+ }
+
+ //decommit the specified region
+ err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/testinfo.dat
new file mode 100644
index 0000000000..a3d5401493
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = VirtualAlloc
+Name = Positive test for VirtualAlloc API
+TYPE = DEFAULT
+EXE1 = virtualalloc
+Description
+=Test the VirtualAlloc with MEM_COMMIT allocation type
+=and PAGE_EXECUTE access protection
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/CMakeLists.txt
new file mode 100644
index 0000000000..5ce80bf52f
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ VirtualAlloc.c
+)
+
+add_executable(paltest_virtualalloc_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_virtualalloc_test4 coreclrpal)
+
+target_link_libraries(paltest_virtualalloc_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/VirtualAlloc.c
new file mode 100644
index 0000000000..c134a14eb1
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/VirtualAlloc.c
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: virtualalloc.c
+**
+** Purpose: Positive test the VirtualAlloc API.
+** Call VirtualAlloc with MEM_COMMIT allocation type
+** and PAGE_EXECUTE_READ access protection
+
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ LPVOID lpVirtualAddress;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ //Allocate the physical storage in memory or in the paging file on disk
+ lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region
+ 1024, //specify the size
+ MEM_COMMIT, //allocation type
+ PAGE_EXECUTE_READ); //access protection
+ if(NULL == lpVirtualAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API!\n");
+ }
+
+ //decommit the specified region
+ err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/testinfo.dat
new file mode 100644
index 0000000000..0e84e7a3ba
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = VirtualAlloc
+Name = Positive test for VirtualAlloc API
+TYPE = DEFAULT
+EXE1 = virtualalloc
+Description
+=Test the VirtualAlloc with MEM_COMMIT allocation type
+=and PAGE_EXECUTE_READ access protection
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/CMakeLists.txt
new file mode 100644
index 0000000000..138d9c9727
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ VirtualAlloc.c
+)
+
+add_executable(paltest_virtualalloc_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_virtualalloc_test5 coreclrpal)
+
+target_link_libraries(paltest_virtualalloc_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/VirtualAlloc.c
new file mode 100644
index 0000000000..8c4f9dcdb6
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/VirtualAlloc.c
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: virtualalloc.c
+**
+** Purpose: Positive test the VirtualAlloc API.
+** Call VirtualAlloc with MEM_COMMIT allocation type
+** and PAGE_READONLY access protection
+**
+
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ LPVOID lpVirtualAddress;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ //Allocate the physical storage in memory or in the paging file on disk
+ lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region
+ 1024, //specify the size
+ MEM_COMMIT, //allocation type
+ PAGE_EXECUTE_READWRITE); //access protection
+ if(NULL == lpVirtualAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API!\n");
+ }
+
+ //decommit the specified region
+ err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/testinfo.dat
new file mode 100644
index 0000000000..332b88b071
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = VirtualAlloc
+Name = Positive test for VirtualAlloc API
+TYPE = DEFAULT
+EXE1 = virtualalloc
+Description
+=Test the VirtualAlloc with MEM_COMMIT allocation type
+=and PAGE_EXECUTE_READWRITE access protection
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/CMakeLists.txt
new file mode 100644
index 0000000000..c61add9db4
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ VirtualAlloc.c
+)
+
+add_executable(paltest_virtualalloc_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_virtualalloc_test6 coreclrpal)
+
+target_link_libraries(paltest_virtualalloc_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/VirtualAlloc.c
new file mode 100644
index 0000000000..e9c33d86df
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/VirtualAlloc.c
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: virtualalloc.c
+**
+** Purpose: Positive test the VirtualAlloc API.
+** Call VirtualAlloc with MEM_COMMIT allocation type
+** and PAGE_NOACCESS access protection
+
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ LPVOID lpVirtualAddress;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ //Allocate the physical storage in memory or in the paging file on disk
+ lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region
+ 1024, //specify the size
+ MEM_COMMIT, //allocation type
+ PAGE_NOACCESS); //access protection
+ if(NULL == lpVirtualAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API!\n");
+ }
+
+ //decommit the specified region
+ err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/testinfo.dat
new file mode 100644
index 0000000000..ac2b91c0dc
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = VirtualAlloc
+Name = Positive test for VirtualAlloc API
+TYPE = DEFAULT
+EXE1 = virtualalloc
+Description
+=Test the VirtualAlloc with MEM_COMMIT allocation type
+=and PAGE_NOACCESS access protection
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/CMakeLists.txt
new file mode 100644
index 0000000000..b5452a0c48
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ VirtualAlloc.c
+)
+
+add_executable(paltest_virtualalloc_test7
+ ${SOURCES}
+)
+
+add_dependencies(paltest_virtualalloc_test7 coreclrpal)
+
+target_link_libraries(paltest_virtualalloc_test7
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/VirtualAlloc.c
new file mode 100644
index 0000000000..bee2735c9f
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/VirtualAlloc.c
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: virtualalloc.c
+**
+** Purpose: Positive test the VirtualAlloc API.
+** Call VirtualAlloc with MEM_RESERVE allocation type
+** and PAGE_READONLY access protection
+
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ LPVOID lpVirtualAddress;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ //Allocate the physical storage in memory or in the paging file on disk
+ lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region
+ 1024, //specify the size
+ MEM_RESERVE, //allocation type
+ PAGE_READONLY); //access protection
+ if(NULL == lpVirtualAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API!\n");
+ PAL_Terminate();
+ return 1;
+ }
+
+ //decommit the specified region
+ err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ PAL_Terminate();
+ return 1;
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/testinfo.dat
new file mode 100644
index 0000000000..2edcb56d3b
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = VirtualAlloc
+Name = Positive test for VirtualAlloc API
+TYPE = DEFAULT
+EXE1 = virtualalloc
+Description
+=Test the VirtualAlloc with MEM_RESERVE allocation type
+=and PAGE_READONLY access protection
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/CMakeLists.txt
new file mode 100644
index 0000000000..584a0c505a
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ VirtualAlloc.c
+)
+
+add_executable(paltest_virtualalloc_test8
+ ${SOURCES}
+)
+
+add_dependencies(paltest_virtualalloc_test8 coreclrpal)
+
+target_link_libraries(paltest_virtualalloc_test8
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/VirtualAlloc.c
new file mode 100644
index 0000000000..d548e0c8db
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/VirtualAlloc.c
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: virtualalloc.c
+**
+** Purpose: Positive test the VirtualAlloc API.
+** Call VirtualAlloc with MEM_RESERVE allocation type
+** and PAGE_READWRITE access protection
+
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ LPVOID lpVirtualAddress;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ //Allocate the physical storage in memory or in the paging file on disk
+ lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region
+ 1024, //specify the size
+ MEM_RESERVE, //allocation type
+ PAGE_READWRITE); //access protection
+ if(NULL == lpVirtualAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API!\n");
+ }
+
+ //decommit the specified region
+ err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/testinfo.dat
new file mode 100644
index 0000000000..c0ee6b6a69
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = VirtualAlloc
+Name = Positive test for VirtualAlloc API
+TYPE = DEFAULT
+EXE1 = virtualalloc
+Description
+=Test the VirtualAlloc with MEM_RESERVE allocation type
+=and PAGE_READWRITE access protection
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/CMakeLists.txt
new file mode 100644
index 0000000000..aee950b2e4
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ VirtualAlloc.c
+)
+
+add_executable(paltest_virtualalloc_test9
+ ${SOURCES}
+)
+
+add_dependencies(paltest_virtualalloc_test9 coreclrpal)
+
+target_link_libraries(paltest_virtualalloc_test9
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/VirtualAlloc.c
new file mode 100644
index 0000000000..2711addacc
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/VirtualAlloc.c
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: virtualalloc.c
+**
+** Purpose: Positive test the VirtualAlloc API.
+** Call VirtualAlloc with MEM_RESERVE allocation type
+** and PAGE_EXECUTE access protection
+
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ LPVOID lpVirtualAddress;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ //Allocate the physical storage in memory or in the paging file on disk
+ lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region
+ 1024, //specify the size
+ MEM_RESERVE, //allocation type
+ PAGE_EXECUTE); //access protection
+ if(NULL == lpVirtualAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API!\n");
+ }
+
+ //decommit the specified region
+ err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/testinfo.dat
new file mode 100644
index 0000000000..1e83744bba
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = VirtualAlloc
+Name = Positive test for VirtualAlloc API
+TYPE = DEFAULT
+EXE1 = virtualalloc
+Description
+=Test the VirtualAlloc with MEM_RESERVE allocation type
+=and PAGE_EXECUTE access protection
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/CMakeLists.txt
new file mode 100644
index 0000000000..1962ade358
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/CMakeLists.txt
new file mode 100644
index 0000000000..1914f76fe6
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ VirtualFree.c
+)
+
+add_executable(paltest_virtualfree_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_virtualfree_test1 coreclrpal)
+
+target_link_libraries(paltest_virtualfree_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/VirtualFree.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/VirtualFree.c
new file mode 100644
index 0000000000..0f4f144aa5
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/VirtualFree.c
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: virtualfree.c
+**
+** Purpose: Positive test the VirtualFree API.
+** Call VirtualFree with MEM_DECOMMIT
+** free operation type
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ LPVOID lpVirtualAddress;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ //Allocate the physical storage in memory or in the paging file on disk
+ lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region
+ 1024, //specify the size
+ MEM_COMMIT, //allocation type
+ PAGE_READONLY); //access protection
+ if(NULL == lpVirtualAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API!\n");
+ }
+
+ //decommit the specified region
+ err = VirtualFree(lpVirtualAddress,1024,MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/testinfo.dat
new file mode 100644
index 0000000000..2848635681
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = VirtualFree
+Name = Positive test for VirtualFree API
+TYPE = DEFAULT
+EXE1 = virtualfree
+Description
+=Test the VirtualFree with MEM_DECOMMIT free
+=operation type
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/CMakeLists.txt
new file mode 100644
index 0000000000..a288b37154
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ VirtualFree.c
+)
+
+add_executable(paltest_virtualfree_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_virtualfree_test2 coreclrpal)
+
+target_link_libraries(paltest_virtualfree_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/VirtualFree.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/VirtualFree.c
new file mode 100644
index 0000000000..70064a3bf9
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/VirtualFree.c
@@ -0,0 +1,54 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: virtualfree.c
+**
+** Purpose: Positive test the VirtualFree API.
+** Call VirtualFree with MEM_RELEASE
+** free operation type
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ LPVOID lpVirtualAddress;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ //Allocate the physical storage in memory or in the paging file on disk
+ lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region
+ 1024, //specify the size
+ MEM_COMMIT, //allocation type
+ PAGE_READONLY); //access protection
+ if(NULL == lpVirtualAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API!\n");
+ PAL_Terminate();
+ return 1;
+ }
+
+ //decommit the specified region
+ err = VirtualFree(lpVirtualAddress,//base address
+ 0, //must be zero with MEM_RELEASE
+ MEM_RELEASE);//free operation
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ PAL_Terminate();
+ return 1;
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/testinfo.dat
new file mode 100644
index 0000000000..ea380c3676
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = VirtualFree
+Name = Positive test for VirtualFree API
+TYPE = DEFAULT
+EXE1 = virtualfree
+Description
+=Test the VirtualFree with MEM_RELEASE free
+=operation type
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/CMakeLists.txt
new file mode 100644
index 0000000000..993189c1aa
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ VirtualFree.c
+)
+
+add_executable(paltest_virtualfree_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_virtualfree_test3 coreclrpal)
+
+target_link_libraries(paltest_virtualfree_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/VirtualFree.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/VirtualFree.c
new file mode 100644
index 0000000000..27f1936be7
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/VirtualFree.c
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: virtualfree.c
+**
+** Purpose: Positive test the VirtualFree API.
+** Call VirtualFree with MEM_RELEASE
+** and MEM_DECOMMIT free operation type
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+#define VIRTUALSIZE 1024
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ LPVOID lpVirtualAddress;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ //Allocate the physical storage in memory or in the paging file on disk
+ lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region
+ VIRTUALSIZE, //specify the size
+ MEM_RESERVE, //allocation type
+ PAGE_NOACCESS); //access protection
+ if(NULL == lpVirtualAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API!\n");
+ }
+
+ //decommit and release the specified region
+ err = VirtualFree(lpVirtualAddress, //base address
+ VIRTUALSIZE, //decommited size
+ MEM_DECOMMIT|MEM_RELEASE);//free operation
+ if(0 != err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/testinfo.dat
new file mode 100644
index 0000000000..c27b7ad3e5
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = VirtualFree
+Name = Positive test for VirtualFree API
+TYPE = DEFAULT
+EXE1 = virtualfree
+Description
+=Test the VirtualFree with MEM_DECOMMIT|MEM_RELEASE free
+=operation type
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/CMakeLists.txt
new file mode 100644
index 0000000000..cac5452ec9
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/CMakeLists.txt
@@ -0,0 +1,9 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test6)
+add_subdirectory(test7)
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/CMakeLists.txt
new file mode 100644
index 0000000000..214cf460ae
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ VirtualProtect.c
+)
+
+add_executable(paltest_virtualprotect_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_virtualprotect_test1 coreclrpal)
+
+target_link_libraries(paltest_virtualprotect_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/VirtualProtect.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/VirtualProtect.c
new file mode 100644
index 0000000000..1a28bd156d
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/VirtualProtect.c
@@ -0,0 +1,69 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: virtualprotect.c
+**
+** Purpose: Positive test the VirtualProtect API.
+** Call VirtualProtect to set new protect as
+** PAGE_READWRITE
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+#define REGIONSIZE 1024
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ LPVOID lpVirtualAddress;
+ DWORD OldProtect;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ //Allocate the physical storage in memory or in the paging file on disk
+ lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region
+ REGIONSIZE, //specify the size
+ MEM_COMMIT, //allocation type
+ PAGE_READONLY); //access protection
+ if(NULL == lpVirtualAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API!\n");
+ }
+
+ OldProtect = PAGE_READONLY;
+ //Set new access protection
+ err = VirtualProtect(lpVirtualAddress,
+ REGIONSIZE, //specify the region size
+ PAGE_READWRITE,//desied access protection
+ &OldProtect);//old access protection
+ if(0 == err)
+ {
+ Trace("\nFailed to call VirtualProtect API!\n");
+ err = VirtualFree(lpVirtualAddress,REGIONSIZE,MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+ Fail("");
+ }
+
+
+ //decommit the specified region
+ err = VirtualFree(lpVirtualAddress,REGIONSIZE,MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/testinfo.dat
new file mode 100644
index 0000000000..6b78c079e7
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = VirtualProtect
+Name = Positive test for VirtualProtect - with PAGE_READWRITE
+TYPE = DEFAULT
+EXE1 = virtualprotect
+Description
+=Test the VirtualProtect to set new access protection
+=as PAGE_READWRITE
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/CMakeLists.txt
new file mode 100644
index 0000000000..27f43477ea
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ VirtualProtect.c
+)
+
+add_executable(paltest_virtualprotect_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_virtualprotect_test2 coreclrpal)
+
+target_link_libraries(paltest_virtualprotect_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/VirtualProtect.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/VirtualProtect.c
new file mode 100644
index 0000000000..64a08d7885
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/VirtualProtect.c
@@ -0,0 +1,69 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: virtualprotect.c
+**
+** Purpose: Positive test the VirtualProtect API.
+** Call VirtualProtect to set new protect as
+** PAGE_EXECUTE
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+#define REGIONSIZE 1024
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ LPVOID lpVirtualAddress;
+ DWORD OldProtect;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ //Allocate the physical storage in memory or in the paging file on disk
+ lpVirtualAddress = VirtualAlloc(NULL,//determine where to allocate the region
+ REGIONSIZE, //specify the size
+ MEM_COMMIT, //allocation type
+ PAGE_READONLY); //access protection
+ if(NULL == lpVirtualAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API!\n");
+ }
+
+ OldProtect = PAGE_READONLY;
+ //Set new access protection
+ err = VirtualProtect(lpVirtualAddress,
+ REGIONSIZE, //specify the region size
+ PAGE_EXECUTE,//desied access protection
+ &OldProtect);//old access protection
+ if(0 == err)
+ {
+ Trace("\nFailed to call VirtualProtect API!\n");
+ err = VirtualFree(lpVirtualAddress,REGIONSIZE,MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+ Fail("");
+ }
+
+
+ //decommit the specified region
+ err = VirtualFree(lpVirtualAddress,REGIONSIZE,MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/testinfo.dat
new file mode 100644
index 0000000000..d5fa0cfbc2
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = VirtualProtect
+Name = Positive test for VirtualProtect - with PAGE_EXECUTE
+TYPE = DEFAULT
+EXE1 = virtualprotect
+Description
+=Test the VirtualProtect to set new access protection
+=as PAGE_EXECUTE
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/CMakeLists.txt
new file mode 100644
index 0000000000..994d4e2f41
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ VirtualProtect.c
+)
+
+add_executable(paltest_virtualprotect_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_virtualprotect_test3 coreclrpal)
+
+target_link_libraries(paltest_virtualprotect_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/VirtualProtect.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/VirtualProtect.c
new file mode 100644
index 0000000000..0f738630ee
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/VirtualProtect.c
@@ -0,0 +1,69 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: virtualprotect.c
+**
+** Purpose: Positive test the VirtualProtect API.
+** Call VirtualProtect to set new protect as
+** PAGE_EXECUTE_READ
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+#define REGIONSIZE 1024
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ LPVOID lpVirtualAddress;
+ DWORD OldProtect;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ //Allocate the physical storage in memory or in the paging file on disk
+ lpVirtualAddress = VirtualAlloc(NULL,//determine where to allocate the region
+ REGIONSIZE, //specify the size
+ MEM_COMMIT, //allocation type
+ PAGE_READONLY); //access protection
+ if(NULL == lpVirtualAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API!\n");
+ }
+
+ OldProtect = PAGE_READONLY;
+ //Set new access protection
+ err = VirtualProtect(lpVirtualAddress,
+ REGIONSIZE, //specify the region size
+ PAGE_EXECUTE_READ,//desied access protection
+ &OldProtect);//old access protection
+ if(0 == err)
+ {
+ Trace("\nFailed to call VirtualProtect API!\n");
+ err = VirtualFree(lpVirtualAddress,REGIONSIZE,MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+ Fail("");
+ }
+
+
+ //decommit the specified region
+ err = VirtualFree(lpVirtualAddress,REGIONSIZE,MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/testinfo.dat
new file mode 100644
index 0000000000..7c64c3092e
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = VirtualProtect
+Name = Positive test for VirtualProtect - with PAGE_EXECUTE_READ
+TYPE = DEFAULT
+EXE1 = virtualprotect
+Description
+=Test the VirtualProtect to set new access protection
+=as PAGE_EXECUTE_READ
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/CMakeLists.txt
new file mode 100644
index 0000000000..2e0fba50bb
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ VirtualProtect.c
+)
+
+add_executable(paltest_virtualprotect_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_virtualprotect_test4 coreclrpal)
+
+target_link_libraries(paltest_virtualprotect_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/VirtualProtect.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/VirtualProtect.c
new file mode 100644
index 0000000000..926d501d0d
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/VirtualProtect.c
@@ -0,0 +1,68 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: virtualprotect.c
+**
+** Purpose: Positive test the VirtualProtect API.
+** Call VirtualProtect to set new protect as
+** PAGE_EXECUTE_READWRITE
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+#define REGIONSIZE 1024
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ LPVOID lpVirtualAddress;
+ DWORD OldProtect;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ //Allocate the physical storage in memory or in the paging file on disk
+ lpVirtualAddress = VirtualAlloc(NULL,//determine where to allocate the region
+ REGIONSIZE, //specify the size
+ MEM_COMMIT, //allocation type
+ PAGE_READONLY); //access protection
+ if(NULL == lpVirtualAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API!\n");
+ }
+
+ OldProtect = PAGE_READONLY;
+ //Set new access protection
+ err = VirtualProtect(lpVirtualAddress,
+ REGIONSIZE, //specify the region size
+ PAGE_EXECUTE_READWRITE,//desied access protection
+ &OldProtect);//old access protection
+ if(0 == err)
+ {
+ Trace("\nFailed to call VirtualProtect API!\n");
+ err = VirtualFree(lpVirtualAddress,REGIONSIZE,MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+ Fail("");
+ }
+
+ //decommit the specified region
+ err = VirtualFree(lpVirtualAddress,REGIONSIZE,MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/testinfo.dat
new file mode 100644
index 0000000000..c344073113
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = VirtualProtect
+Name = Positive test for VirtualProtect - with PAGE_EXECUTE_READWRITE
+TYPE = DEFAULT
+EXE1 = virtualprotect
+Description
+=Test the VirtualProtect to set new access protection
+=as PAGE_EXECUTE_READWRITE
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/CMakeLists.txt
new file mode 100644
index 0000000000..6d6fd07df8
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ VirtualProtect.c
+)
+
+add_executable(paltest_virtualprotect_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_virtualprotect_test6 coreclrpal)
+
+target_link_libraries(paltest_virtualprotect_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/VirtualProtect.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/VirtualProtect.c
new file mode 100644
index 0000000000..d60b323ec6
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/VirtualProtect.c
@@ -0,0 +1,68 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: virtualprotect.c
+**
+** Purpose: Positive test the VirtualProtect API.
+** Call VirtualProtect to set new protect as
+** PAGE_NOACCESS
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+#define REGIONSIZE 1024
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ LPVOID lpVirtualAddress;
+ DWORD OldProtect;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+ //Allocate the physical storage in memory or in the paging file on disk
+ lpVirtualAddress = VirtualAlloc(NULL,//determine where to allocate the region
+ REGIONSIZE, //specify the size
+ MEM_COMMIT, //allocation type
+ PAGE_READONLY); //access protection
+ if(NULL == lpVirtualAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API!\n");
+ }
+
+ OldProtect = PAGE_READONLY;
+ //Set new access protection
+ err = VirtualProtect(lpVirtualAddress,
+ REGIONSIZE, //specify the region size
+ PAGE_NOACCESS,//desied access protection
+ &OldProtect);//old access protection
+ if(0 == err)
+ {
+ Trace("\nFailed to call VirtualProtect API!\n");
+ err = VirtualFree(lpVirtualAddress,REGIONSIZE,MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+ Fail("");
+ }
+
+
+ //decommit the specified region
+ err = VirtualFree(lpVirtualAddress,REGIONSIZE,MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/testinfo.dat
new file mode 100644
index 0000000000..71ccad5639
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = VirtualProtect
+Name = Positive test for VirtualProtect - with PAGE_NOACCESS
+TYPE = DEFAULT
+EXE1 = virtualprotect
+Description
+=Test the VirtualProtect to set new access protection
+=as PAGE_NOACCESS
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/CMakeLists.txt
new file mode 100644
index 0000000000..06af860559
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ VirtualProtect.c
+)
+
+add_executable(paltest_virtualprotect_test7
+ ${SOURCES}
+)
+
+add_dependencies(paltest_virtualprotect_test7 coreclrpal)
+
+target_link_libraries(paltest_virtualprotect_test7
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/VirtualProtect.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/VirtualProtect.c
new file mode 100644
index 0000000000..edc37711f4
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/VirtualProtect.c
@@ -0,0 +1,69 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: virtualprotect.c
+**
+** Purpose: Positive test the VirtualProtect API.
+** Call VirtualProtect to set new protect as
+** PAGE_READONLY
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+#define REGIONSIZE 1024
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ LPVOID lpVirtualAddress;
+ DWORD OldProtect;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ //Allocate the physical storage in memory or in the paging file on disk
+ lpVirtualAddress = VirtualAlloc(NULL,//determine where to allocate the region
+ REGIONSIZE, //specify the size
+ MEM_COMMIT, //allocation type
+ PAGE_READWRITE); //access protection
+ if(NULL == lpVirtualAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API!\n");
+ }
+
+ OldProtect = PAGE_READONLY;
+ //Set new access protection
+ err = VirtualProtect(lpVirtualAddress,
+ REGIONSIZE, //specify the region size
+ PAGE_READONLY,//desied access protection
+ &OldProtect);//old access protection
+ if(0 == err)
+ {
+ Trace("\nFailed to call VirtualProtect API!\n");
+ err = VirtualFree(lpVirtualAddress,REGIONSIZE,MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+ Fail("");
+ }
+
+
+ //decommit the specified region
+ err = VirtualFree(lpVirtualAddress,REGIONSIZE,MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/testinfo.dat
new file mode 100644
index 0000000000..6b6eb58b34
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = VirtualProtect
+Name = Positive test for VirtualProtect - with PAGE_READONLY
+TYPE = DEFAULT
+EXE1 = virtualprotect
+Description
+=Test the VirtualProtect to set new access protection
+=as PAGE_READONLY
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/CMakeLists.txt
new file mode 100644
index 0000000000..4f4e4bc5f0
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ VirtualQuery.c
+)
+
+add_executable(paltest_virtualquery_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_virtualquery_test1 coreclrpal)
+
+target_link_libraries(paltest_virtualquery_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/VirtualQuery.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/VirtualQuery.c
new file mode 100644
index 0000000000..44216ae563
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/VirtualQuery.c
@@ -0,0 +1,68 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: virtualquery.c
+**
+** Purpose: Positive test the VirtualQuery API.
+** Call VirtualQuery to get the virtual
+** page info
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+#define VIRTUALMEMORYSIZE 1024
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ LPVOID lpVirtualAddress;
+ MEMORY_BASIC_INFORMATION PageInfo;
+ DWORD dwBufferSize;
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ //Allocate the physical storage in memory or in the paging file on disk
+ lpVirtualAddress = VirtualAlloc(NULL,//determine where to allocate the region
+ VIRTUALMEMORYSIZE, //specify the size
+ MEM_COMMIT, //allocation type
+ PAGE_READONLY); //access protection
+ if(NULL == lpVirtualAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API!\n");
+ }
+
+ //get the virtual page info
+ dwBufferSize =
+ VirtualQuery(lpVirtualAddress,&PageInfo,sizeof(MEMORY_BASIC_INFORMATION));
+
+ if(dwBufferSize <= 0 ||
+ PageInfo.RegionSize <=0 ||
+ PAGE_READONLY != PageInfo.AllocationProtect ||
+ MEM_COMMIT != PageInfo.State)
+ {
+ Fail("\nFailed to call VirtualQuery API!\n");
+ }
+
+
+
+ //decommit the specified region
+ err = VirtualFree(lpVirtualAddress, //virtual page base address
+ VIRTUALMEMORYSIZE,//specify the size
+ MEM_DECOMMIT);//free operation
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/testinfo.dat
new file mode 100644
index 0000000000..b3462cd2f7
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = VirtualQuery
+Name = Positive test for VirtualQuery API
+TYPE = DEFAULT
+EXE1 = virtualquery
+Description
+=Test the VirtualQuery to get the virtual page info
diff --git a/src/pal/tests/palsuite/loader/CMakeLists.txt b/src/pal/tests/palsuite/loader/CMakeLists.txt
new file mode 100644
index 0000000000..2c213b8426
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(LoadLibraryA)
+add_subdirectory(LoadLibraryW)
+
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/CMakeLists.txt b/src/pal/tests/palsuite/loader/LoadLibraryA/CMakeLists.txt
new file mode 100644
index 0000000000..ff4c550d38
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryA/CMakeLists.txt
@@ -0,0 +1,8 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test5)
+add_subdirectory(test7)
+
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test1/CMakeLists.txt b/src/pal/tests/palsuite/loader/LoadLibraryA/test1/CMakeLists.txt
new file mode 100644
index 0000000000..542f8d3277
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryA/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ LoadLibraryA.c
+)
+
+add_executable(paltest_loadlibrarya_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_loadlibrarya_test1 coreclrpal)
+
+target_link_libraries(paltest_loadlibrarya_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test1/LoadLibraryA.c b/src/pal/tests/palsuite/loader/LoadLibraryA/test1/LoadLibraryA.c
new file mode 100644
index 0000000000..b4a8de1367
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryA/test1/LoadLibraryA.c
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: loadlibrarya.c
+**
+** Purpose: Positive test the LoadLibrary API.
+** Call LoadLibrary to map a module into the calling
+** process address space(DLL file)
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+/* SHLEXT is defined only for Unix variants */
+
+#if defined(SHLEXT)
+#define ModuleName "librotor_pal"SHLEXT
+#else
+#define ModuleName "rotor_pal.dll"
+#endif
+
+int __cdecl main(int argc, char *argv[])
+{
+ HMODULE ModuleHandle;
+ int err;
+
+ /* Initialize the PAL environment */
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ /* load a module */
+ ModuleHandle = LoadLibrary(ModuleName);
+ if(!ModuleHandle)
+ {
+ Fail("Failed to call LoadLibrary API!\n");
+ }
+
+ /* decrement the reference count of the loaded dll */
+ err = FreeLibrary(ModuleHandle);
+ if(0 == err)
+ {
+ Fail("\nFailed to all FreeLibrary API!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test1/testinfo.dat b/src/pal/tests/palsuite/loader/LoadLibraryA/test1/testinfo.dat
new file mode 100644
index 0000000000..096aab958b
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryA/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Loader
+Function = LoadLibraryA
+Name = Positive test for LoadLibraryA API to load Dynamic library module
+TYPE = DEFAULT
+EXE1 = loadlibrarya
+Description
+=Test the LoadLibraryA to map module into calling process address space
+
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test2/CMakeLists.txt b/src/pal/tests/palsuite/loader/LoadLibraryA/test2/CMakeLists.txt
new file mode 100644
index 0000000000..63cfb22545
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryA/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ LoadLibraryA.c
+)
+
+add_executable(paltest_loadlibrarya_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_loadlibrarya_test2 coreclrpal)
+
+target_link_libraries(paltest_loadlibrarya_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test2/LoadLibraryA.c b/src/pal/tests/palsuite/loader/LoadLibraryA/test2/LoadLibraryA.c
new file mode 100644
index 0000000000..d7cd9cb875
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryA/test2/LoadLibraryA.c
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: loadlibrarya.c
+**
+** Purpose: Negative test the LoadLibraryA API.
+** Call LoadLibraryA with a not exist module Name
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ HMODULE ModuleHandle;
+ int err;
+ const char *pModuleName = "Not-exist-module-name";
+
+ /* Initialize the PAL environment */
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+ /*try to load a not exist module */
+ ModuleHandle = LoadLibraryA(pModuleName);
+ if(NULL != ModuleHandle)
+ {
+ Trace("Failed to call LoadLibraryA with a not exist mudule name, "
+ "a NULL module handle is expected, but no NULL module handle "
+ "is returned, error code=%u\n", GetLastError());
+
+ /* decrement the reference count of the loaded module */
+ err = FreeLibrary(ModuleHandle);
+ if(0 == err)
+ {
+ Trace("\nFailed to all FreeLibrary API to decrement "
+ "the reference count of the loaded module, "
+ "error code = %u\n", GetLastError());
+
+ }
+
+ Fail("");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test2/MyModule.c b/src/pal/tests/palsuite/loader/LoadLibraryA/test2/MyModule.c
new file mode 100644
index 0000000000..883b3fbc4a
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryA/test2/MyModule.c
@@ -0,0 +1,19 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: mymoduale.c
+**
+** Purpose: Positive test the LoadLibrary API.
+**
+
+**
+**============================================================*/
+
+int __cdecl main(int argc, char *argv[])
+{
+ //only for testing LoadLibrary
+ return 0;
+}
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test2/testinfo.dat b/src/pal/tests/palsuite/loader/LoadLibraryA/test2/testinfo.dat
new file mode 100644
index 0000000000..97b7222b9e
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryA/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Loader
+Function = LoadLibraryA
+Name = Negative test LoadLibraryA API to load a not exist module
+TYPE = DEFAULT
+EXE1 = loadlibrarya
+Description
+=Test the LoadLibraryA to load a not exist module
+
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test3/CMakeLists.txt b/src/pal/tests/palsuite/loader/LoadLibraryA/test3/CMakeLists.txt
new file mode 100644
index 0000000000..143d0ec096
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryA/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ loadlibrarya.c
+)
+
+add_executable(paltest_loadlibrarya_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_loadlibrarya_test3 coreclrpal)
+
+target_link_libraries(paltest_loadlibrarya_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test3/loadlibrarya.c b/src/pal/tests/palsuite/loader/LoadLibraryA/test3/loadlibrarya.c
new file mode 100644
index 0000000000..da38f98d04
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryA/test3/loadlibrarya.c
@@ -0,0 +1,40 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: loadlibrarya.c
+**
+** Purpose: Negative test the LoadLibrary API with NULL module
+** name.
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ HMODULE ModuleHandle;
+ int err;
+
+ /*Initialize the PAL environment*/
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+ /*load a module by passing a NULL module name*/
+ ModuleHandle = LoadLibraryA(NULL);
+ if(NULL != ModuleHandle)
+ {
+ Fail("\nFailed to call loadlibrarya API for a negative test, "
+ "call loadibrarya with NULL moudle name, a NULL module "
+ "handle is expected, but no NULL module handle is returned, "
+ "error code =%u\n", GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test3/testinfo.dat b/src/pal/tests/palsuite/loader/LoadLibraryA/test3/testinfo.dat
new file mode 100644
index 0000000000..c27c8e0eea
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryA/test3/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Loader
+Function = LoadLibraryA
+Name = Negative test LoadLibraryA API with a NULL module name
+TYPE = DEFAULT
+EXE1 = loadlibrarya
+Description
+=Test the LoadLibraryA to map NULL module into calling
+=process address space
+
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test5/CMakeLists.txt b/src/pal/tests/palsuite/loader/LoadLibraryA/test5/CMakeLists.txt
new file mode 100644
index 0000000000..a9d791c916
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryA/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ loadlibrarya.c
+)
+
+add_executable(paltest_loadlibrarya_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_loadlibrarya_test5 coreclrpal)
+
+target_link_libraries(paltest_loadlibrarya_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test5/loadlibrarya.c b/src/pal/tests/palsuite/loader/LoadLibraryA/test5/loadlibrarya.c
new file mode 100644
index 0000000000..d1e6b6d1dc
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryA/test5/loadlibrarya.c
@@ -0,0 +1,67 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: loadlibrarya.c
+**
+** Purpose: Negative test the LoadLibraryA API.
+** Call LoadLibraryA by passing a module name
+** without extension but with a trailing dot.
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ HMODULE ModuleHandle;
+ char ModuleName[_MAX_FNAME];
+ int err;
+
+ /* Initialize the PAL environment */
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+ memset(ModuleName, 0, _MAX_FNAME);
+
+ /*Module name without extension but with a trailing dot*/
+#if WIN32
+ sprintf(ModuleName, "%s", "rotor_pal.");
+#else
+ /* Under FreeBSD */
+ sprintf(ModuleName, "%s", "librotor_pal.");
+#endif
+
+ /* load a module which does not have the file extension,
+ * but has a trailing dot
+ */
+ ModuleHandle = LoadLibraryA(ModuleName);
+ if(NULL != ModuleHandle)
+ {
+ Trace("Failed to call LoadLibraryA API for a negative test "
+ "call LoadLibraryA with module name which does not have "
+ "extension except a trailing dot, a NULL module handle is"
+ "expected, but no NULL module handle is returned, "
+ "error code = %u\n", GetLastError());
+
+
+ /* decrement the reference count of the loaded dll */
+ err = FreeLibrary(ModuleHandle);
+ if(0 == err)
+ {
+ Trace("\nFailed to call FreeLibrary API, "
+ "error code = %u\n", GetLastError());
+ }
+
+ Fail("");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test5/testinfo.dat b/src/pal/tests/palsuite/loader/LoadLibraryA/test5/testinfo.dat
new file mode 100644
index 0000000000..e2cd16c6f1
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryA/test5/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Loader
+Function = LoadLibraryA
+Name = Negative test for LoadLibraryA API by passing a module name without extension but with a trailing dot.
+TYPE = DEFAULT
+EXE1 = loadlibrarya
+Description
+=Test the LoadLibraryA by passing a module name without extension
+=but with a trailing dot.
+
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test6/CMakeLists.txt b/src/pal/tests/palsuite/loader/LoadLibraryA/test6/CMakeLists.txt
new file mode 100644
index 0000000000..bb66adef77
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryA/test6/CMakeLists.txt
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(TESTSOURCES
+ loadlibrarya.c
+)
+
+add_executable(paltest_loadlibrarya_test6
+ ${TESTSOURCES}
+)
+
+add_dependencies(paltest_loadlibrarya_test6 coreclrpal)
+
+target_link_libraries(paltest_loadlibrarya_test6
+ pthread
+ m
+ coreclrpal
+)
+
+
+set(HELPERSOURCES
+ dlltest.c
+)
+
+add_executable(paltest_loadlibrarya_test6_dlltest
+ ${HELPERSOURCES}
+)
+
+add_dependencies(paltest_loadlibrarya_test6_dlltest coreclrpal)
+
+target_link_libraries(paltest_loadlibrarya_test6_dlltest
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test6/dlltest.c b/src/pal/tests/palsuite/loader/LoadLibraryA/test6/dlltest.c
new file mode 100644
index 0000000000..72380eebb5
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryA/test6/dlltest.c
@@ -0,0 +1,72 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: dllmain.c
+**
+** Purpose: Test to ensure DllMain() is called with DLL_THREAD_DETACH
+** only the initial time that the library is loaded.
+**
+** Depends: None
+**
+
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+/* count of the number of times DllMain()
+ * was called with THREAD_ATTACH.
+ */
+static int g_attachCount = 0;
+
+/* standard DllMain() */
+BOOL __stdcall DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID lpvReserved)
+{
+ switch( reason )
+ {
+ case DLL_PROCESS_ATTACH:
+ {
+ g_attachCount++;
+ break;
+ }
+
+ case DLL_PROCESS_DETACH:
+ {
+ break;
+ }
+
+ case DLL_THREAD_ATTACH:
+ {
+ break;
+ }
+
+ case DLL_THREAD_DETACH:
+ {
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
+#if _WIN32
+BOOL __stdcall _DllMainCRTStartup(HINSTANCE hinstDLL, DWORD reason, LPVOID lpvReserved)
+{
+ return DllMain(hinstDLL, reason, lpvReserved);
+}
+#endif
+
+
+
+/* function to return the current attach count */
+#if _WIN32
+__declspec(dllexport)
+#endif
+int PALAPI GetAttachCount( void )
+{
+ return g_attachCount;
+}
+
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test6/loadlibrarya.c b/src/pal/tests/palsuite/loader/LoadLibraryA/test6/loadlibrarya.c
new file mode 100644
index 0000000000..ee825e6439
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryA/test6/loadlibrarya.c
@@ -0,0 +1,172 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: loadlibrary.c (test 6)
+**
+** Purpose: Positive test the LoadLibrary API. Test will verify
+** that it is unable to load the library twice. Once by
+** using the full path name and secondly by using the
+** short name.
+**
+
+**
+**============================================================*/
+#include <palsuite.h>
+
+/*Define platform specific information*/
+#if defined(SHLEXT)
+#define LibraryName "dlltest"SHLEXT
+#define GETATTACHCOUNTNAME "GetAttachCount"
+#else
+typedef int (*dllfunct)();
+#define LibraryName "dlltest.dll"
+#define GETATTACHCOUNTNAME "_GetAttachCount@0"
+#endif
+
+
+/* Helper function to test the loaded library.
+ */
+BOOL PALAPI TestDll(HMODULE hLib)
+{
+ int RetVal;
+ char FunctName[] = GETATTACHCOUNTNAME;
+ FARPROC DllFunc;
+
+ /* Access a function from the loaded library.
+ */
+ DllFunc = GetProcAddress(hLib, FunctName);
+ if(DllFunc == NULL)
+ {
+ Trace("ERROR: Unable to load function \"%s\" from library \"%s\"\n",
+ FunctName,
+ LibraryName);
+ return (FALSE);
+ }
+
+ /* Verify that the DLL_PROCESS_ATTACH is only
+ * accessed once.*/
+ RetVal = DllFunc();
+ if (RetVal != 1)
+ {
+ Trace("ERROR: Unable to receive correct information from DLL! "
+ ":expected \"1\", returned \"%d\"\n",
+ RetVal);
+ return (FALSE);
+ }
+
+ return (TRUE);
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE hFullLib;
+ HANDLE hShortLib;
+ int iRetVal = FAIL;
+ char fullPath[_MAX_DIR];
+ char drive[_MAX_DRIVE];
+ char dir[_MAX_DIR];
+ char fname[_MAX_FNAME];
+ char ext[_MAX_EXT];
+
+
+
+ /* Initialize the PAL. */
+ if ((PAL_Initialize(argc, argv)) != 0)
+ {
+ return (FAIL);
+ }
+
+ /* Initalize the buffer.
+ */
+ memset(fullPath, 0, _MAX_DIR);
+
+ /* Get the full path to the library (DLL).
+ */
+
+ if (NULL != _fullpath(fullPath,argv[0],_MAX_DIR)) {
+
+ _splitpath(fullPath,drive,dir,fname,ext);
+ _makepath(fullPath,drive,dir,LibraryName,"");
+
+
+ } else {
+ Fail("ERROR: conversion from relative path \" %s \" to absolute path failed. _fullpath returned NULL\n",argv[0]);
+ }
+
+ /* Call Load library with the short name of
+ * the dll.
+ */
+ hShortLib = LoadLibrary(LibraryName);
+ if(hShortLib == NULL)
+ {
+ Fail("ERROR:%u:Unable to load library %s\n",
+ GetLastError(),
+ LibraryName);
+ }
+
+ /* Test the loaded library.
+ */
+ if (!TestDll(hShortLib))
+ {
+ iRetVal = FAIL;
+ goto cleanUpOne;
+ }
+
+ /* Call Load library with the full name of
+ * the dll.
+ */
+ hFullLib = LoadLibrary(fullPath);
+ if(hFullLib == NULL)
+ {
+ Trace("ERROR:%u:Unable to load library %s\n",
+ GetLastError(),
+ fullPath);
+ iRetVal = FAIL;
+ goto cleanUpTwo;
+ }
+
+ /* Test the loaded library.
+ */
+ if (!TestDll(hFullLib))
+ {
+ iRetVal = FAIL;
+ goto cleanUpTwo;
+ }
+
+ /* Test Succeeded.
+ */
+ iRetVal = PASS;
+
+cleanUpTwo:
+
+ /* Call the FreeLibrary API.
+ */
+ if (!FreeLibrary(hFullLib))
+ {
+ Trace("ERROR:%u: Unable to free library \"%s\"\n",
+ GetLastError(),
+ fullPath);
+ iRetVal = FAIL;
+ }
+
+cleanUpOne:
+
+ /* Call the FreeLibrary API.
+ */
+ if (!FreeLibrary(hShortLib))
+ {
+ Trace("ERROR:%u: Unable to free library \"%s\"\n",
+ GetLastError(),
+ LibraryName);
+ iRetVal = FAIL;
+ }
+
+ /* Terminate the PAL.
+ */
+ PAL_Terminate();
+ return iRetVal;
+
+}
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test6/testinfo.dat b/src/pal/tests/palsuite/loader/LoadLibraryA/test6/testinfo.dat
new file mode 100644
index 0000000000..4be93b8092
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryA/test6/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Loader
+Function = LoadLibraryA
+Name = Positive test for LoadLibrary API
+TYPE = DEFAULT
+EXE1 = loadlibrarya
+LIB1 = dlltest
+Description
+= Positive test the LoadLibrary API. Test will verify
+= that it is unable to load the library twice. Once by
+= using the full path name and secondly by using the
+= short name.
+
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test7/CMakeLists.txt b/src/pal/tests/palsuite/loader/LoadLibraryA/test7/CMakeLists.txt
new file mode 100644
index 0000000000..6c0d174600
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryA/test7/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ LoadLibraryA.c
+)
+
+add_executable(paltest_loadlibrarya_test7
+ ${SOURCES}
+)
+
+add_dependencies(paltest_loadlibrarya_test7 coreclrpal)
+
+target_link_libraries(paltest_loadlibrarya_test7
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test7/LoadLibraryA.c b/src/pal/tests/palsuite/loader/LoadLibraryA/test7/LoadLibraryA.c
new file mode 100644
index 0000000000..5e6db8bb68
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryA/test7/LoadLibraryA.c
@@ -0,0 +1,83 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: loadlibrarya.c
+**
+** Purpose: Positive test the LoadLibrary API by calling it multiple times.
+** Call LoadLibrary to map a module into the calling
+** process address space(DLL file)
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+/* SHLEXT is defined only for Unix variants */
+
+#if defined(SHLEXT)
+#define ModuleName "librotor_pal"SHLEXT
+#else
+#define ModuleName "rotor_pal.dll"
+#endif
+
+int __cdecl main(int argc, char *argv[])
+{
+ HMODULE ModuleHandle;
+ HMODULE ReturnHandle;
+ int err;
+
+ /* Initialize the PAL environment */
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ /* load a module */
+ ModuleHandle = LoadLibrary(ModuleName);
+ if(!ModuleHandle)
+ {
+ Fail("Error[%u]:Failed to call LoadLibrary API!\n", GetLastError());
+ }
+
+ /* Call LoadLibrary again, should return same handle as returned for first time */
+ ReturnHandle = LoadLibrary(ModuleName);
+ if(!ReturnHandle)
+ {
+ Fail("Error[%u]:Failed to call LoadLibrary API second time!\n", GetLastError());
+ }
+
+ if(ModuleHandle != ReturnHandle)
+ {
+ Fail("Error[%u]:Failed to return the same handle while calling LoadLibrary API twice!\n", GetLastError());
+ }
+
+ Trace("Value of handle ModuleHandle[%x], ReturnHandle[%x]\n", ModuleHandle, ReturnHandle);
+ /* decrement the reference count of the loaded dll */
+ err = FreeLibrary(ModuleHandle);
+
+ if(0 == err)
+ {
+ Fail("Error[%u]:Failed to FreeLibrary API!\n", GetLastError());
+ }
+
+ /* Try Freeing a library again, should not fail */
+ err = FreeLibrary(ReturnHandle);
+
+ if(0 == err)
+ {
+ Fail("Error[%u][%d]: Was not successful in freeing a Library twice using FreeLibrary!\n", GetLastError(), err);
+ }
+
+ /* Try Freeing a library again, should fail */
+ err = FreeLibrary(ReturnHandle);
+
+ if(1 != err)
+ {
+ Fail("Error[%u][%d]: Was successful in freeing a Library thrice using FreeLibrary!\n", GetLastError(), err);
+ }
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test7/testinfo.dat b/src/pal/tests/palsuite/loader/LoadLibraryA/test7/testinfo.dat
new file mode 100644
index 0000000000..416caf34fb
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryA/test7/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Loader
+Function = LoadLibraryA
+Name = Positive and Negative test for LoadLibraryA API to load Dynamic library module
+TYPE = DEFAULT
+EXE1 = loadlibrarya
+Description
+=Test the LoadLibraryA to load multiple times and call unload more times than load
+
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test8/CMakeLists.txt b/src/pal/tests/palsuite/loader/LoadLibraryA/test8/CMakeLists.txt
new file mode 100644
index 0000000000..b663a7b5bc
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryA/test8/CMakeLists.txt
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(TESTSOURCES
+ loadlibrarya.c
+)
+
+add_executable(paltest_loadlibrarya_test8
+ ${TESTSOURCES}
+)
+
+add_dependencies(paltest_loadlibrarya_test8 coreclrpal)
+
+target_link_libraries(paltest_loadlibrarya_test8
+ pthread
+ m
+ coreclrpal
+)
+
+
+set(HELPERSOURCES
+ dlltest.c
+)
+
+add_executable(paltest_loadlibrarya_test8_dlltest
+ ${HELPERSOURCES}
+)
+
+add_dependencies(paltest_loadlibrarya_test8_dlltest coreclrpal)
+
+target_link_libraries(paltest_loadlibrarya_test8_dlltest
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test8/dlltest.c b/src/pal/tests/palsuite/loader/LoadLibraryA/test8/dlltest.c
new file mode 100644
index 0000000000..72380eebb5
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryA/test8/dlltest.c
@@ -0,0 +1,72 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: dllmain.c
+**
+** Purpose: Test to ensure DllMain() is called with DLL_THREAD_DETACH
+** only the initial time that the library is loaded.
+**
+** Depends: None
+**
+
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+/* count of the number of times DllMain()
+ * was called with THREAD_ATTACH.
+ */
+static int g_attachCount = 0;
+
+/* standard DllMain() */
+BOOL __stdcall DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID lpvReserved)
+{
+ switch( reason )
+ {
+ case DLL_PROCESS_ATTACH:
+ {
+ g_attachCount++;
+ break;
+ }
+
+ case DLL_PROCESS_DETACH:
+ {
+ break;
+ }
+
+ case DLL_THREAD_ATTACH:
+ {
+ break;
+ }
+
+ case DLL_THREAD_DETACH:
+ {
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
+#if _WIN32
+BOOL __stdcall _DllMainCRTStartup(HINSTANCE hinstDLL, DWORD reason, LPVOID lpvReserved)
+{
+ return DllMain(hinstDLL, reason, lpvReserved);
+}
+#endif
+
+
+
+/* function to return the current attach count */
+#if _WIN32
+__declspec(dllexport)
+#endif
+int PALAPI GetAttachCount( void )
+{
+ return g_attachCount;
+}
+
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test8/loadlibrarya.c b/src/pal/tests/palsuite/loader/LoadLibraryA/test8/loadlibrarya.c
new file mode 100644
index 0000000000..6556e9c896
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryA/test8/loadlibrarya.c
@@ -0,0 +1,235 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: loadlibrary.c (test 8)
+**
+** Purpose: Positive test the LoadLibrary API. Test will verify
+** that it is unable to load the library twice. Once by
+** using the full path name and secondly by using the
+** short name.
+**
+
+**
+**============================================================*/
+#include <palsuite.h>
+
+/*Define platform specific information*/
+#if defined(SHLEXT)
+#define LibraryName "dlltest"SHLEXT
+#define GETATTACHCOUNTNAME "GetAttachCount"
+#else
+typedef int (*dllfunct)();
+#define LibraryName "dlltest.dll"
+#define GETATTACHCOUNTNAME "_GetAttachCount@0"
+#endif
+
+
+/* Helper function to test the loaded library.
+ */
+BOOL PALAPI TestDll(HMODULE hLib)
+{
+ int RetVal;
+ char FunctName[] = GETATTACHCOUNTNAME;
+ FARPROC DllFunc;
+
+ /* Access a function from the loaded library.
+ */
+ DllFunc = GetProcAddress(hLib, FunctName);
+ if(DllFunc == NULL)
+ {
+ Trace("ERROR: Unable to load function \"%s\" from library \"%s\"\n",
+ FunctName,
+ LibraryName);
+ return (FALSE);
+ }
+
+ /* Verify that the DLL_PROCESS_ATTACH is only
+ * accessed once.*/
+ RetVal = DllFunc();
+ if (RetVal != 1)
+ {
+ Trace("ERROR: Unable to receive correct information from DLL! "
+ ":expected \"1\", returned \"%d\"\n",
+ RetVal);
+ return (FALSE);
+ }
+
+ return (TRUE);
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ HANDLE hFullLib;
+ HANDLE hShortLib;
+ HANDLE hRelLib;
+
+ int iRetVal = FAIL;
+ char fullPath[_MAX_DIR];
+ char drive[_MAX_DRIVE];
+ char dir[_MAX_DIR];
+ char relTestDir[_MAX_DIR];
+ char fname[_MAX_FNAME];
+ char ext[_MAX_EXT];
+
+ BOOL bRc = FALSE;
+ char relLibPath[_MAX_DIR];
+
+
+ /* Initialize the PAL. */
+ if ((PAL_Initialize(argc, argv)) != 0)
+ {
+ return (FAIL);
+ }
+
+ /* Initalize the buffer.
+ */
+ memset(fullPath, 0, _MAX_DIR);
+
+ /* Get the full path to the library (DLL).
+ */
+
+ if (NULL != _fullpath(fullPath,argv[0],_MAX_DIR)) {
+
+ _splitpath(fullPath,drive,dir,fname,ext);
+ _makepath(fullPath,drive,dir,LibraryName,"");
+
+
+ } else {
+ Fail("ERROR: conversion from relative path \" %s \" to absolute path failed. _fullpath returned NULL\n",argv[0]);
+ }
+
+ /* Get relative path to the library
+ */
+ _splitpath(argv[0], drive, relTestDir, fname, ext);
+ _makepath(relLibPath,drive,relTestDir,LibraryName,"");
+
+
+ /* Call Load library with the short name of
+ * the dll.
+ */
+ hShortLib = LoadLibrary(LibraryName);
+ if(hShortLib == NULL)
+ {
+ Fail("ERROR:%u:Short:Unable to load library %s\n",
+ GetLastError(),
+ LibraryName);
+ }
+
+ /* Test the loaded library.
+ */
+ if (!TestDll(hShortLib))
+ {
+ iRetVal = FAIL;
+ goto cleanUpOne;
+ }
+
+ /* Call Load library with the full name of
+ * the dll.
+ */
+ hFullLib = LoadLibrary(fullPath);
+ if(hFullLib == NULL)
+ {
+ Trace("ERROR:%u:Full:Unable to load library %s\n",
+ GetLastError(),
+ fullPath);
+ iRetVal = FAIL;
+ goto cleanUpTwo;
+ }
+
+ /* Test the loaded library.
+ */
+ if (!TestDll(hFullLib))
+ {
+ iRetVal = FAIL;
+ goto cleanUpTwo;
+ }
+
+ /*
+ ** Call the load library with the relative path
+ ** wrt to the directory ./testloadlibrary/..
+ ** since we don't want to make any assumptions
+ ** regarding the type of build
+ */
+ hRelLib = LoadLibrary(relLibPath);
+ if(hRelLib == NULL)
+ {
+ Trace("ERROR:%u:Rel:Unable to load library at %s\n",
+ GetLastError(), relLibPath);
+ iRetVal = FAIL;
+ goto cleanUpTwo;
+ }
+
+ /* Test the loaded library.
+ */
+ if (!TestDll(hRelLib))
+ {
+ iRetVal = FAIL;
+ goto cleanUpThree;
+ }
+
+ if( hRelLib != hFullLib )
+ {
+ Trace("Relative and Absolute Paths to libraries don't have same handle\n");
+ iRetVal = FAIL;
+ goto cleanUpThree;
+ }
+
+ if( hRelLib != hShortLib )
+ {
+ Trace("Relative and Short Paths to libraries don't have same handle\n");
+ iRetVal = FAIL;
+ goto cleanUpThree;
+ }
+
+
+ /* Test Succeeded.
+ */
+ iRetVal = PASS;
+
+cleanUpThree:
+
+ /* Call the FreeLibrary API.
+ */
+
+ if (!FreeLibrary(hRelLib))
+ {
+ Trace("ERROR:%u: Unable to free library \"%s\"\n",
+ GetLastError(),
+ relLibPath);
+ iRetVal = FAIL;
+ }
+
+cleanUpTwo:
+
+ /* Call the FreeLibrary API.
+ */
+ if (!FreeLibrary(hFullLib))
+ {
+ Trace("ERROR:%u: Unable to free library \"%s\"\n",
+ GetLastError(),
+ fullPath);
+ iRetVal = FAIL;
+ }
+
+cleanUpOne:
+
+ /* Call the FreeLibrary API.
+ */
+ if (!FreeLibrary(hShortLib))
+ {
+ Trace("ERROR:%u: Unable to free library \"%s\"\n",
+ GetLastError(),
+ LibraryName);
+ iRetVal = FAIL;
+ }
+
+
+ /* Terminate the PAL.
+ */
+ PAL_TerminateEx(iRetVal);
+ return iRetVal;
+
+}
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test8/testinfo.dat b/src/pal/tests/palsuite/loader/LoadLibraryA/test8/testinfo.dat
new file mode 100644
index 0000000000..b552b72082
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryA/test8/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Loader
+Function = LoadLibraryA
+Name = Positive test for LoadLibrary API
+TYPE = DEFAULT
+EXE1 = loadlibrarya
+LIB1 = dlltest
+Description
+= Positive test the LoadLibrary API. Test will verify
+= that it is able to load the library thrice. Once by
+= using the full path name, second by using the
+= short name and third by using relative paths
+
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryW/CMakeLists.txt b/src/pal/tests/palsuite/loader/LoadLibraryW/CMakeLists.txt
new file mode 100644
index 0000000000..37abc032af
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryW/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test5)
+
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryW/test1/CMakeLists.txt b/src/pal/tests/palsuite/loader/LoadLibraryW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..87038012b7
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ LoadLibraryW.c
+)
+
+add_executable(paltest_loadlibraryw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_loadlibraryw_test1 coreclrpal)
+
+target_link_libraries(paltest_loadlibraryw_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryW/test1/LoadLibraryW.c b/src/pal/tests/palsuite/loader/LoadLibraryW/test1/LoadLibraryW.c
new file mode 100644
index 0000000000..4c1a551de1
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryW/test1/LoadLibraryW.c
@@ -0,0 +1,62 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: loadlibraryw.c
+**
+** Purpose: Positive test the LoadLibrary API.
+** Call LoadLibrary to map a module into the calling
+** process address space(DLL file)
+**
+**
+**============================================================*/
+#define UNICODE
+#include <palsuite.h>
+/* SHLEXT is defined only for Unix variants */
+
+#if defined(SHLEXT)
+#define ModuleName "librotor_pal"SHLEXT
+#else
+#define ModuleName "rotor_pal.dll"
+#endif
+
+int __cdecl main(int argc, char *argv[])
+{
+ HMODULE ModuleHandle;
+ int err;
+ WCHAR *lpModuleName;
+
+ /* Initialize the PAL environment */
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ /* convert a normal string to a wide one */
+ lpModuleName = convert(ModuleName);
+
+ /* load a module */
+ ModuleHandle = LoadLibrary(lpModuleName);
+
+ /* free the memory */
+ free(lpModuleName);
+
+ if(!ModuleHandle)
+ {
+ Fail("Failed to call LoadLibrary API!\n");
+ }
+
+
+ /* decrement the reference count of the loaded dll */
+ err = FreeLibrary(ModuleHandle);
+ if(0 == err)
+ {
+ Fail("\nFailed to all FreeLibrary API!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryW/test1/testinfo.dat b/src/pal/tests/palsuite/loader/LoadLibraryW/test1/testinfo.dat
new file mode 100644
index 0000000000..c5c4adc75a
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryW/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Loader
+Function = LoadLibraryW
+Name = Positive test for LoadLibraryW API to load a dynamic library module
+TYPE = DEFAULT
+EXE1 = loadlibraryw
+Description
+=Test the LoadLibraryW to map module into calling process address space
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryW/test2/CMakeLists.txt b/src/pal/tests/palsuite/loader/LoadLibraryW/test2/CMakeLists.txt
new file mode 100644
index 0000000000..5e8486d23b
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryW/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ loadlibraryw.c
+)
+
+add_executable(paltest_loadlibraryw_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_loadlibraryw_test2 coreclrpal)
+
+target_link_libraries(paltest_loadlibraryw_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryW/test2/loadlibraryw.c b/src/pal/tests/palsuite/loader/LoadLibraryW/test2/loadlibraryw.c
new file mode 100644
index 0000000000..e8aebf77e9
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryW/test2/loadlibraryw.c
@@ -0,0 +1,62 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: loadlibraryw.c
+**
+** Purpose: Negative test the LoadLibraryW API.
+** Call LoadLibraryW with a not exist module Name
+**
+**
+**============================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ HMODULE ModuleHandle;
+ int err;
+ WCHAR *pwModuleName;
+ const char *pModuleName = "Not-exist-module-name";
+
+ /* Initialize the PAL environment */
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+ /* convert a normal string to a wide one */
+ pwModuleName = convert((char *)pModuleName);
+
+
+ /*try to load a not exist module */
+ ModuleHandle = LoadLibraryW(pwModuleName);
+
+ /* free the memory */
+ free(pwModuleName);
+
+ if(NULL != ModuleHandle)
+ {
+ Trace("Failed to call LoadLibraryW with a not exist mudule name, "
+ "a NULL module handle is expected, but no NULL module handle "
+ "is returned, error code=%u\n", GetLastError());
+
+ /* decrement the reference count of the loaded module */
+ err = FreeLibrary(ModuleHandle);
+ if(0 == err)
+ {
+ Trace("\nFailed to all FreeLibrary API to decrement "
+ "the reference count of the loaded module, "
+ "error code = %u\n", GetLastError());
+
+ }
+
+ Fail("");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryW/test2/testinfo.dat b/src/pal/tests/palsuite/loader/LoadLibraryW/test2/testinfo.dat
new file mode 100644
index 0000000000..bc107f0069
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryW/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Loader
+Function = LoadLibraryW
+Name = Negative test LoadLibraryW API to load a not exist module
+TYPE = DEFAULT
+EXE1 = loadlibraryw
+Description
+=Test the LoadLibraryW to load a not exist module
+
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryW/test3/CMakeLists.txt b/src/pal/tests/palsuite/loader/LoadLibraryW/test3/CMakeLists.txt
new file mode 100644
index 0000000000..2c96fa23da
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryW/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ loadlibraryw.c
+)
+
+add_executable(paltest_loadlibraryw_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_loadlibraryw_test3 coreclrpal)
+
+target_link_libraries(paltest_loadlibraryw_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryW/test3/loadlibraryw.c b/src/pal/tests/palsuite/loader/LoadLibraryW/test3/loadlibraryw.c
new file mode 100644
index 0000000000..c722edaf13
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryW/test3/loadlibraryw.c
@@ -0,0 +1,41 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: loadlibraryw.c
+**
+** Purpose: Negative test the loadlibraryw API.
+** Call loadlibraryw with NULL module name
+**
+**
+**============================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ HMODULE ModuleHandle;
+ int err;
+
+ /* Initialize the PAL environment */
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+ /* load a module with a NULL module name */
+ ModuleHandle = LoadLibraryW(NULL);
+ if(NULL != ModuleHandle)
+ {
+ Fail("\nFailed to call loadlibraryw API for a negative test, "
+ "call loadibraryw with NULL moudle name, a NULL module "
+ "handle is expected, but no NULL module handle is returned, "
+ "error code =%u\n", GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryW/test3/testinfo.dat b/src/pal/tests/palsuite/loader/LoadLibraryW/test3/testinfo.dat
new file mode 100644
index 0000000000..bd20aaf995
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryW/test3/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Loader
+Function = LoadLibraryW
+Name = Negative test loadlibraryw API with a NULL module name
+TYPE = DEFAULT
+EXE1 = loadlibraryw
+Description
+=Test the LoadLibraryW with a NULL module name
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryW/test5/CMakeLists.txt b/src/pal/tests/palsuite/loader/LoadLibraryW/test5/CMakeLists.txt
new file mode 100644
index 0000000000..7b8931a961
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryW/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ loadlibraryw.c
+)
+
+add_executable(paltest_loadlibraryw_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_loadlibraryw_test5 coreclrpal)
+
+target_link_libraries(paltest_loadlibraryw_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryW/test5/loadlibraryw.c b/src/pal/tests/palsuite/loader/LoadLibraryW/test5/loadlibraryw.c
new file mode 100644
index 0000000000..acaa200a06
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryW/test5/loadlibraryw.c
@@ -0,0 +1,71 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: loadlibraryw.c
+**
+** Purpose: Negative test the LoadLibraryW API.
+** Call LoadLibraryW by passing a module name
+** without extension but with a trailing dot.
+**
+**
+**============================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ HMODULE ModuleHandle;
+ int err;
+ WCHAR *lpModuleName;
+ char ModuleName[_MAX_FNAME];
+
+ /* Initialize the PAL environment */
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+ memset(ModuleName, 0, _MAX_FNAME);
+
+ /*Module name without extension but with a trailing dot*/
+#if WIN32
+ sprintf(ModuleName,"%s","rotor_pal.");
+#else
+ sprintf(ModuleName,"%s","librotor_pal.");
+#endif
+
+ /* convert a normal string to a wide one */
+ lpModuleName = convert(ModuleName);
+
+ /* load a module */
+ ModuleHandle = LoadLibraryW(lpModuleName);
+
+ /* free the memory */
+ free(lpModuleName);
+
+ if(NULL != ModuleHandle)
+ {
+ Trace("Failed to call LoadLibraryW API for a negative test "
+ "call LoadLibraryW with module name which does not have "
+ "extension except a trailing dot, a NULL module handle is"
+ "expected, but no NULL module handle is returned, "
+ "error code = %u\n", GetLastError());
+
+ /* decrement the reference count of the loaded dll */
+ err = FreeLibrary(ModuleHandle);
+ if(0 == err)
+ {
+ Trace("\nFailed to call FreeLibrary API, "
+ "error code = %u\n", GetLastError());
+ }
+
+ Fail("");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/loader/LoadLibraryW/test5/testinfo.dat b/src/pal/tests/palsuite/loader/LoadLibraryW/test5/testinfo.dat
new file mode 100644
index 0000000000..8275f41644
--- /dev/null
+++ b/src/pal/tests/palsuite/loader/LoadLibraryW/test5/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Loader
+Function = LoadLibraryw
+Name = Negative test for LoadLibraryW API by passing a module name without extension but with a trailing dot.
+TYPE = DEFAULT
+EXE1 = loadlibraryw
+Description
+=Test the LoadLibraryW by passing a module name without extension
+=but with a trailing dot.
+
diff --git a/src/pal/tests/palsuite/locale_info/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/CMakeLists.txt
new file mode 100644
index 0000000000..52482daa41
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/CMakeLists.txt
@@ -0,0 +1,26 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+# TODO: make the following tests compile if they are needed
+# add_subdirectory(CompareStringA)
+# add_subdirectory(CompareStringW)
+# add_subdirectory(GetLocaleInfoW)
+# add_subdirectory(GetStringTypeExW)
+# add_subdirectory(GetSystemDefaultLangID)
+# add_subdirectory(GetThreadLocale)
+# add_subdirectory(GetTimeZoneInformation)
+# add_subdirectory(GetUserDefaultLangID)
+# add_subdirectory(GetUserDefaultLCID)
+# add_subdirectory(IsValidLocale)
+# add_subdirectory(SetThreadLocale)
+
+add_subdirectory(GetACP)
+add_subdirectory(GetCPInfo)
+add_subdirectory(IsDBCSLeadByte)
+add_subdirectory(IsDBCSLeadByteEx)
+add_subdirectory(IsValidCodePage)
+add_subdirectory(MultiByteToWideChar)
+add_subdirectory(WideCharToMultiByte)
+
+
+
+
diff --git a/src/pal/tests/palsuite/locale_info/CompareStringA/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/CompareStringA/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/CompareStringA/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/locale_info/CompareStringA/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/CompareStringA/test1/CMakeLists.txt
new file mode 100644
index 0000000000..96ee18d857
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/CompareStringA/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_comparestringa_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_comparestringa_test1 coreclrpal)
+
+target_link_libraries(paltest_comparestringa_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/locale_info/CompareStringA/test1/test1.c b/src/pal/tests/palsuite/locale_info/CompareStringA/test1/test1.c
new file mode 100644
index 0000000000..98c147af48
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/CompareStringA/test1/test1.c
@@ -0,0 +1,99 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests that CompareStringA returns the correct value and can handle
+** invalid parameters.
+**
+**
+**==========================================================================*/
+
+#define CSTR_LESS_THAN 1
+#define CSTR_EQUAL 2
+#define CSTR_GREATER_THAN 3
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ char str1[] = {'f','o','o',0};
+ char str2[] = {'f','o','o','x',0};
+ char str3[] = {'f','O','o',0};
+ int flags = NORM_IGNORECASE | NORM_IGNOREWIDTH;
+ int ret;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ ret = CompareStringA(0x0409, flags, str1, -1, str2, -1);
+ if (ret != CSTR_LESS_THAN)
+ {
+ Fail("CompareStringA with \"%S\" (%d) and \"%S\" (%d) did not return "
+ "CSTR_LESS_THAN!\n", str1, -1, str2, -1);
+ }
+
+ ret = CompareStringA(0x0409, flags, str1, -1, str2, 3);
+ if (ret != CSTR_EQUAL)
+ {
+ Fail("CompareStringA with \"%S\" (%d) and \"%S\" (%d) did not return "
+ "CSTR_EQUAL!\n", str1, -1, str2, 3);
+ }
+
+ ret = CompareStringA(0x0409, flags, str2, -1, str1, -1);
+ if (ret != CSTR_GREATER_THAN)
+ {
+ Fail("CompareStringA with \"%S\" (%d) and \"%S\" (%d) did not return "
+ "CSTR_GREATER_THAN!\n", str2, -1, str1, -1);
+ }
+
+ ret = CompareStringA(0x0409, flags, str1, -1, str3, -1);
+ if (ret != CSTR_EQUAL)
+ {
+ Fail("CompareStringA with \"%S\" (%d) and \"%S\" (%d) did not return "
+ "CSTR_EQUAL!\n", str1, -1, str3, -1);
+ }
+
+ ret = CompareStringA(0x0409, flags, str3, -1, str1, -1);
+ if (ret != CSTR_EQUAL)
+ {
+ Fail("CompareStringA with \"%S\" (%d) and \"%S\" (%d) did not return "
+ "CSTR_EQUAL!\n", str3, -1, str1, -1);
+ }
+
+ ret = CompareStringA(0x0409, flags, str3, -1, str1, -1);
+ if (ret != CSTR_EQUAL)
+ {
+ Fail("CompareStringA with \"%S\" (%d) and \"%S\" (%d) did not return "
+ "CSTR_EQUAL!\n", str3, -1, str1, -1);
+ }
+
+ ret = CompareStringA(0x0409, flags, str1, 0, str3, -1);
+ if (ret != CSTR_LESS_THAN)
+ {
+ Fail("CompareStringA with \"%S\" (%d) and \"%S\" (%d) did not return "
+ "CSTR_GREATER_THAN!\n", str1, 0, str3, -1);
+ }
+
+
+ ret = CompareStringA(0x0409, flags, NULL, -1, str3, -1);
+ if (ret != 0)
+ {
+ Fail("CompareStringA should have returned 0, got %d!\n", ret);
+ }
+ if (GetLastError() != ERROR_INVALID_PARAMETER)
+ {
+ Fail("CompareStringA should have set the last error to "
+ "ERROR_INVALID_PARAMETER!\n");
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/locale_info/CompareStringA/test1/testinfo.dat b/src/pal/tests/palsuite/locale_info/CompareStringA/test1/testinfo.dat
new file mode 100644
index 0000000000..e934b13763
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/CompareStringA/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Locale Information
+Function = CompareStringA
+Name = Test #1 for CompareStringA
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Tests that CompareStringA returns the correct value and can handle
+=invalid parameters.
diff --git a/src/pal/tests/palsuite/locale_info/CompareStringW/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/CompareStringW/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/CompareStringW/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/locale_info/CompareStringW/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/CompareStringW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..8652977387
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/CompareStringW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_comparestringw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_comparestringw_test1 coreclrpal)
+
+target_link_libraries(paltest_comparestringw_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/locale_info/CompareStringW/test1/test1.c b/src/pal/tests/palsuite/locale_info/CompareStringW/test1/test1.c
new file mode 100644
index 0000000000..bdf2c3dcf3
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/CompareStringW/test1/test1.c
@@ -0,0 +1,99 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests that CompareStringW returns the correct value and can handle
+** invalid parameters.
+**
+**
+**==========================================================================*/
+
+#define CSTR_LESS_THAN 1
+#define CSTR_EQUAL 2
+#define CSTR_GREATER_THAN 3
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR str1[] = {'f','o','o',0};
+ WCHAR str2[] = {'f','o','o','x',0};
+ WCHAR str3[] = {'f','O','o',0};
+ int flags = NORM_IGNORECASE | NORM_IGNOREWIDTH;
+ int ret;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ ret = CompareStringW(0x0409, flags, str1, -1, str2, -1);
+ if (ret != CSTR_LESS_THAN)
+ {
+ Fail("CompareStringW with \"%S\" (%d) and \"%S\" (%d) did not return "
+ "CSTR_LESS_THAN!\n", str1, -1, str2, -1);
+ }
+
+ ret = CompareStringW(0x0409, flags, str1, -1, str2, 3);
+ if (ret != CSTR_EQUAL)
+ {
+ Fail("CompareStringW with \"%S\" (%d) and \"%S\" (%d) did not return "
+ "CSTR_EQUAL!\n", str1, -1, str2, 3);
+ }
+
+ ret = CompareStringW(0x0409, flags, str2, -1, str1, -1);
+ if (ret != CSTR_GREATER_THAN)
+ {
+ Fail("CompareStringW with \"%S\" (%d) and \"%S\" (%d) did not return "
+ "CSTR_GREATER_THAN!\n", str2, -1, str1, -1);
+ }
+
+ ret = CompareStringW(0x0409, flags, str1, -1, str3, -1);
+ if (ret != CSTR_EQUAL)
+ {
+ Fail("CompareStringW with \"%S\" (%d) and \"%S\" (%d) did not return "
+ "CSTR_EQUAL!\n", str1, -1, str3, -1);
+ }
+
+ ret = CompareStringW(0x0409, flags, str3, -1, str1, -1);
+ if (ret != CSTR_EQUAL)
+ {
+ Fail("CompareStringW with \"%S\" (%d) and \"%S\" (%d) did not return "
+ "CSTR_EQUAL!\n", str3, -1, str1, -1);
+ }
+
+ ret = CompareStringW(0x0409, flags, str3, -1, str1, -1);
+ if (ret != CSTR_EQUAL)
+ {
+ Fail("CompareStringW with \"%S\" (%d) and \"%S\" (%d) did not return "
+ "CSTR_EQUAL!\n", str3, -1, str1, -1);
+ }
+
+ ret = CompareStringW(0x0409, flags, str1, 0, str3, -1);
+ if (ret != CSTR_LESS_THAN)
+ {
+ Fail("CompareStringW with \"%S\" (%d) and \"%S\" (%d) did not return "
+ "CSTR_GREATER_THAN!\n", str1, 0, str3, -1);
+ }
+
+
+ ret = CompareStringW(0x0409, flags, NULL, -1, str3, -1);
+ if (ret != 0)
+ {
+ Fail("CompareStringW should have returned 0, got %d!\n", ret);
+ }
+ if (GetLastError() != ERROR_INVALID_PARAMETER)
+ {
+ Fail("CompareStringW should have set the last error to "
+ "ERROR_INVALID_PARAMETER!\n");
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/locale_info/CompareStringW/test1/testinfo.dat b/src/pal/tests/palsuite/locale_info/CompareStringW/test1/testinfo.dat
new file mode 100644
index 0000000000..d41de3ee68
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/CompareStringW/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Locale Information
+Function = CompareStringW
+Name = Test #1 for CompareStringW
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Tests that CompareStringW returns the correct value and can handle
+=invalid parameters.
diff --git a/src/pal/tests/palsuite/locale_info/GetACP/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetACP/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetACP/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/locale_info/GetACP/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetACP/test1/CMakeLists.txt
new file mode 100644
index 0000000000..c5513da2c1
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetACP/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_getacp_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getacp_test1 coreclrpal)
+
+target_link_libraries(paltest_getacp_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/locale_info/GetACP/test1/test1.c b/src/pal/tests/palsuite/locale_info/GetACP/test1/test1.c
new file mode 100644
index 0000000000..8ea078ee69
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetACP/test1/test1.c
@@ -0,0 +1,42 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests that GetACP returns the expected default code page.
+**
+**
+**==========================================================================*/
+
+
+#include <palsuite.h>
+
+/*
+ * NOTE: We only support code page 65001 (UTF-8).
+ */
+
+#define EXPECTED_CP 65001
+
+int __cdecl main(int argc, char *argv[])
+{
+ int ret;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ ret = GetACP();
+ if (ret != EXPECTED_CP)
+ {
+ Fail("ERROR: got incorrect result for current ANSI code page!\n"
+ "Expected %d, got %d\n", EXPECTED_CP, ret);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/locale_info/GetACP/test1/testinfo.dat b/src/pal/tests/palsuite/locale_info/GetACP/test1/testinfo.dat
new file mode 100644
index 0000000000..63a58f681b
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetACP/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Locale Information
+Function = GetACP
+Name = Test #1 for GetACP
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Tests that GetACP returns code-page 1252.
diff --git a/src/pal/tests/palsuite/locale_info/GetCPInfo/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetCPInfo/CMakeLists.txt
new file mode 100644
index 0000000000..1962ade358
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetCPInfo/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+
diff --git a/src/pal/tests/palsuite/locale_info/GetCPInfo/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetCPInfo/test1/CMakeLists.txt
new file mode 100644
index 0000000000..c209b121b2
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetCPInfo/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_getcpinfo_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getcpinfo_test1 coreclrpal)
+
+target_link_libraries(paltest_getcpinfo_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/locale_info/GetCPInfo/test1/test1.c b/src/pal/tests/palsuite/locale_info/GetCPInfo/test1/test1.c
new file mode 100644
index 0000000000..ed9bbf93fc
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetCPInfo/test1/test1.c
@@ -0,0 +1,54 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests that GetCPInfo works for CP_ACP and 0x4E4 (default codepage)
+** Also makes sure it correctly handles an invalid code page.
+**
+**
+**==========================================================================*/
+
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ CPINFO cpinfo;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ if (!GetCPInfo(CP_ACP, &cpinfo))
+ {
+ Fail("GetCPInfo() unable to get info for CP_ACP\n");
+ }
+
+ if (!GetCPInfo(65001, &cpinfo))
+ {
+ Fail("GetCPInfo() unable to get info for code page 65001 (utf8)\n");
+ }
+
+ if (GetCPInfo(-1, &cpinfo))
+ {
+ Fail("GetCPInfo() did not error on invalid code page!\n");
+ }
+
+ if (GetLastError() != ERROR_INVALID_PARAMETER)
+ {
+ Fail("GetCPInfo() failed to set the last error to"
+ " ERROR_INVALID_PARAMETER!\n");
+ }
+
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/locale_info/GetCPInfo/test1/testinfo.dat b/src/pal/tests/palsuite/locale_info/GetCPInfo/test1/testinfo.dat
new file mode 100644
index 0000000000..31be1d5536
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetCPInfo/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Locale Information
+Function = GetCPInfo
+Name = Test #1 for GetCPInfo
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Tests that GetCPInfo works for CP_ACP and 0x4E4 (default codepage)
+=Also makes sure it correctly handles an invalid code page.
diff --git a/src/pal/tests/palsuite/locale_info/GetCPInfo/test2/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetCPInfo/test2/CMakeLists.txt
new file mode 100644
index 0000000000..6132e9b3fa
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetCPInfo/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_getcpinfo_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getcpinfo_test2 coreclrpal)
+
+target_link_libraries(paltest_getcpinfo_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/locale_info/GetCPInfo/test2/test2.c b/src/pal/tests/palsuite/locale_info/GetCPInfo/test2/test2.c
new file mode 100644
index 0000000000..f52320f167
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetCPInfo/test2/test2.c
@@ -0,0 +1,60 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test2.c
+**
+** Purpose: Tests that GetCPInfo gives the correct information for codepage 0x4E4
+** (the default).
+**
+**
+**==========================================================================*/
+
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ CPINFO cpinfo;
+ int codepage;
+ unsigned int i;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /*
+ * codepage 1252 (0x4E4): Windows 3.1 Latin 1 (U.S., Western Europe)
+ */
+ codepage = 1252;
+
+ if (!GetCPInfo(codepage, &cpinfo))
+ {
+ Fail("GetCPInfo() failed on default ansi code page!\n");
+ }
+ if (cpinfo.MaxCharSize != 1)
+ {
+ Fail("GetCPInfo() returned incorrect MaxCharSize information!\n");
+ }
+ if (cpinfo.DefaultChar[0] != '?' || cpinfo.DefaultChar[1] != 0)
+ {
+ Fail("GetCPInfo() returned incorrect DefaultChar information");
+ }
+
+ for (i = 0; i<MAX_LEADBYTES; i++)
+ {
+ if (cpinfo.LeadByte[i] != 0)
+ {
+ Fail("GetCPInfo() returned incorrect LeadByte information");
+ }
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/locale_info/GetCPInfo/test2/testinfo.dat b/src/pal/tests/palsuite/locale_info/GetCPInfo/test2/testinfo.dat
new file mode 100644
index 0000000000..fee6849858
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetCPInfo/test2/testinfo.dat
@@ -0,0 +1,9 @@
+Version = 1.0
+Section = Locale Information
+Function = GetCPInfo
+Name = Test #2 for GetCPInfo
+TYPE = DEFAULT
+EXE1 = test2
+Description
+=Tests that GetCPInfo gives the correct information for codepage 0x4E4
+=(the default).
diff --git a/src/pal/tests/palsuite/locale_info/GetCPInfo/test3/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetCPInfo/test3/CMakeLists.txt
new file mode 100644
index 0000000000..3e4a09b51d
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetCPInfo/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_getcpinfo_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getcpinfo_test3 coreclrpal)
+
+target_link_libraries(paltest_getcpinfo_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/locale_info/GetCPInfo/test3/test3.c b/src/pal/tests/palsuite/locale_info/GetCPInfo/test3/test3.c
new file mode 100644
index 0000000000..aa9df935b8
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetCPInfo/test3/test3.c
@@ -0,0 +1,41 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test3.c
+**
+** Purpose: Test that passes CP_ACP to GetCPInfo, verifying the results.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+/* Currently only one CodePage "CP_ACP" is supported by the PAL */
+
+int __cdecl main(int argc, char *argv[])
+{
+ CPINFO cpinfo;
+
+ /* Initialize the PAL.
+ */
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Test GetCPInfo with CP_ACP.
+ */
+ if (!GetCPInfo(CP_ACP, &cpinfo))
+ {
+ Fail("GetCPInfo() unable to get info for code page %d!\n", CP_ACP);
+ }
+
+ /* Terminate the PAL.
+ */
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/locale_info/GetCPInfo/test3/testinfo.dat b/src/pal/tests/palsuite/locale_info/GetCPInfo/test3/testinfo.dat
new file mode 100644
index 0000000000..13f7a29262
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetCPInfo/test3/testinfo.dat
@@ -0,0 +1,8 @@
+Version = 1.0
+Section = Locale Information
+Function = GetCPInfo
+Name = Test #3 for GetCPInfo
+TYPE = DEFAULT
+EXE1 = test3
+Description
+=Tests that GetCPInfo passes for all valid code pages
diff --git a/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..f373b98f7c
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_getlocaleinfow_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getlocaleinfow_test1 coreclrpal)
+
+target_link_libraries(paltest_getlocaleinfow_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test1/test1.c b/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test1/test1.c
new file mode 100644
index 0000000000..0994940a57
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test1/test1.c
@@ -0,0 +1,89 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests that GetLocaleInfoW gives the correction information for
+** LOCALE_NEUTRAL.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+
+int Types[] = { LOCALE_SDECIMAL, LOCALE_STHOUSAND, LOCALE_ILZERO,
+ LOCALE_SCURRENCY, LOCALE_SMONDECIMALSEP, LOCALE_SMONTHOUSANDSEP };
+
+char *TypeStrings[] = { "LOCALE_SDECIMAL", "LOCALE_STHOUSAND", "LOCALE_ILZERO",
+ "LOCALE_SCURRENCY", "LOCALE_SMONDECIMALSEP", "LOCALE_SMONTHOUSANDSEP" };
+
+#define NUM_TYPES (sizeof(Types) / sizeof(Types[0]))
+
+typedef WCHAR InfoStrings[NUM_TYPES][4];
+
+typedef struct
+{
+ LCID lcid;
+ InfoStrings Strings;
+} LocalInfoType;
+
+LocalInfoType Locales[] =
+{
+ {LOCALE_NEUTRAL,
+ {{'.',0}, {',',0}, {'1',0}, {'$',0}, {'.',0}, {',',0}}},
+};
+
+int NumLocales = sizeof(Locales) / sizeof(Locales[0]);
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR buffer[256] = { 0 };
+ int ret;
+ int i,j;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ for (i=0; i<NumLocales; i++)
+ {
+ for (j=0; j<NUM_TYPES; j++)
+ {
+ ret = GetLocaleInfoW(Locales[i].lcid, Types[j], buffer, 256);
+
+ if (ret == 0)
+ {
+ Fail("GetLocaleInfoW returned an unexpected error!\n");
+ }
+
+
+ if (wcscmp(buffer, Locales[i].Strings[j]) != 0)
+ {
+
+ Fail("GetLocaleInfoW gave incorrect result for %s, "
+ "locale %#x:\nExpected \"%S\", got \"%S\"!\n", TypeStrings[j],
+ Locales[i].lcid, Locales[i].Strings[j], buffer);
+
+ }
+
+ if (ret != wcslen(Locales[i].Strings[j]) + 1)
+ {
+ Fail("GetLocaleInfoW returned incorrect value for %s, "
+ "locale %#x:\nExpected %d, got %d!\n", TypeStrings[j],
+ Locales[i].lcid, wcslen(Locales[i].Strings[j])+1, ret);
+ }
+ }
+ }
+
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test1/testinfo.dat b/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test1/testinfo.dat
new file mode 100644
index 0000000000..00d974a71c
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Locale Information
+Function = GetLocaleInfoW
+Name = Test #1 for GetLocaleInfoW
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Tests that GetLocaleInfoW gives the correction information for LOCALE_NEUTRAL
diff --git a/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test2/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test2/CMakeLists.txt
new file mode 100644
index 0000000000..dd5b82ef61
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_getlocaleinfow_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getlocaleinfow_test2 coreclrpal)
+
+target_link_libraries(paltest_getlocaleinfow_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test2/test2.c b/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test2/test2.c
new file mode 100644
index 0000000000..f00fa79c59
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test2/test2.c
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test2.c
+**
+** Purpose: Tests that GetLocaleInfoW will correctly return the amount of
+** buffer space required. Also tests that it correctly handles a
+** buffer of insufficient space.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR buffer[256] = { 0 };
+ int ret;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ ret = GetLocaleInfoW(LOCALE_NEUTRAL, LOCALE_SDECIMAL, buffer, 0);
+ if (ret != 2)
+ {
+ Fail("GetLocaleInfoW gave incorrect desired length for buffer.\n"
+ "Expected 2, got %d.\n", ret);
+ }
+
+ ret = GetLocaleInfoW(LOCALE_NEUTRAL, LOCALE_SDECIMAL, buffer, 1);
+ if (ret != 0)
+ {
+ Fail("GetLocaleInfoW expected to return 0, returned %d", ret);
+ }
+
+ if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+ {
+ Fail("GetLocaleInfoW failed to set last error to "
+ "ERROR_INSUFFICIENT_BUFFER!\n");
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test2/testinfo.dat b/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test2/testinfo.dat
new file mode 100644
index 0000000000..b9fc4886ee
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test2/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Locale Information
+Function = GetLocaleInfoW
+Name = Test #2 for GetLocaleInfoW
+TYPE = DEFAULT
+EXE1 = test2
+Description
+=Tests that GetLocaleInfoW will correctly return the amount of
+=buffer space required. Also tests that it correctly handles a
+=buffer of insufficient space.
diff --git a/src/pal/tests/palsuite/locale_info/GetStringTypeExW/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetStringTypeExW/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetStringTypeExW/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/locale_info/GetStringTypeExW/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetStringTypeExW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..5bb7b8c8b5
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetStringTypeExW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_getstringtypeexw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getstringtypeexw_test1 coreclrpal)
+
+target_link_libraries(paltest_getstringtypeexw_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/locale_info/GetStringTypeExW/test1/test1.c b/src/pal/tests/palsuite/locale_info/GetStringTypeExW/test1/test1.c
new file mode 100644
index 0000000000..e15c3d66cd
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetStringTypeExW/test1/test1.c
@@ -0,0 +1,54 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests GetStringTypeExW with values that will ensure all possible
+** flags get set once.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR wideStr[] = {'9',' '};
+ WORD values1[] = { C1_DIGIT, C1_SPACE };
+ int len = 2;
+ WORD Info[256];
+ BOOL ret;
+ int i;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ for (i=0; i<len; i++)
+ {
+ ret = GetStringTypeExW(LOCALE_USER_DEFAULT, CT_CTYPE1, &wideStr[i], 1, &Info[i]);
+ if (!ret)
+ {
+ Fail("GetStringTypeExW failed!\n");
+ }
+
+ if ((Info[i] & values1[i])!= values1[i])
+ {
+
+ Fail("GetStringTypeExW returned wrong type info for %c (%d)\n"
+ "Expected %#x, got %#x\n", wideStr[i], wideStr[i],
+ values1[i], Info[i]);
+
+ }
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/locale_info/GetStringTypeExW/test1/testinfo.dat b/src/pal/tests/palsuite/locale_info/GetStringTypeExW/test1/testinfo.dat
new file mode 100644
index 0000000000..b0fbea4c05
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetStringTypeExW/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Locale Information
+Function = GetStringTypeExW
+Name = Test #1 for GetStringTypeExW
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Tests GetStringTypeExW with values that will ensure all possible
+=flags get set once.
diff --git a/src/pal/tests/palsuite/locale_info/GetStringTypeExW/test2/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetStringTypeExW/test2/CMakeLists.txt
new file mode 100644
index 0000000000..4a8fab243e
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetStringTypeExW/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_getstringtypeexw_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getstringtypeexw_test2 coreclrpal)
+
+target_link_libraries(paltest_getstringtypeexw_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/locale_info/GetStringTypeExW/test2/test2.c b/src/pal/tests/palsuite/locale_info/GetStringTypeExW/test2/test2.c
new file mode 100644
index 0000000000..6dca7e8ac5
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetStringTypeExW/test2/test2.c
@@ -0,0 +1,78 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test2.c
+**
+** Purpose: Tests GetStringTypeExW with values from every possible unicode
+** category.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+
+/*
+ * A random selection of unicode characters, each representing a distinct
+ * unicode category
+ */
+WCHAR TestStr[] =
+{
+ 0x05D0, /* 4, HEBREW LETTER ALEF */
+ 0x0488, /* 7, COMBINING CYRILLIC HUNDRED THOUSANDS SIGN */
+ 0x0030, /* 8, DIGIT ZERO */
+ 0x0020, /* 22, SPACE */
+};
+
+#define TEST_LEN (sizeof(TestStr) / sizeof(WCHAR))
+
+WORD TestFlags[TEST_LEN] =
+{
+ C1_ALPHA,
+ 0,
+ C1_DIGIT,
+ C1_BLANK|C1_SPACE
+};
+
+int __cdecl main(int argc, char *argv[])
+{
+ WORD Info;
+ BOOL ret;
+ int i;
+
+ /* check only the bits listed in rotor_pal.doc */
+ const WORD PAL_VALID_C1_BITS = C1_DIGIT | C1_SPACE;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ for (i=0; i <TEST_LEN; i++)
+ {
+ ret = GetStringTypeExW(LOCALE_USER_DEFAULT, CT_CTYPE1, &TestStr[i], 1, &Info);
+
+ if (!ret)
+ {
+ Fail("GetStringTypeExW failed!\n");
+ }
+
+ if ((Info & PAL_VALID_C1_BITS) != (TestFlags[i] & PAL_VALID_C1_BITS))
+ {
+
+ Fail("GetStringTypeExW (test #%i) returned wrong type info for %c (%d)\n"
+ "Expected %#x, got %#x\n", i, TestStr[i], TestStr[i],
+ TestFlags[i], Info);
+
+ }
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/locale_info/GetStringTypeExW/test2/testinfo.dat b/src/pal/tests/palsuite/locale_info/GetStringTypeExW/test2/testinfo.dat
new file mode 100644
index 0000000000..361d29b450
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetStringTypeExW/test2/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Locale Information
+Function = GetStringTypeExW
+Name = Test #2 for GetStringTypeExW
+TYPE = DEFAULT
+EXE1 = test2
+Description
+=Tests GetStringTypeExW with values from every possible unicode category.
diff --git a/src/pal/tests/palsuite/locale_info/GetSystemDefaultLangID/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetSystemDefaultLangID/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetSystemDefaultLangID/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/locale_info/GetSystemDefaultLangID/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetSystemDefaultLangID/test1/CMakeLists.txt
new file mode 100644
index 0000000000..ef87b5f87f
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetSystemDefaultLangID/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_getsystemdefaultlangid_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getsystemdefaultlangid_test1 coreclrpal)
+
+target_link_libraries(paltest_getsystemdefaultlangid_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/locale_info/GetSystemDefaultLangID/test1/test1.c b/src/pal/tests/palsuite/locale_info/GetSystemDefaultLangID/test1/test1.c
new file mode 100644
index 0000000000..1bc5120815
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetSystemDefaultLangID/test1/test1.c
@@ -0,0 +1,59 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Checks that GetSystemDefaultLangID can be used to make a valid
+** locale, and that it is consistent with LOCALE_USER_DEFAULT.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ LCID lcid;
+ LANGID LangID;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ LangID = GetSystemDefaultLangID();
+ if (LangID == 0)
+ {
+ Fail("GetSystemDefaultLangID failed!\n");
+ }
+
+ /* Try using the langid (with default sort) as a locale */
+ if (!SetThreadLocale(MAKELCID(LangID, SORT_DEFAULT)))
+ {
+ Fail("Unable to use GetSystemDefaultLangID as a locale!\n");
+ }
+ lcid = GetThreadLocale();
+ if (!IsValidLocale(lcid, LCID_INSTALLED))
+ {
+ Fail("Unable to use GetSystemDefaultLangID as a locale!\n");
+ }
+
+ /* Make sure results consistent with using LOCALE_USER_DEFAULT */
+ if (!SetThreadLocale(LOCALE_USER_DEFAULT))
+ {
+ Fail("Unexpected error testing GetSystemDefaultLangID!\n");
+ }
+ if (GetThreadLocale() != lcid)
+ {
+ Fail("Results from GetSystemDefaultLangID inconsistent with "
+ "LOCALE_USER_DEFAULT!\n");
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/locale_info/GetSystemDefaultLangID/test1/testinfo.dat b/src/pal/tests/palsuite/locale_info/GetSystemDefaultLangID/test1/testinfo.dat
new file mode 100644
index 0000000000..e37ce45a44
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetSystemDefaultLangID/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Locale Information
+Function = GetSystemDefaultLangID
+Name = Test #1 for GetSystemDefaultLangID
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Checks that GetSystemDefaultLangID can be used to make a valid
+=locale, and that it is consistent with LOCALE_USER_DEFAULT.
diff --git a/src/pal/tests/palsuite/locale_info/GetThreadLocale/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetThreadLocale/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetThreadLocale/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/locale_info/GetThreadLocale/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetThreadLocale/test1/CMakeLists.txt
new file mode 100644
index 0000000000..8cec9d8306
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetThreadLocale/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_getthreadlocale_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getthreadlocale_test1 coreclrpal)
+
+target_link_libraries(paltest_getthreadlocale_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/locale_info/GetThreadLocale/test1/test1.c b/src/pal/tests/palsuite/locale_info/GetThreadLocale/test1/test1.c
new file mode 100644
index 0000000000..8eb7252e37
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetThreadLocale/test1/test1.c
@@ -0,0 +1,36 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests that GetThreadLocale returns a valid locale.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ LCID lcid;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ lcid = GetThreadLocale();
+
+ if (!IsValidLocale(lcid, LCID_INSTALLED))
+ {
+ Fail("GetThreadLocale returned a locale that is not installed!\n");
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/locale_info/GetThreadLocale/test1/testinfo.dat b/src/pal/tests/palsuite/locale_info/GetThreadLocale/test1/testinfo.dat
new file mode 100644
index 0000000000..a58782a38c
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetThreadLocale/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Locale Information
+Function = GetThreadLocale
+Name = Test #1 for GetThreadLocale
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Tests that GetThreadLocale returns a valid locale
diff --git a/src/pal/tests/palsuite/locale_info/GetTimeZoneInformation/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetTimeZoneInformation/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetTimeZoneInformation/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/locale_info/GetTimeZoneInformation/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetTimeZoneInformation/test1/CMakeLists.txt
new file mode 100644
index 0000000000..281f3bf9c3
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetTimeZoneInformation/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_gettimezoneinformation_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_gettimezoneinformation_test1 coreclrpal)
+
+target_link_libraries(paltest_gettimezoneinformation_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/locale_info/GetTimeZoneInformation/test1/test1.c b/src/pal/tests/palsuite/locale_info/GetTimeZoneInformation/test1/test1.c
new file mode 100644
index 0000000000..bb83ade231
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetTimeZoneInformation/test1/test1.c
@@ -0,0 +1,73 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests that GetTimeZoneInformation gives reasonable values.
+**
+**
+**==========================================================================*/
+
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ TIME_ZONE_INFORMATION tzi;
+ DWORD ret;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ ret = GetTimeZoneInformation(&tzi);
+ if (ret == TIME_ZONE_ID_UNKNOWN)
+ {
+ /* Occurs in time zones that do not use daylight savings time. */
+ if (tzi.StandardBias != 0)
+ {
+ Fail("GetTimeZoneInformation() gave invalid data!\n"
+ "Returned TIME_ZONE_ID_UNKNOWN but StandardBias != 0!\n");
+ }
+ if (tzi.DaylightBias != 0)
+ {
+ Fail("GetTimeZoneInformation() gave invalid data!\n"
+ "Returned TIME_ZONE_ID_UNKNOWN but DaylightBias != 0!\n");
+ }
+ }
+ else if (ret == TIME_ZONE_ID_STANDARD)
+ {
+ if (tzi.StandardBias != 0)
+ {
+ Fail("GetTimeZoneInformation() gave invalid data!\n"
+ "StandardBias is %d, should be 0!\n", tzi.StandardBias);
+ }
+ }
+ else if (ret == TIME_ZONE_ID_DAYLIGHT)
+ {
+ if (tzi.DaylightBias != -60 && tzi.DaylightBias != 0)
+ {
+ Fail("GetTimeZoneInformation() gave invalid data!\n"
+ "DaylightBias is %d, should be 0 or -60!\n", tzi.DaylightBias);
+ }
+ }
+ else
+ {
+ Fail("GetTimeZoneInformation() returned an invalid value!\n");
+ }
+
+ if (tzi.Bias % 30 != 0)
+ {
+ Fail("GetTimeZoneInformation() gave an invalid bias of %d!\n",
+ tzi.Bias);
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/locale_info/GetTimeZoneInformation/test1/testinfo.dat b/src/pal/tests/palsuite/locale_info/GetTimeZoneInformation/test1/testinfo.dat
new file mode 100644
index 0000000000..382b8d5351
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetTimeZoneInformation/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Locale Information
+Function = GetTimeZoneInformation
+Name = Test #1 for GetTimeZoneInformation
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Tests that GetTimeZoneInformation gives reasonable values.
diff --git a/src/pal/tests/palsuite/locale_info/GetUserDefaultLCID/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetUserDefaultLCID/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetUserDefaultLCID/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/locale_info/GetUserDefaultLCID/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetUserDefaultLCID/test1/CMakeLists.txt
new file mode 100644
index 0000000000..e039d46ccd
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetUserDefaultLCID/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_getuserdefaultlcid_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getuserdefaultlcid_test1 coreclrpal)
+
+target_link_libraries(paltest_getuserdefaultlcid_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/locale_info/GetUserDefaultLCID/test1/test1.c b/src/pal/tests/palsuite/locale_info/GetUserDefaultLCID/test1/test1.c
new file mode 100644
index 0000000000..4a336f9bb7
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetUserDefaultLCID/test1/test1.c
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests that GetUserDefaultLCID returns a valid locale that is
+** consistent with LOCALE_USER_DEFAULT.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ LCID lcid;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ lcid = GetUserDefaultLCID();
+ if (lcid == 0)
+ {
+ Fail("GetUserDefaultLCID failed!\n");
+ }
+
+ if (!IsValidLocale(lcid, LCID_INSTALLED))
+ {
+ Fail("GetUserDefaultLCID gave an invalid locale!\n");
+ }
+
+ /* Make sure results consistent with using LOCALE_USER_DEFAULT */
+ if (!SetThreadLocale(LOCALE_USER_DEFAULT))
+ {
+ Fail("Unexpected error testing GetUserDefaultLCID!\n");
+ }
+ if (GetThreadLocale() != lcid)
+ {
+ Fail("Results from GetUserDefaultLCID inconsistent with "
+ "LOCALE_USER_DEFAULT!\n");
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/locale_info/GetUserDefaultLCID/test1/testinfo.dat b/src/pal/tests/palsuite/locale_info/GetUserDefaultLCID/test1/testinfo.dat
new file mode 100644
index 0000000000..73565b03c5
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetUserDefaultLCID/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Locale Information
+Function = GetUserDefaultLCID
+Name = Test #1 for GetUserDefaultLCID
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Tests that GetUserDefaultLCID returns a valid locale that is
+=consistent with LOCALE_USER_DEFAULT.
diff --git a/src/pal/tests/palsuite/locale_info/GetUserDefaultLangID/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetUserDefaultLangID/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetUserDefaultLangID/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/locale_info/GetUserDefaultLangID/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetUserDefaultLangID/test1/CMakeLists.txt
new file mode 100644
index 0000000000..71fa0464bb
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetUserDefaultLangID/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_getuserdefaultlangid_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getuserdefaultlangid_test1 coreclrpal)
+
+target_link_libraries(paltest_getuserdefaultlangid_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/locale_info/GetUserDefaultLangID/test1/test1.c b/src/pal/tests/palsuite/locale_info/GetUserDefaultLangID/test1/test1.c
new file mode 100644
index 0000000000..51c5678086
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetUserDefaultLangID/test1/test1.c
@@ -0,0 +1,60 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Checks that GetUserDefaultLangID can be used to make a valid
+** locale, and that it is consistent with LOCALE_USER_DEFAULT.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ LCID lcid;
+ LANGID LangID;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ LangID = GetUserDefaultLangID();
+ if (LangID == 0)
+ {
+ Fail("GetUserDefaultLangID failed!\n");
+ }
+
+ /* Try using the langid (with default sort) as a locale */
+ if (!SetThreadLocale(MAKELCID(LangID, SORT_DEFAULT)))
+ {
+ Fail("Unable to use GetUserDefaultLangID as a locale!\n");
+ }
+ lcid = GetThreadLocale();
+ if (!IsValidLocale(lcid, LCID_INSTALLED))
+ {
+ Fail("Unable to use GetUserDefaultLangID as a locale!\n");
+ }
+
+ /* Make sure results consistent with using LOCALE_USER_DEFAULT */
+ if (!SetThreadLocale(LOCALE_USER_DEFAULT))
+ {
+ Fail("Unexpected error testing GetUserDefaultLangID!\n");
+ }
+ if (GetThreadLocale() != lcid)
+ {
+ Fail("Results from GetUserDefaultLangID inconsistent with "
+ "LOCALE_USER_DEFAULT!\n");
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/locale_info/GetUserDefaultLangID/test1/testinfo.dat b/src/pal/tests/palsuite/locale_info/GetUserDefaultLangID/test1/testinfo.dat
new file mode 100644
index 0000000000..a46125757e
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/GetUserDefaultLangID/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Locale Information
+Function = GetUserDefaultLangID
+Name = Test #1 for GetUserDefaultLangID
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Checks that GetUserDefaultLangID can be used to make a valid
+=locale, and that it is consistent with LOCALE_USER_DEFAULT.
diff --git a/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/CMakeLists.txt
new file mode 100644
index 0000000000..ad5ad7508d
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_isdbcsleadbyte_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_isdbcsleadbyte_test1 coreclrpal)
+
+target_link_libraries(paltest_isdbcsleadbyte_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/test1.c b/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/test1.c
new file mode 100644
index 0000000000..ad326be084
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/test1.c
@@ -0,0 +1,64 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests that IsDBCSLeadByte does not find any lead-bytes in the
+** current ansi code page
+**
+**
+** TODO: Test for positive, i.e., if it is potentially isdbcsleadbyte
+**==========================================================================*/
+
+
+#include <palsuite.h>
+
+void DoTest()
+{
+ int value;
+ int ret;
+ int i;
+
+
+ for (i=0; i<256; i++)
+ {
+ value = IsDBCSLeadByte(i);
+
+ ret = GetLastError();
+ if (ret == ERROR_INVALID_PARAMETER)
+ {
+ Fail("IsDBCSLeadByte unexpectedly errored with ERROR_INVALID_PARAMETER for %d!\n", i);
+ }
+ else if (ret != 0)
+ {
+ Fail("IsDBCSLeadByte had an unexpected error [%d] for %d!\n", ret, i);
+ }
+ else if (value)
+ {
+ Fail("IsDBCSLeadByte incorrectly found a lead byte in value [%d] for"
+ " %d\n", value, i);
+ }
+
+ }
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ DoTest();
+
+ PAL_Terminate();
+
+// setlocale( "japan", );
+
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/testinfo.dat b/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/testinfo.dat
new file mode 100644
index 0000000000..43cd2aebb6
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Locale Information
+Function = IsDBCSLeadByte
+Name = Test #1 for IsDBCSLeadByte
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Tests that IsDBCSLeadByte does not find any lead-bytes in the
+=current ansi code page
diff --git a/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/CMakeLists.txt
new file mode 100644
index 0000000000..9d53ee9b3b
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_isdbcsleadbyteex_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_isdbcsleadbyteex_test1 coreclrpal)
+
+target_link_libraries(paltest_isdbcsleadbyteex_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/test1.c b/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/test1.c
new file mode 100644
index 0000000000..9466f4817f
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/test1.c
@@ -0,0 +1,72 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests that IsDBCSLeadByteEx does not find any lead-bytes in the
+** current ansi code page or the default code page. Also tests that
+** it correctly handles an invalid codepage.
+**
+**
+**==========================================================================*/
+
+
+#include <palsuite.h>
+
+void DoTest(int codepage)
+{
+ int value;
+ int ret;
+ int i;
+
+
+ for (i=0; i<256; i++)
+ {
+ value = IsDBCSLeadByteEx(codepage, i);
+
+ ret = GetLastError();
+ if (ret == ERROR_INVALID_PARAMETER)
+ {
+ Fail("IsDBCSLeadByteEx unexpectedly errored with ERROR_INVALID_PARAMETER!\n");
+ }
+ else if (ret != 0)
+ {
+ Fail("IsDBCSLeadByteEx had an unexpected error!\n");
+ }
+ else if (value)
+ {
+ Fail("IsDBCSLeadByteEx incorrectly found a lead byte in code "
+ "page %d\n", codepage);
+ }
+
+ }
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ if (IsDBCSLeadByteEx(-1, 0))
+ {
+ Fail("IsDBCSLeadByteEx did not error on an invalid code page!\n");
+ }
+
+ /* Clear the last error. */
+ SetLastError(0);
+
+
+ DoTest(0);
+ DoTest(CP_ACP);
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/testinfo.dat b/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/testinfo.dat
new file mode 100644
index 0000000000..b85e387272
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Locale Information
+Function = IsDBCSLeadByteEx
+Name = Test #1 for IsDBCSLeadByteEx
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Tests that IsDBCSLeadByteEx does not find any lead-bytes in the
+=current ansi code page or the default code page. Also tests that
+=it correctly handles an invalid codepage.
diff --git a/src/pal/tests/palsuite/locale_info/IsValidCodePage/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/IsValidCodePage/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/IsValidCodePage/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/locale_info/IsValidCodePage/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/IsValidCodePage/test1/CMakeLists.txt
new file mode 100644
index 0000000000..d87e8c0d6b
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/IsValidCodePage/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_isvalidcodepage_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_isvalidcodepage_test1 coreclrpal)
+
+target_link_libraries(paltest_isvalidcodepage_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/locale_info/IsValidCodePage/test1/test1.c b/src/pal/tests/palsuite/locale_info/IsValidCodePage/test1/test1.c
new file mode 100644
index 0000000000..deb6a7ae72
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/IsValidCodePage/test1/test1.c
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests IsValidCodePage with a collection of valid and invalid
+** code pages.
+**
+**
+**==========================================================================*/
+
+
+#include <palsuite.h>
+
+
+UINT InvalidCodePages[] =
+{
+ 0, 0x1, 0x2, 0x3, 0xfff
+};
+
+int NumInvalidPages = sizeof(InvalidCodePages) / sizeof(InvalidCodePages[0]);
+
+int __cdecl main(int argc, char *argv[])
+{
+ int i;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+
+ for (i=0; i<NumInvalidPages; i++)
+ {
+ if (IsValidCodePage(InvalidCodePages[i]))
+ {
+ Fail("IsValidCodePage() found code page %#x valid!\n",
+ InvalidCodePages[i]);
+ }
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/locale_info/IsValidCodePage/test1/testinfo.dat b/src/pal/tests/palsuite/locale_info/IsValidCodePage/test1/testinfo.dat
new file mode 100644
index 0000000000..f3b0fb8cb3
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/IsValidCodePage/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Locale Information
+Function = IsValidCodePage
+Name = Test #1 for IsValidCodePage
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Tests IsValidCodePage with a collection of valid and invalid code pages.
diff --git a/src/pal/tests/palsuite/locale_info/IsValidCodePage/test2/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/IsValidCodePage/test2/CMakeLists.txt
new file mode 100644
index 0000000000..adcae86ff9
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/IsValidCodePage/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_isvalidcodepage_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_isvalidcodepage_test2 coreclrpal)
+
+target_link_libraries(paltest_isvalidcodepage_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/locale_info/IsValidCodePage/test2/test2.c b/src/pal/tests/palsuite/locale_info/IsValidCodePage/test2/test2.c
new file mode 100644
index 0000000000..d9362cfd96
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/IsValidCodePage/test2/test2.c
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test2.c
+**
+** Purpose: Tests IsValidCodePage with all the code pages valid on W2K.
+**
+**
+**==========================================================================*/
+
+
+
+#include <palsuite.h>
+
+UINT ValidCodePages[] =
+{
+ 0x25, 0x1b5, 0x1f4, 0x352, 0x35c, 0x35d, 0x35f, 0x361,
+ 0x36a, 0x3a4, 0x3a8, 0x3b5, 0x3b6, 0x4e2, 0x4e3, 0x4e4, 0x4e5, 0x4e6,
+ 0x4e7, 0x4e8, 0x4e9, 0x4ea, 0x2710, 0x275f, 0x4e9f, 0x4f25, 0x5182, 0x6faf,
+ 0x6fb0, 0x6fbd, 0xfde8, 0xfde9
+};
+
+
+int NumValidPages = sizeof(ValidCodePages) / sizeof(ValidCodePages[0]);
+int __cdecl main(int argc, char *argv[])
+{
+ int i;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ for (i=0; i<NumValidPages; i++)
+ {
+ if (!IsValidCodePage(ValidCodePages[i]))
+ {
+ Fail("IsValidCodePage() found code page %#x invalid!\n",
+ ValidCodePages[i]);
+ }
+ }
+
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/locale_info/IsValidCodePage/test2/testinfo.dat b/src/pal/tests/palsuite/locale_info/IsValidCodePage/test2/testinfo.dat
new file mode 100644
index 0000000000..f4507b411e
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/IsValidCodePage/test2/testinfo.dat
@@ -0,0 +1,8 @@
+Version = 1.0
+Section = Locale Information
+Function = IsValidCodePage
+Name = Test #2 for IsValidCodePage
+TYPE = DEFAULT
+EXE1 = test2
+Description
+=Tests IsValidCodePage with all the code pages valid on W2K.
diff --git a/src/pal/tests/palsuite/locale_info/IsValidLocale/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/IsValidLocale/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/IsValidLocale/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/locale_info/IsValidLocale/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/IsValidLocale/test1/CMakeLists.txt
new file mode 100644
index 0000000000..8fc7604a49
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/IsValidLocale/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_isvalidlocale_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_isvalidlocale_test1 coreclrpal)
+
+target_link_libraries(paltest_isvalidlocale_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/locale_info/IsValidLocale/test1/test1.c b/src/pal/tests/palsuite/locale_info/IsValidLocale/test1/test1.c
new file mode 100644
index 0000000000..4dd63653f5
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/IsValidLocale/test1/test1.c
@@ -0,0 +1,76 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests IsValidLocale with the current locale, -1, and
+** LOCALE_USER_DEFAULT (which actually isn't valid).
+**
+**
+**==========================================================================*/
+
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ LCID lcid;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /*
+ * Passing LOCALE_USER_DEFAULT to IsValidLocale will fail, so instead
+ * the current thread localed is changed to it, and that lcid is passed
+ * to IsValidLocale (which should always pass)
+ */
+ if (!SetThreadLocale(LOCALE_USER_DEFAULT))
+ {
+ Fail("Unable to set locale to LOCALE_USER_DEFAULT!\n");
+ }
+
+ lcid = GetThreadLocale();
+
+ if (!IsValidLocale(lcid, LCID_SUPPORTED))
+ {
+ Fail("IsValidLocale found the default user locale unsupported!\n");
+ }
+ if (!IsValidLocale(lcid, LCID_INSTALLED))
+ {
+ Fail("IsValidLocale found the default user locale uninstalled!\n");
+ }
+
+ /*
+ * Test out bad parameters
+ */
+ if (IsValidLocale(-1, LCID_SUPPORTED))
+ {
+ Fail("IsValideLocale passed with an invalid LCID!\n");
+ }
+ if (IsValidLocale(-1, LCID_INSTALLED))
+ {
+ Fail("IsValideLocale passed with an invalid LCID!\n");
+ }
+
+ if (IsValidLocale(LOCALE_USER_DEFAULT, LCID_SUPPORTED))
+ {
+ Fail("IsValidLocale passed with LOCALE_USER_DEFAULT!\n");
+ }
+ if (IsValidLocale(LOCALE_USER_DEFAULT, LCID_INSTALLED))
+ {
+ Fail("IsValidLocale passed with LOCALE_USER_DEFAULT!\n");
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/locale_info/IsValidLocale/test1/testinfo.dat b/src/pal/tests/palsuite/locale_info/IsValidLocale/test1/testinfo.dat
new file mode 100644
index 0000000000..e9fcc18cf3
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/IsValidLocale/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Locale Information
+Function = IsValidLocale
+Name = Test #1 for IsValidLocale
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Tests IsValidLocale with the current locale, -1, and LOCALE_USER_DEFAULT
+=(which actually isn't valid).
diff --git a/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/CMakeLists.txt
new file mode 100644
index 0000000000..0b8ae6062e
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
diff --git a/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/CMakeLists.txt
new file mode 100644
index 0000000000..044c47712b
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_multibytetowidechar_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_multibytetowidechar_test1 coreclrpal)
+
+target_link_libraries(paltest_multibytetowidechar_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/test1.c b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/test1.c
new file mode 100644
index 0000000000..81f58a532c
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/test1.c
@@ -0,0 +1,81 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests MultiByteToWideChar with all the ASCII characters (0-127).
+** Also tests that WideCharToMultiByte handles different buffer
+** lengths correctly (0, -1, and a valid length)
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+/*
+ * For now, it is assumed that MultiByteToWideChar will only be used in the PAL
+ * with CP_ACP, and that dwFlags will be 0.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ char mbStr[128];
+ WCHAR wideStr[128];
+ int ret;
+ int i;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ for (i=0; i<128; i++)
+ {
+ mbStr[i] = 127 - i;
+ wideStr[i] = 0;
+ }
+
+
+ ret = MultiByteToWideChar(CP_ACP, 0, mbStr, -1, wideStr, 0);
+ if (ret != 128)
+ {
+ Fail("MultiByteToWideChar did not return correct string length!\n"
+ "Got %d, expected %d\n", ret, 128);
+ }
+
+ /* Make sure the ASCII set (0-127) gets translated correctly */
+ ret = MultiByteToWideChar(CP_ACP, 0, mbStr, -1, wideStr, 128);
+ if (ret != 128)
+ {
+ Fail("MultiByteToWideChar did not return correct string length!\n"
+ "Got %d, expected %d\n", ret, 128);
+ }
+
+ for (i=0; i<128; i++)
+ {
+ if (wideStr[i] != (WCHAR)(127 - i))
+ {
+ Fail("MultiByteToWideChar failed to translate correctly!\n"
+ "Expected character %d to be %c (%x), got %c (%x)\n",
+ i, 127 - i, 127 - i,wideStr[i], wideStr[i]);
+ }
+ }
+
+
+ /* try a 0 length string */
+ mbStr[0] = 0;
+ ret = MultiByteToWideChar(CP_ACP, 0, mbStr, -1, wideStr, 0);
+ if (ret != 1)
+ {
+ Fail("MultiByteToWideChar did not return correct string length!\n"
+ "Got %d, expected %d\n", ret, 1);
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/testinfo.dat b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/testinfo.dat
new file mode 100644
index 0000000000..0e4591d247
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Locale Information
+Function = MultiByteToWideChar
+Name = Test #1 for MultiByteToWideChar
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Tests MultiByteToWideChar with all the ASCII characters (0-127).
+=Also tests that WideCharToMultiByte handles different buffer
+=lengths correctly (0, -1, and a valid length)
diff --git a/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/CMakeLists.txt
new file mode 100644
index 0000000000..0367d53938
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_multibytetowidechar_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_multibytetowidechar_test2 coreclrpal)
+
+target_link_libraries(paltest_multibytetowidechar_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/test2.c b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/test2.c
new file mode 100644
index 0000000000..1370dba894
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/test2.c
@@ -0,0 +1,68 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test2.c
+**
+** Purpose: Tests that MultiByteToWideChar respects the length of the wide
+** character string.
+
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+/*
+ * For now, it is assumed that MultiByteToWideChar will only be used in the PAL
+ * with CP_ACP, and that dwFlags will be 0.
+ */
+
+int __cdecl main(int argc, char *argv[])
+{
+ char mbStr[128];
+ WCHAR wideStr[128];
+ int ret;
+ int i;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ for (i=0; i<128; i++)
+ {
+ mbStr[i] = 'a';
+ wideStr[i] = 0;
+ }
+
+ mbStr[127] = 0;
+
+
+ ret = MultiByteToWideChar(CP_ACP, 0, mbStr, 10, wideStr, 0);
+ if (ret != 10)
+ {
+ Fail("MultiByteToWideChar did not return correct string length!\n"
+ "Got %d, expected %d\n", ret, 10);
+ }
+
+ wideStr[10] = (WCHAR) 'b';
+
+ ret = MultiByteToWideChar(CP_ACP, 0, mbStr, 10, wideStr, 128);
+ if (ret != 10)
+ {
+ Fail("MultiByteToWideChar did not return correct string length!\n"
+ "Got %d, expected %d\n", ret, 10);
+ }
+
+ if (wideStr[10] != 'b')
+ {
+ Fail("WideCharToMultiByte overflowed the destination buffer!\n");
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/testinfo.dat b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/testinfo.dat
new file mode 100644
index 0000000000..5211db1256
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Locale Information
+Function = MultiByteToWideChar
+Name = Test #2 for MultiByteToWideChar
+TYPE = DEFAULT
+EXE1 = test2
+Description
+=Tests that MultiByteToWideChar respects the length of the wide
+=character string.
diff --git a/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/CMakeLists.txt
new file mode 100644
index 0000000000..57e3d66faf
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_multibytetowidechar_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_multibytetowidechar_test3 coreclrpal)
+
+target_link_libraries(paltest_multibytetowidechar_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/test3.c b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/test3.c
new file mode 100644
index 0000000000..1b3a4bd4f5
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/test3.c
@@ -0,0 +1,73 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test3.c
+**
+** Purpose: Tests that MultiByteToWideChar correctly handles the following
+** error conditions: insufficient buffer space, invalid code pages,
+** and invalid flags.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ char mbStr[128];
+ WCHAR wideStr[128];
+ int ret;
+ int i;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ for (i=0; i<128; i++)
+ {
+ mbStr[i] = 'a';
+ wideStr[i] = 0;
+ }
+
+ mbStr[127] = 0;
+
+ /* try with insufficient buffer space */
+ ret = MultiByteToWideChar(CP_ACP, 0, mbStr, -1, wideStr, 10);
+ if (ret != 0)
+ {
+ Fail("MultiByteToWideChar did not return an error!\n"
+ "Expected return of 0, got %d", ret);
+ }
+
+ ret = GetLastError();
+ if (ret != ERROR_INSUFFICIENT_BUFFER)
+ {
+ Fail("MultiByteToWideChar did not set the last error to "
+ "ERROR_INSUFFICIENT_BUFFER!\n");
+ }
+
+ /* try with a wacky code page */
+ ret = MultiByteToWideChar(-1, 0, mbStr, -1, wideStr, 128);
+ if (ret != 0)
+ {
+ Fail("MultiByteToWideChar did not return an error!\n"
+ "Expected return of 0, got %d", ret);
+ }
+
+ ret = GetLastError();
+ if (ret != ERROR_INVALID_PARAMETER)
+ {
+ Fail("MultiByteToWideChar did not set the last error to "
+ "ERROR_INVALID_PARAMETER!\n");
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/testinfo.dat b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/testinfo.dat
new file mode 100644
index 0000000000..c59f285dca
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Locale Information
+Function = MultiByteToWideChar
+Name = Test #3 for MultiByteToWideChar
+TYPE = DEFAULT
+EXE1 = test3
+Description
+=Tests that MultiByteToWideChar correctly handles the following
+=error conditions: insufficient buffer space, invalid code pages,
+=and invalid flags.
+
diff --git a/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/CMakeLists.txt
new file mode 100644
index 0000000000..3d167dff7c
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_multibytetowidechar_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_multibytetowidechar_test4 coreclrpal)
+
+target_link_libraries(paltest_multibytetowidechar_test4
+ pthread
+ m
+ coreclrpal
+) \ No newline at end of file
diff --git a/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/test4.c b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/test4.c
new file mode 100644
index 0000000000..2ba606cf35
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/test4.c
@@ -0,0 +1,230 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test4.c
+**
+** Purpose: Tests MultiByteToWideChar with a UTF-8 encoding
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int ret;
+ int ret2;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ const char * const utf8Strings[] =
+ {
+ // Correct strings
+
+ // Empty string
+ "",
+ // 1 byte encoded 1 character long string
+ "A",
+ // 2 byte encoded 1 character long string
+ "\xC2\x80",
+ // 3 byte encoded 1 character long string
+ "\xE0\xA0\x80",
+ // 1 byte encoded characters only
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
+ // valid 2 byte encoded characters only
+ "\xC2\x80\xC3\xBF\xC7\x81\xDF\xBF",
+ // valid 3 byte encoded characters only
+ "\xE0\xA0\x80\xE1\xB6\x88\xE1\x80\x80\xEF\xBF\xBF",
+ // 1 byte and 2 byte encoded characters interleaved 1:1 starting and ending with 1 byte char
+ "\x41\xC2\x80\x42\xC3\xBF\x43\xC7\x81\x44\xDF\xBF\x45",
+ // 1 byte and 2 byte encoded characters interleaved 1:1 starting with 1 byte char, ending with 2 byte one
+ "\x41\xC2\x80\x42\xC3\xBF\x43\xC7\x81\x44\xDF\xBF",
+ // 1 byte and 2 byte encoded characters interleaved 1:1 starting with 2 byte char, ending with 1 byte one
+ "\xC2\x80\x42\xC3\xBF\x43\xC7\x81\x44\xDF\xBF\x45",
+ // 1 byte and 2 byte encoded characters interleaved 1:1 starting and ending with 2 byte char
+ "\xC2\x80\x42\xC3\xBF\x43\xC7\x81\x44\xDF\xBF",
+ // 1 byte and 2 byte encoded characters interleaved 2:2 starting and ending with 1 byte char
+ "\x41\x42\xC2\x80\xC3\xBF\x43\x44\xC7\x81\xDF\xBF\x45\x46",
+ // 1 byte and 2 byte encoded characters interleaved 2:2 starting with 1 byte char, ending with 2 byte one
+ "\x41\x42\xC2\x80\xC3\xBF\x43\x44\xC7\x81\xDF\xBF",
+ // 1 byte and 2 byte encoded characters interleaved 2:2 starting with 2 byte char, ending with 1 byte one
+ "\xC2\x80\xC3\xBF\x43\x44\xC7\x81\xDF\xBF\x45\x46",
+ // 1 byte and 2 byte encoded characters interleaved 2:2 starting and ending with 2 byte char
+ "\xC2\x80\xC3\xBF\x43\x44\xC7\x81\xDF\xBF",
+ // surrogates
+ "\xF0\x90\x80\x80\xF0\x90\x89\x80\xF3\x80\x8E\xB0\xF4\x8F\xBF\xBF",
+
+ // Strings with errors
+ // Incomplete 2 byte encoded character 1 byte missing standalone
+ "\xC2",
+ // Incomplete 3 byte encoded character 1 byte missing standalone
+ "\xE0\xA0",
+ // Incomplete 3 byte encoded character 2 bytes missing standalone
+ "\xE0",
+ // Incomplete surrogate character 1 byte missing standalone
+ "\xF0\x90\x80",
+ // Incomplete surrogate character 2 bytes missing standalone
+ "\xF0\x90",
+ // Incomplete surrogate character 3 bytes missing standalone
+ "\xF0",
+ // Trailing byte with no lead byte standalone
+ "\x80",
+ // Incomplete 2 byte encoded character 1 byte missing between 1 byte chars
+ "\x41\xC2\x42",
+ // Incomplete 3 byte encoded character 1 byte missing between 1 byte chars
+ "\x41\xE0\xA0\x42",
+ // Incomplete 3 byte encoded character 2 bytes missing between 1 byte chars
+ "\x41\xE0\x42",
+ // Trailing byte with no lead byte between 1 byte chars
+ "\x41\x80\x42",
+ // Incomplete 2 byte encoded character 1 byte missing before 1 byte char
+ "\xC2\x42",
+ // Incomplete 3 byte encoded character 1 byte missing before 1 byte char
+ "\xE0\xA0\x42",
+ // Incomplete 3 byte encoded character 2 bytes missing before 1 byte char
+ "\xE0\x42",
+ // Trailing byte with no lead byte before 1 byte char
+ "\x80\x42",
+ // Incomplete 2 byte encoded character 1 byte missing after 1 byte char
+ "\x41\xC2",
+ // Incomplete 3 byte encoded character 1 byte missing after 1 byte char
+ "\x41\xE0\xA0",
+ // Incomplete 3 byte encoded character 2 bytes missing after 1 byte char
+ "\x41\xE0",
+ // Trailing byte with no lead byte after 1 byte char
+ "\x41\x80",
+ // Incomplete 2 byte encoded character 1 byte missing between 2 byte chars
+ "\xC2\x80\xC2\xC3\xBF",
+ // Incomplete 3 byte encoded character 1 byte missing between 2 byte chars
+ "\xC2\x80\xE0\xA0\xC3\xBF",
+ // Incomplete 3 byte encoded character 2 bytes missing between 2 byte chars
+ "\xC2\x80\xE0\xC3\xBF",
+ // Trailing byte with no lead byte between 2 byte chars
+ "\xC2\x80\x80\xC3\xBF",
+ // 2 byte encoded character in non-shortest form encodings (these are not allowed)
+ "\xC0\x80",
+ // 3 byte encoded character in non-shortest form encodings (these are not allowed)
+ "\xE0\x80\x80",
+ // 4 byte encoded character in non-shortest form encodings (these are not allowed)
+ "\xF0\x80\x80\x80",
+ };
+
+ const WCHAR * const unicodeStrings[] =
+ {
+ // Empty string
+ W(""),
+ // 1 byte encoded 1 character long string
+ W("A"),
+ // 2 byte encoded 1 character long string
+ W("\x0080"),
+ // 3 byte encoded 1 character long string
+ W("\x0800"),
+ // 1 byte encoded characters only
+ W("ABCDEFGHIJKLMNOPQRSTUVWXYZ"),
+ // 2 byte encoded characters only
+ W("\x0080\x00FF\x01C1\x07FF"),
+ // valid 3 byte encoded characters only
+ W("\x0800\x1D88\x1000\xFFFF"),
+ // 1 byte and 2 byte encoded characters interleaved 1:1 starting and ending with 1 byte char
+ W("\x0041\x0080\x0042\x00FF\x0043\x01C1\x0044\x07FF\x0045"),
+ // 1 byte and 2 byte encoded characters interleaved 1:1 starting with 1 byte char, ending with 2 byte one
+ W("\x0041\x0080\x0042\x00FF\x0043\x01C1\x0044\x07FF"),
+ // 1 byte and 2 byte encoded characters interleaved 1:1 starting with 2 byte char, ending with 1 byte one
+ W("\x0080\x0042\x00FF\x0043\x01C1\x0044\x07FF\x0045"),
+ // 1 byte and 2 byte encoded characters interleaved 1:1 starting and ending with 2 byte char
+ W("\x0080\x0042\x00FF\x0043\x01C1\x0044\x07FF"),
+ // 1 byte and 2 byte encoded characters interleaved 2:2 starting and ending with 1 byte char
+ W("\x0041\x0042\x0080\x00FF\x0043\x0044\x01C1\x07FF\x0045\x0046"),
+ // 1 byte and 2 byte encoded characters interleaved 2:2 starting with 1 byte char, ending with 2 byte one
+ W("\x0041\x0042\x0080\x00FF\x0043\x0044\x01C1\x07FF"),
+ // 1 byte and 2 byte encoded characters interleaved 2:2 starting with 2 byte char, ending with 1 byte one
+ W("\x0080\x00FF\x0043\x0044\x01C1\x07FF\x0045\x0046"),
+ // 1 byte and 2 byte encoded characters interleaved 2:2 starting and ending with 2 byte char
+ W("\x0080\x00FF\x0043\x0044\x01C1\x07FF"),
+ // surrogates
+ W("\xD800\xDC00\xD800\xDE40\xDAC0\xDFB0\xDBFF\xDFFF"),
+
+ // Strings with errors
+ // Incomplete 2 byte encoded character standalone
+ W(""),
+ // Incomplete 3 byte encoded character 1 byte missing standalone
+ W(""),
+ // Incomplete 3 byte encoded character 2 bytes missing standalone
+ W(""),
+ // Incomplete surrogate character 1 byte missing standalone
+ W(""),
+ // Incomplete surrogate character 2 bytes missing standalone
+ W(""),
+ // Incomplete surrogate character 3 bytes missing standalone
+ W(""),
+ // Trailing byte with no lead byte standalone
+ W(""),
+ // Incomplete 2 byte encoded character 1 byte missing between 1 byte chars
+ W("\x0041\x0042"),
+ // Incomplete 3 byte encoded character 1 byte missing between 1 byte chars
+ W("\x0041\x0042"),
+ // Incomplete 3 byte encoded character 2 bytes missing between 1 byte chars
+ W("\x0041\x0042"),
+ // Trailing byte with no lead byte between 1 byte chars
+ W("\x0041\x0042"),
+ // Incomplete 2 byte encoded character 1 byte missing before 1 byte char
+ W("\x0042"),
+ // Incomplete 3 byte encoded character 1 byte missing before 1 byte char
+ W("\x0042"),
+ // Incomplete 3 byte encoded character 2 bytes missing before 1 byte char
+ W("\x0042"),
+ // Trailing byte with no lead byte before 1 byte char
+ W("\x0042"),
+ // Incomplete 2 byte encoded character 1 byte missing after 1 byte char
+ W("\x0041"),
+ // Incomplete 3 byte encoded character 1 byte missing after 1 byte char
+ W("\x0041"),
+ // Incomplete 3 byte encoded character 2 bytes missing after 1 byte char
+ W("\x0041"),
+ // Trailing byte with no lead byte after 1 byte char
+ W("\x0041"),
+ // Incomplete 2 byte encoded character 1 byte missing between 2 byte chars
+ W("\x0080\x00FF"),
+ // Incomplete 3 byte encoded character 1 byte missing between 2 byte chars
+ W("\x0080\x00FF"),
+ // Incomplete 3 byte encoded character 2 bytes missing between 2 byte chars
+ W("\x0080\x00FF"),
+ // Trailing byte with no lead byte between 2 byte chars
+ W("\x0080\x00FF"),
+ // 2 byte encoded character in non-shortest form encodings (these are not allowed)
+ W(""),
+ // 3 byte encoded character in non-shortest form encodings (these are not allowed)
+ W(""),
+ // 4 byte encoded character in non-shortest form encodings (these are not allowed)
+ W(""),
+ };
+
+ for (int i = 0; i < (sizeof(utf8Strings) / sizeof(utf8Strings[0])); i++)
+ {
+ ret = MultiByteToWideChar(CP_UTF8, 0, utf8Strings[i], -1, NULL, 0);
+ WCHAR* wideBuffer = malloc(ret * sizeof(WCHAR));
+ ret2 = MultiByteToWideChar(CP_UTF8, 0, utf8Strings[i], -1, wideBuffer, ret);
+ if (ret != ret2)
+ {
+ Fail("MultiByteToWideChar string %d: returned different string length for empty and real dest buffers!\n"
+ "Got %d for the empty one, %d for real one.\n", i, ret2, ret);
+ }
+
+ if (wcscmp(wideBuffer, unicodeStrings[i]) != 0)
+ {
+ Fail("MultiByteToWideChar string %d: the resulting string doesn't match the expected one!\n", i);
+ }
+
+ free(wideBuffer);
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+} \ No newline at end of file
diff --git a/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/testinfo.dat b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/testinfo.dat
new file mode 100644
index 0000000000..e95f413904
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/testinfo.dat
@@ -0,0 +1,13 @@
+#
+# Copyright (c) Microsoft Corporation. All rights reserved.
+#
+
+Version = 1.0
+Section = Locale Information
+Function = MultiByteToWideChar
+Name = Test #4 for MultiByteToWideChar
+TYPE = DEFAULT
+EXE1 = test4
+Description
+=Tests MultiByteToWideChar with UTF-8 encoded strings
+=containing various corner cases \ No newline at end of file
diff --git a/src/pal/tests/palsuite/locale_info/SetThreadLocale/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/SetThreadLocale/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/SetThreadLocale/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/locale_info/SetThreadLocale/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/SetThreadLocale/test1/CMakeLists.txt
new file mode 100644
index 0000000000..85824dd836
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/SetThreadLocale/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_setthreadlocale_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setthreadlocale_test1 coreclrpal)
+
+target_link_libraries(paltest_setthreadlocale_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/locale_info/SetThreadLocale/test1/test1.c b/src/pal/tests/palsuite/locale_info/SetThreadLocale/test1/test1.c
new file mode 100644
index 0000000000..794093cf4c
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/SetThreadLocale/test1/test1.c
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests SetThreadLocale with every valid locale to see that it passes
+** and that it actually sets the locale.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int i;
+
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Try all possible locale's */
+ for (i=0; i<0x000fffff; i++)
+ {
+ if (!IsValidLocale(i, LCID_INSTALLED))
+ {
+ continue;
+ }
+
+ if (!SetThreadLocale(i))
+ {
+ Fail("SetThreadLocale failed for an installed locale!\n");
+ }
+
+ if (GetThreadLocale() != i)
+ {
+ Fail("SetThreadLocale didn't actually change to LCID %#x!\n", i);
+ }
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/locale_info/SetThreadLocale/test1/testinfo.dat b/src/pal/tests/palsuite/locale_info/SetThreadLocale/test1/testinfo.dat
new file mode 100644
index 0000000000..ba0f5b7eeb
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/SetThreadLocale/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Locale Information
+Function = SetThreadLocale
+Name = Test #1 for SetThreadLocale
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Tests SetThreadLocale with every valid locale to see that it passes
+=and that it actually sets the locale.
diff --git a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/CMakeLists.txt
new file mode 100644
index 0000000000..dc5d5131ec
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
diff --git a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/CMakeLists.txt
new file mode 100644
index 0000000000..0d1d12b41e
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_widechartomultibyte_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_widechartomultibyte_test1 coreclrpal)
+
+target_link_libraries(paltest_widechartomultibyte_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/test1.c b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/test1.c
new file mode 100644
index 0000000000..cd763f33be
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/test1.c
@@ -0,0 +1,102 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests WideCharToMultiByte with all the ASCII characters (0-127).
+** Also tests that WideCharToMultiByte handles different buffer
+** lengths correctly (0, -1, and a valid length)
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ char mbStr[128];
+ WCHAR wideStr[128];
+ int ret;
+ int i;
+ int k;
+ BOOL bRet=TRUE;
+
+ /* These codepages are currently supported by the PAL */
+ int codePages[] ={
+ CP_ACP,
+ CP_UTF8
+ };
+
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /* Go through all of the code pages */
+ for(i=0; i<(sizeof(codePages)/sizeof(int)); i++)
+ {
+
+ for (k=0; k<128; k++)
+ {
+ wideStr[k] = 127 - k;
+ mbStr[k] = 0;
+ }
+
+ /* Convert with buffer size of 0 */
+ ret = WideCharToMultiByte(codePages[i], 0, wideStr, -1,
+ mbStr, 0, NULL, NULL);
+ if (ret != 128)
+ {
+ Trace("WideCharToMultiByte did not return correct string length!\n"
+ "Got %d, expected %d for code page %d with error %u.\n",
+ ret, 128,codePages[i],GetLastError());
+ bRet=FALSE;
+ }
+
+ /* Make sure the ASCII set (0-127) gets translated correctly */
+ ret = WideCharToMultiByte(codePages[i], 0, wideStr, -1,
+ mbStr, 128, NULL, NULL);
+ if (ret != 128)
+ {
+ Trace("WideCharToMultiByte did not return correct string length!\n"
+ "Got %d, expected %d for code page %d with error %u.\n",
+ ret, 128,codePages[i],GetLastError());
+ bRet=FALSE;
+ }
+
+ for (k=0; k<128; k++)
+ {
+ if (mbStr[k] != 127 - k)
+ {
+ Trace("WideCharToMultiByte failed to translate correctly!\n"
+ "Expected character %d to be %c (%x), got %c (%x) for "
+ "code page %d\n",k, 127 - k, 127 - k,mbStr[k], mbStr[k],
+ codePages[i]);
+ bRet=FALSE;
+ }
+ }
+
+
+ /* try a 0 length string ("") */
+ wideStr[0] = '\0';
+ ret = WideCharToMultiByte(codePages[i], 0, wideStr, -1,
+ mbStr, 0, NULL, NULL);
+ if (ret != 1)
+ {
+ Trace("WideCharToMultiByte did not return correct string length!\n"
+ "Got %d, expected %d for code page %d with error %u.\n",
+ ret, 1,codePages[i],GetLastError());
+ bRet=FALSE;
+ }
+ }
+
+ int result = bRet ? PASS : FAIL;
+ PAL_TerminateEx(result);
+ return result;
+}
+
diff --git a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/testinfo.dat b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/testinfo.dat
new file mode 100644
index 0000000000..9fb5f0f032
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Locale Information
+Function = WideCharToMultiByte
+Name = Test #1 for WideCharToMultiByte
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Tests WideCharToMultiByte with all the ASCII characters (0-127).
+=Also tests that WideCharToMultiByte handles different buffer
+=lengths correctly (0, -1, and a valid length)
diff --git a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/CMakeLists.txt
new file mode 100644
index 0000000000..bbfad2ca9f
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_widechartomultibyte_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_widechartomultibyte_test2 coreclrpal)
+
+target_link_libraries(paltest_widechartomultibyte_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/test2.c b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/test2.c
new file mode 100644
index 0000000000..f5d40ae903
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/test2.c
@@ -0,0 +1,88 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test2.c
+**
+** Purpose: Tests that WideCharToMultiByte respects the length of the wide
+** character string.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ char mbStr[128];
+ WCHAR wideStr[128];
+ int ret;
+ int i;
+ int k;
+ BOOL bRet=TRUE;
+
+ /* These codepages are currently supported by the PAL */
+ int codePages[] ={
+ CP_ACP,
+ CP_UTF8
+ };
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Go through all of the code pages */
+ for(i=0; i<(sizeof(codePages)/sizeof(int)); i++)
+ {
+
+ /* Filling the arrays */
+ for (k=0; k<128; k++)
+ {
+ wideStr[k] = 'a';
+ mbStr[i] = 0;
+ }
+
+ wideStr[127] = 0;
+
+ /* Passing a buffer that is too small */
+ ret = WideCharToMultiByte(codePages[i], 0, wideStr, 10,
+ mbStr, 0, NULL, NULL);
+ if (ret != 10)
+ {
+ Trace("WideCharToMultiByte did not return correct string length!\n"
+ "Got %d, expected %d for %d with error %u.\n", ret, 10,
+ codePages[i], GetLastError());
+ bRet = FALSE;
+ }
+
+ /* Passing a sufficiently large buffer */
+ mbStr[10] = 'b';
+ ret = WideCharToMultiByte(codePages[i], 0, wideStr, 10,
+ mbStr, 128, NULL, NULL);
+ if (ret != 10)
+ {
+ Trace("WideCharToMultiByte did not return correct string length!\n"
+ "Got %d, expected %d for code page %d with error %u.\n",
+ ret, 10, codePages[i], GetLastError());
+ bRet = FALSE;
+ }
+
+ /* Verifying overflow of the destination string did not occur */
+ if (mbStr[10] != 'b')
+ {
+ Trace("WideCharToMultiByte overflowed the destination buffer for "
+ "code page %d.\n", codePages[i]);
+ bRet = FALSE;
+ }
+
+ }
+
+ int result = bRet ? PASS : FAIL;
+ PAL_TerminateEx(result);
+ return result;
+}
+
diff --git a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/testinfo.dat b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/testinfo.dat
new file mode 100644
index 0000000000..e5b50b8143
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Locale Information
+Function = WideCharToMultiByte
+Name = Test #2 for WideCharToMultiByte
+TYPE = DEFAULT
+EXE1 = test2
+Description
+=Tests that WideCharToMultiByte respects the length of the wide
+=character string.
diff --git a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/CMakeLists.txt
new file mode 100644
index 0000000000..0edfd73931
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_widechartomultibyte_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_widechartomultibyte_test3 coreclrpal)
+
+target_link_libraries(paltest_widechartomultibyte_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/test3.c b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/test3.c
new file mode 100644
index 0000000000..ecd26addb4
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/test3.c
@@ -0,0 +1,100 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test3.c
+**
+** Purpose: Tests that WideCharToMultiByte correctly handles the following
+** error conditions: insufficient buffer space, invalid code pages,
+** and invalid flags.
+**
+**
+**==========================================================================*/
+
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ char mbStr[128];
+ WCHAR wideStr[128];
+ int ret;
+ int i;
+ int k;
+ BOOL bRet=TRUE;
+
+ /* These codepages are currently supported by the PAL */
+ int codePages[] ={
+ CP_ACP,
+ CP_UTF8
+ };
+
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Go through all of the code pages */
+ for(i=0; i<(sizeof(codePages)/sizeof(int)); i++)
+ {
+
+ for (k=0; k<128; k++)
+ {
+ wideStr[k] = 'a';
+ mbStr[k] = 0;
+ }
+
+ wideStr[127] = 0;
+
+ /* try with insufficient buffer space */
+ ret = WideCharToMultiByte(codePages[i], 0, wideStr, -1,
+ mbStr, 10, NULL, NULL);
+ if (ret != 0)
+ {
+ Trace("WideCharToMultiByte did not return an error!\n"
+ "Expected return of 0, got %d for code page %d.\n", ret,
+ codePages[i]);
+ bRet = FALSE;
+ }
+
+ ret = GetLastError();
+ if (ret != ERROR_INSUFFICIENT_BUFFER)
+ {
+ Fail("WideCharToMultiByte set the last error to %u instead of "
+ "ERROR_INSUFFICIENT_BUFFER for code page %d.\n",
+ GetLastError(),codePages[i]);
+ bRet = FALSE;
+ }
+ }
+
+ /* Return failure if any of the code pages returned the wrong results */
+ if(!bRet)
+ {
+ return FAIL;
+ }
+
+ /* try with a wacky code page */
+ ret = WideCharToMultiByte(-1, 0, wideStr, -1, mbStr, 128, NULL, NULL);
+ if (ret != 0)
+ {
+ Fail("WideCharToMultiByte did not return an error!\n"
+ "Expected return of 0, got %d for invalid code page.\n", ret);
+ }
+
+ ret = GetLastError();
+ if (ret != ERROR_INVALID_PARAMETER)
+ {
+ Fail("WideCharToMultiByte set the last error to %u instead of "
+ "ERROR_INVALID_PARAMETER for invalid code page -1.\n",
+ GetLastError());
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/testinfo.dat b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/testinfo.dat
new file mode 100644
index 0000000000..b737686c39
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Locale Information
+Function = WideCharToMultiByte
+Name = Test #3 for WideCharToMultiByte
+TYPE = DEFAULT
+EXE1 = test3
+Description
+=Tests that WideCharToMultiByte correctly handles the following
+=error conditions: insufficient buffer space and invalid code pages.
+
diff --git a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/CMakeLists.txt
new file mode 100644
index 0000000000..f0ffd84ee9
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_widechartomultibyte_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_widechartomultibyte_test4 coreclrpal)
+
+target_link_libraries(paltest_widechartomultibyte_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/test4.c b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/test4.c
new file mode 100644
index 0000000000..8ab5fe90af
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/test4.c
@@ -0,0 +1,131 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test4.c
+**
+** Purpose: Tests that WideCharToMultiByte correctly handles WC_NO_BEST_FIT_CHARS
+**
+**
+**==========================================================================*/
+
+
+#include <palsuite.h>
+
+/* C with a circumflex */
+wchar_t ustr[2] = { 0x108, 0 };
+
+/* expected conversion when best fit is allowed on Windows */
+char* lpBestFitRes = "C";
+
+/* expected conversion when no default character is specified */
+char* lpResStr1 = "?";
+
+/* expected conversion when the default character is 'k' */
+char myDefaultChar = 'k';
+char* lpResStr2 = "k";
+
+int
+TestWideCharToMultiByte(
+ IN UINT CodePage,
+ IN DWORD dwFlags,
+ IN LPCSTR lpDefaultChar,
+ IN LPSTR lpResStr)
+{
+ char mbstr[30];
+ int ret;
+ int testStatus = PASS;
+ BOOL usedDefaultChar = FALSE;
+
+ printf("WideCharToMultiByte (CodePage=%d, dwFlags=%#x, default=%c)\n",
+ CodePage, dwFlags, lpDefaultChar?*lpDefaultChar:' ');
+ ret = WideCharToMultiByte(CodePage, dwFlags, ustr, -1, mbstr, sizeof(mbstr),
+ lpDefaultChar, &usedDefaultChar);
+ if (ret != 0) {
+ printf(" converted C with circumflex to in Unicode to multibyte: "
+ "\"%s\"\n", mbstr);
+ printf(" used default character?: %d\n", usedDefaultChar);
+ if (strcmp(mbstr, lpResStr) != 0 || usedDefaultChar != TRUE)
+ {
+ printf("!!!! failed conversion !!!!\n");
+ testStatus = FAIL;
+ }
+ }
+ else {
+ printf("!!!! failed conversion !!!!\n");
+ testStatus = FAIL;
+ }
+ return testStatus;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ int testStatus = PASS;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Use WideCharToMultiByte to convert the string in code page CP_ACP.
+ * Note that the resulting string will be different on Windows PAL and
+ * Unix PAL. On Windows, the default best fit behavior will map C with
+ * circumflex to C.
+ *
+ * testStatus |= TestWideCharToMultiByte(CP_ACP, 0, NULL, lpBestFitRes);
+ *
+ * On Unix, where there is no support for finding best fit, it will be
+ * mapped to a '?'. In addition, it will trigger an ASSERT in the dbg/chk
+ * builds.
+ *
+ * testStatus |= TestWideCharToMultiByte(CP_ACP, 0, NULL, lpResStr1);
+ */
+
+ /* Use WideCharToMultiByte with WC_NO_BEST_FIR_CHARS to convert the string
+ * in CP_ACP (1252 by default). This will prevent it from mapping the C
+ * with circumflex to its closest match in the ANSI code page: C
+ */
+ testStatus |= TestWideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, NULL, lpResStr1);
+
+
+ /* Use WideCharToMultiByte with WC_NO_BEST_FIR_CHARS and a default character
+ * to convert the string. This will prevent it from mapping the C with
+ * circumflex to its closest match in the ANSI code page: C. It will be
+ * replaced with the specified default character.
+ */
+ testStatus |= TestWideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, &myDefaultChar, lpResStr2);
+
+ /* Use WideCharToMultiByte to convert the string in code page 1253
+ * Note that the resulting string will be different on Windows PAL and
+ * Unix PAL. On Windows, the default best fit behavior will map C with
+ * circumflex to C.
+ *
+ * testStatus |= TestWideCharToMultiByte(1253, 0, NULL, lpBestFitRes);
+ *
+ * On Unix, where there is no support for finding best fit, it will be
+ * mapped to a '?'. In addition, it will trigger an ASSERT in the dbg/chk
+ * builds.
+ *
+ * testStatus |= TestWideCharToMultiByte(1253, 0, NULL, lpResStr1);
+ */
+
+ /* Use WideCharToMultiByte with WC_NO_BEST_FIR_CHARS to convert the string
+ * in 1253. This will prevent it from mapping the C
+ * with circumflex to its closest match in the ANSI code page: C
+ */
+ testStatus |= TestWideCharToMultiByte(1253, WC_NO_BEST_FIT_CHARS, NULL, lpResStr1);
+
+ /* Use WideCharToMultiByte with WC_NO_BEST_FIR_CHARS and a default
+ * character to convert the string in 1253. This will prevent it from
+ * mapping the C with circumflex to its closest match in the ANSI code
+ * page: C. It will be replaced with the specified default character.
+ */
+ testStatus |= TestWideCharToMultiByte(1253, WC_NO_BEST_FIT_CHARS, &myDefaultChar, lpResStr2);
+
+ PAL_TerminateEx(testStatus);
+
+ return testStatus;
+}
+
diff --git a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/testinfo.dat b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/testinfo.dat
new file mode 100644
index 0000000000..03b00d3548
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Locale Information
+Function = WideCharToMultiByte
+Name = Test #4 for WideCharToMultiByte
+TYPE = DEFAULT
+EXE1 = test4
+Description
+=Tests that WideCharToMultiByte correctly handles WC_NO_BEST_FIT_CHARS
diff --git a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/CMakeLists.txt
new file mode 100644
index 0000000000..6ca2a628bf
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test5.c
+)
+
+add_executable(paltest_widechartomultibyte_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_widechartomultibyte_test5 coreclrpal)
+
+target_link_libraries(paltest_widechartomultibyte_test5
+ pthread
+ m
+ coreclrpal
+) \ No newline at end of file
diff --git a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/test5.c b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/test5.c
new file mode 100644
index 0000000000..3ca0d90d0f
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/test5.c
@@ -0,0 +1,154 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test4.c
+**
+** Purpose: Tests WideCharMultiByte with UTF-8 encoding
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int ret;
+ int ret2;
+
+ if (PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ const WCHAR * const unicodeStrings[] =
+ {
+ // Correct strings
+
+ // Empty string
+ W(""),
+ // 1 byte encoded 1 character long string
+ W("A"),
+ // 2 byte encoded 1 character long string
+ W("\x0080"),
+ // 3 byte encoded 1 character long string
+ W("\x0800"),
+ // 1 byte encoded characters only
+ W("ABCDEFGHIJKLMNOPQRSTUVWXYZ"),
+ // 2 byte encoded characters only
+ W("\x0080\x00FF\x01C1\x07FF"),
+ // valid 3 byte encoded characters only
+ W("\x0800\x1D88\x1000\xFFFF"),
+ // 1 byte and 2 byte encoded characters interleaved 1:1 starting and ending with 1 byte char
+ W("\x0041\x0080\x0042\x00FF\x0043\x01C1\x0044\x07FF\x0045"),
+ // 1 byte and 2 byte encoded characters interleaved 1:1 starting with 1 byte char, ending with 2 byte one
+ W("\x0041\x0080\x0042\x00FF\x0043\x01C1\x0044\x07FF"),
+ // 1 byte and 2 byte encoded characters interleaved 1:1 starting with 2 byte char, ending with 1 byte one
+ W("\x0080\x0042\x00FF\x0043\x01C1\x0044\x07FF\x0045"),
+ // 1 byte and 2 byte encoded characters interleaved 1:1 starting and ending with 2 byte char
+ W("\x0080\x0042\x00FF\x0043\x01C1\x0044\x07FF"),
+ // 1 byte and 2 byte encoded characters interleaved 2:2 starting and ending with 1 byte char
+ W("\x0041\x0042\x0080\x00FF\x0043\x0044\x01C1\x07FF\x0045\x0046"),
+ // 1 byte and 2 byte encoded characters interleaved 2:2 starting with 1 byte char, ending with 2 byte one
+ W("\x0041\x0042\x0080\x00FF\x0043\x0044\x01C1\x07FF"),
+ // 1 byte and 2 byte encoded characters interleaved 2:2 starting with 2 byte char, ending with 1 byte one
+ W("\x0080\x00FF\x0043\x0044\x01C1\x07FF\x0045\x0046"),
+ // 1 byte and 2 byte encoded characters interleaved 2:2 starting and ending with 2 byte char
+ W("\x0080\x00FF\x0043\x0044\x01C1\x07FF"),
+ // Surrogates
+ W("\xD800\xDC00\xD800\xDE40\xDAC0\xDFB0\xDBFF\xDFFF"),
+
+ // Strings with errors
+
+ // Single high surrogate
+ W("\xD800"),
+ // Single low surrogate
+ W("\xDC00"),
+ // Character followed by single high surrogate
+ W("\x0041\xD800"),
+ // Character followed by single low surrogate
+ W("\x0041\xDC00"),
+ // Single high surrogate between two characters
+ W("\x0041\xD800\x0042"),
+ // Single low surrogate between two characters
+ W("\x0041\xDC00\x0042"),
+ };
+
+ const char * const utf8Strings[] =
+ {
+ // Correct strings
+
+ // Empty string
+ "",
+ // 1 byte encoded 1 character long string
+ "A",
+ // 2 byte encoded 1 character long string
+ "\xC2\x80",
+ // 3 byte encoded 1 character long string
+ "\xE0\xA0\x80",
+ // 1 byte encoded characters only
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
+ // valid 2 byte encoded characters only
+ "\xC2\x80\xC3\xBF\xC7\x81\xDF\xBF",
+ // valid 3 byte encoded characters only
+ "\xE0\xA0\x80\xE1\xB6\x88\xE1\x80\x80\xEF\xBF\xBF",
+ // 1 byte and 2 byte encoded characters interleaved 1:1 starting and ending with 1 byte char
+ "\x41\xC2\x80\x42\xC3\xBF\x43\xC7\x81\x44\xDF\xBF\x45",
+ // 1 byte and 2 byte encoded characters interleaved 1:1 starting with 1 byte char, ending with 2 byte one
+ "\x41\xC2\x80\x42\xC3\xBF\x43\xC7\x81\x44\xDF\xBF",
+ // 1 byte and 2 byte encoded characters interleaved 1:1 starting with 2 byte char, ending with 1 byte one
+ "\xC2\x80\x42\xC3\xBF\x43\xC7\x81\x44\xDF\xBF\x45",
+ // 1 byte and 2 byte encoded characters interleaved 1:1 starting and ending with 2 byte char
+ "\xC2\x80\x42\xC3\xBF\x43\xC7\x81\x44\xDF\xBF",
+ // 1 byte and 2 byte encoded characters interleaved 2:2 starting and ending with 1 byte char
+ "\x41\x42\xC2\x80\xC3\xBF\x43\x44\xC7\x81\xDF\xBF\x45\x46",
+ // 1 byte and 2 byte encoded characters interleaved 2:2 starting with 1 byte char, ending with 2 byte one
+ "\x41\x42\xC2\x80\xC3\xBF\x43\x44\xC7\x81\xDF\xBF",
+ // 1 byte and 2 byte encoded characters interleaved 2:2 starting with 2 byte char, ending with 1 byte one
+ "\xC2\x80\xC3\xBF\x43\x44\xC7\x81\xDF\xBF\x45\x46",
+ // 1 byte and 2 byte encoded characters interleaved 2:2 starting and ending with 2 byte char
+ "\xC2\x80\xC3\xBF\x43\x44\xC7\x81\xDF\xBF",
+ // Surrogates
+ "\xF0\x90\x80\x80\xF0\x90\x89\x80\xF3\x80\x8E\xB0\xF4\x8F\xBF\xBF",
+
+ // Strings with errors
+
+ // Single high surrogate
+ "\xEF\xBF\xBD",
+ // Single low surrogate
+ "\xEF\xBF\xBD",
+ // Character followed by single high surrogate
+ "\x41\xEF\xBF\xBD",
+ // Character followed by single low surrogate
+ "\x41\xEF\xBF\xBD",
+ // Single high surrogate between two characters
+ "\x41\xEF\xBF\xBD\x42",
+ // Single low surrogate between two characters
+ "\x41\xEF\xBF\xBD\x42",
+ };
+
+ for (int i = 0; i < (sizeof(unicodeStrings) / sizeof(unicodeStrings[0])); i++)
+ {
+ ret = WideCharToMultiByte(CP_UTF8, 0, unicodeStrings[i], -1, NULL, 0, NULL, NULL);
+ CHAR* utf8Buffer = malloc(ret * sizeof(CHAR));
+ ret2 = WideCharToMultiByte(CP_UTF8, 0, unicodeStrings[i], -1, utf8Buffer, ret, NULL, NULL);
+ if (ret != ret2)
+ {
+ Fail("WideCharToMultiByte string %d: returned different string length for empty and real dest buffers!\n"
+ "Got %d for the empty one, %d for real one.\n", i, ret2, ret);
+ }
+
+ if (strcmp(utf8Buffer, utf8Strings[i]) != 0)
+ {
+ Fail("WideCharToMultiByte string %d: the resulting string doesn't match the expected one!\n", i);
+ }
+
+ free(utf8Buffer);
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+} \ No newline at end of file
diff --git a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/testinfo.dat b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/testinfo.dat
new file mode 100644
index 0000000000..485d9401e5
--- /dev/null
+++ b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/testinfo.dat
@@ -0,0 +1,13 @@
+#
+# Copyright (c) Microsoft Corporation. All rights reserved.
+#
+
+Version = 1.0
+Section = Locale Information
+Function = WideCharToMultiByte
+Name = Test #5 for WideCharToMultiByte
+TYPE = DEFAULT
+EXE1 = test5
+Description
+=Tests WideCharToMultiByte conversion to UTF-8
+=containing various corner cases \ No newline at end of file
diff --git a/src/pal/tests/palsuite/manual-inspect.dat b/src/pal/tests/palsuite/manual-inspect.dat
new file mode 100644
index 0000000000..c541b2ff85
--- /dev/null
+++ b/src/pal/tests/palsuite/manual-inspect.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+# Automatable to detect gross errors; also manually inspect for proper behaviour
+miscellaneous/messageboxw/test1,1
+# Automatable to detect gross errors; also manually inspect for proper behaviour
+# Env var PAL_DISABLE_MESSAGEBOX=1 disables msg boxes for automation on Windows
+miscellaneous/messageboxw/test2,1
+# Automatable to detect gross errors; also manually inspect for proper behaviour
+pal_specific/pal_get_stderr/test1,1
+pal_specific/pal_get_stdout/test1,1
+# The tests for the sleep api may fail depending upon what other
+# processes are running and their relative priority.
+threading/sleep/test1,1
+threading/sleepex/test1,1
+
diff --git a/src/pal/tests/palsuite/manual-unautomatable.dat b/src/pal/tests/palsuite/manual-unautomatable.dat
new file mode 100644
index 0000000000..0a9a7a1b63
--- /dev/null
+++ b/src/pal/tests/palsuite/manual-unautomatable.dat
@@ -0,0 +1,35 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+#This test is negative and will exit with exit(1).
+#Therefore, the harness would record it as a failure
+c_runtime/exit/test2,1
+# A successful DebugBreak test run dumps core or throws up an ASSERT
+# dialog box (or...) and returns an exit code != 0
+debug_api/debugbreak/test1,1
+# debug_api/outputdebugstringa/test1 attempts to send "Foo!" to the debugger
+# The PAL behaviour is implementation dependant and can include an interactive
+# dialog
+debug_api/outputdebugstringw/test1,1
+debug_api/outputdebugstringa/test1,1
+# The return code on success is NOT the usual 0, instead it's 3
+exception_handling/setunhandledexceptionfilter/test1,1
+# These tests require user intervention and cannot be automated
+pal_specific/pal_get_stdin/test1,1
+threading/setconsolectrlhandler/test1,1
+threading/setconsolectrlhandler/test4,1
+# These tests take several minutes to run and time out when run with the harness
+file_io/gettempfilenamea/test2,1
+file_io/gettempfilenamew/test2,1
+# getstdhandle fails under Windows if the output is redirected so
+# it must be run from the command line
+file_io/getstdhandle/test1,1
+# This test runs calculations in a nested loop to occupy the processor.
+# This causes the test harness to time out on some machines.
+threading/threadpriority/test1,1
+# This test runs for 96 minutes and will time out with the harness.
+threading/sleep/test2,1
+# This test runs forever by design.
+threading/waitformultipleobjects/test2,1
+
diff --git a/src/pal/tests/palsuite/miscellaneous/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/CMakeLists.txt
new file mode 100644
index 0000000000..86f194198b
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/CMakeLists.txt
@@ -0,0 +1,44 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(CharNextA)
+add_subdirectory(CharNextExA)
+add_subdirectory(CloseHandle)
+add_subdirectory(CreatePipe)
+add_subdirectory(FlushInstructionCache)
+add_subdirectory(FormatMessageW)
+add_subdirectory(FreeEnvironmentStringsW)
+add_subdirectory(GetCommandLineW)
+add_subdirectory(GetComputerNameW)
+add_subdirectory(GetEnvironmentStringsW)
+add_subdirectory(GetEnvironmentVariableA)
+add_subdirectory(GetEnvironmentVariableW)
+add_subdirectory(GetLastError)
+add_subdirectory(GetSystemInfo)
+add_subdirectory(GetTickCount)
+add_subdirectory(InterlockedBit)
+add_subdirectory(InterlockedCompareExchange)
+add_subdirectory(InterlockedCompareExchange64)
+add_subdirectory(InterlockedCompareExchangePointer)
+add_subdirectory(InterlockedDecrement)
+add_subdirectory(InterlockedDecrement64)
+add_subdirectory(InterlockedExchange)
+add_subdirectory(InterlockedExchange64)
+add_subdirectory(InterLockedExchangeAdd)
+add_subdirectory(InterlockedExchangePointer)
+add_subdirectory(InterlockedIncrement)
+add_subdirectory(InterlockedIncrement64)
+add_subdirectory(lstrcatW)
+add_subdirectory(lstrcpynW)
+add_subdirectory(lstrcpyW)
+add_subdirectory(lstrlenA)
+add_subdirectory(lstrlenW)
+add_subdirectory(queryperformancecounter)
+add_subdirectory(queryperformancefrequency)
+add_subdirectory(SetEnvironmentVariableA)
+add_subdirectory(SetEnvironmentVariableW)
+add_subdirectory(SetLastError)
+add_subdirectory(wsprintfA)
+add_subdirectory(wsprintfW)
+add_subdirectory(_i64tow)
+add_subdirectory(_ui64tow)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/CharNextA/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/CharNextA/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/CharNextA/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/CharNextA/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/CharNextA/test1/CMakeLists.txt
new file mode 100644
index 0000000000..8506d86737
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/CharNextA/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_charnexta_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_charnexta_test1 coreclrpal)
+
+target_link_libraries(paltest_charnexta_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/CharNextA/test1/test.c b/src/pal/tests/palsuite/miscellaneous/CharNextA/test1/test.c
new file mode 100644
index 0000000000..d2a3db31d5
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/CharNextA/test1/test.c
@@ -0,0 +1,62 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for CharNextA, ensures it returns the proper char for an
+** entire string
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc,char *argv[])
+{
+
+ char * AnExampleString = "this is the string";
+ char * StringPointer = AnExampleString;
+ int count = 0;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Use CharNext to move through an entire string. Ensure the pointer that
+ is returned points to the correct character, by comparing it with
+ 'StringPointer' which isn't touched by CharNext.
+ */
+
+ while(*AnExampleString != '\0')
+ {
+
+ /* Fail if any characters are different. This is comparing the
+ * addresses of both characters, not the characters themselves.
+ */
+
+ if(AnExampleString != &StringPointer[count])
+ {
+ Fail("ERROR: %#x and %#x are different. These should be the same "
+ " address.\n",AnExampleString,&StringPointer[count]);
+
+
+ }
+
+ AnExampleString = CharNextA(AnExampleString);
+ ++count;
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/CharNextA/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/CharNextA/test1/testinfo.dat
new file mode 100644
index 0000000000..e2b5e501d7
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/CharNextA/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = CharNextA
+Name = Positive Test for CharNextA
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test to see if CharNextA works properly
+= when calling it repeatedly on a single string.
diff --git a/src/pal/tests/palsuite/miscellaneous/CharNextA/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/CharNextA/test2/CMakeLists.txt
new file mode 100644
index 0000000000..04f4679630
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/CharNextA/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_charnexta_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_charnexta_test2 coreclrpal)
+
+target_link_libraries(paltest_charnexta_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/CharNextA/test2/test.c b/src/pal/tests/palsuite/miscellaneous/CharNextA/test2/test.c
new file mode 100644
index 0000000000..7261959021
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/CharNextA/test2/test.c
@@ -0,0 +1,67 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for CharNextA, ensures it returns an LPTSTR
+**
+**
+**=========================================================*/
+
+/* Depends on strcmp() */
+
+#include <palsuite.h>
+
+void testString(LPSTR input, LPSTR expected)
+{
+
+ LPTSTR pReturned = NULL;
+
+ pReturned = CharNextA(input);
+
+ /* Compare the Returned String to what it should be */
+ if(strcmp(expected,pReturned) != 0)
+ {
+ Fail("ERROR: CharNextA Failed: [%s] and [%s] are not equal, "
+ "they should be after calling CharNextA.\n",
+ pReturned,expected);
+ }
+
+
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* test several Strings */
+ testString("this is the string", "his is the string");
+ testString("t", "");
+ testString("", "");
+ testString("a\t", "\t");
+ testString("a\a", "\a");
+ testString("a\b", "\b");
+ testString("a\"", "\"");
+ testString("a\\", "\\");
+ testString("\\", "");
+ testString("\f", "");
+ testString("\b", "");
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/CharNextA/test2/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/CharNextA/test2/testinfo.dat
new file mode 100644
index 0000000000..4b663851b3
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/CharNextA/test2/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = CharNextA
+Name = Positive Test for CharNextA
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test to ensure it returns an LPTSTR when called on a string
diff --git a/src/pal/tests/palsuite/miscellaneous/CharNextExA/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/CharNextExA/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/CharNextExA/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/CharNextExA/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/CharNextExA/test1/CMakeLists.txt
new file mode 100644
index 0000000000..bfa12b5526
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/CharNextExA/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_charnextexa_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_charnextexa_test1 coreclrpal)
+
+target_link_libraries(paltest_charnextexa_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/CharNextExA/test1/test.c b/src/pal/tests/palsuite/miscellaneous/CharNextExA/test1/test.c
new file mode 100644
index 0000000000..9671ca86b8
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/CharNextExA/test1/test.c
@@ -0,0 +1,63 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for CharNextExA function
+**
+**
+**=========================================================*/
+
+/*
+ This test is FINISHED. This function is the same as CharNextA it seems,
+ since the only fields that differ are always 0.
+*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ char * AnExampleString = "this is the string";
+ char * StringPointer = AnExampleString;
+ int count = 0;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Use CharNext to move through an entire string. Ensure the pointer
+ * that is returned points to the correct character, by comparing it with
+ * 'stringPointer' which isn't touched by CharNext.
+ */
+
+ while(*AnExampleString != 0)
+ {
+ /* Fail if any characters are different. This is comparing the
+ * addresses of both characters, not the characters themselves.
+ */
+
+ if(AnExampleString != &StringPointer[count])
+ {
+ Fail("ERROR: %#x and %#x are different. These should be the "
+ "same address.\n",AnExampleString,&StringPointer[count]);
+ }
+
+ AnExampleString = CharNextExA(0,AnExampleString,0);
+ ++count;
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/CharNextExA/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/CharNextExA/test1/testinfo.dat
new file mode 100644
index 0000000000..ea36fa61e0
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/CharNextExA/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = CharNextA
+Name = Positive Test for CharNextExA
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test to see if CharNextExA works properly
+= when calling it repeatedly on a single string.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/CharNextExA/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/CharNextExA/test2/CMakeLists.txt
new file mode 100644
index 0000000000..556043abcd
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/CharNextExA/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_charnextexa_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_charnextexa_test2 coreclrpal)
+
+target_link_libraries(paltest_charnextexa_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/CharNextExA/test2/test.c b/src/pal/tests/palsuite/miscellaneous/CharNextExA/test2/test.c
new file mode 100644
index 0000000000..ffc153f5e6
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/CharNextExA/test2/test.c
@@ -0,0 +1,66 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for CharNextExA, ensures it returns an LPTSTR
+**
+**
+**=========================================================*/
+
+/* Depends on strcmp() */
+
+#include <palsuite.h>
+
+void testString(LPSTR input, LPSTR expected)
+{
+
+ LPTSTR pReturned = NULL;
+
+ pReturned = CharNextExA(0,input,0);
+
+ /* Compare the Returned String to what it should be */
+ if(strcmp(expected,pReturned) != 0)
+ {
+ Fail("ERROR: CharNextExA Failed: [%s] and [%s] are not equal, "
+ "they should be after calling CharNextExA.\n",
+ pReturned,expected);
+ }
+
+
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* test several Strings */
+ testString("this is the string", "his is the string");
+ testString("t", "");
+ testString("", "");
+ testString("a\t", "\t");
+ testString("a\a", "\a");
+ testString("a\b", "\b");
+ testString("a\"", "\"");
+ testString("a\\", "\\");
+ testString("\\", "");
+ testString("\f", "");
+ testString("\bx", "x");
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/CharNextExA/test2/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/CharNextExA/test2/testinfo.dat
new file mode 100644
index 0000000000..adc110769b
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/CharNextExA/test2/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = CharNextExA
+Name = Return Value test for CharNextExA
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test to ensure it returns an LPTSTR when called on a string
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/CloseHandle/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/CloseHandle/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/CloseHandle/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/CMakeLists.txt
new file mode 100644
index 0000000000..bbe37ddd19
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_closehandle_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_closehandle_test1 coreclrpal)
+
+target_link_libraries(paltest_closehandle_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/test.c b/src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/test.c
new file mode 100644
index 0000000000..8e42229c29
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/test.c
@@ -0,0 +1,64 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for CloseHandle function
+**
+**
+**=========================================================*/
+
+/* Depends on: CreateFile and WriteFile */
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ HANDLE FileHandle = NULL;
+ LPDWORD WriteBuffer; /* Used with WriteFile */
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ WriteBuffer = malloc(sizeof(WORD));
+
+ if ( WriteBuffer == NULL )
+ {
+ Fail("ERROR: Failed to allocate memory for WriteBuffer pointer. "
+ "Can't properly exec test case without this.\n");
+ }
+
+
+ /* Create a file, since this returns to us a HANDLE we can use */
+ FileHandle = CreateFile("testfile",
+ GENERIC_READ | GENERIC_WRITE,0,NULL,CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ /* Should be able to close this handle */
+ if(CloseHandle(FileHandle) == 0)
+ {
+ free(WriteBuffer);
+ Fail("ERROR: (Test 1) Attempted to close a HANDLE on a file, but the "
+ "return value was <=0, indicating failure.\n");
+ }
+
+ free(WriteBuffer);
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/testinfo.dat
new file mode 100644
index 0000000000..891e1dfcfc
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = CloseHandle
+Name = Positive Test for CloseHandle
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Open a file to get a handle, and then close the file using CloseHandle
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/CMakeLists.txt
new file mode 100644
index 0000000000..75de513be7
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_closehandle_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_closehandle_test2 coreclrpal)
+
+target_link_libraries(paltest_closehandle_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/test.c b/src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/test.c
new file mode 100644
index 0000000000..c1eea44070
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/test.c
@@ -0,0 +1,46 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for CloseHandle function, try to close an unopened HANDLE
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ HANDLE SomeHandle = NULL;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* If the handle is already closed and you can close it again,
+ * something is wrong.
+ */
+
+ if(CloseHandle(SomeHandle) != 0)
+ {
+ Fail("ERROR: Called CloseHandle on an already closed Handle "
+ "and it still returned as a success.\n");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/testinfo.dat
new file mode 100644
index 0000000000..6917e8586a
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = CloseHandle
+Name = Positive Test for CloseHandle
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Attempt to close an unintialized HANDLE, should be unable to do this.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/CreatePipe/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/CreatePipe/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/CreatePipe/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/CMakeLists.txt
new file mode 100644
index 0000000000..af878cb873
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_createpipe_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createpipe_test1 coreclrpal)
+
+target_link_libraries(paltest_createpipe_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/test1.c b/src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/test1.c
new file mode 100644
index 0000000000..3930183b60
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/test1.c
@@ -0,0 +1,113 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c (CreatePipe)
+**
+** Purpose: Tests the PAL implementation of the CreatePipe function.
+** This test will create two pipes, a read and a write. Once
+** the pipes have been created, they will be tested by writing
+** and then reading, then comparing the results.
+**
+** Depends: WriteFile
+** ReadFile
+** memcmp
+** CloseHandle
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+const char* cTestString = "one fish, two fish, red fish, blue fish.";
+
+int __cdecl main(int argc, char **argv)
+{
+ HANDLE hReadPipe = NULL;
+ HANDLE hWritePipe = NULL;
+ BOOL bRetVal = FALSE;
+ DWORD dwBytesWritten;
+ DWORD dwBytesRead;
+ char buffer[256];
+
+ SECURITY_ATTRIBUTES lpPipeAttributes;
+
+ /*Initialize the PAL*/
+ if ((PAL_Initialize(argc, argv)) != 0)
+ {
+ return (FAIL);
+ }
+
+ /*Setup SECURITY_ATTRIBUTES structure for CreatePipe*/
+ lpPipeAttributes.nLength = sizeof(lpPipeAttributes);
+ lpPipeAttributes.lpSecurityDescriptor = NULL;
+ lpPipeAttributes.bInheritHandle = TRUE;
+
+ /*Create a Pipe*/
+ bRetVal = CreatePipe(&hReadPipe, /* read handle*/
+ &hWritePipe, /* write handle */
+ &lpPipeAttributes, /* security attributes*/
+ 0); /* pipe size*/
+ if (bRetVal == FALSE)
+ {
+ Fail("ERROR: %ld :Unable to create pipe\n", GetLastError());
+ }
+
+ /*Write to the write pipe handle*/
+ bRetVal = WriteFile(hWritePipe, /* handle to write pipe*/
+ cTestString, /* buffer to write*/
+ strlen(cTestString),/* number of bytes to write*/
+ &dwBytesWritten, /* number of bytes written*/
+ NULL); /* overlapped buffer*/
+ if (bRetVal == FALSE)
+ {
+ Fail("ERROR: %ld :unable to write to write pipe handle "
+ "hWritePipe=0x%lx\n", GetLastError(), hWritePipe);
+ }
+
+ /*Read, 256 bytes, more bytes then actually written.
+ This will give allow us to use the value that ReadFile
+ returns for comparision.*/
+ bRetVal = ReadFile(hReadPipe, /* handle to read pipe*/
+ buffer, /* buffer to write to*/
+ 256, /* number of bytes to read*/
+ &dwBytesRead, /* number of bytes read*/
+ NULL); /* overlapped buffer*/
+ if (bRetVal == FALSE)
+ {
+ Fail("ERROR: %ld : unable read hWritePipe=0x%lx\n",
+ GetLastError(), hWritePipe);
+ }
+
+ /*Compare what was read with what was written.*/
+ if ((memcmp(cTestString, buffer, dwBytesRead)) != 0)
+ {
+ Fail("ERROR: read \"%s\" expected \"%s\" \n", buffer, cTestString);
+ }
+
+ /*Compare values returned from WriteFile and ReadFile.*/
+ if (dwBytesWritten != dwBytesRead)
+ {
+ Fail("ERROR: WriteFile wrote \"%d\", but ReadFile read \"%d\","
+ " these should be the same\n", buffer, cTestString);
+ }
+
+ /*Close write pipe handle*/
+ if (CloseHandle(hWritePipe) == 0)
+ {
+ Fail("ERROR: %ld : Unable to close write pipe handle "
+ "hWritePipe=0x%lx\n",GetLastError(), hWritePipe);
+ }
+
+ /*Close Read pipe handle*/
+ if (CloseHandle(hReadPipe) == 0)
+ {
+ Fail("ERROR: %ld : Unable to close read pipe handle "
+ "hReadPipe=0x%lx\n", GetLastError(), hReadPipe);
+ }
+
+ PAL_Terminate();
+ return (PASS);
+}
diff --git a/src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/testinfo.dat
new file mode 100644
index 0000000000..b9422b0627
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = CreatePipe
+Name = Test for CreatePipe
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests the PAL implementation of the CreatePipe function.
+= This test will create two pipes, a read and a write. Once
+= the pipes have been created, they will be tested by writing
+= and then reading, then comparing the results.
diff --git a/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/CMakeLists.txt
new file mode 100644
index 0000000000..fbd8b0f87d
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_flushinstructioncache_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_flushinstructioncache_test1 coreclrpal)
+
+target_link_libraries(paltest_flushinstructioncache_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/test1.c b/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/test1.c
new file mode 100644
index 0000000000..cdbefd01cc
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/test1.c
@@ -0,0 +1,66 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests that FlushInstructionCache returns the correct value for a
+** number of different inputs.
+**
+**
+** Note :
+** For this function, what constitutes "invalid parameters" will depend entirely
+** on the platform; because of this we can't simply test values on Windows and
+** then ask for the same results everywhere. Because of this, this test can
+** ensure that the function succeeds for some "obviously" valid values, but
+** can't make sure that it fails for invalid values.
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+void DoTest(void *Buffer, int Size, int Expected)
+{
+ int ret;
+
+ SetLastError(0);
+ ret = FlushInstructionCache(GetCurrentProcess(), Buffer, Size);
+ if (!ret && Expected)
+ {
+ Fail("Expected FlushInstructionCache to return non-zero, got zero!\n"
+ "region: %p, size: %d, GetLastError: %d\n", Buffer, Size,
+ GetLastError());
+ }
+ else if (ret && !Expected)
+ {
+ Fail("Expected FlushInstructionCache to return zero, got non-zero!\n"
+ "region: %p, size: %d, GetLastError: %d\n", Buffer, Size,
+ GetLastError());
+ }
+
+ if (!Expected && ERROR_NOACCESS != GetLastError())
+ {
+ Fail("FlushInstructionCache failed to set the last error to "
+ "ERROR_NOACCESS!\n");
+ }
+
+}
+
+int __cdecl main(int argc,char *argv[])
+{
+ char ValidPtr[256];
+
+ if(PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* with valid pointer, zero-size and valid size must succeed */
+ DoTest(ValidPtr, 0, 1);
+ DoTest(ValidPtr, 42, 1);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/testinfo.dat
new file mode 100644
index 0000000000..78ab5f77ff
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = FlushInstructionCache
+Name = Positive Test #1 for FlushInstructionCache
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Tests that FlushInstructionCache returns the correct value for a
+=number of different inputs.
diff --git a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/CMakeLists.txt
new file mode 100644
index 0000000000..7c20179353
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/CMakeLists.txt
@@ -0,0 +1,9 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..0f242e9b30
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_formatmessagew_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_formatmessagew_test1 coreclrpal)
+
+target_link_libraries(paltest_formatmessagew_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/test.c b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/test.c
new file mode 100644
index 0000000000..0cc4c43432
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/test.c
@@ -0,0 +1,63 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: Test for FormatMessageW() function
+**
+**
+**=========================================================*/
+
+#define UNICODE
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[]) {
+
+ WCHAR TheString[] = {'P','a','l',' ','T','e','s','t','\0'};
+ WCHAR OutBuffer[128];
+ int ReturnResult;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+
+ ReturnResult = FormatMessage(
+ FORMAT_MESSAGE_FROM_STRING, /* source and processing options */
+ TheString, /* message source */
+ 0, /* message identifier */
+ 0, /* language identifier */
+ OutBuffer, /* message buffer */
+ 1024, /* maximum size of message buffer */
+ NULL /* array of message inserts */
+ );
+
+
+ if(ReturnResult == 0)
+ {
+ Fail("ERROR: The return value was 0, which indicates failure. "
+ "The function failed when trying to Format a simple string"
+ ", with no formatters in it.");
+ }
+
+ if(memcmp(OutBuffer,TheString,wcslen(OutBuffer)*2+2) != 0)
+ {
+ Fail("ERROR: The formatted string should be %s but is really %s.",
+ convertC(TheString),
+ convertC(OutBuffer));
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/testinfo.dat
new file mode 100644
index 0000000000..5bd46bf604
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = FormatMessageW
+Name = Positive test of FormatMessageW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test a very simple case -- basically just copy a string into a buffer,
+= no formatting.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/CMakeLists.txt
new file mode 100644
index 0000000000..26092ac300
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_formatmessagew_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_formatmessagew_test2 coreclrpal)
+
+target_link_libraries(paltest_formatmessagew_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/test.c b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/test.c
new file mode 100644
index 0000000000..6c2d80b3f4
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/test.c
@@ -0,0 +1,581 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: Test for FormatMessageW() function
+**
+**
+**=========================================================*/
+
+#define UNICODE
+#include <palsuite.h>
+
+WCHAR OutBuffer[1024];
+
+/* Pass this test the string "INSERT" and it will succeed */
+
+int test1(int num, ...)
+{
+
+ WCHAR * TheString = convert("Pal %1!s! Testing");
+ int ReturnResult;
+ va_list TheList;
+ va_start(TheList,num);
+ memset( OutBuffer, 0, 1024 );
+
+ ReturnResult = FormatMessage(
+ FORMAT_MESSAGE_FROM_STRING, /* source and processing options */
+ TheString, /* message source */
+ 0, /* message identifier */
+ 0, /* language identifier */
+ OutBuffer, /* message buffer */
+ 1024, /* maximum size of message buffer */
+ &TheList /* array of message inserts */
+ );
+
+ va_end(TheList);
+
+ if(ReturnResult == 0)
+ {
+ Fail("ERROR: The return value was 0, which indicates failure. "
+ "The function failed when trying to Format a simple string,"
+ " with the 's' formatter.");
+
+ }
+
+ if(memcmp(OutBuffer, convert("Pal INSERT Testing"),
+ wcslen(OutBuffer)*2+2) != 0)
+ {
+ Fail("ERROR: The formated string should have been 'Pal INSERT "
+ "Testing' but '%s' was returned.",
+ convertC(OutBuffer));
+ }
+
+
+ return PASS;
+}
+
+/* Pass this test the int 40 and it will succeed */
+
+int test2(int num, ...)
+{
+
+ WCHAR * TheString = convert("Pal %1!i! Testing");
+ int ReturnResult;
+ va_list TheList;
+ va_start(TheList,num);
+
+ memset( OutBuffer, 0, 1024 );
+
+ ReturnResult = FormatMessage(
+ FORMAT_MESSAGE_FROM_STRING, /* source and processing options */
+ TheString, /* message source */
+ 0, /* message identifier */
+ 0, /* language identifier */
+ OutBuffer, /* message buffer */
+ 1024, /* maximum size of message buffer */
+ &TheList /* array of message inserts */
+ );
+
+ va_end(TheList);
+
+ if(ReturnResult == 0)
+ {
+ Fail("ERROR: The return value was 0, which indicates failure. "
+ "The function failed when trying to Format a simple string,"
+ " with the 'i' formatter.");
+ }
+
+ if(memcmp(OutBuffer, convert("Pal 40 Testing"),wcslen(OutBuffer)*2+2) != 0)
+ {
+ Fail("ERROR: The formated string should have been 'Pal 40 Testing' "
+ "but '%s' was returned.", convertC(OutBuffer));
+ }
+ return PASS;
+}
+
+/* Pass this test the character 'a' and it will succeed */
+
+int test3(int num, ...) {
+
+ WCHAR * TheString = convert("Pal %1!c! Testing");
+ int ReturnResult;
+ va_list TheList;
+ va_start(TheList,num);
+ memset( OutBuffer, 0, 1024 );
+ ReturnResult = FormatMessage(
+ FORMAT_MESSAGE_FROM_STRING, /* source and processing options */
+ TheString, /* message source */
+ 0, /* message identifier */
+ 0, /* language identifier */
+ OutBuffer, /* message buffer */
+ 1024, /* maximum size of message buffer */
+ &TheList /* array of message inserts */
+ );
+
+ va_end(TheList);
+
+ if(ReturnResult == 0)
+ {
+ Fail("ERROR: The return value was 0, which indicates failure. "
+ "The function failed when trying to Format a simple string,"
+ " with the 'c' formatter.");
+ }
+
+ if(memcmp(OutBuffer, convert("Pal a Testing"),wcslen(OutBuffer)*2+2) != 0)
+ {
+ Fail("ERROR: The formated string should have been 'Pal a Testing' "
+ "but '%s' was returned.", convertC(OutBuffer));
+
+ }
+
+ return PASS;
+}
+
+/* Pass this test the character 'a' and it will succeed */
+
+int test4(int num, ...) {
+
+ WCHAR * TheString = convert("Pal %1!C! Testing");
+ int ReturnResult;
+ va_list TheList;
+ va_start(TheList,num);
+ memset( OutBuffer, 0, 1024 );
+ ReturnResult = FormatMessage(
+ FORMAT_MESSAGE_FROM_STRING, /* source and processing options */
+ TheString, /* message source */
+ 0, /* message identifier */
+ 0, /* language identifier */
+ OutBuffer, /* message buffer */
+ 1024, /* maximum size of message buffer */
+ &TheList /* array of message inserts */
+ );
+
+ va_end(TheList);
+
+ if(ReturnResult == 0)
+ {
+ Fail("ERROR: The return value was 0, which indicates failure. "
+ "The function failed when trying to Format a simple string,"
+ " with the 'C' formatter.");
+ }
+
+ if(memcmp(OutBuffer, convert("Pal a Testing"),wcslen(OutBuffer)*2+2) != 0)
+ {
+ Fail("ERROR: The formated string should have been 'Pal a Testing' "
+ "but '%s' was returned.",convertC(OutBuffer));
+ }
+
+ return PASS;
+}
+
+/* Pass this test the number 57 and it will succeed */
+
+int test5(int num, ...)
+{
+
+ WCHAR * TheString = convert("Pal %1!d! Testing");
+ int ReturnResult;
+ va_list TheList;
+ va_start(TheList,num);
+ memset( OutBuffer, 0, 1024 );
+
+ ReturnResult = FormatMessage(
+ FORMAT_MESSAGE_FROM_STRING, /* source and processing options */
+ TheString, /* message source */
+ 0, /* message identifier */
+ 0, /* language identifier */
+ OutBuffer, /* message buffer */
+ 1024, /* maximum size of message buffer */
+ &TheList /* array of message inserts */
+ );
+
+ va_end(TheList);
+
+ if(ReturnResult == 0)
+ {
+ Fail("ERROR: The return value was 0, which indicates failure. "
+ "The function failed when trying to Format a simple string, "
+ "with the 'd' formatter.");
+
+ }
+
+ if(memcmp(OutBuffer, convert("Pal 57 Testing"),wcslen(OutBuffer)*2+2) != 0)
+ {
+ Fail("ERROR: The formated string should have been 'Pal 57 Testing' "
+ "but '%s' was returned.",convertC(OutBuffer));
+
+ }
+
+ return PASS;
+}
+
+/* Pass this test the characters 'a' and 'b' and it will succeed. */
+
+int test6(int num, ...) {
+
+ WCHAR * TheString = convert("Pal %1!hc! and %2!hC! Testing");
+ int ReturnResult;
+ va_list TheList;
+ va_start(TheList,num);
+ memset( OutBuffer, 0, 1024 );
+
+ ReturnResult = FormatMessage(
+ FORMAT_MESSAGE_FROM_STRING, /* source and processing options */
+ TheString, /* message source */
+ 0, /* message identifier */
+ 0, /* language identifier */
+ OutBuffer, /* message buffer */
+ 1024, /* maximum size of message buffer */
+ &TheList /* array of message inserts */
+ );
+
+ va_end(TheList);
+
+ if(ReturnResult == 0)
+ {
+ Fail("ERROR: The return value was 0, which indicates failure. "
+ "The function failed when trying to Format a simple string, "
+ "with the 'hc' and 'hC' formatters.");
+
+ }
+
+ if(memcmp(OutBuffer, convert("Pal a and b Testing"),
+ wcslen(OutBuffer)*2+2) != 0)
+ {
+ Fail("ERROR: The formated string should have been 'Pal a and b "
+ "Testing' but '%s' was returned.", convertC(OutBuffer));
+
+ }
+
+ return PASS;
+}
+
+/* Pass this test 90, the string 'foo' and the string 'bar' to succeed */
+
+int test7(int num, ...)
+{
+
+ WCHAR * TheString = convert("Pal %1!hd! and %2!hs! and %3!hS! Testing");
+ int ReturnResult;
+ va_list TheList;
+ va_start(TheList,num);
+ memset( OutBuffer, 0, 1024 );
+
+ ReturnResult = FormatMessage(
+ FORMAT_MESSAGE_FROM_STRING, /* source and processing options */
+ TheString, /* message source */
+ 0, /* message identifier */
+ 0, /* language identifier */
+ OutBuffer, /* message buffer */
+ 1024, /* maximum size of message buffer */
+ &TheList /* array of message inserts */
+ );
+
+ va_end(TheList);
+
+ if(ReturnResult == 0)
+ {
+ Fail("ERROR: The return value was 0, which indicates failure. "
+ "The function failed when trying to Format a simple string, "
+ "with the 'hd', 'hs' and 'hS' formatters.");
+
+ }
+
+ if(memcmp(OutBuffer,
+ convert("Pal 90 and foo and bar Testing"),
+ wcslen(OutBuffer)*2+2) != 0)
+ {
+ Fail("ERROR: The formated string should have been 'Pal 90 and foo "
+ "and bar Testing' but '%s' was returned.",convertC(OutBuffer));
+ }
+
+ return PASS;
+}
+
+/* Pass this test the characters 'a', 'b' and the numbers 50 and 100 */
+
+int test8(int num, ...)
+{
+
+ WCHAR * TheString =
+ convert("Pal %1!lc! and %2!lC! and %3!ld! and %4!li! Testing");
+ int ReturnResult;
+ va_list TheList;
+ va_start(TheList,num);
+ memset( OutBuffer, 0, 1024 );
+
+ ReturnResult = FormatMessage(
+ FORMAT_MESSAGE_FROM_STRING, /* source and processing options */
+ TheString, /* message source */
+ 0, /* message identifier */
+ 0, /* language identifier */
+ OutBuffer, /* message buffer */
+ 1024, /* maximum size of message buffer */
+ &TheList /* array of message inserts */
+ );
+
+ va_end(TheList);
+
+ if(ReturnResult == 0)
+ {
+ Fail("ERROR: The return value was 0, which indicates failure. "
+ "The function failed when trying to Format a simple string, "
+ "with the 'lc', 'lC', 'ld' and 'li' formatters.");
+
+ }
+
+ if(memcmp(OutBuffer,
+ convert("Pal a and b and 50 and 100 Testing"),
+ wcslen(OutBuffer)*2+2) != 0)
+ {
+ Fail("ERROR: The formated string should have been 'Pal a and b and 50"
+ " and 100 Testing' but '%s' was returned.",convertC(OutBuffer));
+
+ }
+
+ return PASS;
+}
+
+/* Pass this test the wide string 'foo' and 'bar' and the unsigned
+ int 56 to pass
+*/
+
+int test9(int num, ...) {
+
+ WCHAR * TheString = convert("Pal %1!ls! and %2!ls! and %3!lu! Testing");
+ int ReturnResult;
+ va_list TheList;
+ va_start(TheList,num);
+ memset( OutBuffer, 0, 1024 );
+ ReturnResult = FormatMessage(
+ FORMAT_MESSAGE_FROM_STRING, /* source and processing options */
+ TheString, /* message source */
+ 0, /* message identifier */
+ 0, /* language identifier */
+ OutBuffer, /* message buffer */
+ 1024, /* maximum size of message buffer */
+ &TheList /* array of message inserts */
+ );
+
+ va_end(TheList);
+
+ if(ReturnResult == 0)
+ {
+ Fail("ERROR: The return value was 0, which indicates failure. "
+ "The function failed when trying to Format a simple string,"
+ " with the 'ls', 'lS' and 'lu' formatters.");
+
+ }
+
+ if(memcmp(OutBuffer,
+ convert("Pal foo and bar and 56 Testing"),
+ wcslen(OutBuffer)*2+2) != 0)
+ {
+ Fail("ERROR: The formated string should have been 'Pal foo and bar "
+ "and 56 Testing' but '%s' was returned.",convertC(OutBuffer));
+
+ }
+
+ return PASS;
+}
+
+/* Pass this test the hex values 0x123ab and 0x123cd */
+
+int test10(int num, ...)
+{
+
+ WCHAR * TheString = convert("Pal %1!lx! and %2!lX! Testing");
+ int ReturnResult;
+ va_list TheList;
+ va_start(TheList,num);
+ memset( OutBuffer, 0, 1024 );
+ ReturnResult = FormatMessage(
+ FORMAT_MESSAGE_FROM_STRING, /* source and processing options */
+ TheString, /* message source */
+ 0, /* message identifier */
+ 0, /* language identifier */
+ OutBuffer, /* message buffer */
+ 1024, /* maximum size of message buffer */
+ &TheList /* array of message inserts */
+ );
+
+ va_end(TheList);
+
+ if(ReturnResult == 0)
+ {
+ Fail("ERROR: The return value was 0, which indicates failure. "
+ "The function failed when trying to Format a simple string, "
+ "with the 'lx' and 'lX' formatters.");
+
+ }
+
+ if(memcmp(OutBuffer,
+ convert("Pal 123ab and 123CD Testing"),
+ wcslen(OutBuffer)*2+2) != 0)
+ {
+ Fail("ERROR: The formated string should have been 'Pal 123ab and "
+ "123CD Testing' but '%s' was returned.", convertC(OutBuffer));
+
+ }
+
+ return PASS;
+}
+
+/* Pass this test a pointer to 0x123ab and the string 'foo' to pass */
+
+int test11(int num, ...)
+{
+
+ WCHAR * TheString = convert("Pal %1!p! and %2!S! Testing");
+ int ReturnResult;
+ va_list TheList;
+ va_start(TheList,num);
+ memset( OutBuffer, 0, 1024 );
+
+ ReturnResult = FormatMessage(
+ FORMAT_MESSAGE_FROM_STRING, /* source and processing options */
+ TheString, /* message source */
+ 0, /* message identifier */
+ 0, /* language identifier */
+ OutBuffer, /* message buffer */
+ 1024, /* maximum size of message buffer */
+ &TheList /* array of message inserts */
+ );
+
+ va_end(TheList);
+
+ if(ReturnResult == 0)
+ {
+ Fail("ERROR: The return value was 0, which indicates failure. "
+ "The function failed when trying to Format a simple string, "
+ "with the 'p' and 'S' formatters.");
+
+ }
+
+/*
+** Run only on 64 bit platforms
+*/
+#if defined(BIT64) && defined(PLATFORM_UNIX)
+ Trace("Testing for 64 Bit Platforms \n");
+ if(memcmp(OutBuffer,
+ convert("Pal 00000000000123AB and foo Testing"),
+ wcslen(OutBuffer)*2+2) != 0 &&
+ /* BSD style */
+ memcmp( OutBuffer,
+ convert( "Pal 0x123ab and foo Testing" ),
+ wcslen(OutBuffer)*2+2 ) != 0 )
+ {
+ Fail("ERROR: The formated string should have been 'Pal 000123AB and "
+ "foo Testing' but '%s' was returned.",convertC(OutBuffer));
+
+ }
+
+#else
+ Trace("Testing for Non 64 Bit Platforms \n");
+ if(memcmp(OutBuffer,
+ convert("Pal 000123AB and foo Testing"),
+ wcslen(OutBuffer)*2+2) != 0 &&
+ /* BSD style */
+ memcmp( OutBuffer,
+ convert( "Pal 0x123ab and foo Testing" ),
+ wcslen(OutBuffer)*2+2 ) != 0 )
+ {
+ Fail("ERROR: The formated string should have been 'Pal 000123AB and "
+ "foo Testing' but '%s' was returned.",convertC(OutBuffer));
+
+ }
+
+#endif
+
+ return PASS;
+}
+
+/* Pass this test the unsigned int 100 and the hex values 0x123ab and 0x123cd
+to succeed */
+
+int test12(int num, ...)
+{
+
+ WCHAR * TheString = convert("Pal %1!u! and %2!x! and %3!X! Testing");
+ int ReturnResult;
+ va_list TheList;
+ va_start(TheList,num);
+ memset( OutBuffer, 0, 1024 );
+
+ ReturnResult = FormatMessage(
+ FORMAT_MESSAGE_FROM_STRING, /* source and processing options */
+ TheString, /* message source */
+ 0, /* message identifier */
+ 0, /* language identifier */
+ OutBuffer, /* message buffer */
+ 1024, /* maximum size of message buffer */
+ &TheList /* array of message inserts */
+ );
+
+ va_end(TheList);
+
+ if(ReturnResult == 0)
+ {
+ Fail("ERROR: The return value was 0, which indicates failure. "
+ "The function failed when trying to Format a simple string, "
+ "with the 'u', 'x' and 'X' formatters.");
+
+ }
+
+ if(memcmp(OutBuffer,
+ convert("Pal 100 and 123ab and 123CD Testing"),
+ wcslen(OutBuffer)*2+2) != 0)
+ {
+ Fail("ERROR: The formated string should have been 'Pal 100 and "
+ "123ab and 123CD Testing' but '%s' was returned.",
+ convertC(OutBuffer));
+
+ }
+
+ return PASS;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR szwInsert[] = {'I','N','S','E','R','T','\0'};
+ WCHAR szwFoo[] = {'f','o','o','\0'};
+ WCHAR szwBar[] = {'b','a','r','\0'};
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ if(test1(0,szwInsert) || /* Test %s */
+ test2(0,40) || /* Test %i */
+ test3(0,'a') || /* Test %c */
+ test4(0,'a') || /* Test %C */
+ test5(0,57) || /* Test %d */
+ test6(0,'a','b') || /* Test %hc, %hC */
+ test7(0,90,"foo","bar") || /* Test %hd,hs,hS */
+ test8(0,'a','b',50,100) || /* Test %lc, lC, ld, li */
+ test9(0,szwFoo,szwBar,56) || /* Test %ls,lS,lu */
+ test10(0,0x123ab,0x123cd) || /* Test %lx, %lX */
+ test11(0,(void *)0x123ab,"foo") || /* Test %p, %S */
+ test12(0,100,0x123ab,0x123cd)) /* Test %u,x,X */
+ {
+
+
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/testinfo.dat
new file mode 100644
index 0000000000..5e4a35428e
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = FormatMessageW
+Name = Positive test of FormatMessageW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= A collection of tests to check and make sure all the standard formatters work.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/CMakeLists.txt
new file mode 100644
index 0000000000..b430511c4c
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_formatmessagew_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_formatmessagew_test3 coreclrpal)
+
+target_link_libraries(paltest_formatmessagew_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/test.c b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/test.c
new file mode 100644
index 0000000000..a390c00fea
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/test.c
@@ -0,0 +1,85 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: Test for FormatMessageW() function
+**
+**
+**=========================================================*/
+
+#define UNICODE
+#include <palsuite.h>
+
+WCHAR OutBuffer[1024];
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ WCHAR * TheString;
+ WCHAR * CorrectString;
+ int ReturnResult;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ TheString = convert("Pal %1!u! %2!i! %3!s! Testing");
+
+ /* The resulting value in the buffer shouldn't be formatted at all,
+ because the inserts are being ignored.
+ */
+
+ ReturnResult = FormatMessage(
+ FORMAT_MESSAGE_FROM_STRING |
+ FORMAT_MESSAGE_IGNORE_INSERTS, /* source and processing options */
+ TheString, /* message source */
+ 0, /* message identifier */
+ 0, /* language identifier */
+ OutBuffer, /* message buffer */
+ 1024, /* maximum size of message buffer */
+ NULL /* array of message inserts */
+ );
+
+
+
+ if(ReturnResult == 0)
+ {
+ free(TheString);
+ Fail("ERROR: The return value was 0, which indicates failure. "
+ "The function failed when trying to Format a simple string, "
+ "using the IGNORE_INSERTS flag.\n");
+ }
+
+
+ /* Note: Since 's' is the default insert, when this function is called
+ with ignore inserts, it strips %3!s! down to just %3 -- as they're
+ equal.
+ */
+ if(memcmp(OutBuffer,
+ (CorrectString = convert("Pal %1!u! %2!i! %3 Testing")),
+ wcslen(OutBuffer)*2+2) != 0)
+ {
+ free(TheString);
+ free(CorrectString);
+ Fail("ERROR: Since the IGNORE_INSERTS flag was set, the result "
+ "should have been 'Pal %%1!u! %%2!i! %%3 Testing' but was "
+ "really '%S'.\n",OutBuffer);
+ }
+
+ free(TheString);
+ free(CorrectString);
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/testinfo.dat
new file mode 100644
index 0000000000..cad1f63817
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = FormatMessageW
+Name = Positive test of FormatMessageW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test to ensure the IGNORE_INSERTS flag works properly.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/CMakeLists.txt
new file mode 100644
index 0000000000..cae8ff149c
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_formatmessagew_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_formatmessagew_test4 coreclrpal)
+
+target_link_libraries(paltest_formatmessagew_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/test.c b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/test.c
new file mode 100644
index 0000000000..4f865efe7e
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/test.c
@@ -0,0 +1,77 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: Test for FormatMessageW() function
+**
+**
+**=========================================================*/
+
+#define UNICODE
+#include <palsuite.h>
+
+WCHAR OutBuffer[1024];
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ WCHAR * TheString;
+ WCHAR* TheArray[3];
+ int ReturnResult;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ TheString = convert("Pal %1 %2 %3 Testing");
+ TheArray[0] = convert("Foo");
+ TheArray[1] = convert("Bar");
+ TheArray[2] = convert("FooBar");
+
+ /* This should just use the 3 strings in the array to replace
+ inserts in the given string.
+ */
+
+ ReturnResult = FormatMessage(
+ FORMAT_MESSAGE_FROM_STRING |
+ FORMAT_MESSAGE_ARGUMENT_ARRAY, /* source and processing options */
+ TheString, /* message source */
+ 0, /* message identifier */
+ 0, /* language identifier */
+ OutBuffer, /* message buffer */
+ 1024, /* maximum size of message buffer */
+ (va_list *) TheArray /* array of message inserts */
+ );
+
+ if(ReturnResult == 0)
+ {
+ Fail("ERROR: The return value was 0, which indicates failure. "
+ "The function failed when trying to Format a simple string, "
+ "usin gthe ARGUMENT_ARRAY flag.");
+ }
+
+ if(memcmp(OutBuffer,
+ convert("Pal Foo Bar FooBar Testing"),
+ wcslen(OutBuffer)*2+2) != 0)
+ {
+ Fail("ERROR: Since the FORMAT_MESSAGE_ARGUMENT_ARRAY flag was set, "
+ "the result should have been 'Pal Foo Bar FooBar Testing' but was"
+ " really '%s'.",convertC(OutBuffer));
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/testinfo.dat
new file mode 100644
index 0000000000..33e0cfa827
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = FormatMessageW
+Name = Positive test of FormatMessageW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test to ensure the FORMAT_MESSAGE_ARGUMENT_ARRAY flag works properly.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/CMakeLists.txt
new file mode 100644
index 0000000000..6779f94ff9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_formatmessagew_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_formatmessagew_test5 coreclrpal)
+
+target_link_libraries(paltest_formatmessagew_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/test.c b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/test.c
new file mode 100644
index 0000000000..148c2ff236
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/test.c
@@ -0,0 +1,76 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: Test for FormatMessageW() function
+**
+**
+**=========================================================*/
+
+
+#define UNICODE
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[]) {
+
+ WCHAR * TheString;
+ LPWSTR OutBuffer;
+ WCHAR* TheArray[3];
+ int ReturnResult;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ TheString = convert("Pal %1 %2 %3 Testing");
+ TheArray[0] = convert("Foo");
+ TheArray[1] = convert("Bar");
+ TheArray[2] = convert("FooBar");
+
+ /* OutBuffer will be allocated in the function, if the flag
+ is working properly.
+ */
+
+ ReturnResult = FormatMessage(
+ FORMAT_MESSAGE_FROM_STRING |
+ FORMAT_MESSAGE_ARGUMENT_ARRAY |
+ FORMAT_MESSAGE_ALLOCATE_BUFFER, /* source and processing options */
+ TheString, /* message source */
+ 0, /* message identifier */
+ 0, /* language identifier */
+ (LPWSTR)&OutBuffer, /* message buffer */
+ 0, /* maximum size of message buffer */
+ (va_list *) TheArray /* array of message inserts */
+ );
+
+ if(ReturnResult == 0)
+ {
+ Fail("ERROR: The return value was 0, which indicates failure. "
+ "The function failed when trying to Format a simple string, "
+ "using the ALLOCATE_BUFFER flag.");
+ }
+
+ if(memcmp(OutBuffer,
+ convert("Pal Foo Bar FooBar Testing"),
+ wcslen(OutBuffer)*2+2) != 0)
+ {
+ Fail("ERROR: Since the FORMAT_MESSAGE_ALLOCATE_BUFFER flag was set, "
+ "the result should have been 'Pal Foo Bar FooBar Testing' but "
+ "was really '%s'.",convertC(OutBuffer));
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/testinfo.dat
new file mode 100644
index 0000000000..6f497c23cc
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = FormatMessageW
+Name = Positive test of FormatMessageW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test to ensure the FORMAT_MESSAGE_ALLOCATE_BUFFER flag works properly.
diff --git a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/CMakeLists.txt
new file mode 100644
index 0000000000..450b2b808b
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_formatmessagew_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_formatmessagew_test6 coreclrpal)
+
+target_link_libraries(paltest_formatmessagew_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/test.c b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/test.c
new file mode 100644
index 0000000000..48f5e3e93d
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/test.c
@@ -0,0 +1,78 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: Test for FormatMessageW() function
+**
+**
+**=========================================================*/
+
+
+#define UNICODE
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[]) {
+
+
+ LPWSTR OutBuffer;
+ int ReturnResult;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+
+ /* This is testing the use of FROM_SYSTEM. We can't check to ensure
+ the error message it extracts is correct, only that it does place some
+ information into the buffer when it is called.
+ */
+
+ /*
+
+ ERROR_SUCCESS (0L) is normally returned by GetLastError,
+ But, the ERROR_SUCCESS is removed from messages for Unix based Systems
+ To ensure that we have some information into the buffer we are using the message
+ identifier value 2L (ERROR_FILE_NOT_FOUND)
+ */
+ ReturnResult = FormatMessage(
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_ALLOCATE_BUFFER, /* source and processing options */
+ NULL, /* message source */
+ 2L, /* message identifier */
+ 0, /* language identifier */
+ (LPWSTR)&OutBuffer, /* message buffer */
+ 0, /* maximum size of message buffer */
+ NULL /* array of message inserts */
+ );
+
+ if(ReturnResult == 0)
+ {
+ Fail("ERROR: The return value was 0, which indicates failure. The "
+ "function failed when trying to Format a FROM_SYSTEM message.");
+ }
+
+ if(wcslen(OutBuffer) <= 0)
+ {
+ Fail("ERROR: There are no characters in the buffer, and when the "
+ "FORMAT_MESSAGE_FROM_SYSTEM flag is used with ERROR_FILE_NOT_FOUND error, "
+ "something should be put into the buffer.");
+ }
+
+ LocalFree(OutBuffer);
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/testinfo.dat
new file mode 100644
index 0000000000..7eda505271
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = FormatMessageW
+Name = Positive test of FormatMessageW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test to ensure the FORMAT_SYSTEM_MESSAGE flag works properly.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..be39b63ec9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_freeenvironmentstringsw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_freeenvironmentstringsw_test1 coreclrpal)
+
+target_link_libraries(paltest_freeenvironmentstringsw_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/test.c b/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/test.c
new file mode 100644
index 0000000000..56010039d7
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/test.c
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for FreeEnvironmentStringsW() function
+**
+**
+**=========================================================*/
+
+#define UNICODE
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ LPWSTR CapturedEnvironment = NULL;
+ BOOL TheResult = 0;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ CapturedEnvironment = GetEnvironmentStrings();
+
+ /* If it's pointing to NULL, it failed. This checks the dependency */
+ if(CapturedEnvironment == NULL) {
+ Fail("The function GetEnvironmentStrings() failed, and the "
+ "FreeEnvironmentStrings() tests is dependant on it.\n");
+ }
+
+ /* This should return 1, if it succeeds, otherwise, test fails */
+ TheResult = FreeEnvironmentStrings(CapturedEnvironment);
+ if(TheResult != 1) {
+ Fail("The function returned %d which indicates failure to Free the "
+ "Environment Strings.\n",TheResult);
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/testinfo.dat
new file mode 100644
index 0000000000..f653bf5dc2
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = FreeEnvironmentStringsW
+Name = Return value test for FreeEnvironmentStringsW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Get a set of strings and then free it to see if function returns success
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/CMakeLists.txt
new file mode 100644
index 0000000000..a3688dd24a
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_freeenvironmentstringsw_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_freeenvironmentstringsw_test2 coreclrpal)
+
+target_link_libraries(paltest_freeenvironmentstringsw_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/test.c b/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/test.c
new file mode 100644
index 0000000000..1bb05cdb12
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/test.c
@@ -0,0 +1,71 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for FreeEnvironmentStringsW() function
+**
+**
+**=========================================================*/
+
+#define UNICODE
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ WCHAR CapturedEnvironment[] = {'T','E','S','T','\0'};
+ BOOL TheResult = 0;
+ LPWSTR lpCapturedEnvironment = NULL;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ lpCapturedEnvironment = (LPWSTR)malloc( sizeof(CapturedEnvironment) /
+ sizeof(CapturedEnvironment[0]) );
+
+ if ( lpCapturedEnvironment )
+ {
+ memcpy( lpCapturedEnvironment, CapturedEnvironment,
+ sizeof(CapturedEnvironment) / sizeof(CapturedEnvironment[0]) );
+ }
+ else
+ {
+ Fail( "malloc() failed to allocate memory.\n" );
+ }
+ /* Even if this is not a valid Environment block, the function will
+ still return success
+ */
+
+ TheResult = FreeEnvironmentStrings( lpCapturedEnvironment );
+ if(TheResult == 0)
+ {
+ Fail("The function should still return a success value even if it is "
+ "passed a LPWSTR which is not an environment block properly "
+ "aquired from GetEnvironmentStrings\n");
+ }
+
+ /* Even passing this function NULL, should still return a success value */
+ TheResult = FreeEnvironmentStrings(NULL);
+ if(TheResult == 0)
+ {
+ Fail("The function should still return a success value even if pass "
+ "NULL.\n");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/testinfo.dat
new file mode 100644
index 0000000000..c426a7ccbd
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = FreeEnvironmentStringsW
+Name = Positive Return value test for FreeEnvironmentStringsW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Ensure that FreeEnvironmentStringsW returns success when passed pointers
+= that don't point to an environment block.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..e3acf4061a
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetCalendarInfoW.c
+)
+
+add_executable(paltest_getcalendarinfow_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getcalendarinfow_test1 coreclrpal)
+
+target_link_libraries(paltest_getcalendarinfow_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test1/GetCalendarInfoW.c b/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test1/GetCalendarInfoW.c
new file mode 100644
index 0000000000..4876fe180f
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test1/GetCalendarInfoW.c
@@ -0,0 +1,57 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: GetCalendarInfoW.c
+**
+** Purpose: Positive test the GetCalendarInfoW API.
+** Call GetCalendarInfoW to retrieve the information of a
+** calendar
+**
+**
+**============================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ LCID Locale = LOCALE_USER_DEFAULT;
+ CALTYPE CalType = CAL_ITWODIGITYEARMAX|CAL_RETURN_NUMBER;
+ DWORD dwValue;
+
+ /*Initialize the PAL environment*/
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+ err = GetCalendarInfoW(Locale,/*locale idendifier*/
+ CAL_GREGORIAN, /*calendar identifier*/
+ CalType, /*calendar tyope*/
+ NULL, /*buffer to store the retrieve info*/
+ 0, /*alwayse zero*/
+ &dwValue);/*to store the requrest data*/
+ if (0 == err)
+ {
+ Fail("GetCalendarInfoW failed for CAL_GREGORIAN!\n");
+ }
+
+ err = GetCalendarInfoW(Locale,/*locale idendifier*/
+ CAL_GREGORIAN_US, /*calendar identifier*/
+ CalType, /*calendar tyope*/
+ NULL, /*buffer to store the retreive info*/
+ 0, /*alwayse zero*/
+ &dwValue);/*to store the requrest data*/
+ if (0 == err)
+ {
+ Fail("GetCalendarInfoW failed for CAL_GREGORIAN_US!\n");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test1/testinfo.dat
new file mode 100644
index 0000000000..59c806c22a
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = miscellaneous
+Function = GetCalendarInfoW
+Name = Positive test for GetCalendarInfoW API to retrieve the info of a calendar
+TYPE = DEFAULT
+EXE1 = getcalendarinfow
+Description
+= Test the GetCalendarInfoW to retrieve the information of a calendar
+= This test for US English
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test2/CMakeLists.txt
new file mode 100644
index 0000000000..cbfd1aa5db
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetCalendarInfoW.c
+)
+
+add_executable(paltest_getcalendarinfow_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getcalendarinfow_test2 coreclrpal)
+
+target_link_libraries(paltest_getcalendarinfow_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test2/GetCalendarInfoW.c b/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test2/GetCalendarInfoW.c
new file mode 100644
index 0000000000..d8a59a0fc0
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test2/GetCalendarInfoW.c
@@ -0,0 +1,79 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: GetCalendarInfoW.c
+**
+** Purpose: Positive test the GetCalendarInfoW API.
+** Call GetCalendarInfoW to retrieve the information of all
+** calendars
+**
+**
+**============================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ int index = 0;
+ LCID Locale = LOCALE_USER_DEFAULT;
+ CALID Calendar;
+ CALTYPE CalType = CAL_ITWODIGITYEARMAX|CAL_RETURN_NUMBER;
+ DWORD dwValue;
+ char *CalendarID[]={"CAL_GREGORIAN",
+ "CAL_GREGORIAN_US",
+ "CAL_JAPAN",
+ "CAL_TAIWAN",
+ "CAL_KOREA",
+ "CAL_HIJRI",
+ "CAL_THAI",
+ "CAL_HEBREW",
+ "CAL_GREGORIAN_ME_FRENCH",
+ "CAL_GREGORIAN_ARABIC",
+ "CAL_GREGORIAN_XLIT_ENGLISH",
+ "CAL_GREGORIAN_XLIT_FRENCH",
+ "CAL_JULIAN"};
+
+ char errBuffer[1024];
+
+
+ /*Initialize the PAL environment*/
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+ memset(errBuffer, 0, 1024);
+
+ for(index=0; index<13; index++)
+ {
+ Calendar = index + 1;
+ /*retrieve the specified calendar info*/
+ err = GetCalendarInfoW(Locale,/*locale idendifier*/
+ Calendar, /*calendar identifier*/
+ CalType, /*calendar tyope*/
+ NULL, /*buffer to store the retreive info*/
+ 0, /*alwayse zero*/
+ &dwValue);/*to store the requrest data*/
+ if(0 == err)
+ {
+ strcat(errBuffer, CalendarID[index]);
+ strcat(errBuffer, ", ");
+ }
+ }
+
+
+ if(strlen(errBuffer) > 0)
+ {
+ Fail("\nFailed to call GetCalendarInfoW API by passing %s"
+ " Calendar identifier(s)\n",errBuffer);
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test2/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test2/testinfo.dat
new file mode 100644
index 0000000000..ea85e99a30
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test2/testinfo.dat
@@ -0,0 +1,11 @@
+Version = 1.0
+Section = miscellaneous
+Function = GetCalendarInfoW
+Name = Positive test #2 for GetCalendarInfoW API to retrieve the info of a
+calendar
+TYPE = DEFAULT
+EXE1 = getcalendarinfow
+Description
+= Test the GetCalendarInfoW to retrieve the information of all calendars
+= but US English
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetCommandLineW/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetCommandLineW/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetCommandLineW/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetCommandLineW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetCommandLineW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..491fdca9b5
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetCommandLineW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_getcommandlinew_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getcommandlinew_test1 coreclrpal)
+
+target_link_libraries(paltest_getcommandlinew_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/GetCommandLineW/test1/test.c b/src/pal/tests/palsuite/miscellaneous/GetCommandLineW/test1/test.c
new file mode 100644
index 0000000000..d8a81746b6
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetCommandLineW/test1/test.c
@@ -0,0 +1,71 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: Test for GetCommandLineW() function
+**
+**
+**=========================================================*/
+
+#define UNICODE
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ LPWSTR TheResult = NULL;
+ WCHAR *CommandLine;
+ int i;
+ WCHAR * p;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ CommandLine = malloc(1024);
+ wcscpy(CommandLine,convert(argv[0]));
+
+ for(i=1;i<argc;++i)
+ {
+ wcscat(CommandLine,convert(" "));
+ wcscat(CommandLine,convert(argv[i]));
+ }
+
+ TheResult = GetCommandLine();
+
+ /* If it is NULL, it failed. */
+ if(TheResult == NULL)
+ {
+ Fail("ERROR: The command line returned was NULL -- but should be "
+ "a LPWSTR.");
+ }
+
+ // It's ok that if there is trailing white spaces in "TheResult"
+ // Let's trim them.
+ p = TheResult + wcslen(TheResult) - 1;
+ while (* p == L' ' || * p == L'\t') { printf("%c\n", *p); * p-- = 0 ; }
+
+ if(memcmp(TheResult,CommandLine,wcslen(TheResult)*2+2) != 0)
+ {
+ Fail("ERROR: The command line returned was %s instead of %s "
+ "which was the command.\n",
+ convertC(TheResult), convertC(CommandLine));
+ }
+
+ free(CommandLine);
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetCommandLineW/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/GetCommandLineW/test1/testinfo.dat
new file mode 100644
index 0000000000..668cb7d249
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetCommandLineW/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = GetCommandLineW
+Name = Positive test for GetCommandLineW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Ensure that this function returns the correct CommandLine
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetComputerNameW/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetComputerNameW/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetComputerNameW/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetComputerNameW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetComputerNameW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..980dae88ae
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetComputerNameW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_getcomputernamew_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getcomputernamew_test1 coreclrpal)
+
+target_link_libraries(paltest_getcomputernamew_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/GetComputerNameW/test1/test.c b/src/pal/tests/palsuite/miscellaneous/GetComputerNameW/test1/test.c
new file mode 100644
index 0000000000..7a00cad598
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetComputerNameW/test1/test.c
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: Positive Test for GetComputerName() function
+**
+**
+**=========================================================*/
+
+#define UNICODE
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ int HOST_NAME_MAX = 255;
+ WCHAR wzComputerName[HOST_NAME_MAX+1];
+ DWORD dwSize = sizeof(wzComputerName)/sizeof(wzComputerName[0]);
+
+ // Initialize the PAL and return FAILURE if this fails
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ Fail ("ERROR: PAL_Initialize() call failed!\n");
+ }
+
+ if (0 == GetComputerName(wzComputerName, &dwSize))
+ {
+ Fail("ERROR: GetComputerName failed with %d!\n", GetLastError());
+ }
+
+ // dwSize is the length of wzComputerName without NULL
+ if (dwSize < 0 || dwSize > (sizeof(wzComputerName)/sizeof(wzComputerName[0]) - 1))
+ {
+ Fail("ERROR: GetComputerName returned %S with dwSize = %u whereas the passed in buffer size is %d!\n",
+ wzComputerName, dwSize, sizeof(wzComputerName)/sizeof(wzComputerName[0]));
+ }
+
+ // dwSize is the length of wzComputerName without NULL
+ if (dwSize != wcslen(wzComputerName))
+ {
+ Fail("ERROR: GetComputerName returned %S of length %d which is not equal to dwSize = %u!\n",
+ wzComputerName, wcslen(wzComputerName), dwSize);
+ }
+
+ printf ("GetComputerName returned %S of length %u\n", wzComputerName, dwSize);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/miscellaneous/GetComputerNameW/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/GetComputerNameW/test1/testinfo.dat
new file mode 100644
index 0000000000..d45bca1c25
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetComputerNameW/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = GetComputerNameW
+Name = Test for GetComputerNameW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Check to ensure that GetComputerNameW returnes a decent value.
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/CMakeLists.txt
new file mode 100644
index 0000000000..80b6a0d41d
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(GetDateFormatW_neg1)
+add_subdirectory(GetDateFormatW_neg2)
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg1/CMakeLists.txt
new file mode 100644
index 0000000000..5a340c6cfb
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetDateFormatW_neg.c
+)
+
+add_executable(paltest_getdateformatw_getdateformatw_neg1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getdateformatw_getdateformatw_neg1 coreclrpal)
+
+target_link_libraries(paltest_getdateformatw_getdateformatw_neg1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg1/GetDateFormatW_neg.c b/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg1/GetDateFormatW_neg.c
new file mode 100644
index 0000000000..c64dc74cb6
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg1/GetDateFormatW_neg.c
@@ -0,0 +1,85 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: GetDateFormatW_neg.c
+**
+** Purpose: Negative test the GetDateFormatW API.
+** Call GetDateFormatW by passing an invalid parameter
+**
+**
+**============================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ WCHAR *wpFormat;
+ LPCSTR lpString = "gg";
+ CONST SYSTEMTIME *lpDate = NULL;
+ LCID DefaultLocale;
+ DWORD dwFlags;
+ int DateSize;
+ WCHAR *wpBuffer = NULL;
+
+ /*Initialize the PAL environment*/
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+ /*convert to a wide character string*/
+ wpFormat = convert((char *)lpString);
+
+ dwFlags = DATE_USE_ALT_CALENDAR; /*set the flags*/
+
+
+ DateSize = 0;
+
+ /*retrieve the buffer size*/
+ DateSize = GetDateFormatW(
+ DefaultLocale, /*system default locale*/
+ dwFlags, /*function option*/
+ (SYSTEMTIME *)lpDate, /*always is NULL*/
+ wpFormat, /*pointer to a picture string*/
+ wpBuffer, /*out buffer*/
+ DateSize); /*buffer size*/
+
+ if(DateSize <= 0)
+ {
+ free(wpFormat);
+ Fail("\nRetrieved an invalid buffer size\n");
+ }
+
+ wpBuffer = malloc((DateSize + 1)*sizeof(WCHAR));
+ if(NULL == wpBuffer)
+ {
+ free(wpFormat);
+ Fail("\nFailed to allocate memory to store the formatted string\n");
+ }
+
+ /*format a date by passing an invalid locale indentifier*/
+ err = GetDateFormatW(
+ -1, /*invalid locale identifier*/
+ dwFlags, /*function option*/
+ (SYSTEMTIME *)lpDate, /*always is NULL, or use system date*/
+ wpFormat, /*pointer to a picture string*/
+ wpBuffer, /*out buffer*/
+ DateSize); /*buffer size*/
+
+ free(wpBuffer);
+ free(wpFormat);
+
+ if(0 != err || GetLastError() != ERROR_INVALID_PARAMETER)
+ {
+ Fail("\nFailed to call GetDateFormatW for a negative test by "
+ "passing an invalid parameter, error code=%d\n", GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg1/testinfo.dat
new file mode 100644
index 0000000000..f02271650c
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg1/testinfo.dat
@@ -0,0 +1,8 @@
+Version = 1.0
+Section = miscellaneous
+Function = GetDateFormatW
+Name = Negative test for GetDateFormatW by passing an invlid locale identifier
+TYPE = DEFAULT
+EXE1 = getdateformatw_neg
+Description
+=negative test GetDateFormatW by passing an invalid locale identifier
diff --git a/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg2/CMakeLists.txt
new file mode 100644
index 0000000000..646de9160b
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetDateFormatW_neg.c
+)
+
+add_executable(paltest_getdateformatw_getdateformatw_neg2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getdateformatw_getdateformatw_neg2 coreclrpal)
+
+target_link_libraries(paltest_getdateformatw_getdateformatw_neg2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg2/GetDateFormatW_neg.c b/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg2/GetDateFormatW_neg.c
new file mode 100644
index 0000000000..676038f03a
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg2/GetDateFormatW_neg.c
@@ -0,0 +1,98 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: GetDateFormatW_neg.c
+**
+** Purpose: Negative test the GetDateFormatW API.
+** Call GetDateFormatW by passing an invalid flag
+**
+**
+**============================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ WCHAR *wpFormat;
+ LPCSTR lpString = "gg";
+ CONST SYSTEMTIME *lpDate = NULL;
+ LCID DefaultLocale;
+ DWORD dwFlags;
+ int DateSize;
+ WCHAR *wpBuffer = NULL;
+
+ /*Initialize the PAL environment*/
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+ /*convert to a wide character string*/
+ wpFormat = convert((char *)lpString);
+
+ /*
+ DefaultLocale = GetSystemDefaultLCID() which is not defined in PAL;
+
+ LOCALE_SYSTEM_DEFAULT = MAKELCID(LANG_SYSTEM_DEFAULT, SORT_DEFAULT)
+
+ LANG_SYSTEM_DEFAULT = MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT);
+ SUBLANG_SYS_DEFAULT is not defined in PAL, here use hardcoding,
+ the value is from winnt.h
+ */
+
+ DefaultLocale = MAKELCID(MAKELANGID(LANG_NEUTRAL, 0x02), SORT_DEFAULT);
+
+ dwFlags = DATE_USE_ALT_CALENDAR; /*set the flags*/
+
+
+ DateSize = 0;
+
+ /*retrieve the buffer size*/
+ DateSize = GetDateFormatW(
+ DefaultLocale, /*system default locale*/
+ dwFlags, /*function option*/
+ (SYSTEMTIME *)lpDate, /*always is NULL*/
+ wpFormat, /*pointer to a picture string*/
+ wpBuffer, /*out buffer*/
+ DateSize); /*buffer size*/
+
+ if(DateSize <= 0)
+ {
+ free(wpFormat);
+ Fail("\nRetrieved an invalid buffer size\n");
+ }
+
+ wpBuffer = malloc((DateSize + 1)*sizeof(WCHAR));
+ if(NULL == wpBuffer)
+ {
+ free(wpFormat);
+ Fail("\nFailed to allocate memory to store the formatted string\n");
+ }
+
+ err = GetDateFormatW(
+ DefaultLocale, /*system default locale*/
+ 0x00000001|0x00000008,/*DATE_SHORTDATE|DATE_YEARMONTH */
+ /*an invalid flag*/
+ (SYSTEMTIME *)lpDate, /*always is NULL, or use system date*/
+ wpFormat, /*pointer to a picture string*/
+ wpBuffer, /*out buffer*/
+ DateSize); /*buffer size*/
+
+ free(wpBuffer);
+ free(wpFormat);
+
+ if(0 != err || GetLastError() != ERROR_INVALID_FLAGS)
+ {
+ Fail("\nFailed to call GetDateFormatW for a negative test by "
+ "passing an invalid flag, error code=%d\n", GetLastError());
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg2/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg2/testinfo.dat
new file mode 100644
index 0000000000..fe5bc9b06e
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg2/testinfo.dat
@@ -0,0 +1,9 @@
+Version = 1.0
+Section = miscellaneous
+Function = GetDateFormatW
+Name = Negative test for GetDateFormatW by passing an invalid flag
+TYPE = DEFAULT
+EXE1 = getdateformatw_neg
+Description
+=test for GetDateFormatW by passing an invalid flag which is not
+=supported
diff --git a/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..8c1e4b024e
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ GetDateFormatW.c
+)
+
+add_executable(paltest_getdateformatw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getdateformatw_test1 coreclrpal)
+
+target_link_libraries(paltest_getdateformatw_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/test1/GetDateFormatW.c b/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/test1/GetDateFormatW.c
new file mode 100644
index 0000000000..264e397a49
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/test1/GetDateFormatW.c
@@ -0,0 +1,100 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: GetDateFormatW.c
+**
+** Purpose: Positive test the GetDateFormatW API.
+** Call GetDateFormatW to format a date string for
+** a specified locale
+**
+**
+**============================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ WCHAR *wpFormat;
+ LPCSTR lpString = "gg";
+ CONST SYSTEMTIME *lpDate = NULL;
+ LCID DefaultLocale;
+ DWORD dwFlags;
+ int DateSize;
+ WCHAR *wpBuffer = NULL;
+
+ /*Initialize the PAL environment*/
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+ /*convert to a wide character string*/
+ wpFormat = convert((char *)lpString);
+
+ /*
+ DefaultLocale = GetSystemDefaultLCID() which is not defined in PAL;
+
+ LOCALE_SYSTEM_DEFAULT = MAKELCID(LANG_SYSTEM_DEFAULT, SORT_DEFAULT)
+
+ LANG_SYSTEM_DEFAULT = MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT);
+ SUBLANG_SYS_DEFAULT is not defined in PAL, here use hardcoding,
+ the value is from winnt.h
+ */
+ DefaultLocale = MAKELCID(MAKELANGID(LANG_NEUTRAL, 0x02), SORT_DEFAULT);
+
+ dwFlags = DATE_USE_ALT_CALENDAR; /*set the flags*/
+
+
+ DateSize = 0;
+
+ /*retrieve the buffer size*/
+ DateSize = GetDateFormatW(
+ DefaultLocale, /*system default locale*/
+ dwFlags, /*function option*/
+ (SYSTEMTIME *)lpDate, /*always is NULL*/
+ wpFormat, /*pointer to a picture string*/
+ wpBuffer, /*out buffer*/
+ DateSize); /*buffer size*/
+
+ if(DateSize <= 0)
+ {
+ free(wpFormat);
+ Fail("\nRetrieved an invalid buffer size\n");
+ }
+
+
+ wpBuffer = malloc((DateSize+1)*sizeof(WCHAR));
+ if(NULL == wpBuffer)
+ {
+ free(wpFormat);
+ Fail("\nFailed to allocate memory to store a formatted string\n");
+ }
+
+ /*retrieve the formatted string for a specified locale*/
+ err = GetDateFormatW(
+ DefaultLocale, /*system default locale*/
+ dwFlags, /*function option*/
+ (SYSTEMTIME *)lpDate, /*always is NULL*/
+ wpFormat, /*pointer to a picture string*/
+ wpBuffer, /*out buffer*/
+ DateSize); /*buffer size*/
+
+ if(0 == err)
+ {
+ free(wpBuffer);
+ free(wpFormat);
+ Fail("\nFailed to call GetDateFormatW to format a system data "
+ "as a data string for system default locale!\n");
+ }
+
+ free(wpBuffer);
+ free(wpFormat);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/test1/testinfo.dat
new file mode 100644
index 0000000000..6ed9ee7cef
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/test1/testinfo.dat
@@ -0,0 +1,9 @@
+Version = 1.0
+Section = miscellaneous
+Function = GetDateFormatW
+Name = Positive test for GetDateFormatW to format a date as a date string
+TYPE = DEFAULT
+EXE1 = getdateformatw
+Description
+=test for GetDateFormatW to format a date as a date string
+=for a specified locale
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..306400e558
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_getenvironmentstringsw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getenvironmentstringsw_test1 coreclrpal)
+
+target_link_libraries(paltest_getenvironmentstringsw_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/test1/test.c b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/test1/test.c
new file mode 100644
index 0000000000..2bd9153e59
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/test1/test.c
@@ -0,0 +1,81 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: Test for GetEnvironmentStringsW() function
+**
+**
+**=========================================================*/
+
+/* Depends on SetEnvironmentVariable(), wcsstr() and wcslen() */
+
+#define UNICODE
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[]) {
+
+ LPWSTR CapturedEnvironmentStrings = NULL;
+ LPWSTR EnviroStringReturned = NULL;
+ WCHAR EnvironmentVariableBuffer[] =
+ {'P','A','L','T','E','S','T','I','N','G','\0'};
+ WCHAR EnvironmentValueBuffer[] = {'T','e','s','t','i','n','g','\0'};
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* This test depends on SetEnvironmentVariableW working.
+ We need to set a variable so we can test and ensure it's there
+ when we get them back
+ */
+
+ SetEnvironmentVariable(EnvironmentVariableBuffer,EnvironmentValueBuffer);
+
+ CapturedEnvironmentStrings = GetEnvironmentStrings();
+
+ /* If it's pointing to NULL, it failed. */
+ if(CapturedEnvironmentStrings == NULL) {
+ Fail("The function returned a pointer to NULL, which it shouldn't do. "
+ "It should point to a block of Environment Strings.\n");
+ }
+
+ /* Now that we've grabbed the list of envrionment strings, go through
+ each one, and check for a match to 'PALTESTING'. If this is missing
+ it's not pointing at the environment block.
+ */
+
+ while(*CapturedEnvironmentStrings != 0)
+ {
+ EnviroStringReturned = wcsstr(CapturedEnvironmentStrings,
+ EnvironmentVariableBuffer);
+ CapturedEnvironmentStrings += wcslen(CapturedEnvironmentStrings)+1;
+ if(EnviroStringReturned != NULL)
+ {
+ break;
+ }
+ }
+
+ if(EnviroStringReturned == NULL)
+ {
+ Fail("The memory block returned was searched, but nothing was found to "
+ "prove this was really the environment block. Either this "
+ "function, SetEnvironmentVariable or wcsstr() is broken.\n");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/test1/testinfo.dat
new file mode 100644
index 0000000000..fa712ab823
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = GetEnvironmentStringsW
+Name = Test for correct return of GetEnvironmentStringsW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Get a set of strings, and check to make sure it contains a predetermined
+= string that was placed there.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/CMakeLists.txt
new file mode 100644
index 0000000000..7c20179353
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/CMakeLists.txt
@@ -0,0 +1,9 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/CMakeLists.txt
new file mode 100644
index 0000000000..184a6ef1f0
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_getenvironmentvariablea_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getenvironmentvariablea_test1 coreclrpal)
+
+target_link_libraries(paltest_getenvironmentvariablea_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/test.c b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/test.c
new file mode 100644
index 0000000000..8862e823bc
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/test.c
@@ -0,0 +1,84 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: Test for GetEnvironmentVariable() function
+** Assign a properly sized buffer and get an environment
+** variable, check to ensure it returns the correct values.
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[]) {
+
+ /* Define some buffers needed for the function */
+ char * pResultBuffer = NULL;
+ int size = 0;
+
+ /* A place to stash the returned values */
+ int ReturnValueForLargeBuffer = 0;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Recieve and allocate the correct amount of memory for the buffer */
+ size = ReturnValueForLargeBuffer = GetEnvironmentVariable("PATH",
+ pResultBuffer,
+ 0);
+ pResultBuffer = malloc(size);
+ if ( pResultBuffer == NULL )
+ {
+ Fail("ERROR: Failed to allocate memory for pResultBuffer pointer. "
+ "Can't properly exec test case without this.\n");
+ }
+
+
+ /* Normal case, PATH should fit into this buffer */
+ ReturnValueForLargeBuffer = GetEnvironmentVariable("PATH",
+ pResultBuffer,
+ size);
+
+ /* Ensure that it returned a positive value */
+ if(ReturnValueForLargeBuffer <= 0)
+ {
+ free(pResultBuffer);
+
+ Fail("The return was %d, which indicates that the function failed.\n",
+ ReturnValueForLargeBuffer);
+ }
+
+ /* Ensure that it succeeded and copied the correct number of characters.
+ If this is true, then the return value should be one less of the size of
+ the buffer. (Doesn't include that NULL byte)
+ */
+
+ if(ReturnValueForLargeBuffer != size-1)
+ {
+ free(pResultBuffer);
+
+ Fail("The value returned was %d when it should have been %d. "
+ "This should be the number of characters copied, minus the "
+ "NULL byte.\n",ReturnValueForLargeBuffer, size-1);
+ }
+
+
+ free(pResultBuffer);
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/testinfo.dat
new file mode 100644
index 0000000000..ee81e2ec3b
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = GetEnvironmentVariableA
+Name = Return value test for GetEnvironmentVariableA
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Assign a properly sized buffer and get an environment variable, check to
+= ensure it returns the correct values.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/CMakeLists.txt
new file mode 100644
index 0000000000..abfd73f458
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_getenvironmentvariablea_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getenvironmentvariablea_test2 coreclrpal)
+
+target_link_libraries(paltest_getenvironmentvariablea_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/test.c b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/test.c
new file mode 100644
index 0000000000..d26588e907
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/test.c
@@ -0,0 +1,56 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: Test for GetEnvironmentVariable() function
+** Pass a small buffer to GetEnvironmentVariableA to ensure
+** it returns the size it requires.
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+#define SMALL_BUFFER_SIZE 1
+
+int __cdecl main(int argc, char *argv[]) {
+
+ /* A place to stash the returned values */
+ int ReturnValueForSmallBuffer = 0;
+
+ char pSmallBuffer[SMALL_BUFFER_SIZE];
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* PATH won't fit in this buffer, it should return how many
+ characters it needs
+ */
+
+ ReturnValueForSmallBuffer = GetEnvironmentVariable("PATH",
+ pSmallBuffer,
+ SMALL_BUFFER_SIZE);
+ if(ReturnValueForSmallBuffer <= 0)
+ {
+ Fail("The return value was %d when it should have been greater "
+ "than 0. "
+ "This should return the number of characters needed to contained "
+ "the contents of PATH in a buffer.\n",ReturnValueForSmallBuffer);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/testinfo.dat
new file mode 100644
index 0000000000..990649fad9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = GetEnvironmentVariableA
+Name = Return value test on GetEnvironmentVariableA
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Pass a small buffer to GetEnvironmentVariableA
+= to ensure it returns the size it requires.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/CMakeLists.txt
new file mode 100644
index 0000000000..a63c11b1a3
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_getenvironmentvariablea_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getenvironmentvariablea_test3 coreclrpal)
+
+target_link_libraries(paltest_getenvironmentvariablea_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/test.c b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/test.c
new file mode 100644
index 0000000000..b51e139c95
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/test.c
@@ -0,0 +1,67 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: Test for GetEnvironmentVariable() function
+** Pass a nonexisting environment variable and a null to
+** the function to check return values.
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+#define BUFFER_SIZE 5000
+#define SMALL_BUFFER_SIZE 5
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ int ReturnValueForNonExisting = 0;
+ int ReturnValueForNull = 0;
+
+ char pResultBuffer[BUFFER_SIZE];
+ char pSmallBuffer[SMALL_BUFFER_SIZE];
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* This variable doesn't exist, it should return 0 */
+ ReturnValueForNonExisting = GetEnvironmentVariable("NonExistingVariable",
+ pSmallBuffer,
+ SMALL_BUFFER_SIZE);
+
+ if(ReturnValueForNonExisting != 0)
+ {
+ Fail("ERROR: The return should have been 0, but it was %d. "
+ "The function attempted to get an Environment Variable that "
+ "doesn't exist and should return 0 as a result.\n",
+ ReturnValueForNonExisting);
+ }
+
+
+ /* Passing a NULL string should return 0 */
+ ReturnValueForNull = GetEnvironmentVariable(NULL,
+ pResultBuffer,
+ BUFFER_SIZE);
+
+ if(ReturnValueForNull != 0)
+ {
+ Fail("ERROR: The return should have been 0, but it was %d. "
+ "The function attempted to get a NULL pointer and should return "
+ "0 as a result.\n",ReturnValueForNull);
+
+ }
+
+ PAL_Terminate();
+ return PASS;
+ }
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/testinfo.dat
new file mode 100644
index 0000000000..afaa04b8fa
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = GetEnvironmentVariableA
+Name = Return value test for GetEnvironmentVariableA
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Pass a nonexisting environment variable and a null to the function
+= to check return values.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/CMakeLists.txt
new file mode 100644
index 0000000000..76cfdb6d49
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_getenvironmentvariablea_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getenvironmentvariablea_test4 coreclrpal)
+
+target_link_libraries(paltest_getenvironmentvariablea_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/test.c b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/test.c
new file mode 100644
index 0000000000..1fea5719b4
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/test.c
@@ -0,0 +1,75 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: Test for GetEnvironmentVariable() function
+** Set an Environment Variable, then use GetEnvironmentVariable to
+** retrieve it -- ensure that it retrieves properly.
+**
+**
+**=========================================================*/
+
+/* Depends on SetEnvironmentVariableW (because we're implmenting
+ the wide version) and strcmp()
+*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[]) {
+
+ /* Define some buffers needed for the function */
+ char * pResultBuffer = NULL;
+ WCHAR SomeEnvironmentVariable[] = {'P','A','L','T','E','S','T','\0'};
+ WCHAR TheEnvironmentValue[] = {'T','E','S','T','\0'};
+ int size = 0;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ SetEnvironmentVariableW(SomeEnvironmentVariable,
+ TheEnvironmentValue);
+
+
+ /* Normal case, PATH should fit into this buffer */
+ size = GetEnvironmentVariable("PALTEST", // Variable Name
+ pResultBuffer, // Buffer for Value
+ 0); // Buffer size
+
+ pResultBuffer = malloc(size);
+ if ( pResultBuffer == NULL )
+ {
+ Fail("ERROR: Failed to allocate memory for pResultBuffer pointer. "
+ "Can't properly exec test case without this.\n");
+ }
+
+
+ GetEnvironmentVariable("PALTEST",
+ pResultBuffer,
+ size);
+
+ if(strcmp(pResultBuffer,"TEST") != 0)
+ {
+ free(pResultBuffer);
+ Fail("ERROR: The value in the buffer should have been 'TEST' but "
+ "was really '%s'.\n",pResultBuffer);
+
+ }
+
+ free(pResultBuffer);
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/testinfo.dat
new file mode 100644
index 0000000000..8fb16c778c
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = GetEnvironmentVariableA
+Name = Positive Test for GetEnvironmentVariableA
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Set an Environment Variable, then use GetEnvironmentVariable
+= to retrieve it ensure that it retrieves properly.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/CMakeLists.txt
new file mode 100644
index 0000000000..548d86bb03
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test5.c
+)
+
+add_executable(paltest_getenvironmentvariablea_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getenvironmentvariablea_test5 coreclrpal)
+
+target_link_libraries(paltest_getenvironmentvariablea_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/test5.c b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/test5.c
new file mode 100644
index 0000000000..8d63a1aecb
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/test5.c
@@ -0,0 +1,145 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+** Source : test5.c
+**
+** Purpose: Test for GetEnvironmentVariableA() function
+** Create environment variables that differ only
+** in case and verify that they return the appropriate
+** value on the BSD environment.
+**
+**
+===========================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+#if WIN32
+
+ return PASS;
+
+#else
+
+ /* Define some buffers needed for the function */
+ char * pResultBuffer = NULL;
+
+ char FirstEnvironmentVariable[] = {"PALTEST"};
+ char FirstEnvironmentValue[] = {"FIRST"};
+
+ char SecondEnvironmentVariable[] = {"paltest"};
+ char SecondEnvironmentValue[] = {"SECOND"};
+
+ DWORD size = 0;
+ BOOL bRc = TRUE;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Set the first environment variable */
+ bRc = SetEnvironmentVariableA(FirstEnvironmentVariable,
+ FirstEnvironmentValue);
+
+ if(!bRc)
+ {
+ Fail("ERROR: SetEnvironmentVariable failed to set a "
+ "proper environment variable with error %u.\n", GetLastError());
+ }
+
+
+ /* Normal case, PATH should fit into this buffer */
+ size = GetEnvironmentVariableA(FirstEnvironmentVariable,
+ pResultBuffer,
+ 0);
+
+ /* To account for the null character at the end of the string */
+ size = size + 1;
+
+ pResultBuffer = malloc(sizeof(char)*size);
+ if ( pResultBuffer == NULL )
+ {
+ Fail("ERROR: Failed to allocate memory for pResultBuffer pointer\n.");
+ }
+
+ /* Try to retrieve the value of the first environment variable */
+ GetEnvironmentVariableA(FirstEnvironmentVariable,
+ pResultBuffer,
+ size);
+
+ if ( pResultBuffer == NULL )
+ {
+ free(pResultBuffer);
+ Fail("ERROR: GetEnvironmentVariable failed to return a value "
+ "from a proper environment variable with error %u.\n",
+ GetLastError());
+ }
+
+ /* Compare the strings to see that the correct variable was returned */
+ if(strcmp(pResultBuffer,FirstEnvironmentValue) != 0)
+ {
+ free(pResultBuffer);
+ Fail("ERROR: The value in the buffer should have been '%s' but "
+ "was really '%s'.\n",FirstEnvironmentValue, pResultBuffer);
+ }
+
+ free(pResultBuffer);
+
+ /* Set the second environment Variable */
+ bRc = SetEnvironmentVariableA(SecondEnvironmentVariable,
+ SecondEnvironmentValue);
+
+ if(!bRc)
+ {
+ Fail("ERROR: SetEnvironmentVariable failed to set a "
+ "proper environment variable with error %u.\n",
+ GetLastError());
+ }
+
+ /* Reallocate the memory for the string */
+ pResultBuffer = malloc(sizeof(char)*size);
+ if ( pResultBuffer == NULL )
+ {
+ Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.");
+ }
+
+ /* Try retrieving the value of the first variable, even though the
+ second variable has the same spelling and only differs in case */
+ GetEnvironmentVariableA(FirstEnvironmentVariable,
+ pResultBuffer,
+ size);
+
+ if ( pResultBuffer == NULL )
+ {
+ free(pResultBuffer);
+ Fail("ERROR: GetEnvironmentVariable failed to return a value "
+ "from a proper environment variable with error %u.\n",
+ GetLastError());
+ }
+
+ /* Compare the two strings to confirm that the right value is returned */
+ if(strcmp(pResultBuffer,FirstEnvironmentValue) != 0)
+ {
+ free(pResultBuffer);
+ Fail("ERROR: The value in the buffer should have been '%s' but "
+ "was really '%s'.\n",FirstEnvironmentValue,pResultBuffer);
+ }
+
+ free(pResultBuffer);
+
+ PAL_Terminate();
+ return PASS;
+
+#endif
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/testinfo.dat
new file mode 100644
index 0000000000..0bcec5973b
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = GetEnvironmentVariableA
+Name = Positive Test for GetEnvironmentVariableA
+TYPE = DEFAULT
+EXE1 = test5
+Description
+= Set environment variables that differ only in case
+= and verify that on BSD they return two different
+= values.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/CMakeLists.txt
new file mode 100644
index 0000000000..a0873bb7e7
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test6.c
+)
+
+add_executable(paltest_getenvironmentvariablea_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getenvironmentvariablea_test6 coreclrpal)
+
+target_link_libraries(paltest_getenvironmentvariablea_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/test6.c b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/test6.c
new file mode 100644
index 0000000000..8ef7571f59
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/test6.c
@@ -0,0 +1,99 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+** Source : test6.c
+**
+** Purpose: Test for GetEnvironmentVariableA() function
+** Create environment variables that differ only
+** in case and verify that they return the appropriate
+** value on the BSD environment.
+**
+
+**
+===========================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+#if WIN32
+
+ /* Define some buffers needed for the function */
+ char * pResultBuffer = NULL;
+
+ char FirstEnvironmentVariable[] = {"PALTEST"};
+ char FirstEnvironmentValue[] = {"FIRST"};
+ char ModifiedEnvVar[] = {"paltest"};
+
+ DWORD size = 0;
+ BOOL bRc = TRUE;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Set the first environment variable */
+ bRc = SetEnvironmentVariableA(FirstEnvironmentVariable,
+ FirstEnvironmentValue);
+
+ if(!bRc)
+ {
+ Fail("ERROR: SetEnvironmentVariable failed to set a "
+ "proper environment variable with error %u.\n",
+ GetLastError());
+ }
+
+ /* Normal case, PATH should fit into this buffer */
+ size = GetEnvironmentVariableA(ModifiedEnvVar,
+ pResultBuffer,
+ 0);
+
+ /* To account for the nul character at the end of the string */
+ size = size + 1;
+
+ pResultBuffer = malloc(sizeof(char)*size);
+ if ( pResultBuffer == NULL )
+ {
+ Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n");
+ }
+
+ /* Try to retrieve the value of the first environment variable */
+ GetEnvironmentVariableA(ModifiedEnvVar,
+ pResultBuffer,
+ size);
+
+ if ( pResultBuffer == NULL )
+ {
+ free(pResultBuffer);
+ Fail("ERROR: GetEnvironmentVariable failed to return a value "
+ "from a proper environment variable with error %u.\n",
+ GetLastError());
+ }
+
+ /* Compare the strings to see that the correct variable was returned */
+ if(strcmp(pResultBuffer,FirstEnvironmentValue) != 0)
+ {
+ free(pResultBuffer);
+ Fail("ERROR: The value in the buffer should have been '%s' but "
+ "was really '%s'.\n",FirstEnvironmentValue, pResultBuffer);
+ }
+
+ free(pResultBuffer);
+
+ PAL_Terminate();
+ return PASS;
+
+
+#else
+
+ return PASS;
+#endif
+}
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/testinfo.dat
new file mode 100644
index 0000000000..5de219a959
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = GetEnvironmentVariableA
+Name = Positive Test for GetEnvironmentVariableA
+TYPE = DEFAULT
+EXE1 = test6
+Description
+= Set an Environment Variable, then use GetEnvironmentVariable
+= to retrieve the Variable, using a name that differs only in
+= Case. In Windows this should not affect the return value
+= of the function.
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/CMakeLists.txt
new file mode 100644
index 0000000000..7c20179353
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/CMakeLists.txt
@@ -0,0 +1,9 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..567c992461
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_getenvironmentvariablew_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getenvironmentvariablew_test1 coreclrpal)
+
+target_link_libraries(paltest_getenvironmentvariablew_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/test.c b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/test.c
new file mode 100644
index 0000000000..6c764509d0
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/test.c
@@ -0,0 +1,79 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: Test for GetEnvironmentVariable() function
+**
+**
+**=========================================================*/
+
+#define UNICODE
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ /* Define some buffers needed for the function */
+ WCHAR * pResultBuffer = NULL;
+ int size = 0;
+
+ /* A place to stash the returned values */
+ int ReturnValueForLargeBuffer = 0;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Recieve and allocate the correct amount of memory for the buffer */
+ size = ReturnValueForLargeBuffer =
+ GetEnvironmentVariable(convert("PATH"),
+ pResultBuffer,
+ 0);
+
+ pResultBuffer = malloc(size*sizeof(WCHAR));
+ if ( pResultBuffer == NULL )
+ {
+ Fail("ERROR: Failed to allocate memory for pResultBuffer pointer. "
+ "Can't properly exec test case without this.\n");
+ }
+
+
+ /* Normal case, PATH should fit into this buffer */
+ ReturnValueForLargeBuffer = GetEnvironmentVariable(convert("PATH"),
+ pResultBuffer,
+ size);
+ free(pResultBuffer);
+
+ /* Ensure that it returned a positive value */
+ if(ReturnValueForLargeBuffer <= 0)
+ {
+ Fail("The return was %d, which indicates that the function failed.\n",
+ ReturnValueForLargeBuffer);
+ }
+
+ /* Ensure that it succeeded and copied the correct number of characters.
+ If this is true, then the return value should be one less of the
+ size of the buffer. (Doesn't include that NULL byte)
+ */
+ if(ReturnValueForLargeBuffer != size-1)
+ {
+ Fail("The value returned was %d when it should have been %d. This "
+ "should be the number of characters copied, "
+ "minus the NULL byte.\n", ReturnValueForLargeBuffer, size-1);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/testinfo.dat
new file mode 100644
index 0000000000..467f2b7b94
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = GetEnvironmentVariableW
+Name = Return value test for GetEnvironmentVariableW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Assign a properly sized buffer and get an environment variable,
+= check to ensure it returns the correct values.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/CMakeLists.txt
new file mode 100644
index 0000000000..7234f61ed3
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_getenvironmentvariablew_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getenvironmentvariablew_test2 coreclrpal)
+
+target_link_libraries(paltest_getenvironmentvariablew_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/test.c b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/test.c
new file mode 100644
index 0000000000..6fa753c8d3
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/test.c
@@ -0,0 +1,56 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: Test for GetEnvironmentVariable() function
+**
+**
+**=========================================================*/
+
+#define UNICODE
+
+#include <palsuite.h>
+
+#define SMALL_BUFFER_SIZE 1
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ WCHAR pSmallBuffer[SMALL_BUFFER_SIZE];
+
+ /* A place to stash the returned values */
+ int ReturnValueForSmallBuffer;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* PATH won't fit in this buffer, it should return how many characters
+ it needs
+ */
+
+ ReturnValueForSmallBuffer = GetEnvironmentVariable(convert("PATH"),
+ pSmallBuffer,
+ SMALL_BUFFER_SIZE);
+
+ if(ReturnValueForSmallBuffer <= 0)
+ {
+ Fail("The return value was %d when it should have been greater "
+ "than 0. This should return the number of characters needed "
+ "to contained the contents of PATH in a buffer.\n",
+ ReturnValueForSmallBuffer);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/testinfo.dat
new file mode 100644
index 0000000000..372f5af316
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = GetEnvironmentVariableW
+Name = Return value test on GetEnvironmentVariableW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Pass a small buffer to GetEnvironmentVariableW
+= to ensure it returns the size it requires.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/CMakeLists.txt
new file mode 100644
index 0000000000..bafd75e52e
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_getenvironmentvariablew_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getenvironmentvariablew_test3 coreclrpal)
+
+target_link_libraries(paltest_getenvironmentvariablew_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/test.c b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/test.c
new file mode 100644
index 0000000000..03781e723f
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/test.c
@@ -0,0 +1,71 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: Test for GetEnvironmentVariable() function
+**
+**
+**=========================================================*/
+
+#define UNICODE
+#include <palsuite.h>
+
+#define BUFFER_SIZE 5000
+#define SMALL_BUFFER_SIZE 5
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ /* Define some buffers needed for the function */
+ WCHAR pResultBuffer[BUFFER_SIZE];
+ WCHAR pSmallBuffer[SMALL_BUFFER_SIZE];
+
+ /* A place to stash the returned values */
+ int ReturnValueForNonExisting, ReturnValueForNull;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* This variable doesn't exist, it should return 0 */
+ ReturnValueForNonExisting =
+ GetEnvironmentVariable(convert("NonExistingVariable"),
+ pSmallBuffer,
+ SMALL_BUFFER_SIZE);
+
+ if(ReturnValueForNonExisting != 0)
+ {
+ Fail("ERROR: The return should have been 0, but it was %d. The "
+ "function attempted to get an Environment Variable that doesn't "
+ "exist and should return 0 as a result.\n",
+ ReturnValueForNonExisting);
+ }
+
+
+ /* Passing a NULL string should return 0 */
+ ReturnValueForNull = GetEnvironmentVariable(NULL,
+ pResultBuffer,
+ BUFFER_SIZE);
+
+ if(ReturnValueForNull != 0)
+ {
+ Fail("ERROR: The return should have been 0, but it was %d. The "
+ "function attempted to get a NULL pointer and should return 0 "
+ "as a result.\n",ReturnValueForNull);
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/testinfo.dat
new file mode 100644
index 0000000000..d41c19c908
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = GetEnvironmentVariableW
+Name = Return value test for GetEnvironmentVariableW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Pass a nonexisting environment variable and a null to the function
+= to check return values.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/CMakeLists.txt
new file mode 100644
index 0000000000..f870bd6b22
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_getenvironmentvariablew_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getenvironmentvariablew_test4 coreclrpal)
+
+target_link_libraries(paltest_getenvironmentvariablew_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/test.c b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/test.c
new file mode 100644
index 0000000000..b5894efc6e
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/test.c
@@ -0,0 +1,63 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: Test for GetEnvironmentVariable() function
+**
+**
+**=========================================================*/
+
+/* Depends on SetEnvironmentVariableW (because we're implmenting the wide
+ version) and strcmp() */
+
+#define UNICODE
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[]) {
+
+ /* Define some buffers needed for the function */
+ WCHAR * pResultBuffer = NULL;
+ WCHAR SomeEnvironmentVariable[] = {'P','A','L','T','E','S','T','\0'};
+ WCHAR TheEnvironmentValue[] = {'T','E','S','T','\0'};
+ int size;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ SetEnvironmentVariable(SomeEnvironmentVariable,
+ TheEnvironmentValue);
+
+
+ /* Normal case, PATH should fit into this buffer */
+ size = GetEnvironmentVariable(convert("PALTEST"), // Variable Name
+ pResultBuffer, // Buffer for Value
+ 0); // Buffer size
+
+ pResultBuffer = malloc(size*sizeof(WCHAR));
+
+ GetEnvironmentVariable(convert("PALTEST"),
+ pResultBuffer,
+ size);
+
+ if(wcsncmp(pResultBuffer,convert("TEST"),wcslen(pResultBuffer) * 2) != 0)
+ {
+ Fail("ERROR: The value in the buffer should have been 'TEST' but was "
+ "really '%s'.",convertC(pResultBuffer));
+ }
+
+ free(pResultBuffer);
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/testinfo.dat
new file mode 100644
index 0000000000..64204fa698
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = GetEnvironmentVariableW
+Name = Positive Test for GetEnvironmentVariableW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Set an Environment Variable, then use GetEnvironmentVariable
+= to retrieve it -- ensure that it retrieves properly.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/CMakeLists.txt
new file mode 100644
index 0000000000..ab44781279
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test5.c
+)
+
+add_executable(paltest_getenvironmentvariablew_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getenvironmentvariablew_test5 coreclrpal)
+
+target_link_libraries(paltest_getenvironmentvariablew_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/test5.c b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/test5.c
new file mode 100644
index 0000000000..58eba3a380
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/test5.c
@@ -0,0 +1,144 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+** Source : test5.c
+**
+** Purpose: Test for GetEnvironmentVariableW() function
+** Create environment variables that differ only
+** in case and verify that they return the appropriate
+** value on the BSD environment.
+**
+**
+===========================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+#if WIN32
+
+ return PASS;
+
+#else
+
+ /* Define some buffers needed for the function */
+ WCHAR * pResultBuffer = NULL;
+
+ WCHAR FirstEnvironmentVariable[] = {'P','A','L','T','E','S','T','\0'};
+ WCHAR FirstEnvironmentValue[] = {'F','I','R','S','T','\0'};
+
+ WCHAR SecondEnvironmentVariable[] = {'p','a','l','t','e','s','t','\0'};
+ WCHAR SecondEnvironmentValue[] = {'S','E','C','O','N','D','\0'};
+
+ DWORD size = 0;
+ BOOL bRc = TRUE;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Set the first environment variable */
+ bRc = SetEnvironmentVariableW(FirstEnvironmentVariable,
+ FirstEnvironmentValue);
+
+ if(!bRc)
+ {
+ Fail("ERROR: SetEnvironmentVariable failed to set a "
+ "proper environment variable with error %u.\n", GetLastError());
+ }
+
+ /* Normal case, PATH should fit into this buffer */
+ size = GetEnvironmentVariableW(FirstEnvironmentVariable,
+ pResultBuffer,
+ 0);
+
+ /* To account for the nul character at the end of the string */
+ size = size + 1;
+
+ pResultBuffer = malloc(sizeof(WCHAR)*size);
+ if ( pResultBuffer == NULL )
+ {
+ Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n");
+ }
+
+ /* Try to retrieve the value of the first environment variable */
+ GetEnvironmentVariableW(FirstEnvironmentVariable,
+ pResultBuffer,
+ size);
+
+ if ( pResultBuffer == NULL )
+ {
+ free(pResultBuffer);
+ Fail("ERROR: GetEnvironmentVariable failed to return a value "
+ "from a proper environment variable with error %u.\n",
+ GetLastError());
+ }
+
+ /* Compare the strings to see that the correct variable was returned */
+ if(wcsncmp(pResultBuffer,FirstEnvironmentValue,wcslen(pResultBuffer)) != 0)
+ {
+ free(pResultBuffer);
+ Fail("ERROR: The value in the buffer should have been '%S' but "
+ "was really '%S'.\n",FirstEnvironmentValue, pResultBuffer);
+ }
+
+ free(pResultBuffer);
+
+ /* Set the second environment Variable */
+ bRc = SetEnvironmentVariableW(SecondEnvironmentVariable,
+ SecondEnvironmentValue);
+
+ if(!bRc)
+ {
+ Fail("ERROR: SetEnvironmentVariable failed to set a "
+ "proper environment variable with error %u.\n",
+ GetLastError());
+ }
+
+ /* Reallocate the memory for the string */
+ pResultBuffer = malloc(sizeof(WCHAR)*size);
+ if ( pResultBuffer == NULL )
+ {
+ Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n");
+ }
+
+ /* Try retrieving the value of the first variable, even though the
+ second variable has the same spelling and only differs in case */
+ GetEnvironmentVariableW(FirstEnvironmentVariable,
+ pResultBuffer,
+ size);
+
+ if ( pResultBuffer == NULL )
+ {
+ free(pResultBuffer);
+ Fail("ERROR: GetEnvironmentVariable failed to return a value "
+ "from a proper environment variable with error %u.\n",
+ GetLastError());
+ }
+
+ /* Compare the two strings to confirm that the right value is returned */
+ if(wcsncmp(pResultBuffer,FirstEnvironmentValue,wcslen(pResultBuffer)) != 0)
+ {
+ free(pResultBuffer);
+ Fail("ERROR: The value in the buffer should have been '%S' but "
+ "was really '%S'.\n",FirstEnvironmentValue,pResultBuffer);
+ }
+
+ free(pResultBuffer);
+
+ PAL_Terminate();
+ return PASS;
+
+#endif
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/testinfo.dat
new file mode 100644
index 0000000000..cbc214e8ca
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = GetEnvironmentVariableW
+Name = Positive Test for GetEnvironmentVariableW
+TYPE = DEFAULT
+EXE1 = test5
+Description
+= Set an Environment Variable, then use GetEnvironmentVariable
+= to retrieve it. Then set another environment variable that differs
+= from the original variable only by case and verify that
+= GetEnvironmnetVariable returns the correct value.
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/CMakeLists.txt
new file mode 100644
index 0000000000..e504c8323a
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test6.c
+)
+
+add_executable(paltest_getenvironmentvariablew_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getenvironmentvariablew_test6 coreclrpal)
+
+target_link_libraries(paltest_getenvironmentvariablew_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/test6.c b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/test6.c
new file mode 100644
index 0000000000..85f31be9c2
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/test6.c
@@ -0,0 +1,99 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+** Source : test6.c
+**
+** Purpose: Test for GetEnvironmentVariableW() function
+** Create environment variables that differ only
+** in case and verify that they return the appropriate
+** value on the BSD environment.
+**
+**
+===========================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+#if WIN32
+
+ /* Define some buffers needed for the function */
+ WCHAR * pResultBuffer = NULL;
+
+ WCHAR FirstEnvironmentVariable[] = {'P','A','L','T','E','S','T','\0'};
+ WCHAR FirstEnvironmentValue[] = {'F','I','R','S','T','\0'};
+
+ WCHAR ModifiedEnvironmentVariable[] = {'p','a','l','t','e','s','t','\0'};
+
+ DWORD size = 0;
+ BOOL bRc = TRUE;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Set the first environment variable */
+ bRc = SetEnvironmentVariableW(FirstEnvironmentVariable,
+ FirstEnvironmentValue);
+
+ if(!bRc)
+ {
+ Fail("ERROR: SetEnvironmentVariable failed to set a "
+ "proper environment variable with error %u.\n",
+ GetLastError());
+ }
+
+ /* Normal case, PATH should fit into this buffer */
+ size = GetEnvironmentVariableW(ModifiedEnvironmentVariable,
+ pResultBuffer,
+ 0);
+
+ /* To account for the nul character at the end of the string */
+ size = size + 1;
+
+ pResultBuffer = malloc(sizeof(WCHAR)*size);
+ if ( pResultBuffer == NULL )
+ {
+ Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n");
+ }
+
+ /* Try to retrieve the value of the first environment variable */
+ GetEnvironmentVariableW(ModifiedEnvironmentVariable,
+ pResultBuffer,
+ size);
+
+ if ( pResultBuffer == NULL )
+ {
+ free(pResultBuffer);
+ Fail("ERROR: GetEnvironmentVariable failed to return a value "
+ "from a proper environment variable with error %u.\n",
+ GetLastError());
+ }
+
+ /* Compare the strings to see that the correct variable was returned */
+ if(wcsncmp(pResultBuffer,FirstEnvironmentValue,wcslen(pResultBuffer)) != 0)
+ {
+ free(pResultBuffer);
+ Fail("ERROR: The value in the buffer should have been '%S' but "
+ "was really '%S'.\n",FirstEnvironmentValue, pResultBuffer);
+ }
+
+ free(pResultBuffer);
+
+ PAL_Terminate();
+ return PASS;
+
+
+#else
+
+ return PASS;
+#endif
+}
diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/testinfo.dat
new file mode 100644
index 0000000000..fad1ad69a6
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = GetEnvironmentVariableW
+Name = Positive Test for GetEnvironmentVariableW
+TYPE = DEFAULT
+EXE1 = test6
+Description
+= Set an Environment Variable, then use GetEnvironmentVariable
+= to retrieve the Variable, using a name that differs only in
+= Case. In Windows this should not affect the return value
+= of the function.
diff --git a/src/pal/tests/palsuite/miscellaneous/GetLastError/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetLastError/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetLastError/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetLastError/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetLastError/test1/CMakeLists.txt
new file mode 100644
index 0000000000..09e650c924
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetLastError/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_getlasterror_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getlasterror_test1 coreclrpal)
+
+target_link_libraries(paltest_getlasterror_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/GetLastError/test1/test.c b/src/pal/tests/palsuite/miscellaneous/GetLastError/test1/test.c
new file mode 100644
index 0000000000..65f56e595f
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetLastError/test1/test.c
@@ -0,0 +1,63 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: Test for GetLastError() function
+**
+**
+**=========================================================*/
+
+/* Depends on SetLastError() */
+
+#include <palsuite.h>
+
+/**
+ * Helper functions that does the actual test
+ */
+static void test(DWORD error )
+{
+ DWORD TheResult;
+
+ /* Set error */
+ SetLastError(error);
+
+ /* Check to make sure it returns the error value we just set */
+ TheResult = GetLastError();
+ if(TheResult!= error)
+ {
+ Fail("ERROR: The last error should have been %u, but when "
+ "GetLastError was called, it returned %u.\n",error,TheResult);
+ }
+
+}
+
+int __cdecl main(int argc, char *argv[]) {
+
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* test setting and getting some values */
+ test(5);
+ test(0xffffffff);
+ test(0xEEEEEEEE);
+ test(0xAAAAAAAA);
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetLastError/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/GetLastError/test1/testinfo.dat
new file mode 100644
index 0000000000..be41f52c63
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetLastError/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = GetLastError
+Name = Positive Test for GetLastError
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Ensure GetLastError returns the error message which was set.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/CMakeLists.txt
new file mode 100644
index 0000000000..960291fe79
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_getsysteminfo_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getsysteminfo_test1 coreclrpal)
+
+target_link_libraries(paltest_getsysteminfo_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/test.c b/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/test.c
new file mode 100644
index 0000000000..5f3608fb70
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/test.c
@@ -0,0 +1,70 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: Test for GetSystemInfo() function
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[]) {
+
+ SYSTEM_INFO TheSystemInfo;
+ SYSTEM_INFO* pSystemInfo = &TheSystemInfo;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ GetSystemInfo(pSystemInfo);
+
+ /* Ensure both valules are > than 0 */
+ if(pSystemInfo->dwNumberOfProcessors < 1)
+ {
+ Fail("ERROR: The dwNumberofProcessors values should be > 0.");
+ }
+
+ if(pSystemInfo->dwPageSize < 1)
+ {
+ Fail("ERROR: The dwPageSize should be greater than 0.");
+ }
+
+ /* If this isn't WIN32, ensure all the other variables are 0 */
+
+#if UNIX
+ if(pSystemInfo->dwOemId != 0 ||
+ pSystemInfo->wProcessorArchitecture != 0 ||
+ pSystemInfo->wReserved != 0 ||
+ pSystemInfo->lpMinimumApplicationAddress != 0 ||
+ pSystemInfo->lpMaximumApplicationAddress != 0 ||
+ pSystemInfo->dwActiveProcessorMask != 0 ||
+ pSystemInfo->dwProcessorType !=0 ||
+ pSystemInfo->dwAllocationGranularity !=0 ||
+ pSystemInfo->wProcessorLevel != 0 ||
+ pSystemInfo->wProcessorRevision != 0) {
+ Fail("ERROR: Under FreeBSD, OemId, ProcessorArchitecture, Reserved, "
+ "MinimumApplicationAddress, MaximumApplicationAddress, "
+ "ActiveProcessorMask, ProcessorType, AllocationGranularity, "
+ "ProcessorLevel and ProcessorRevision should be equal to 0.");
+
+
+ }
+#endif
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/testinfo.dat
new file mode 100644
index 0000000000..7f03c6355c
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = GetSystemInfo
+Name = Positive Test for GetSystemInfo
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Ensures the two required System Info fields can be aquired,
+= and the others are all 0.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetTickCount/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetTickCount/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetTickCount/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/CMakeLists.txt
new file mode 100644
index 0000000000..5c6ea26a41
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_gettickcount_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_gettickcount_test1 coreclrpal)
+
+target_link_libraries(paltest_gettickcount_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/test.c b/src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/test.c
new file mode 100644
index 0000000000..ad71ba5d6c
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/test.c
@@ -0,0 +1,58 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source:
+**
+** Source : test1.c
+**
+** Purpose: Test for GetTickCount() function
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[]) {
+
+ DWORD FirstCount = 0;
+ DWORD SecondCount = 0;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Grab a FirstCount, then loop for a bit to make the clock increase */
+ FirstCount = GetTickCount();
+
+ /* Make sure some time passes */
+ Sleep(60); //Since the get tick count is accurate within 55 milliseconds.
+
+ /* Get a second count */
+ SecondCount = GetTickCount();
+
+ /* Make sure the second one is bigger than the first.
+ This isn't the best test, but it at least shows that it's returning a
+ DWORD which is increasing.
+ */
+
+ if(FirstCount >= SecondCount)
+ {
+ Fail("ERROR: The first time (%d) was greater/equal than the second time "
+ " (%d). The tick count should have increased.\n",
+ FirstCount,SecondCount);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/testinfo.dat
new file mode 100644
index 0000000000..78888abd53
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = GetTickCount
+Name = Positive Test for GetTickCount
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Grab two Tick Counts with this function, and ensure that
+= the second is larger to show that the tick count is increasing.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetUserNameW/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetUserNameW/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetUserNameW/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetUserNameW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetUserNameW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..a1d5ab21b8
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetUserNameW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_getusernamew_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getusernamew_test1 coreclrpal)
+
+target_link_libraries(paltest_getusernamew_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/GetUserNameW/test1/test.c b/src/pal/tests/palsuite/miscellaneous/GetUserNameW/test1/test.c
new file mode 100644
index 0000000000..809f14c12d
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetUserNameW/test1/test.c
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: Positive Test for GetUserName() function
+**
+**
+**=========================================================*/
+
+#define UNICODE
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ WCHAR wzUserName[UNLEN+1];
+ DWORD dwSize = sizeof(wzUserName)/sizeof(wzUserName[0]);
+
+ // Initialize the PAL and return FAILURE if this fails
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ Fail ("ERROR: PAL_Initialize() call failed!\n");
+ }
+
+ if (0 == GetUserName(wzUserName, &dwSize))
+ {
+ Fail("ERROR: GetUserName failed with %d!\n", GetLastError());
+ }
+
+ // dwSize is the length of wzUserName with NULL
+ if (dwSize <= 0 || dwSize > (sizeof(wzUserName)/sizeof(wzUserName[0])))
+ {
+ Fail("ERROR: GetUserName returned %S with dwSize = %u whereas the passed in buffer size is %d!\n",
+ wzUserName, dwSize, sizeof(wzUserName)/sizeof(wzUserName[0]));
+ }
+
+ // dwSize is the length of wzUserName with NULL
+ if (dwSize != wcslen(wzUserName)+1)
+ {
+ Fail("ERROR: GetUserName returned %S of length %d which is not equal to dwSize-1 = %u!\n",
+ wzUserName, wcslen(wzUserName), dwSize-1);
+ }
+
+ printf ("GetUserName returned %S of length %u\n", wzUserName, dwSize-1);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/miscellaneous/GetUserNameW/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/GetUserNameW/test1/testinfo.dat
new file mode 100644
index 0000000000..3e0aa48bd0
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetUserNameW/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = GetUserNameW
+Name = Test for GetUserNameW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Check to ensure that GetUserNameW returnes a decent value.
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetVersionExA/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetVersionExA/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetVersionExA/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetVersionExA/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetVersionExA/test1/CMakeLists.txt
new file mode 100644
index 0000000000..b9dd711d36
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetVersionExA/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_getversionexa_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getversionexa_test1 coreclrpal)
+
+target_link_libraries(paltest_getversionexa_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/GetVersionExA/test1/test.c b/src/pal/tests/palsuite/miscellaneous/GetVersionExA/test1/test.c
new file mode 100644
index 0000000000..5dd20c6576
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetVersionExA/test1/test.c
@@ -0,0 +1,83 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: Test for GetVersionExA() function
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[]) {
+
+ OSVERSIONINFO TheVersionInfo;
+ OSVERSIONINFO* pVersionInfo = &TheVersionInfo;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+
+ /* This needs to be done before using GetVersionEx */
+ pVersionInfo->dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+
+ /* If GetVersionEx fails, then the test fails */
+ if(GetVersionEx(pVersionInfo) == 0)
+ {
+ Fail("ERROR: The GetVersionEx function returned 0, which indicates "
+ "failure.");
+ }
+
+ /* These values are fixed, ensure they're set properly */
+ if(pVersionInfo->dwMajorVersion != 5)
+ {
+ Fail("ERROR: The fixed value of dwMajorVersion shoud be 5, "
+ "but is really %d.",pVersionInfo->dwMajorVersion);
+ }
+
+ /* The minor version values for Win2k and XP are different
+ for Win2k minor version equals 0 and for XP minor version
+ equals 1. Both values are excepted here. */
+ if((pVersionInfo->dwMinorVersion != 0) &&
+ (pVersionInfo->dwMinorVersion != 1))
+ {
+ Fail("ERROR: The fixed value of dwMinorVersion shoud be 0 or 1, "
+ "but is really %d.",pVersionInfo->dwMinorVersion);
+ }
+ if(pVersionInfo->dwBuildNumber_PAL_Undefined < 0)
+ {
+ Fail("ERROR: The value of dwBuildNumber shoud be at least 0, but "
+ "is really %d.",pVersionInfo->dwBuildNumber_PAL_Undefined);
+ }
+
+#if !WIN32
+ /* Under BSD, the PlatformID should be UNIX and the Service Pack
+ version should be set to "".
+ */
+
+ if(pVersionInfo->dwPlatformId != VER_PLATFORM_UNIX ||
+ pVersionInfo->szCSDVersion_PAL_Undefined[0] != 0)
+ {
+ Fail("ERROR: The dwPlatformId should be %d but is really %d. And the "
+ "szCSDVerion should be NULL.",
+ VER_PLATFORM_UNIX,pVersionInfo->dwPlatformId);
+ }
+#endif
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetVersionExA/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/GetVersionExA/test1/testinfo.dat
new file mode 100644
index 0000000000..1e9c570c60
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetVersionExA/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = GetVersionExA
+Name = Positive Test for GetVersionExA
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test that all the values in the OSVERSION structure are set properly
+= for the current environment.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetVersionExW/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetVersionExW/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetVersionExW/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetVersionExW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetVersionExW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..d7eb683343
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetVersionExW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_getversionexw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getversionexw_test1 coreclrpal)
+
+target_link_libraries(paltest_getversionexw_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/GetVersionExW/test1/test.c b/src/pal/tests/palsuite/miscellaneous/GetVersionExW/test1/test.c
new file mode 100644
index 0000000000..69aae54bcf
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetVersionExW/test1/test.c
@@ -0,0 +1,88 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: Test for GetVersionExW() function
+**
+**
+**=========================================================*/
+
+#define UNICODE
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ OSVERSIONINFO TheVersionInfo;
+ OSVERSIONINFO* pVersionInfo = &TheVersionInfo;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* This needs to be done before using GetVersionEx */
+ pVersionInfo->dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+
+ /* If GetVersionEx fails, then the test fails */
+ if(GetVersionEx(pVersionInfo) == 0)
+ {
+ Fail("ERROR: The GetVersionEx function returned 0, which indicates "
+ "failure.");
+ }
+
+ /* These values are fixed, ensure they're set properly */
+ if(pVersionInfo->dwMajorVersion != 5)
+ {
+ Fail("ERROR: The fixed value of dwMajorVersion shoud be 5, but is "
+ " really %d.",pVersionInfo->dwMajorVersion);
+ }
+
+ /* The minor version values for Win2k and XP are different
+ for Win2k minor version equals 0 and for XP minor version
+ equals 1. Both values are excepted here. */
+ if((pVersionInfo->dwMinorVersion != 0) &&
+ (pVersionInfo->dwMinorVersion != 1))
+ {
+ Fail("ERROR: The fixed value of dwMinorVersion shoud be 0 or 1, "
+ "but is really %d.",pVersionInfo->dwMinorVersion);
+ }
+
+ if(pVersionInfo->dwBuildNumber_PAL_Undefined < 0)
+ {
+ Fail("ERROR: The value of dwBuildNumber shoud be at least 0, but is "
+ "really %d.",pVersionInfo->dwBuildNumber_PAL_Undefined);
+ }
+
+#if !WIN32
+
+
+ /* Under BSD, the PlatformID should be UNIX and the Service Pack
+ version should be set to "".
+ */
+
+ if(pVersionInfo->dwPlatformId != VER_PLATFORM_UNIX ||
+ pVersionInfo->szCSDVersion_PAL_Undefined[0] != 0)
+ {
+ Fail("ERROR: The dwPlatformId should be %d but is really %d. And the "
+ "szCSDVerion should be NULL.",VER_PLATFORM_UNIX,
+ pVersionInfo->dwPlatformId);
+ }
+#endif
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/GetVersionExW/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/GetVersionExW/test1/testinfo.dat
new file mode 100644
index 0000000000..7773245b3f
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/GetVersionExW/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = GetVersionExW
+Name = Positive Test for GetVersionExW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test that all the values in the OSVERSION structure are set properly
+= for the current environment.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterLockedExchangeAdd/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/InterLockedExchangeAdd/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterLockedExchangeAdd/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterLockedExchangeAdd/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/InterLockedExchangeAdd/test1/CMakeLists.txt
new file mode 100644
index 0000000000..e5ba709c11
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterLockedExchangeAdd/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.cpp
+)
+
+add_executable(paltest_interlockedexchangeadd_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_interlockedexchangeadd_test1 coreclrpal)
+
+target_link_libraries(paltest_interlockedexchangeadd_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/InterLockedExchangeAdd/test1/test.cpp b/src/pal/tests/palsuite/miscellaneous/InterLockedExchangeAdd/test1/test.cpp
new file mode 100644
index 0000000000..ca9e5bb5bf
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterLockedExchangeAdd/test1/test.cpp
@@ -0,0 +1,102 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: InterlockedExchangeAdd() function
+**
+**
+**=========================================================*/
+
+/*
+** The InterlockedExchangeAdd function performs an atomic addition of Value
+** to the value pointed to by Addend.
+** The result is stored in the address specified by Addend.
+** The initial value of the variable pointed to by Addend is returned as the function value.
+*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ LONG TheReturn;
+
+ LONG *ptrValue = NULL;
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+
+
+#if defined(BIT64) && defined(PLATFORM_UNIX)
+ ptrValue = (LONG *) malloc(sizeof(LONG));
+
+ if(ptrValue == NULL)
+ {
+ Fail("Error:%d:Malloc failed for ptrValue\n", GetLastError());
+ }
+
+ *ptrValue = (LONG) 0;
+
+ TheReturn = InterlockedExchangeAdd( ptrValue, (LONG) 5);
+
+
+ /* Added, it should be 5 now */
+ if(*ptrValue != 5)
+ {
+
+ Trace("ERROR: After an add operation, the value should be 5, "
+ "but it is really %d.", *ptrValue);
+ free(ptrValue);
+ Fail("");
+ }
+
+ /* Check to make sure the function returns the original value (5 in this case) */
+ if(TheReturn != 0)
+ {
+ Trace("ERROR: The function should have returned the new value of %d "
+ "but instead returned %d.", *ptrValue, TheReturn);
+ free(ptrValue);
+ Fail("");
+ }
+
+ TheReturn = InterlockedExchangeAdd( ptrValue, (LONG) 1);
+
+
+ /* Added twice, it should be 6 now */
+ if(*ptrValue != 6)
+ {
+
+ Trace("ERROR: After having two add operations, the value should be 6, "
+ "but it is really %d.", *ptrValue);
+ free(ptrValue);
+ Fail("");
+ }
+
+ /* Check to make sure the function returns the original value (5 in this case) */
+ if(TheReturn != 5)
+ {
+ Trace("ERROR: The function should have returned the new value of %d "
+ "but instead returned %d.", *ptrValue, TheReturn);
+ free(ptrValue);
+ Fail("");
+ }
+
+ free(ptrValue);
+#endif
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedBit/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/InterlockedBit/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedBit/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test1/CMakeLists.txt
new file mode 100644
index 0000000000..a70802ea2d
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.cpp
+)
+
+add_executable(paltest_interlockedbit_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_interlockedbit_test1 coreclrpal)
+
+target_link_libraries(paltest_interlockedbit_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test1/test.cpp b/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test1/test.cpp
new file mode 100644
index 0000000000..1f7c43cddb
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test1/test.cpp
@@ -0,0 +1,77 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: Test for InterlockedBitTestAndReset() function
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+typedef struct tag_TEST_DATA
+{
+ LONG baseValue;
+ UINT bitPosition;
+ LONG expectedValue;
+ UCHAR expectedReturnValue;
+} TEST_DATA;
+
+TEST_DATA test_data[] =
+{
+ { (LONG)0x00000000, 3, (LONG)0x00000000, 0 },
+ { (LONG)0x12341234, 2, (LONG)0x12341230, 1 },
+ { (LONG)0x12341234, 3, (LONG)0x12341234, 0 },
+ { (LONG)0x12341234, 31, (LONG)0x12341234, 0 },
+ { (LONG)0x12341234, 28, (LONG)0x02341234, 1 },
+ { (LONG)0xffffffff, 28, (LONG)0xefffffff, 1 }
+};
+
+int __cdecl main(int argc, char *argv[]) {
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < sizeof (test_data) / sizeof (TEST_DATA); i++)
+ {
+ LONG baseVal = test_data[i].baseValue;
+ LONG bitPosition = test_data[i].bitPosition;
+
+ UCHAR ret = InterlockedBitTestAndReset(
+ &baseVal, /* Variable to manipulate */
+ bitPosition);
+
+ if (ret != test_data[i].expectedReturnValue)
+ {
+ Fail("ERROR: InterlockedBitTestAndReset(%d): Expected return value is %d,"
+ "Actual return value is %d.",
+ i,
+ test_data[i].expectedReturnValue,
+ ret);
+ }
+
+ if (baseVal != test_data[i].expectedValue)
+ {
+ Fail("ERROR: InterlockedBitTestAndReset(%d): Expected value is %x,"
+ "Actual value is %x.",
+ i,
+ test_data[i].expectedValue,
+ baseVal);
+ }
+
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test1/testinfo.dat
new file mode 100644
index 0000000000..677999906f
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = InterlockedBitTestAndReset
+Name = Test for InterlockedBitTestAndReset
+TYPE = DEFAULT
+EXE1 = test
+Description
+Test validates that function InterlockedBitTestAndReset work as intended.
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test2/CMakeLists.txt
new file mode 100644
index 0000000000..6b50a755fe
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.cpp
+)
+
+add_executable(paltest_interlockedbit_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_interlockedbit_test2 coreclrpal)
+
+target_link_libraries(paltest_interlockedbit_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test2/test.cpp b/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test2/test.cpp
new file mode 100644
index 0000000000..4230c8a805
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test2/test.cpp
@@ -0,0 +1,77 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: Test for InterlockedBitTestAndSet() function
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+typedef struct tag_TEST_DATA
+{
+ LONG baseValue;
+ UINT bitPosition;
+ LONG expectedValue;
+ UCHAR expectedReturnValue;
+} TEST_DATA;
+
+TEST_DATA test_data[] =
+{
+ { (LONG)0x00000000, 2, (LONG)0x00000004, 0 },
+ { (LONG)0x12341234, 2, (LONG)0x12341234, 1 },
+ { (LONG)0x12341234, 3, (LONG)0x1234123c, 0 },
+ { (LONG)0x12341234, 31, (LONG)0x92341234, 0 },
+ { (LONG)0x12341234, 28, (LONG)0x12341234, 1 },
+ { (LONG)0xffffffff, 28, (LONG)0xffffffff, 1 }
+};
+
+int __cdecl main(int argc, char *argv[]) {
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ for (int i = 0; i < sizeof (test_data) / sizeof (TEST_DATA); i++)
+ {
+ LONG baseVal = test_data[i].baseValue;
+ LONG bitPosition = test_data[i].bitPosition;
+
+ UCHAR ret = InterlockedBitTestAndSet(
+ &baseVal, /* Variable to manipulate */
+ bitPosition);
+
+ if (ret != test_data[i].expectedReturnValue)
+ {
+ Fail("ERROR: InterlockedBitTestAndSet(%d): Expected return value is %d,"
+ "Actual return value is %d.",
+ i,
+ test_data[i].expectedReturnValue,
+ ret);
+ }
+
+ if (baseVal != test_data[i].expectedValue)
+ {
+ Fail("ERROR: InterlockedBitTestAndSet(%d): Expected value is %x,"
+ "Actual value is %x.",
+ i,
+ test_data[i].expectedValue,
+ baseVal);
+ }
+
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test2/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test2/testinfo.dat
new file mode 100644
index 0000000000..3ad431701a
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedBit/test2/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = InterlockedBitTestAndSet
+Name = Test for InterlockedBitTestAndSet
+TYPE = DEFAULT
+EXE1 = test
+Description
+Test validates that function InterlockedBitTestAndSet work as intended.
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test1/CMakeLists.txt
new file mode 100644
index 0000000000..d9e867256a
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.cpp
+)
+
+add_executable(paltest_interlockedcompareexchange_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_interlockedcompareexchange_test1 coreclrpal)
+
+target_link_libraries(paltest_interlockedcompareexchange_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test1/test.cpp b/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test1/test.cpp
new file mode 100644
index 0000000000..77f2c4c449
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test1/test.cpp
@@ -0,0 +1,100 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: Test for InterlockedCompareExchange() function
+**
+**
+**=========================================================*/
+
+/* This test is FINISHED. Note: The biggest feature of this function is that
+ it locks the value before it increments it -- in order to make it so only
+ one thread can access it. But, I really don't have a great test to make
+ sure it's thread safe. Any ideas?
+*/
+
+#include <palsuite.h>
+
+#define START_VALUE 0
+#define SECOND_VALUE 5
+#define THIRD_VALUE 10
+
+int __cdecl main(int argc, char *argv[]) {
+
+ int BaseVariableToManipulate = START_VALUE;
+ int ValueToExchange = SECOND_VALUE;
+ int TempValue;
+ int TheReturn;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Compare START_VALUE with BaseVariableToManipulate, they're equal,
+ so exchange
+ */
+
+ TheReturn = InterlockedCompareExchange(
+ &BaseVariableToManipulate, /* Destination */
+ ValueToExchange, /* Exchange value */
+ START_VALUE); /* Compare value */
+
+ /* Exchanged, these should be equal now */
+ if(BaseVariableToManipulate != ValueToExchange)
+ {
+ Fail("ERROR: A successful compare and exchange should have occurred, "
+ "making the variable have the value of %d, as opposed to the "
+ "current value of %d.",
+ ValueToExchange,BaseVariableToManipulate);
+ }
+
+ /* Check to make sure it returns the original number which
+ 'BaseVariableToManipulate' was set to.
+ */
+ if(TheReturn != START_VALUE)
+ {
+ Fail("ERROR: The return value after the first exchange should be the "
+ "former value of the variable, which was %d, but it is now %d.",
+ START_VALUE,TheReturn);
+ }
+
+
+
+ ValueToExchange = THIRD_VALUE; /* Give this a new value */
+ TempValue = BaseVariableToManipulate; /* Note value of Base */
+
+ /*
+ Do an exchange where 'BaseVariableToManipulate' doesn't
+ match -- therefore the exchange shouldn't happen.
+ So, it should end up the same as the 'TempValue' we saved.
+ */
+
+ InterlockedCompareExchange(&BaseVariableToManipulate,
+ ValueToExchange,
+ START_VALUE);
+
+ if(BaseVariableToManipulate != TempValue)
+ {
+ Fail("ERROR: An attempted exchange should have failed due to "
+ "the compare failing. But, it seems to have succeeded. The "
+ "value should be %d but is %d in this case.",
+ TempValue,BaseVariableToManipulate);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test1/testinfo.dat
new file mode 100644
index 0000000000..04b1dfe783
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = InterlockedCompareExchange
+Name = Positive test of InterlockedCompareExchange
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test to see if both successful and unsuccessful compare exchanges workp
+= roperly -- ie. Exchange and don't exchange.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test2/CMakeLists.txt
new file mode 100644
index 0000000000..038d375273
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.cpp
+)
+
+add_executable(paltest_interlockedcompareexchange_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_interlockedcompareexchange_test2 coreclrpal)
+
+target_link_libraries(paltest_interlockedcompareexchange_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test2/test.cpp b/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test2/test.cpp
new file mode 100644
index 0000000000..902f626d47
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange/test2/test.cpp
@@ -0,0 +1,168 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: Test for InterlockedCompareExchange() function using multiple threads
+**
+**
+**=========================================================*/
+
+
+
+#include <palsuite.h>
+
+#define MAX_THREADS 10
+#define REPEAT_COUNT 10
+
+//Global Variable Declaration
+LONG g_Total = 0;
+LONG Lock=0;
+
+
+void ModifyGlobalResource(void);
+void AcquireLock(PLONG pLock);
+void ReleaseLock(PLONG pLock);
+
+
+
+//Main entry point of the program
+int __cdecl main(int argc, char *argv[]) {
+
+ int i = 0;
+ DWORD dwThreadID=0;
+ LONG totalOperations = 0;
+
+ HANDLE hThread[MAX_THREADS];
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+
+ totalOperations = MAX_THREADS * REPEAT_COUNT;
+
+
+ //Create MAX_THREADS threads that will operate on the global counter
+ for (i=0;i<MAX_THREADS;i++)
+ {
+ hThread[i] = CreateThread(
+ NULL, // default security attributes
+ 0, // use default stack size
+ (LPTHREAD_START_ROUTINE) ModifyGlobalResource, // thread function
+ NULL, // argument to thread function
+ 0, // use default creation flags
+ &dwThreadID); // returns the thread identifier
+
+ // Check the return value for success.
+
+ if (hThread[i] == NULL)
+ {
+ Fail("ERROR: Was not able to create thread\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+ }
+
+
+ //Wait for all threads to finish
+ for (i=0;i<MAX_THREADS;i++)
+ {
+
+ if (WAIT_OBJECT_0 != WaitForSingleObject (hThread[i], INFINITE))
+ {
+ Fail ("Main: Wait for Single Object failed. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+ }
+
+
+ if (0!= g_Total)
+ {
+ Fail("Test Failed \n");
+ }
+
+ Trace("Global Counter Value at the end of the test %d \n", g_Total);
+
+ /*
+ * Terminate PAL
+ */
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+void ModifyGlobalResource(void)
+{
+
+ int i =0;
+
+ for (i=0;i<REPEAT_COUNT;i++)
+ {
+
+ /*
+ Acquire Lock Provides Synchronization Around g_Total global variable
+ */
+
+ AcquireLock(&Lock);
+
+ /*
+ The following set of operations is gauranteed to be atomic by virtue of the fact
+ that InterLockedCompareExchange was able to gaurantee that the compare
+ and exchange operation on pLock was thread safe. If the same set of code was
+ executed without using InterlockedCompareExchange the code would fail most of
+ time.
+
+ */
+ g_Total++;
+ Sleep(100);
+ g_Total--;
+ if (0!=g_Total)
+ {
+ Fail("Test Failed beacuse g_Total was not protected \n");
+ }
+
+
+ /*
+ Acquire Lock releases the lock around g_Total Global variable
+ */
+
+ ReleaseLock(&Lock);
+ }
+
+
+}
+
+
+void AcquireLock(PLONG pLock)
+{
+ //Spin Lock implemented with the help of InterlockedCompareExchange
+
+
+ while(1)
+ {
+ if (InterlockedCompareExchange(pLock,1,0)==0)
+ break;
+ }
+
+}
+
+
+void ReleaseLock(PLONG pLock)
+{
+
+
+ MemoryBarrier();
+ *pLock = 0;
+}
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test1/CMakeLists.txt
new file mode 100644
index 0000000000..722603eb4a
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.cpp
+)
+
+add_executable(paltest_interlockedcompareexchange64_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_interlockedcompareexchange64_test1 coreclrpal)
+
+target_link_libraries(paltest_interlockedcompareexchange64_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test1/test.cpp b/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test1/test.cpp
new file mode 100644
index 0000000000..56430e60cf
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test1/test.cpp
@@ -0,0 +1,122 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: Test for InterlockedCompareExchange() function
+**
+**
+**=========================================================*/
+
+/* This test is FINISHED. Note: The biggest feature of this function is that
+ it locks the value before it increments it -- in order to make it so only
+ one thread can access it. But, I really don't have a great test to make
+ sure it's thread safe. Any ideas?
+*/
+
+#include <palsuite.h>
+
+#define START_VALUE 0
+#define SECOND_VALUE 5
+#define THIRD_VALUE 10
+
+int __cdecl main(int argc, char *argv[]) {
+
+ LONGLONG BaseVariableToManipulate = START_VALUE;
+ LONGLONG ValueToExchange = SECOND_VALUE;
+ LONGLONG TempValue;
+ LONGLONG TheReturn;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+/*
+** Run only on 64 bit platforms
+*/
+#if defined(BIT64) && defined(PLATFORM_UNIX)
+ /* Compare START_VALUE with BaseVariableToManipulate, they're equal,
+ so exchange
+ */
+
+ TheReturn = InterlockedCompareExchange64(
+ &BaseVariableToManipulate, /* Destination */
+ ValueToExchange, /* Exchange value */
+ START_VALUE); /* Compare value */
+
+ /* Exchanged, these should be equal now */
+ if(BaseVariableToManipulate != ValueToExchange)
+ {
+#ifdef PLATFORM_UNIX
+ Fail("ERROR: A successful compare and exchange should have occurred, "
+ "making the variable have the value of %ll, as opposed to the "
+ "current value of %ll.",
+ ValueToExchange,BaseVariableToManipulate);
+#else
+ Fail("ERROR: A successful compare and exchange should have occurred, "
+ "making the variable have the value of %I64, as opposed to the "
+ "current value of %d.",
+ ValueToExchange,BaseVariableToManipulate);
+
+#endif
+ }
+
+ /* Check to make sure it returns the original number which
+ 'BaseVariableToManipulate' was set to.
+ */
+ if(TheReturn != START_VALUE)
+ {
+#ifdef PLATFORM_UNIX
+ Fail("ERROR: The return value after the first exchange should be the "
+ "former value of the variable, which was %ll, but it is now %ll.",
+ START_VALUE,TheReturn);
+#else
+ Fail("ERROR: The return value after the first exchange should be the "
+ "former value of the variable, which was %I64, but it is now %I64.",
+ START_VALUE,TheReturn);
+#endif
+
+ }
+
+
+
+ ValueToExchange = THIRD_VALUE; /* Give this a new value */
+ TempValue = BaseVariableToManipulate; /* Note value of Base */
+
+ /*
+ Do an exchange where 'BaseVariableToManipulate' doesn't
+ match -- therefore the exchange shouldn't happen.
+ So, it should end up the same as the 'TempValue' we saved.
+ */
+
+ InterlockedCompareExchange64(&BaseVariableToManipulate,
+ ValueToExchange,
+ START_VALUE);
+
+ if(BaseVariableToManipulate != TempValue)
+ {
+#ifdef PLATFORM_UNIX
+ Fail("ERROR: An attempted exchange should have failed due to "
+ "the compare failing. But, it seems to have succeeded. The "
+ "value should be %ll but is %ll in this case.",
+ TempValue,BaseVariableToManipulate);
+#else
+ Fail("ERROR: An attempted exchange should have failed due to "
+ "the compare failing. But, it seems to have succeeded. The "
+ "value should be %I64 but is %I64 in this case.",
+ TempValue,BaseVariableToManipulate);
+#endif
+ }
+
+#endif //if defined(BIT64) && defined(PLATFORM_UNIX)
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test1/testinfo.dat
new file mode 100644
index 0000000000..1849277347
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = InterlockedCompareExchange64
+Name = Positive test of InterlockedCompareExchange64
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test to see if both successful and unsuccessful compare exchanges workp
+= roperly -- ie. Exchange and don't exchange.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test2/CMakeLists.txt
new file mode 100644
index 0000000000..f052ca0b27
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.cpp
+)
+
+add_executable(paltest_interlockedcompareexchange64_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_interlockedcompareexchange64_test2 coreclrpal)
+
+target_link_libraries(paltest_interlockedcompareexchange64_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test2/test.cpp b/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test2/test.cpp
new file mode 100644
index 0000000000..2440543631
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchange64/test2/test.cpp
@@ -0,0 +1,104 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: InterlockedIncrement64() function
+**
+** The test case spawns MAX_THREADS Threads, and each thread call InterlockedDecrement Function to decrement a
+** global counter REPEAT_COUNT Times. The Test case sets the global counter to Zero at the begining of the test.
+** The test cases passes if at the end the test the value of the global counter is MAX_THREADS * REPEAT_COUNT.
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+#define MAX_THREADS 64
+#define REPEAT_COUNT 10000
+
+LONG GlobalCounter = 0;
+void IncrementCounter(void);
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ LONG TotalOperations=0;
+ int i=0;
+ DWORD dwThreadID = 0;
+
+ HANDLE hThread[MAX_THREADS];
+
+ TotalOperations = MAX_THREADS * REPEAT_COUNT;
+
+ GlobalCounter = 0;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /*
+ ** Run only on 64 bit platforms
+ */
+ #if defined(BIT64) && defined(PLATFORM_UNIX)
+
+ //Create MAX_THREADS threads that will operate on the global counter
+ for (i=0;i<MAX_THREADS;i++)
+ {
+ hThread[i] = CreateThread(
+ NULL, // default security attributes
+ 0, // use default stack size
+ (LPTHREAD_START_ROUTINE) IncrementCounter, // thread function
+ NULL, // argument to thread function
+ 0, // use default creation flags
+ &dwThreadID); // returns the thread identifier
+
+ // Check the return value for success.
+ if (hThread[i] == NULL)
+ {
+ Fail("ERROR: Was not able to create thread\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+ }
+ //Wait for all threads to finish
+ for (i=0;i<MAX_THREADS;i++)
+ {
+ if (WAIT_OBJECT_0 != WaitForSingleObject (hThread[i], INFINITE))
+ {
+ Fail ("Main: Wait for Single Object failed. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+ }
+
+ /* Compare the value of global counter with zero.
+ */
+ if (TotalOperations!=GlobalCounter)
+ {
+ Fail("Test Case Failed: InterlockedDecrement \n");
+ }
+
+ #endif //defined(BIT64) && defined(PLATFORM_UNIX)
+
+ PAL_Terminate();
+ return PASS;
+}
+
+void IncrementCounter(void)
+{
+ int i=0;
+
+ for (i=0; i<REPEAT_COUNT;i++)
+ {
+ InterlockedIncrement(&GlobalCounter);
+ }
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchangePointer/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchangePointer/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchangePointer/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchangePointer/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchangePointer/test1/CMakeLists.txt
new file mode 100644
index 0000000000..0c48c4e296
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchangePointer/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.cpp
+)
+
+add_executable(paltest_interlockedcompareexchangepointer_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_interlockedcompareexchangepointer_test1 coreclrpal)
+
+target_link_libraries(paltest_interlockedcompareexchangepointer_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchangePointer/test1/test.cpp b/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchangePointer/test1/test.cpp
new file mode 100644
index 0000000000..c263a6cdc4
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchangePointer/test1/test.cpp
@@ -0,0 +1,80 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for InterlockedCompareExchangePointer() function
+**
+**
+**=========================================================*/
+
+/* This test is FINISHED. Note: The biggest feature of this function is that
+ it locks the value before it increments it -- in order to make it so only
+ one thread can access it. But, I really don't have a great test to
+ make sure it's thread safe. Any ideas?
+*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ long StartValue = 5;
+ long NewValue = 10;
+ PVOID ReturnValue = NULL;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ ReturnValue = InterlockedCompareExchangePointer((PVOID)&StartValue,
+ (PVOID)NewValue,
+ (PVOID)StartValue);
+
+ /* StartValue and NewValue should be equal now */
+ if(StartValue != NewValue)
+ {
+ Fail("ERROR: These values should be equal after the exchange. "
+ "They should both be %d, however the value that should have "
+ "been exchanged is %d.\n",NewValue,StartValue);
+ }
+
+ /* Returnvalue should have been set to what 'StartValue' was
+ (5 in this case)
+ */
+
+ if((int)(size_t)ReturnValue != 5)
+ {
+ Fail("ERROR: The return value should be the value of the "
+ "variable before the exchange took place, which was 5. "
+ "But, the return value was %d.\n",ReturnValue);
+ }
+
+ /* This is a mismatch, so no exchange should happen */
+ InterlockedCompareExchangePointer((PVOID)&StartValue,
+ ReturnValue,
+ ReturnValue);
+ if(StartValue != NewValue)
+ {
+ Fail("ERROR: The compare should have failed and no exchange should "
+ "have been made, but it seems the exchange still happened.\n");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchangePointer/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchangePointer/test1/testinfo.dat
new file mode 100644
index 0000000000..d78515e7cc
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedCompareExchangePointer/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = InterlockedCompareExchangePointer
+Name = Positive test of InterlockedCompareExchangePointer
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test to see if both successful and unsuccessful compare exchanges work
+= properly -- ie. Exchange and don't exchange.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test1/CMakeLists.txt
new file mode 100644
index 0000000000..6cd307d2e8
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.cpp
+)
+
+add_executable(paltest_interlockeddecrement_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_interlockeddecrement_test1 coreclrpal)
+
+target_link_libraries(paltest_interlockeddecrement_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test1/test.cpp b/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test1/test.cpp
new file mode 100644
index 0000000000..9c9a50c73e
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test1/test.cpp
@@ -0,0 +1,60 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: InterlockedDecrement() function
+**
+**
+**=========================================================*/
+
+/* This test is FINISHED. Note: The biggest feature of this function is that
+ it locks the value before it increments it -- in order to make it so only
+ one thread can access it. But, I really don't have a great test to make
+ sure it's thread safe. Any ideas?
+*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int TheValue = 0;
+ int TheReturn;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ InterlockedDecrement(&TheValue);
+ TheReturn = InterlockedDecrement(&TheValue);
+
+ /* Decremented twice, it should be -2 now */
+ if(TheValue != -2)
+ {
+ Fail("ERROR: After being decremented twice, the value should be -2, "
+ "but it is really %d.",TheValue);
+ }
+
+ /* Check to make sure it returns itself */
+ if(TheReturn != TheValue)
+ {
+ Fail("ERROR: The function should have returned the new value of %d "
+ "but instead returned %d.",TheValue,TheReturn);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test1/testinfo.dat
new file mode 100644
index 0000000000..57ee3835cd
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = InterlockedDecrement
+Name = Positive test of InterlockedDecrement
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test to see if this decrements the variable correctly and
+= has the correct return value.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test2/CMakeLists.txt
new file mode 100644
index 0000000000..331d89d5d6
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.cpp
+)
+
+add_executable(paltest_interlockeddecrement_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_interlockeddecrement_test2 coreclrpal)
+
+target_link_libraries(paltest_interlockeddecrement_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test2/test.cpp b/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test2/test.cpp
new file mode 100644
index 0000000000..2f214e29e5
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement/test2/test.cpp
@@ -0,0 +1,94 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: InterlockedDecrement() function
+**
+** The test case spawns MAX_THREADS Threads, and each thread call InterlockedDecrement Function to decrement a
+** global counter REPEAT_COUNT Times. The Test case sets the global counter to MAX_THREADS * REPEAT_COUNT
+** at the begining of the test. The test cases passes if at the end the test the value of the global counter is Zero.
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+#define MAX_THREADS 64
+#define REPEAT_COUNT 10000
+
+LONG GlobalCounter = 0;
+void DecrementCounter(void);
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ LONG TotalOperations=0;
+ int i=0;
+ DWORD dwThreadID = 0;
+ HANDLE hThread[MAX_THREADS];
+ TotalOperations = MAX_THREADS * REPEAT_COUNT;
+ GlobalCounter = TotalOperations;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ //Create MAX_THREADS threads that will operate on the global counter
+ for (i=0;i<MAX_THREADS;i++)
+ {
+ hThread[i] = CreateThread(
+ NULL, // default security attributes
+ 0, // use default stack size
+ (LPTHREAD_START_ROUTINE) DecrementCounter, // thread function
+ NULL, // argument to thread function
+ 0, // use default creation flags
+ &dwThreadID); // returns the thread identifier
+
+ // Check the return value for success.
+
+ if (hThread[i] == NULL)
+ {
+ Fail("ERROR: Was not able to create thread\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+ }
+
+ //Wait for all threads to finish
+ for (i=0;i<MAX_THREADS;i++)
+ {
+ if (WAIT_OBJECT_0 != WaitForSingleObject (hThread[i], INFINITE))
+ {
+ Fail ("Main: Wait for Single Object failed. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+ }
+
+ /* Compare the value of global counter with zero.
+ */
+ if (0!=GlobalCounter)
+ {
+ Fail("Test Case Failed: InterlockedDecrement \n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+void DecrementCounter(void)
+{
+ int i=0;
+ for (i=0; i<REPEAT_COUNT;i++)
+ {
+ InterlockedDecrement(&GlobalCounter);
+ }
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test1/CMakeLists.txt
new file mode 100644
index 0000000000..727a328d07
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.cpp
+)
+
+add_executable(paltest_interlockeddecrement64_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_interlockeddecrement64_test1 coreclrpal)
+
+target_link_libraries(paltest_interlockeddecrement64_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test1/test.cpp b/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test1/test.cpp
new file mode 100644
index 0000000000..326587d9a1
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test1/test.cpp
@@ -0,0 +1,77 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: InterlockedDecrement64() function
+**
+**
+**=========================================================*/
+
+/* This test is FINISHED. Note: The biggest feature of this function is that
+ it locks the value before it increments it -- in order to make it so only
+ one thread can access it. But, I really don't have a great test to make
+ sure it's thread safe. Any ideas?
+*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ LONGLONG TheValue = 0;
+ LONGLONG TheReturn;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+/*
+** Run only on 64 bit platforms
+*/
+#if defined(BIT64) && defined(PLATFORM_UNIX)
+ /* Compare START_VALUE with BaseVariableToManipulate, they're equal,
+ so exchange
+ */
+ InterlockedDecrement64(&TheValue);
+ TheReturn = InterlockedDecrement64(&TheValue);
+
+ /* Decremented twice, it should be -2 now */
+ if(TheValue != -2)
+ {
+#ifdef PLATFORM_UNIX
+ Fail("ERROR: After being decremented twice, the value should be -2, "
+ "but it is really %ll.",TheValue);
+#else
+ Fail("ERROR: After being decremented twice, the value should be -2, "
+ "but it is really %I64.",TheValue);
+#endif
+ }
+
+ /* Check to make sure it returns itself */
+ if(TheReturn != TheValue)
+ {
+#ifdef PLATFORM_UNIX
+ Fail("ERROR: The function should have returned the new value of %d "
+ "but instead returned %ll.",TheValue,TheReturn);
+#else
+ Fail("ERROR: After being decremented twice, the value should be -2, "
+ "but it is really %I64.",TheValue);
+#endif
+ }
+#endif //defined(BIT64) && defined(PLATFORM_UNIX)
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test1/testinfo.dat
new file mode 100644
index 0000000000..8c5b1f087c
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = InterlockedDecrement64
+Name = Positive test of InterlockedDecrement64
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test to see if this decrements the variable correctly and
+= has the correct return value.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test2/CMakeLists.txt
new file mode 100644
index 0000000000..ecea6399a7
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.cpp
+)
+
+add_executable(paltest_interlockeddecrement64_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_interlockeddecrement64_test2 coreclrpal)
+
+target_link_libraries(paltest_interlockeddecrement64_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test2/test.cpp b/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test2/test.cpp
new file mode 100644
index 0000000000..fa748d538d
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedDecrement64/test2/test.cpp
@@ -0,0 +1,99 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: InterlockedDecrement64() function
+**
+** The test case spawns MAX_THREADS Threads, and each thread call InterlockedDecrement Function to decrement a
+** global counter REPEAT_COUNT Times. The Test case sets the global counter to MAX_THREADS * REPEAT_COUNT
+** at the begining of the test. The test cases passes if at the end the test the value of the global counter is Zero.
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+#define MAX_THREADS 64
+#define REPEAT_COUNT 10000
+
+LONG GlobalCounter = 0;
+void DecrementCounter(void);
+
+int __cdecl main(int argc, char *argv[])
+{
+ LONG TotalOperations=0;
+ int i=0;
+ DWORD dwThreadID = 0;
+ HANDLE hThread[MAX_THREADS];
+ TotalOperations = MAX_THREADS * REPEAT_COUNT;
+ GlobalCounter = TotalOperations;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ #if defined(BIT64) && defined(PLATFORM_UNIX)
+
+ //Create MAX_THREADS threads that will operate on the global counter
+ for (i=0;i<MAX_THREADS;i++)
+ {
+ hThread[i] = CreateThread(
+ NULL, // default security attributes
+ 0, // use default stack size
+ (LPTHREAD_START_ROUTINE) DecrementCounter, // thread function
+ NULL, // argument to thread function
+ 0, // use default creation flags
+ &dwThreadID); // returns the thread identifier
+
+ // Check the return value for success.
+ if (hThread[i] == NULL)
+ {
+ Fail("ERROR: Was not able to create thread\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+ }
+
+ //Wait for all threads to finish
+ for (i=0;i<MAX_THREADS;i++)
+ {
+
+ if (WAIT_OBJECT_0 != WaitForSingleObject (hThread[i], INFINITE))
+ {
+ Fail ("Main: Wait for Single Object failed. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+ }
+
+ /* Compare the value of global counter with zero.
+ */
+ if (0!=GlobalCounter)
+ {
+ Fail("Test Case Failed: InterlockedDecrement \n");
+ }
+
+#endif //defined(BIT64) && defined(PLATFORM_UNIX)
+
+ PAL_Terminate();
+ return PASS;
+}
+
+void DecrementCounter(void)
+{
+ int i=0;
+
+ for (i=0; i<REPEAT_COUNT;i++)
+ {
+ InterlockedDecrement(&GlobalCounter);
+ }
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedExchange/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/InterlockedExchange/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedExchange/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedExchange/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/InterlockedExchange/test1/CMakeLists.txt
new file mode 100644
index 0000000000..a1a7f862ed
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedExchange/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.cpp
+)
+
+add_executable(paltest_interlockedexchange_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_interlockedexchange_test1 coreclrpal)
+
+target_link_libraries(paltest_interlockedexchange_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedExchange/test1/test.cpp b/src/pal/tests/palsuite/miscellaneous/InterlockedExchange/test1/test.cpp
new file mode 100644
index 0000000000..517fca1792
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedExchange/test1/test.cpp
@@ -0,0 +1,69 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: InterlockedExchange() function
+**
+**
+**=========================================================*/
+
+/* This test is FINISHED. Note: The biggest feature of this function is that
+ it locks the value before it increments it -- in order to make it so only
+ one thread can access it. But, I really don't have a great test to make
+ sure it's thread safe. Any ideas?
+*/
+
+#include <palsuite.h>
+
+#define START_VALUE 0
+
+int __cdecl main(int argc, char *argv[]) {
+
+ int TheValue = START_VALUE;
+ int NewValue = 5;
+ int TheReturn;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ TheReturn = InterlockedExchange(&TheValue,NewValue);
+
+ /* Compare the exchanged value with the value we exchanged it with. Should
+ be the same.
+ */
+ if(TheValue != NewValue)
+ {
+ Fail("ERROR: The value which was exchanged should now be %d, but "
+ "instead it is %d.",NewValue,TheValue);
+ }
+
+ /* Check to make sure it returns the origional number which 'TheValue' was
+ set to.
+ */
+
+ if(TheReturn != START_VALUE)
+ {
+ Fail("ERROR: The value returned should be the value before the "
+ "exchange happened, which was %d, but %d was returned.",
+ START_VALUE,TheReturn);
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedExchange/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/InterlockedExchange/test1/testinfo.dat
new file mode 100644
index 0000000000..4b7c20a423
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedExchange/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = InterlockedExchange
+Name = Positive test of InterlockedExchange
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test to see if this exchanges the variables correctly and
+= has the correct return value.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedExchange64/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/InterlockedExchange64/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedExchange64/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedExchange64/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/InterlockedExchange64/test1/CMakeLists.txt
new file mode 100644
index 0000000000..3f4cd5e058
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedExchange64/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.cpp
+)
+
+add_executable(paltest_interlockedexchange64_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_interlockedexchange64_test1 coreclrpal)
+
+target_link_libraries(paltest_interlockedexchange64_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedExchange64/test1/test.cpp b/src/pal/tests/palsuite/miscellaneous/InterlockedExchange64/test1/test.cpp
new file mode 100644
index 0000000000..12e8b50580
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedExchange64/test1/test.cpp
@@ -0,0 +1,85 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: InterlockedExchange64() function
+**
+**
+**=========================================================*/
+
+/* This test is FINISHED. Note: The biggest feature of this function is that
+ it locks the value before it increments it -- in order to make it so only
+ one thread can access it. But, I really don't have a great test to make
+ sure it's thread safe. Any ideas?
+*/
+
+#include <palsuite.h>
+
+#define START_VALUE 0
+
+int __cdecl main(int argc, char *argv[]) {
+
+ LONGLONG TheValue = START_VALUE;
+ LONGLONG NewValue = 5;
+ LONGLONG TheReturn;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+/*
+** Run only on 64 bit platforms
+*/
+#if defined(BIT64) && defined(PLATFORM_UNIX)
+
+ TheReturn = InterlockedExchange64(&TheValue,NewValue);
+
+ /* Compare the exchanged value with the value we exchanged it with. Should
+ be the same.
+ */
+ if(TheValue != NewValue)
+ {
+#ifdef PLATFORM_UNIX
+ Fail("ERROR: The value which was exchanged should now be %ll, but "
+ "instead it is %ll.",NewValue,TheValue);
+#else
+ Fail("ERROR: The value which was exchanged should now be %I64, but "
+ "instead it is %I64.",NewValue,TheValue);
+#endif
+ }
+
+ /* Check to make sure it returns the origional number which 'TheValue' was
+ set to.
+ */
+
+ if(TheReturn != START_VALUE)
+ {
+#ifdef PLATFORM_UNIX
+ Fail("ERROR: The value returned should be the value before the "
+ "exchange happened, which was %ll, but %ll was returned.",
+ START_VALUE,TheReturn);
+#else
+ Fail("ERROR: The value returned should be the value before the "
+ "exchange happened, which was %I64, but %I64 was returned.",
+ START_VALUE,TheReturn);
+#endif
+ }
+
+#endif //defined(BIT64) && defined(_IA64_)
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedExchange64/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/InterlockedExchange64/test1/testinfo.dat
new file mode 100644
index 0000000000..3669e99614
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedExchange64/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = InterlockedExchange64
+Name = Positive test of InterlockedExchange64
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test to see if this exchanges the variables correctly and
+= has the correct return value.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedExchangePointer/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/InterlockedExchangePointer/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedExchangePointer/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedExchangePointer/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/InterlockedExchangePointer/test1/CMakeLists.txt
new file mode 100644
index 0000000000..b0858963a0
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedExchangePointer/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ InterlockedExchangePointer.cpp
+)
+
+add_executable(paltest_interlockedexchangepointer_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_interlockedexchangepointer_test1 coreclrpal)
+
+target_link_libraries(paltest_interlockedexchangepointer_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedExchangePointer/test1/InterlockedExchangePointer.cpp b/src/pal/tests/palsuite/miscellaneous/InterlockedExchangePointer/test1/InterlockedExchangePointer.cpp
new file mode 100644
index 0000000000..d36c96724f
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedExchangePointer/test1/InterlockedExchangePointer.cpp
@@ -0,0 +1,64 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: InterlockedExchangePointer
+**
+** Purpose: Positive test the InterlockedExchangePointer API.
+** Call InterlockedExchangePointer to exchange a pair of
+** value
+**
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ int i1 = 10;
+ int i2 = 20;
+ int *pOldValue = &i1;
+ int *pNewValue = &i2;
+ PVOID pReturnValue;
+
+ /*Initialize the PAL environment*/
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+
+
+ /*
+ Testing
+ =======
+ */
+
+ pReturnValue = InterlockedExchangePointer((PVOID)&pOldValue,
+ (PVOID)pNewValue);
+ /*check the returned value*/
+ if(*(int *)pReturnValue != i1)
+ {
+ Fail("\nFailed to call InterlockedExchangePointer API, "
+ "return pointer does not point to the origional value\n");
+ }
+
+ /*check the exchanged value*/
+ if(*pOldValue != *pNewValue)
+ {
+ Fail("\nFailed to call InterlockedExchangePointer API, "
+ "exchanged value is not right\n");
+ }
+
+
+
+ /*
+ Clean Up
+ */
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedExchangePointer/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/InterlockedExchangePointer/test1/testinfo.dat
new file mode 100644
index 0000000000..5e0a36627a
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedExchangePointer/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = miscellaneous
+Function = InterlockedExchangePointer
+Name = Pos test for InterlockedExchangePointer API to excnage a pair of value
+TYPE = DEFAULT
+EXE1 = interlockedexchangepointer
+Description
+=Test the InterlockedExchangePointer to exchange a pair of value
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test1/CMakeLists.txt
new file mode 100644
index 0000000000..f87dc72281
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.cpp
+)
+
+add_executable(paltest_interlockedincrement_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_interlockedincrement_test1 coreclrpal)
+
+target_link_libraries(paltest_interlockedincrement_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test1/test.cpp b/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test1/test.cpp
new file mode 100644
index 0000000000..8b4b3e9148
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test1/test.cpp
@@ -0,0 +1,62 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: InterlockedIncrement() function
+**
+**
+**=========================================================*/
+
+/* This test is FINISHED. Note: The biggest feature of this function is that
+ it locks the value before it increments it -- in order to make it so only
+ one thread can access it. But, I really don't have a great test to make
+ sure it's thread safe. Any ideas? Nothing I've tried has worked.
+*/
+
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ int TheValue = 0;
+ int TheReturn;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ InterlockedIncrement(&TheValue);
+ TheReturn = InterlockedIncrement(&TheValue);
+
+ /* Incremented twice, it should be 2 now */
+ if(TheValue != 2)
+ {
+ Fail("ERROR: The value was incremented twice and shoud now be 2, "
+ "but it is really %d",TheValue);
+ }
+
+ /* Check to make sure it returns itself */
+ if(TheReturn != TheValue)
+ {
+ Fail("ERROR: The function should return the new value, which shoud "
+ "have been %d, but it returned %d.",TheValue,TheReturn);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test1/testinfo.dat
new file mode 100644
index 0000000000..c304960030
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = InterlockedIncreement
+Name = Positive test of InterlockedIncrement
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test to see if this increments the variable correctly and
+= has the correct return value.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test2/CMakeLists.txt
new file mode 100644
index 0000000000..e8c5278cbc
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.cpp
+)
+
+add_executable(paltest_interlockedincrement_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_interlockedincrement_test2 coreclrpal)
+
+target_link_libraries(paltest_interlockedincrement_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test2/test.cpp b/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test2/test.cpp
new file mode 100644
index 0000000000..280a2ea709
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement/test2/test.cpp
@@ -0,0 +1,95 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: InterlockedIncrement() function
+**
+** The test case spawns MAX_THREADS Threads, and each thread call InterlockedDecrement Function to decrement a
+** global counter REPEAT_COUNT Times. The Test case sets the global counter to Zero at the begining of the test.
+** The test cases passes if at the end the test the value of the global counter is MAX_THREADS * REPEAT_COUNT.
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+#define MAX_THREADS 64
+#define REPEAT_COUNT 10000
+
+LONG GlobalCounter = 0;
+
+void IncrementCounter(void);
+
+
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ LONG TotalOperations=0;
+ int i=0;
+ DWORD dwThreadID = 0;
+ HANDLE hThread[MAX_THREADS];
+ TotalOperations = MAX_THREADS * REPEAT_COUNT;
+ GlobalCounter = 0;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ //Create MAX_THREADS threads that will operate on the global counter
+ for (i=0;i<MAX_THREADS;i++)
+ {
+ hThread[i] = CreateThread(
+ NULL, // default security attributes
+ 0, // use default stack size
+ (LPTHREAD_START_ROUTINE) IncrementCounter, // thread function
+ NULL, // argument to thread function
+ 0, // use default creation flags
+ &dwThreadID); // returns the thread identifier
+
+ // Check the return value for success.
+
+ if (hThread[i] == NULL)
+ {
+ Fail("ERROR: Was not able to create thread\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+ }
+
+ //Wait for all threads to finish
+ for (i=0;i<MAX_THREADS;i++)
+ {
+ if (WAIT_OBJECT_0 != WaitForSingleObject (hThread[i], INFINITE))
+ {
+ Fail ("Main: Wait for Single Object failed. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+ }
+
+ /* Compare the value of global counter with zero.
+ */
+
+ if (TotalOperations!=GlobalCounter)
+ {
+ Fail("Test Case Failed: InterlockedDecrement \n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+void IncrementCounter(void)
+{
+ int i=0;
+ for (i=0; i<REPEAT_COUNT;i++)
+ {
+ InterlockedIncrement(&GlobalCounter);
+ }
+}
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test1/CMakeLists.txt
new file mode 100644
index 0000000000..d7bec46d4e
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.cpp
+)
+
+add_executable(paltest_interlockedincrement64_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_interlockedincrement64_test1 coreclrpal)
+
+target_link_libraries(paltest_interlockedincrement64_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test1/test.cpp b/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test1/test.cpp
new file mode 100644
index 0000000000..c02886f5c6
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test1/test.cpp
@@ -0,0 +1,77 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: InterlockedIncrement64() function
+**
+**
+**=========================================================*/
+
+/* This test is FINISHED. Note: The biggest feature of this function is that
+ it locks the value before it increments it -- in order to make it so only
+ one thread can access it. But, I really don't have a great test to make
+ sure it's thread safe. Any ideas? Nothing I've tried has worked.
+*/
+
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ LONGLONG TheValue = 0;
+ LONGLONG TheReturn;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+/*
+** Run only on 64 bit platforms
+*/
+#if defined(BIT64) && defined(PLATFORM_UNIX)
+
+ InterlockedIncrement64(&TheValue);
+ TheReturn = InterlockedIncrement64(&TheValue);
+
+ /* Incremented twice, it should be 2 now */
+ if(TheValue != 2)
+ {
+#ifdef PLATFORM_UNIX
+ Fail("ERROR: The value was incremented twice and shoud now be 2, "
+ "but it is really %ll",TheValue);
+#else
+ Fail("ERROR: The value was incremented twice and shoud now be 2, "
+ "but it is really %I64",TheValue);
+#endif
+ }
+
+ /* Check to make sure it returns itself */
+ if(TheReturn != TheValue)
+ {
+#ifdef PLATFORM_UNIX
+ Fail("ERROR: The function should return the new value, which shoud "
+ "have been %d, but it returned %ll.",TheValue,TheReturn);
+#else
+ Fail("ERROR: The function should return the new value, which shoud "
+ "have been %d, but it returned %I64.",TheValue,TheReturn);
+#endif
+ }
+
+#endif //defined(BIT64) && defined(PLATFORM_UNIX)
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test1/testinfo.dat
new file mode 100644
index 0000000000..fff0c701c6
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = InterlockedIncrement64
+Name = Positive test of InterlockedIncrement64
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test to see if this increments the variable correctly and
+= has the correct return value.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test2/CMakeLists.txt
new file mode 100644
index 0000000000..be571a535b
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.cpp
+)
+
+add_executable(paltest_interlockedincrement64_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_interlockedincrement64_test2 coreclrpal)
+
+target_link_libraries(paltest_interlockedincrement64_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test2/test.cpp b/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test2/test.cpp
new file mode 100644
index 0000000000..1d579fe325
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/InterlockedIncrement64/test2/test.cpp
@@ -0,0 +1,101 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source : test.c
+**
+** Purpose: InterlockedIncrement64() function
+**
+** The test case spawns MAX_THREADS Threads, and each thread call InterlockedDecrement Function to decrement a
+** global counter REPEAT_COUNT Times. The Test case sets the global counter to Zero at the begining of the test.
+** The test cases passes if at the end the test the value of the global counter is MAX_THREADS * REPEAT_COUNT.
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+#define MAX_THREADS 64
+#define REPEAT_COUNT 10000
+
+LONG GlobalCounter = 0;
+void IncrementCounter(void);
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ LONG TotalOperations=0;
+ int i=0;
+ DWORD dwThreadID = 0;
+ HANDLE hThread[MAX_THREADS];
+ TotalOperations = MAX_THREADS * REPEAT_COUNT;
+ GlobalCounter = 0;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /*
+ ** Run only on 64 bit platforms
+ */
+ #if defined(BIT64) && defined(PLATFORM_UNIX)
+
+ //Create MAX_THREADS threads that will operate on the global counter
+ for (i=0;i<MAX_THREADS;i++)
+ {
+ hThread[i] = CreateThread(
+ NULL, // default security attributes
+ 0, // use default stack size
+ (LPTHREAD_START_ROUTINE) IncrementCounter, // thread function
+ NULL, // argument to thread function
+ 0, // use default creation flags
+ &dwThreadID); // returns the thread identifier
+
+ // Check the return value for success.
+ if (hThread[i] == NULL)
+ {
+ Fail("ERROR: Was not able to create thread\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+ }
+
+
+ //Wait for all threads to finish
+ for (i=0;i<MAX_THREADS;i++)
+ {
+ if (WAIT_OBJECT_0 != WaitForSingleObject (hThread[i], INFINITE))
+ {
+ Fail ("Main: Wait for Single Object failed. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+ }
+
+ /* Compare the value of global counter with zero.
+ */
+ if (TotalOperations!=GlobalCounter)
+ {
+ Fail("Test Case Failed: InterlockedDecrement \n");
+ }
+ #endif //defined(BIT64) && defined(PLATFORM_UNIX)
+
+ PAL_Terminate();
+ return PASS;
+}
+
+void IncrementCounter(void)
+{
+ int i=0;
+
+ for (i=0; i<REPEAT_COUNT;i++)
+ {
+ InterlockedIncrement(&GlobalCounter);
+ }
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/IsBadCodePtr/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/IsBadCodePtr/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/IsBadCodePtr/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/IsBadCodePtr/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/IsBadCodePtr/test1/CMakeLists.txt
new file mode 100644
index 0000000000..d41e6bc5ab
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/IsBadCodePtr/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_isbadcodeptr_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_isbadcodeptr_test1 coreclrpal)
+
+target_link_libraries(paltest_isbadcodeptr_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/IsBadCodePtr/test1/test1.c b/src/pal/tests/palsuite/miscellaneous/IsBadCodePtr/test1/test1.c
new file mode 100644
index 0000000000..4b2763d457
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/IsBadCodePtr/test1/test1.c
@@ -0,0 +1,60 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test to ensure that IsBadCodePtr return 0 when
+** it can read memory or non zero when it can't.
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+**
+
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+INT __cdecl main(INT argc, CHAR **argv)
+{
+ BOOL ResultValue = 0;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* This should be readable, and return 0 */
+ ResultValue = IsBadCodePtr((FARPROC)main);
+ if(ResultValue != 0)
+ {
+ Fail("ERROR: IsBadCodePtr returned %d instead of 0, when pointing "
+ "at readable memory.\n",ResultValue);
+ }
+
+ /* 0x00 is usually unreadable memory so the function should
+ return non zero */
+ ResultValue = IsBadCodePtr((FARPROC)0x00);
+
+ if(ResultValue == 0)
+ {
+ Fail("ERROR: IsBadCodePtr returned %d instead of non zero "
+ "when checking on unreadable memory.\n",ResultValue);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/miscellaneous/IsBadCodePtr/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/IsBadCodePtr/test1/testinfo.dat
new file mode 100644
index 0000000000..8b73c0dfca
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/IsBadCodePtr/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = C Runtime
+Function = IsBadCodePtr
+Name = Positive Test for IsBadCodePtr
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= ensure that IsBadCodePtr return 0 when
+= it can read memory or non zero when it can't.
diff --git a/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/CMakeLists.txt
new file mode 100644
index 0000000000..f1e84d73b8
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_isbadreadptr_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_isbadreadptr_test1 coreclrpal)
+
+target_link_libraries(paltest_isbadreadptr_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/test.c b/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/test.c
new file mode 100644
index 0000000000..24b7ceb7e6
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/test.c
@@ -0,0 +1,138 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: IsBadReadPtr() function
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+#define MEMORY_AMOUNT 16
+
+int __cdecl main(int argc, char *argv[])
+{
+ LPVOID TestingPointer = NULL;
+ BOOL ResultValue = 0;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ TestingPointer = malloc(MEMORY_AMOUNT);
+ if ( TestingPointer == NULL )
+ {
+ Fail("ERROR: Failed to allocate memory for TestingPointer pointer. "
+ "Can't properly exec test case without this.\n");
+ }
+
+
+ /* This should be readable, and return 0 */
+ ResultValue = IsBadReadPtr(TestingPointer,MEMORY_AMOUNT);
+ if(ResultValue != 0)
+ {
+ free(TestingPointer);
+
+ Fail("ERROR: The function returned %d instead of 0, when pointing "
+ "at readable memory.\n",ResultValue);
+ }
+
+ /* If we pass 0, the result should be 0 as well */
+ ResultValue = IsBadReadPtr(TestingPointer,0);
+ if(ResultValue != 0)
+ {
+ free(TestingPointer);
+
+ Fail("ERROR: The function returned %d instead of 0, when the "
+ "function was passed a range of 0 bytes.\n",ResultValue);
+ }
+ free(TestingPointer); /* we are done with this */
+
+ /* create a READABLE address */
+ TestingPointer = VirtualAlloc(
+ NULL, /* system selects address */
+ 80, /* size of allocation*/
+ MEM_COMMIT, /* commit */
+ PAGE_READONLY); /* protection = read only */
+
+ if (TestingPointer == NULL )
+ {
+ Fail("ERROR: call to VirtualAlloc failed\n");
+ }
+
+ ResultValue = IsBadReadPtr(TestingPointer,16);
+ if(ResultValue != 0) /* if no access */
+ {
+ if(!VirtualFree(TestingPointer, 0, MEM_RELEASE))
+ {
+ Trace("ERROR: Call to VirtualFree failed with error"
+ " code[ %u ]\n",GetLastError());
+ }
+
+ Fail("ERROR: The function returned %d instead of 1 when checking "
+ "on unreadable memory.\n",ResultValue);
+ }
+
+ if(!VirtualFree(TestingPointer,0, MEM_RELEASE))
+ {
+ Fail("ERROR: Call to VirtualFree failed with error"
+ " code[ %u ]\n",GetLastError());
+ }
+
+ /* create an unreadable address */
+ TestingPointer = VirtualAlloc(
+ NULL, /* system selects address */
+ 80, /* size of allocation */
+ MEM_COMMIT, /* commit */
+ PAGE_NOACCESS); /* protection = no access */
+
+ if (TestingPointer == NULL )
+ {
+ Fail("ERROR: call to VirtualAlloc failed\n");
+ }
+
+ ResultValue = IsBadReadPtr(TestingPointer,16);
+
+ if(ResultValue == 0) /* if access */
+ {
+ if(!VirtualFree(TestingPointer, 0, MEM_RELEASE))
+ {
+ Trace("ERROR: Call to VirtualFree failed with error"
+ " code[ %u ]\n",GetLastError());
+ }
+
+ Fail("ERROR: The function returned %d instead of 1 when checking "
+ "on unreadable memory.\n",ResultValue);
+ }
+
+ if(!VirtualFree(TestingPointer,0, MEM_RELEASE))
+ {
+ Fail("ERROR: Call to VirtualFree failed with error"
+ " code[ %u ]\n",GetLastError());
+ }
+
+
+ /* This should be unreadable and return 1 */
+ ResultValue = IsBadReadPtr(NULL,16);
+ if(ResultValue != 1)
+ {
+ Fail("ERROR: The function returned %d instead of 1 when checking "
+ "to see if NULL was readable.\n",ResultValue);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/testinfo.dat
new file mode 100644
index 0000000000..27668b66c7
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = IsBadReadPtr
+Name = Return value tests for IsBadReadPtr
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Ensure that this returns true and false when it is supposed to.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/CMakeLists.txt
new file mode 100644
index 0000000000..1962ade358
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/CMakeLists.txt
new file mode 100644
index 0000000000..2b2e6aae2e
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_isbadwriteptr_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_isbadwriteptr_test1 coreclrpal)
+
+target_link_libraries(paltest_isbadwriteptr_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/test.c b/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/test.c
new file mode 100644
index 0000000000..018d7beae0
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/test.c
@@ -0,0 +1,81 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: IsBadWritePtr() function
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+#define MEMORY_AMOUNT 16
+
+int __cdecl main(int argc, char *argv[]) {
+
+ void * TestingPointer = NULL;
+ BOOL ResultValue = 0;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ TestingPointer = malloc(MEMORY_AMOUNT);
+ if ( TestingPointer == NULL )
+ {
+ Fail("ERROR: Failed to allocate memory for TestingPointer pointer. "
+ "Can't properly exec test case without this.\n");
+ }
+
+
+ /* This should be writeable, return 0 */
+ ResultValue = IsBadWritePtr(TestingPointer,MEMORY_AMOUNT);
+
+ if(ResultValue != 0)
+ {
+ free(TestingPointer);
+
+ Fail("ERROR: Returned %d when 0 should have been returned, checking "
+ "to see if writable memory is unwriteable.\n",ResultValue);
+ }
+
+ free(TestingPointer);
+
+ /* This should be !writeable, return nonezero */
+ TestingPointer = (void*)0x08; /* non writeable address */
+ ResultValue = IsBadWritePtr(TestingPointer,sizeof(int));
+
+ if(ResultValue == 0)
+ {
+ Fail("ERROR: Returned %d when nonezero should have been returned, "
+ "checking to see if unwriteable memory is writeable.\n",
+ ResultValue);
+ }
+
+ /* This should be !writeable, return Nonezero */
+ ResultValue = IsBadWritePtr(NULL,MEMORY_AMOUNT);
+
+ if(ResultValue == 0)
+ {
+ Fail("ERROR: Returned %d when nonezero should have been "
+ "returned,checking "
+ "to see if a NULL pointer is writeable.\n",
+ ResultValue);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/testinfo.dat
new file mode 100644
index 0000000000..ba4e97ebbc
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = IsBadWritePtr
+Name = Return Value test IsBadWritePtr
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test to ensure that the function returns true and
+= false when it is supposed to.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/CMakeLists.txt
new file mode 100644
index 0000000000..c033f8054f
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_isbadwriteptr_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_isbadwriteptr_test2 coreclrpal)
+
+target_link_libraries(paltest_isbadwriteptr_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/test2.c b/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/test2.c
new file mode 100644
index 0000000000..2d4d53e3b7
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/test2.c
@@ -0,0 +1,128 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test2.c
+**
+** Purpose:
+** Create three consecuative pages, NOACCES, READWRITE and
+** NOACCESS. Check to ensure that the READWRITE page returns 0, to
+** ensure that IsBadWritePtr isn't overflowing. Also check the other two
+** pages to see that they return non-zero.
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+#define PAGE_SIZE 4096
+
+int __cdecl main(int argc, char *argv[]) {
+
+ LPVOID PageOne, PageTwo, PageThree;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Reserve enough space for four pages. We'll commit this memory
+ and set the correct access for each page below.
+ */
+
+ PageOne = VirtualAlloc(NULL,
+ PAGE_SIZE*4,
+ MEM_RESERVE,
+ PAGE_NOACCESS);
+
+ if(PageOne == NULL)
+ {
+ Fail("ERROR: VirtualAlloc failed to reserve the required memory.\n");
+ }
+
+ /* Set the first Page to PAGE_NOACCESS */
+
+ PageOne = VirtualAlloc(PageOne,
+ PAGE_SIZE,
+ MEM_COMMIT,
+ PAGE_NOACCESS);
+
+ if(PageOne == NULL)
+ {
+ VirtualFree(PageOne,0,MEM_RELEASE);
+
+ Fail("ERROR: VirtualAlloc failed to commit the required memory "
+ "for the first page.\n");
+ }
+
+ /* Set the second Page to PAGE_READWRITE */
+
+ PageTwo = VirtualAlloc(((BYTE*)PageOne)+PAGE_SIZE,
+ PAGE_SIZE,
+ MEM_COMMIT,
+ PAGE_READWRITE);
+ if(PageTwo == NULL)
+ {
+ VirtualFree(PageOne,0,MEM_RELEASE);
+
+ Fail("ERROR: VirtualAlloc failed to allocate the required memory "
+ "for the second page. %d\n",GetLastError());
+ }
+
+ /* Set the third Page to PAGE_NOACCESS */
+
+ PageThree = VirtualAlloc(((BYTE*)PageTwo) + (2 * PAGE_SIZE),
+ PAGE_SIZE,
+ MEM_COMMIT,
+ PAGE_NOACCESS);
+
+ if(PageThree == NULL)
+ {
+ VirtualFree(PageOne,0,MEM_RELEASE);
+
+ Fail("ERROR: VirtualAlloc failed to allocate the required memory. "
+ "For the third page.\n");
+ }
+
+
+/* Check that calling IsBadWritePtr on the first page returns non-zero */
+
+ if(IsBadWritePtr(PageThree,PAGE_SIZE) == 0)
+ {
+ VirtualFree(PageOne,0,MEM_RELEASE);
+
+ Fail("ERROR: Called IsBadWritePtr on a page which was set NOACCESS "
+ "but the return value was 0, indicating that the memory is "
+ "writable.\n");
+ }
+
+ /* Check that calling IsBadWritePtr on the middle page returns 0 */
+
+ if(IsBadWritePtr(PageTwo,PAGE_SIZE) != 0)
+ {
+ VirtualFree(PageOne,0,MEM_RELEASE);
+
+ Fail("ERROR: IsBadWritePtr didn't return 0 when called on a "
+ "page which should have been writable.\n");
+ }
+
+ /* Check that calling IsBadWritePtr on the third page returns non-zero */
+
+ if(IsBadWritePtr(PageThree,PAGE_SIZE) == 0)
+ {
+ VirtualFree(PageOne,0,MEM_RELEASE);
+
+ Fail("ERROR: Called IsBadWritePtr on a page which was set NOACCESS "
+ "but the return value was 0, indicating that the memory is "
+ "writable.\n");
+ }
+ VirtualFree(PageOne,0,MEM_RELEASE);
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/testinfo.dat
new file mode 100644
index 0000000000..ad0a5fe90e
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/testinfo.dat
@@ -0,0 +1,19 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = IsBadWritePtr
+Name = Return Value test IsBadWritePtr
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Create three consecuative pages, NOACCES, READWRITE and
+= NOACCESS. Check to ensure that the READWRITE page returns 0, to
+= ensure that IsBadWritePtr isn't overflowing. Also check the other two
+= pages to see that they return non-zero.
+
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/CMakeLists.txt
new file mode 100644
index 0000000000..32cb901e8d
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_isbadwriteptr_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_isbadwriteptr_test3 coreclrpal)
+
+target_link_libraries(paltest_isbadwriteptr_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/test3.c b/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/test3.c
new file mode 100644
index 0000000000..4c058a8987
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/test3.c
@@ -0,0 +1,58 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test3.c
+**
+** Purpose:
+** Check that IsBadWritePtr returns non-zero on Read-only memory.
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+#define PAGE_SIZE 4096
+
+int __cdecl main(int argc, char *argv[]) {
+
+ LPVOID PageOne;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Reserve enough space for four pages. We'll commit this memory
+ and set the correct access for each page below.
+ */
+
+ PageOne = VirtualAlloc(NULL,
+ PAGE_SIZE,
+ MEM_COMMIT,
+ PAGE_READONLY);
+
+ if(PageOne == NULL)
+ {
+ Fail("ERROR: VirtualAlloc failed to commit the required memory.\n");
+ }
+
+ if(IsBadWritePtr(PageOne,PAGE_SIZE) == 0)
+ {
+ VirtualFree(PageOne,0,MEM_RELEASE);
+
+ Fail("ERROR: IsBadWritePtr returned 0 when checking a section of "
+ "read-only memory. It should be non-zero.\n");
+ }
+
+ VirtualFree(PageOne,0,MEM_RELEASE);
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/testinfo.dat
new file mode 100644
index 0000000000..18851d2fde
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = IsBadWritePtr
+Name = Return Value test IsBadWritePtr
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Check that IsBadWritePtr returns non-zero on Read-only memory.
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/MessageBoxW/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/MessageBoxW/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/MessageBoxW/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..5e77e8ba98
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_messageboxw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_messageboxw_test1 coreclrpal)
+
+target_link_libraries(paltest_messageboxw_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/test.c b/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/test.c
new file mode 100644
index 0000000000..8eb8c0eb7e
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/test.c
@@ -0,0 +1,81 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for MessageBoxW() function
+**
+**
+**=========================================================*/
+
+#define UNICODE
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ /* Declare Variables to use with convert()*/
+ WCHAR * PalTitle = NULL;
+ WCHAR * OkTesting = NULL;
+ WCHAR * AbortTesting = NULL;
+ WCHAR * YesTesting = NULL;
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ PalTitle = convert("Pal Testing");
+ OkTesting = convert("Click OK Please!");
+
+ /* Handle, text, title, style */
+ if(MessageBox(NULL, OkTesting,
+ PalTitle,
+ MB_OK) != IDOK)
+ {
+ free(OkTesting);
+ free(PalTitle);
+ Fail("ERROR: The MB_OK style should return IDOK.");
+ }
+
+ free(OkTesting);
+ AbortTesting = convert("Click Abort Please!");
+ if(MessageBox(NULL,
+ AbortTesting,
+ PalTitle,
+ MB_ABORTRETRYIGNORE) != IDABORT)
+ {
+ free(AbortTesting);
+ free(PalTitle);
+ Fail("ERROR: The MB_ABORTRETRYIGNORE style should "
+ "return IDABORT.");
+ }
+
+ free(AbortTesting);
+ YesTesting = convert("Click No Please!");
+
+ if(MessageBox(NULL,
+ YesTesting,
+ PalTitle,
+ MB_YESNO) != IDNO)
+ {
+ free(PalTitle);
+ free(YesTesting);
+ Fail("ERROR: The MB_YESNO style should return IDNO.");
+ }
+
+ free(YesTesting);
+ free(PalTitle);
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/testinfo.dat
new file mode 100644
index 0000000000..e4d46c986b
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = MessageBoxW
+Name = Positive test of MessageBoxW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Ensure that the return values are correct for each type of Message Style.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/CMakeLists.txt
new file mode 100644
index 0000000000..4b0af2e77e
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_messageboxw_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_messageboxw_test2 coreclrpal)
+
+target_link_libraries(paltest_messageboxw_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/test.c b/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/test.c
new file mode 100644
index 0000000000..e2ff0cf6d6
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/test.c
@@ -0,0 +1,76 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for MessageBoxW() function
+**
+**
+**=========================================================*/
+
+#define UNICODE
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[]) {
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Check to make sure there are no problems accepting all the ICON
+ styles and FLAG styles. These don't change anything, unless
+ they don't work at all.
+ */
+
+ if(MessageBox(NULL,
+ convert("Pal Testing"),
+ convert("Pal Title"),
+ MB_OK |MB_ICONEXCLAMATION|MB_TASKMODAL) != IDOK)
+ {
+ Fail("ERROR: The MB_OK style should always return IDOK.");
+ }
+
+ if(MessageBox(NULL,
+ convert("Pal Testing"),
+ convert("Pal Title"),
+ MB_OK |MB_ICONINFORMATION|MB_SYSTEMMODAL) != IDOK)
+ {
+ Fail("ERROR: The MB_OK style should always return IDOK.");
+ }
+
+ /* MB_SERVICE_NOTIFICATION doesn't seem to be available under windows?
+ It claims it exists and it should be supported under FreeBSD.
+ */
+
+#if UNIX
+ if(MessageBox(NULL,
+ convert("Pal Testing"),
+ convert("Pal Title"),
+ MB_OK |MB_ICONSTOP|MB_SERVICE_NOTIFICATION) != IDOK)
+ {
+ Fail("ERROR: The MB_OK style should always return IDOK.");
+ }
+#endif
+
+ if(MessageBox(NULL,
+ convert("Pal Testing"),
+ convert("Pal Title"),
+ MB_OK |MB_ICONQUESTION) != IDOK)
+ {
+ Fail("ERROR: The MB_OK style should always return IDOK.");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/testinfo.dat
new file mode 100644
index 0000000000..e4d46c986b
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = MessageBoxW
+Name = Positive test of MessageBoxW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Ensure that the return values are correct for each type of Message Style.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/CMakeLists.txt
new file mode 100644
index 0000000000..a3847f8ca9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/CMakeLists.txt
new file mode 100644
index 0000000000..b66248522b
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_setenvironmentvariablea_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setenvironmentvariablea_test1 coreclrpal)
+
+target_link_libraries(paltest_setenvironmentvariablea_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/test1.c b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/test1.c
new file mode 100644
index 0000000000..86a44218f1
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/test1.c
@@ -0,0 +1,168 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test1.c
+**
+** Purpose: Test for SetEnvironmentVariableA() function. Set an
+** environment variable and check to ensure success was returned. Then
+** get the environment variable and compare to the correct value. Also, check
+** that calling the function again, resets the variable properly. And that
+** calling with NULL deletes the variable.
+**
+** Depends:
+** GetEnvironmentVariable
+** memcmp
+** memset
+** strlen
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+#define BUF_SIZE 128
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ /* Define some buffers needed for the function */
+ char* VariableBuffer = "PALTEST";
+ char* ValueBuffer = "Testing";
+ char* SecondValueBuffer = "SecondTest";
+ char NewValue[BUF_SIZE];
+ int SetResult = 0;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+
+
+ /*
+ Test #1
+ =======
+ */
+
+ SetResult = SetEnvironmentVariable(VariableBuffer,
+ ValueBuffer);
+
+ /* If result is 0, the SetEnviron function failed */
+ if(SetResult == 0)
+ {
+ Fail("ERROR: SetEnvironmentVariable returned 0, which indicates that "
+ "it failed, even though it should have succeeded in setting the "
+ "variable PALTEST.\n");
+ }
+
+ memset(NewValue,0,BUF_SIZE);
+
+ /* Grab the Environment variable we just set */
+ if(GetEnvironmentVariable(VariableBuffer,NewValue,BUF_SIZE) <= 0)
+ {
+ Fail("ERROR: GetEnvironmentVariable returned 0 or less, which "
+ "indicates that no value was read in from the given variable.");
+ }
+
+ /* Make sure that the value put into NewValue was indeed the environment
+ variable we set.
+ */
+
+ if(memcmp(NewValue,ValueBuffer,strlen(ValueBuffer)+1) != 0)
+ {
+ Fail("ERROR: When retrieving the variable that was just set, a "
+ "difference was found. Instead of the value being '%s' it "
+ "was instead '%s'.\n",ValueBuffer,NewValue);
+ }
+
+
+
+ /*
+ Test #2
+ =======
+ */
+
+ /* If we set the same environment variable with a different value, the
+ old value should be replaced.
+ */
+
+ SetResult = SetEnvironmentVariable(VariableBuffer,
+ SecondValueBuffer);
+
+ /* If result is 0, the SetEnviron function failed */
+ if(SetResult == 0)
+ {
+ Fail("ERROR: SetEnvironmentVariable returned 0, which indicates that "
+ "it failed, even though it should have succeeded in re-setting "
+ "the variable PALTEST.\n");
+ }
+
+ memset(NewValue,0,BUF_SIZE);
+
+ /* Grab the Environment variable we just set */
+ if(GetEnvironmentVariable(VariableBuffer,NewValue,BUF_SIZE) <= 0)
+ {
+ Fail("ERROR: GetEnvironmentVariable returned 0 or less, which "
+ "indicates that no value was read in from the given variable.");
+ }
+
+ /* Make sure that the value put into NewValue was indeed the environment
+ variable we set.
+ */
+
+ if(memcmp(NewValue,SecondValueBuffer,strlen(SecondValueBuffer)+1) != 0)
+ {
+ Fail("ERROR: When retrieving the variable that was just set, a "
+ "difference was found. Instead of the value being '%s' it "
+ "was instead '%s'.\n",SecondValueBuffer,NewValue);
+ }
+
+
+
+ /*
+ Test #3
+ =======
+ */
+
+ /* Finally, set this variable with NULL, which should delete it from the
+ current environment.
+ */
+
+ SetResult = SetEnvironmentVariable(VariableBuffer, NULL);
+
+ /* If result is 0, the SetEnviron function failed */
+ if(SetResult == 0)
+ {
+ Fail("ERROR: SetEnvironmentVariable returned 0, which indicates that "
+ "it failed, even though it should have succeeded in deleting "
+ "the variable PALTEST.\n");
+ }
+
+ memset(NewValue,0,BUF_SIZE);
+
+ /* Grab the Environment variable we just set, ensure that it's
+ empty now.
+ */
+ if(GetEnvironmentVariable(VariableBuffer,NewValue,BUF_SIZE) != 0)
+ {
+ Fail("ERROR: GetEnvironmentVariable returned a non-zero value, "
+ "even though the environment variable which was checked should "
+ "have been empty.");
+ }
+
+
+ /*
+ Clean Up
+ */
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/testinfo.dat
new file mode 100644
index 0000000000..561cd943fc
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/testinfo.dat
@@ -0,0 +1,19 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = SetEnvironmentVariableA
+Name = Positive test of SetEnvironmentVariableA
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Set an environment variable and check to ensure success was returned. Then
+= get the environment variable and compare to the correct value. Also, check
+= that calling the function again, resets the variable properly. And that
+= calling with NULL deletes the variable.
+
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/CMakeLists.txt
new file mode 100644
index 0000000000..c062c6df65
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_setenvironmentvariablea_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setenvironmentvariablea_test2 coreclrpal)
+
+target_link_libraries(paltest_setenvironmentvariablea_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/test2.c b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/test2.c
new file mode 100644
index 0000000000..984007e6f1
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/test2.c
@@ -0,0 +1,85 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test2.c
+**
+** Purpose: Test for SetEnvironmentVariableA() function
+** Test to see that passing NULL to the first param fails.
+** Test that passing NULL to both params fails.
+** Set an environment variable, then pass NULL to the second param
+** to delete it. Then make the same call again, to check that it fails.
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ /* Define some buffers needed for the function */
+ char* VariableBuffer = "PALTEST";
+ char* ValueBuffer = "testing";
+ int SetResult;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Check that it fails if the first param is NULL */
+
+ SetResult = SetEnvironmentVariable(NULL,ValueBuffer);
+
+ if(SetResult != 0)
+ {
+ Fail("ERROR: SetEnvironmentVariable returned a success value, "
+ "even though it was passed NULL as the first parameter and "
+ "should have failed.\n");
+ }
+
+ /* Check that it fails when both params are NULL */
+ SetResult = SetEnvironmentVariable(NULL,NULL);
+ if(SetResult != 0)
+ {
+ Fail("ERROR: SetEnvironmentVariable returned a success value, even "
+ "though it was passed NULL as the first and second parameter and "
+ "should have failed.\n");
+ }
+
+
+ /* First, set the variable, which should be ok. Then call the
+ function with the second parameter NULL twice -- the first call should
+ pass, the second should fail.
+ */
+
+ SetResult = SetEnvironmentVariable(VariableBuffer,ValueBuffer);
+ if(SetResult == 0)
+ {
+ Fail("ERROR: SetEnvironmentVariable returned failure, when "
+ "attempting to set a valid variable.\n");
+ }
+
+ SetResult = SetEnvironmentVariable(VariableBuffer,NULL);
+ if(SetResult == 0)
+ {
+ Fail("ERROR: SetEnvironmentVariable returned failure, when "
+ "attempting to delete a variable.\n");
+ }
+
+ SetResult = SetEnvironmentVariable(VariableBuffer,NULL);
+ if(SetResult != 0)
+ {
+ Fail("ERROR: SetEnvironmentVariable returned success, when "
+ "attempting to delete a variable which doesn't exist.\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/testinfo.dat
new file mode 100644
index 0000000000..446e301500
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/testinfo.dat
@@ -0,0 +1,19 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = SetEnvironmentVariableA
+Name = Return value test of SetEnvironmentVariableA
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Test to see that passing NULL to the first param fails.
+= Test that passing NULL to both params fails.
+= Set an environment variable, then pass NULL to the second param
+= to delete it. Then make the same call again, to check that it fails.
+
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/CMakeLists.txt
new file mode 100644
index 0000000000..159f574abe
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_setenvironmentvariablea_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setenvironmentvariablea_test3 coreclrpal)
+
+target_link_libraries(paltest_setenvironmentvariablea_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/test3.c b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/test3.c
new file mode 100644
index 0000000000..fa24275da7
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/test3.c
@@ -0,0 +1,144 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+** Source : test3.c
+**
+** Purpose: Test for SetEnvironmentVariableA() function
+** Create environment variables that differ only
+** in case and verify that they return the appropriate
+** value on the BSD environment.
+**
+**
+===========================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+#if WIN32
+
+ return PASS;
+
+#else
+
+ /* Define some buffers needed for the function */
+ char * pResultBuffer = NULL;
+
+ char FirstEnvironmentVariable[] = {"PALTEST"};
+ char FirstEnvironmentValue[] = {"FIRST"};
+
+ char SecondEnvironmentVariable[] = {"paltest"};
+ char SecondEnvironmentValue[] = {"SECOND"};
+
+ DWORD size = 0;
+ BOOL bRc = TRUE;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Set the first environment variable */
+ bRc = SetEnvironmentVariableA(FirstEnvironmentVariable,
+ FirstEnvironmentValue);
+
+ if(!bRc)
+ {
+ Fail("ERROR: SetEnvironmentVariable failed to set a "
+ "proper environment variable with error %u.\n",
+ GetLastError());
+ }
+
+ /* Set the second environment Variable */
+ bRc = SetEnvironmentVariableA(SecondEnvironmentVariable,
+ SecondEnvironmentValue);
+
+ if(!bRc)
+ {
+ Fail("ERROR: SetEnvironmentVariable failed to set a "
+ "proper environment variable with error %u.\n",
+ GetLastError());
+ }
+
+
+ /* Normal case, PATH should fit into this buffer */
+ size = GetEnvironmentVariableA(FirstEnvironmentVariable,
+ pResultBuffer,
+ 0);
+
+ /* increase size to account for the null char at the end */
+ size = size + 1;
+
+ pResultBuffer = malloc(sizeof(char)*size);
+ if ( pResultBuffer == NULL )
+ {
+ Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n");
+ }
+
+ /* Try to retrieve the value of the first environment variable */
+ GetEnvironmentVariable(FirstEnvironmentVariable,
+ pResultBuffer,
+ size);
+
+ if ( pResultBuffer == NULL )
+ {
+ free(pResultBuffer);
+ Fail("ERROR: GetEnvironmentVariable failed to return a value "
+ "from a proper environment variable with error %u.\n",
+ GetLastError());
+ }
+
+ /* Compare the strings to see that the correct variable was returned */
+ if(strcmp(pResultBuffer,FirstEnvironmentValue) != 0)
+ {
+ Trace("ERROR: The value in the buffer should have been '%s' but "
+ "was really '%s'.\n",FirstEnvironmentValue, pResultBuffer);
+ free(pResultBuffer);
+ Fail("");
+ }
+
+ free(pResultBuffer);
+
+ /* Reallocate the memory for the string */
+ pResultBuffer = malloc(sizeof(char)*size);
+ if ( pResultBuffer == NULL )
+ {
+ Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n");
+ }
+
+ /* Try retrieving the value of the first variable, even though the
+ second variable has the same spelling and only differs in case */
+ GetEnvironmentVariable(SecondEnvironmentVariable,
+ pResultBuffer,
+ size);
+
+ if ( pResultBuffer == NULL )
+ {
+ Fail("ERROR: GetEnvironmentVariable failed to return a value "
+ "from a proper environment variable with error %u.\n",
+ GetLastError());
+ }
+
+ /* Compare the two strings to confirm that the right value is returned */
+ if(strcmp(pResultBuffer,SecondEnvironmentValue) != 0)
+ {
+ Trace("ERROR: The value in the buffer should have been '%s' but "
+ "was really '%s'.\n",SecondEnvironmentValue,pResultBuffer);
+ free(pResultBuffer);
+ Fail("");
+ }
+
+ free(pResultBuffer);
+
+ PAL_Terminate();
+ return PASS;
+
+#endif
+}
diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/testinfo.dat
new file mode 100644
index 0000000000..05076bb376
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/testinfo.dat
@@ -0,0 +1,18 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = SetEnvironmentVariableA
+Name = Return value test of SetEnvironmentVariableA
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Test creating environment variables that differ only
+= by case and check that they are treated as separate
+= variables in the BSD operating system.
+
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/CMakeLists.txt
new file mode 100644
index 0000000000..29cca8d7b4
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_setenvironmentvariablea_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setenvironmentvariablea_test4 coreclrpal)
+
+target_link_libraries(paltest_setenvironmentvariablea_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/test4.c b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/test4.c
new file mode 100644
index 0000000000..557cef74c9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/test4.c
@@ -0,0 +1,100 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+** Source : test4.c
+**
+** Purpose: Test for SetEnvironmentVariableA() function
+** Create environment variables that differ only
+** in case and verify that they return the appropriate
+** value in the WIN32 Environment
+**
+
+**
+===========================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+#if WIN32
+
+ /* Define some buffers needed for the function */
+ char * pResultBuffer = NULL;
+
+ char FirstEnvironmentVariable[] = {"PALTEST"};
+ char FirstEnvironmentValue[] = {"FIRST"};
+ char ModifiedEnvVar[] = {"paltest"};
+
+ DWORD size = 0;
+ BOOL bRc = TRUE;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Set the first environment variable */
+ bRc = SetEnvironmentVariableA(FirstEnvironmentVariable,
+ FirstEnvironmentValue);
+
+ if(!bRc)
+ {
+ Fail("ERROR: SetEnvironmentVariable failed to set a "
+ "proper environment variable with error %u.\n",
+ GetLastError());
+ }
+
+ /* Normal case, PATH should fit into this buffer */
+ size = GetEnvironmentVariableA(ModifiedEnvVar,
+ pResultBuffer,
+ 0);
+
+ /* To account for the null character at the end of the string */
+ size = size + 1;
+
+ pResultBuffer = malloc(sizeof(char)*size);
+ if ( pResultBuffer == NULL )
+ {
+ Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n");
+ }
+
+ /* Try to retrieve the value of the first environment variable */
+ GetEnvironmentVariableA(ModifiedEnvVar,
+ pResultBuffer,
+ size);
+
+ if ( pResultBuffer == NULL )
+ {
+ free(pResultBuffer);
+ Fail("ERROR: GetEnvironmentVariable failed to return a value "
+ "from a proper environment variable with error %u.\n",
+ GetLastError());
+ }
+
+ /* Compare the strings to see that the correct variable was returned */
+ if(strcmp(pResultBuffer,FirstEnvironmentValue) != 0)
+ {
+ Trace("ERROR: The value in the buffer should have been '%s' but "
+ "was really '%s'.\n",FirstEnvironmentValue, pResultBuffer);
+ free(pResultBuffer);
+ Fail("");
+ }
+
+ free(pResultBuffer);
+
+ PAL_Terminate();
+ return PASS;
+
+
+#else
+
+ return PASS;
+#endif
+}
diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/testinfo.dat
new file mode 100644
index 0000000000..925a917871
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/testinfo.dat
@@ -0,0 +1,18 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = SetEnvironmentVariableA
+Name = Return value test of SetEnvironmentVariableA
+TYPE = DEFAULT
+EXE1 = test4
+Description
+= Test that creating an environment variable and trying
+= to attain the value of the environment variable using
+= a name with different case works in the Windows
+= Environment.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/CMakeLists.txt
new file mode 100644
index 0000000000..a3847f8ca9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..247dceefd9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_setenvironmentvariablew_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setenvironmentvariablew_test1 coreclrpal)
+
+target_link_libraries(paltest_setenvironmentvariablew_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/test.c b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/test.c
new file mode 100644
index 0000000000..bddbba7940
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/test.c
@@ -0,0 +1,142 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose:
+** Set an environment variable and check to ensure success was returned. Then
+** get the environment variable and compare to the correct value. Also, check
+** that calling the function again, resets the variable properly. And that
+** calling with NULL deletes the variable.
+**
+**
+**=========================================================*/
+
+#define UNICODE
+#define BUF_SIZE 128
+
+#include <palsuite.h>
+
+/* Depends on GetEnvironmentVariable */
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ /* Define some buffers needed for the function */
+ WCHAR VariableBuffer[] = {'P','A','L','T','E','S','T','\0'};
+ WCHAR ValueBuffer[] = {'T','e','s','t','i','n','g','\0'};
+ WCHAR SecondValueBuffer[] = {'S','e','c','o','n','d','T','e','s','t','\0'};
+ WCHAR NewValue[BUF_SIZE];
+ int SetResult = 0;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ SetResult = SetEnvironmentVariable(VariableBuffer,
+ ValueBuffer);
+
+ /* If result is 0, the SetEnviron function failed */
+ if(SetResult == 0)
+ {
+ Fail("ERROR: SetEnvironmentVariable returned 0, which indicates that "
+ "it failed, even though it should have succeeded in setting the "
+ "variable PALTEST.\n");
+ }
+
+
+ /* Grab the Environment variable we just set */
+ if(GetEnvironmentVariable(VariableBuffer,NewValue,BUF_SIZE) <= 0)
+ {
+ Fail("ERROR: GetEnvironmentVariable returned 0 or less, which "
+ "indicates that no value was read in from the given variable.");
+ }
+
+ /* Make sure that the value put into NewValue was indeed the environment
+ variable we set.
+ */
+
+ if(memcmp(NewValue,ValueBuffer,wcslen(ValueBuffer)*sizeof(WCHAR)+2) != 0)
+ {
+ Fail("ERROR: When retrieving the variable that was just set, a "
+ "difference was found. Instead of the value being '%s' it "
+ "was instead '%s'.\n",convertC(ValueBuffer),convertC(NewValue));
+ }
+
+ /* If we set the same environment variable with a different value, the
+ old value should be replaced.
+ */
+
+ SetResult = SetEnvironmentVariable(VariableBuffer,
+ SecondValueBuffer);
+
+ /* If result is 0, the SetEnviron function failed */
+ if(SetResult == 0)
+ {
+ Fail("ERROR: SetEnvironmentVariable returned 0, which indicates that "
+ "it failed, even though it should have succeeded in re-setting "
+ "the variable PALTEST.\n");
+ }
+
+ memset(NewValue,0,BUF_SIZE);
+
+ /* Grab the Environment variable we just set */
+ if(GetEnvironmentVariable(VariableBuffer,NewValue,BUF_SIZE) <= 0)
+ {
+ Fail("ERROR: GetEnvironmentVariable returned 0 or less, which "
+ "indicates that no value was read in from the given variable.");
+ }
+
+ /* Make sure that the value put into NewValue was indeed the environment
+ variable we set.
+ */
+
+ if(memcmp(NewValue,SecondValueBuffer,
+ wcslen(SecondValueBuffer)*sizeof(WCHAR)+2) != 0)
+ {
+ Fail("ERROR: When retrieving the variable that was just set, a "
+ "difference was found. Instead of the value being '%s' it "
+ "was instead '%s'.\n",
+ convertC(SecondValueBuffer),convertC(NewValue));
+ }
+
+ /* Finally, set this variable with NULL, which should delete it from the
+ current environment.
+ */
+
+ SetResult = SetEnvironmentVariable(VariableBuffer, NULL);
+
+ /* If result is 0, the SetEnviron function failed */
+ if(SetResult == 0)
+ {
+ Fail("ERROR: SetEnvironmentVariable returned 0, which indicates that "
+ "it failed, even though it should have succeeded in deleting "
+ "the variable PALTEST.\n");
+ }
+
+ memset(NewValue,0,BUF_SIZE);
+
+ /* Grab the Environment variable we just set, ensure that it's
+ empty now.
+ */
+ if(GetEnvironmentVariable(VariableBuffer,NewValue,BUF_SIZE) != 0)
+ {
+ Fail("ERROR: GetEnvironmentVariable returned a non-zero value, "
+ "even though the environment variable which was checked should "
+ "have been empty.");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/testinfo.dat
new file mode 100644
index 0000000000..a44f4674cf
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/testinfo.dat
@@ -0,0 +1,18 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = SetEnvironmentVariableW
+Name = Positive test of SetEnvironmentVariableW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Set an environment variable and check to ensure success was returned. Then
+= get the environment variable and compare to the correct value. Also, check
+= that calling the function again, resets the variable properly. And that
+= calling with NULL deletes the variable.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/CMakeLists.txt
new file mode 100644
index 0000000000..a69343ccd5
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_setenvironmentvariablew_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setenvironmentvariablew_test2 coreclrpal)
+
+target_link_libraries(paltest_setenvironmentvariablew_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/test.c b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/test.c
new file mode 100644
index 0000000000..12f4887b6d
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/test.c
@@ -0,0 +1,88 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for SetEnvironmentVariableW() function
+** Test to see that passing NULL to the first param fails.
+** Test that passing NULL to both params fails.
+** Set an environment variable, then pass NULL to the second param
+** to delete it. Then make the same call again, to check that it fails.
+**
+**
+**=========================================================*/
+
+#define UNICODE
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ /* Define some buffers needed for the function */
+ WCHAR VariableBuffer[] = {'P','A','L','T','E','S','T','\0'};
+ WCHAR ValueBuffer[] = {'T','e','s','t','i','n','g','\0'};
+ int SetResult;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ SetResult = SetEnvironmentVariable(NULL,ValueBuffer);
+
+ /* Check that it fails if the first param is NULL */
+ if(SetResult != 0)
+ {
+ Fail("ERROR: SetEnvironmentVariable returned a success value, "
+ "even though it was passed NULL as the first parameter and "
+ "should have failed.\n");
+ }
+
+ /* Check that it fails when both params are NULL */
+ SetResult = SetEnvironmentVariable(NULL,NULL);
+ if(SetResult != 0)
+ {
+ Fail("ERROR: SetEnvironmentVariable returned a success value, even "
+ "though it was passed NULL as the first and second parameter and "
+ "should have failed.\n");
+ }
+
+ /* First, set the variable, which should be ok. Then call the
+ function with the second parameter NULL twice -- the first call should
+ pass, the second should fail.
+ */
+ SetResult = SetEnvironmentVariable(VariableBuffer,ValueBuffer);
+ if(SetResult == 0)
+ {
+ Fail("ERROR: SetEnvironmentVariable returned failure, when "
+ "attempting to set a valid variable.\n");
+ }
+
+ SetResult = SetEnvironmentVariable(VariableBuffer,NULL);
+ if(SetResult == 0)
+ {
+ Fail("ERROR: SetEnvironmentVariable returned failure, when "
+ "attempting to delete a variable.\n");
+ }
+
+ SetResult = SetEnvironmentVariable(VariableBuffer,NULL);
+ if(SetResult != 0)
+ {
+ Fail("ERROR: SetEnvironmentVariable returned success, when "
+ "attempting to delete a variable which doesn't exist.\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/testinfo.dat
new file mode 100644
index 0000000000..4df82daade
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/testinfo.dat
@@ -0,0 +1,18 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = SetEnvironmentVariableW
+Name = Return value test of SetEnvironmentVariableW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test to see that passing NULL to the first param fails.
+= Test that passing NULL to both params fails.
+= Set an environment variable, then pass NULL to the second param
+= to delete it. Then make the same call again, to check that it fails.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/CMakeLists.txt
new file mode 100644
index 0000000000..e9072c7143
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_setenvironmentvariablew_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setenvironmentvariablew_test3 coreclrpal)
+
+target_link_libraries(paltest_setenvironmentvariablew_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/test3.c b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/test3.c
new file mode 100644
index 0000000000..02d0a2d6d9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/test3.c
@@ -0,0 +1,143 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+** Source : test3.c
+**
+** Purpose: Test for SetEnvironmentVariableW() function
+** Create environment variables that differ only
+** in case and verify that they return the appropriate
+** value on the BSD environment.
+**
+**
+===========================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+#if WIN32
+
+ return PASS;
+
+#else
+
+ /* Define some buffers needed for the function */
+ WCHAR * pResultBuffer = NULL;
+
+ WCHAR FirstEnvironmentVariable[] = {'P','A','L','T','E','S','T','\0'};
+ WCHAR FirstEnvironmentValue[] = {'F','I','R','S','T','\0'};
+
+ WCHAR SecondEnvironmentVariable[] = {'p','a','l','t','e','s','t','\0'};
+ WCHAR SecondEnvironmentValue[] = {'S','E','C','O','N','D','\0'};
+
+ DWORD size = 0;
+ BOOL bRc = TRUE;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Set the first environment variable */
+ bRc = SetEnvironmentVariableW(FirstEnvironmentVariable,
+ FirstEnvironmentValue);
+
+ if(!bRc)
+ {
+ Fail("ERROR: SetEnvironmentVariable failed to set a "
+ "proper environment variable with error %u.\n",
+ GetLastError());
+ }
+
+ /* Set the second environment Variable */
+ bRc = SetEnvironmentVariableW(SecondEnvironmentVariable,
+ SecondEnvironmentValue);
+
+ if(!bRc)
+ {
+ Fail("ERROR: SetEnvironmentVariable failed to set a "
+ "proper environment variable with error %u.\n",
+ GetLastError());
+ }
+
+
+ /* Normal case, PATH should fit into this buffer */
+ size = GetEnvironmentVariableW(FirstEnvironmentVariable,
+ pResultBuffer,
+ 0);
+
+ /* Increase size to account for the null char at the end */
+ size = size + 1;
+
+ pResultBuffer = malloc(sizeof(WCHAR)*size);
+ if ( pResultBuffer == NULL )
+ {
+ Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n");
+ }
+
+ /* Try to retrieve the value of the first environment variable */
+ GetEnvironmentVariableW(FirstEnvironmentVariable,
+ pResultBuffer,
+ size);
+
+ if ( pResultBuffer == NULL )
+ {
+ Fail("ERROR: GetEnvironmentVariable failed to return a value "
+ "from a proper environment variable with error %u.\n",
+ GetLastError());
+ }
+
+ /* Compare the strings to see that the correct variable was returned */
+ if(wcscmp(pResultBuffer,FirstEnvironmentValue) != 0)
+ {
+ Trace("ERROR: The value in the buffer should have been '%S' but "
+ "was really '%S'.\n",FirstEnvironmentValue, pResultBuffer);
+ free(pResultBuffer);
+ Fail("");
+ }
+
+ free(pResultBuffer);
+
+ /* Reallocate the memory for the string */
+ pResultBuffer = malloc(sizeof(WCHAR)*size);
+ if ( pResultBuffer == NULL )
+ {
+ Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n");
+ }
+
+ /* Try retrieving the value of the first variable, even though the
+ second variable has the same spelling and only differs in case */
+ GetEnvironmentVariableW(SecondEnvironmentVariable,
+ pResultBuffer,
+ size);
+
+ if ( pResultBuffer == NULL )
+ {
+ Fail("ERROR: GetEnvironmentVariable failed to return a value "
+ "from a proper environment variable with error %u.\n",
+ GetLastError());
+ }
+
+ /* Compare the two strings to confirm that the right value is returned */
+ if(wcscmp(pResultBuffer,SecondEnvironmentValue) != 0)
+ {
+ Trace("ERROR: The value in the buffer should have been '%S' but "
+ "was really '%S'.\n",SecondEnvironmentValue,pResultBuffer);
+ free(pResultBuffer);
+ Fail("");
+ }
+
+ free(pResultBuffer);
+
+ PAL_Terminate();
+ return PASS;
+
+#endif
+}
diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/testinfo.dat
new file mode 100644
index 0000000000..43a457a76a
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = SetEnvironmentVariableW
+Name = Return value test of SetEnvironmentVariableW
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Create environment variables that differ only by case
+= and verify that they are treated distinctly in the
+= BSD Operating System.
diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/CMakeLists.txt
new file mode 100644
index 0000000000..f5f48bab33
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_setenvironmentvariablew_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setenvironmentvariablew_test4 coreclrpal)
+
+target_link_libraries(paltest_setenvironmentvariablew_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/test4.c b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/test4.c
new file mode 100644
index 0000000000..b8f7734de4
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/test4.c
@@ -0,0 +1,99 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+** Source : test4.c
+**
+** Purpose: Test for SetEnvironmentVariableW() function
+** Create environment variables that differ only
+** in case and verify that they return the appropriate
+** value on the BSD environment.
+**
+**
+===========================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+#if WIN32
+
+ /* Define some buffers needed for the function */
+ WCHAR * pResultBuffer = NULL;
+
+ WCHAR FirstEnvironmentVariable[] = {'P','A','L','T','E','S','T','\0'};
+ WCHAR FirstEnvironmentValue[] = {'F','I','R','S','T','\0'};
+
+ WCHAR ModifiedEnvironmentVariable[] = {'p','a','l','t','e','s','t','\0'};
+
+ DWORD size = 0;
+ BOOL bRc = TRUE;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Set the first environment variable */
+ bRc = SetEnvironmentVariableW(FirstEnvironmentVariable,
+ FirstEnvironmentValue);
+
+ if(!bRc)
+ {
+ Fail("ERROR: SetEnvironmentVariable failed to set a "
+ "proper environment variable with error %u.\n",
+ GetLastError());
+ }
+
+ /* Normal case, PATH should fit into this buffer */
+ size = GetEnvironmentVariableW(ModifiedEnvironmentVariable,
+ pResultBuffer,
+ 0);
+
+ /* To account for the nul character at the end of the string */
+ size = size + 1;
+
+ pResultBuffer = malloc(sizeof(WCHAR)*size);
+ if ( pResultBuffer == NULL )
+ {
+ Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n");
+ }
+
+ /* Try to retrieve the value of the first environment variable */
+ GetEnvironmentVariableW(ModifiedEnvironmentVariable,
+ pResultBuffer,
+ size);
+
+ if ( pResultBuffer == NULL )
+ {
+ Fail("ERROR: GetEnvironmentVariable failed to return a value "
+ "from a proper environment variable with error %u.\n",
+ GetLastError());
+ }
+
+ /* Compare the strings to see that the correct variable was returned */
+ if(wcsncmp(pResultBuffer,FirstEnvironmentValue,wcslen(pResultBuffer)) != 0)
+ {
+ Trace("ERROR: The value in the buffer should have been '%S' but "
+ "was really '%S'.\n",FirstEnvironmentValue, pResultBuffer);
+ free(pResultBuffer);
+ Fail("");
+ }
+
+ free(pResultBuffer);
+
+ PAL_Terminate();
+ return PASS;
+
+
+#else
+
+ return PASS;
+#endif
+}
diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/testinfo.dat
new file mode 100644
index 0000000000..ac3c4325e0
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = SetEnvironmentVariableW
+Name = Return value test of SetEnvironmentVariableW
+TYPE = DEFAULT
+EXE1 = test4
+Description
+= Create environment variable and try to retreive
+= the value of the variable by using a variable name
+= that differs in case. This should not affect the
+= return value in the Windows Operating System.
diff --git a/src/pal/tests/palsuite/miscellaneous/SetLastError/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/SetLastError/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/SetLastError/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/SetLastError/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/SetLastError/test1/CMakeLists.txt
new file mode 100644
index 0000000000..5248d6ce97
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/SetLastError/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_setlasterror_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setlasterror_test1 coreclrpal)
+
+target_link_libraries(paltest_setlasterror_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/SetLastError/test1/test.c b/src/pal/tests/palsuite/miscellaneous/SetLastError/test1/test.c
new file mode 100644
index 0000000000..d414626dd2
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/SetLastError/test1/test.c
@@ -0,0 +1,59 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for SetLastError() function
+**
+**
+**=========================================================*/
+/* Depends on GetLastError() */
+
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[]) {
+
+ /* Error value that we can set to test */
+ const unsigned int FAKE_ERROR = 5;
+ const int NEGATIVE_ERROR = -1;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Set error */
+ SetLastError(FAKE_ERROR);
+
+ /* Check to make sure it returns the error value we just set */
+ if(GetLastError() != FAKE_ERROR)
+ {
+ Fail("ERROR: The last error should have been '%d' but the error "
+ "returned was '%d'\n",FAKE_ERROR,GetLastError());
+ }
+
+ /* Set the error to a negative */
+ SetLastError(NEGATIVE_ERROR);
+
+ /* Check to make sure it returns the error value we just set */
+ if((signed)GetLastError() != NEGATIVE_ERROR)
+ {
+ Fail("ERROR: The last error should have been '%d' but the error "
+ "returned was '%d'\n",NEGATIVE_ERROR,GetLastError());
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/SetLastError/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/SetLastError/test1/testinfo.dat
new file mode 100644
index 0000000000..5333a4bb36
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/SetLastError/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = SetLastError
+Name = Positive test of SetLastError
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Set the Last Error and then use GetLastError to make sure
+= it was set properly. Assumes GetLastError is working.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/_i64tow/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/_i64tow/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/_i64tow/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/_i64tow/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/_i64tow/test1/CMakeLists.txt
new file mode 100644
index 0000000000..6876d1b24e
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/_i64tow/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_i64tow_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_i64tow_test1 coreclrpal)
+
+target_link_libraries(paltest_i64tow_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/_i64tow/test1/test1.c b/src/pal/tests/palsuite/miscellaneous/_i64tow/test1/test1.c
new file mode 100644
index 0000000000..9a87328b0d
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/_i64tow/test1/test1.c
@@ -0,0 +1,76 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests _i64tow with normal values and different radices, negative
+** values, as well as the highest and lowest values.
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+
+typedef struct
+{
+ INT64 value;
+ int radix;
+ char *result;
+} testCase;
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR buffer[256];
+ WCHAR *testStr;
+ WCHAR *ret;
+ int i;
+ testCase testCases[] =
+ {
+ {42, 10, "42"},
+ {42, 2, "101010"},
+ {29, 32, "t"},
+ {-1, 10, "-1"},
+ {-1, 8, "1777777777777777777777"},
+ {-1, 32, "fvvvvvvvvvvvv"},
+ {I64(0x7FFFFFFFFFFFFFFF), 10, "9223372036854775807"},
+ {I64(0x8000000000000000), 10, "-9223372036854775808"},
+ {0,2,"0"},
+ {0,16,"0"},
+ {3,16,"3"},
+ {15,16,"f"},
+ {16,16,"10"},
+
+ };
+
+
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ for (i=0; i<sizeof(testCases) / sizeof(testCase); i++)
+ {
+ ret = _i64tow(testCases[i].value, buffer, testCases[i].radix);
+ if (ret != buffer)
+ {
+ Fail("_i64tow did not return a pointer to the string.\n"
+ "Expected %p, got %p\n", buffer, ret);
+ }
+
+ testStr = convert(testCases[i].result);
+ if (wcscmp(testStr, buffer) != 0)
+ {
+ Fail("_i64tow did not give the correct string.\n"
+ "Expected %S, got %S\n", testStr, buffer);
+ }
+ free(testStr);
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/miscellaneous/_i64tow/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/_i64tow/test1/testinfo.dat
new file mode 100644
index 0000000000..a3979e60da
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/_i64tow/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = miscellaneous
+Function = _i64tow
+Name = Test #1 for _i64tow
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Tests _i64tow with normal values and different radices, negative
+=values, as well as the highest and lowest values.
diff --git a/src/pal/tests/palsuite/miscellaneous/_ui64tow/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/_ui64tow/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/_ui64tow/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/_ui64tow/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/_ui64tow/test1/CMakeLists.txt
new file mode 100644
index 0000000000..f920c4bded
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/_ui64tow/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ _ui64tow.c
+)
+
+add_executable(paltest_ui64tow_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_ui64tow_test1 coreclrpal)
+
+target_link_libraries(paltest_ui64tow_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/_ui64tow/test1/_ui64tow.c b/src/pal/tests/palsuite/miscellaneous/_ui64tow/test1/_ui64tow.c
new file mode 100644
index 0000000000..fb94f2509f
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/_ui64tow/test1/_ui64tow.c
@@ -0,0 +1,101 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: _ui64tow.c
+**
+** Purpose: Positive test the _ui64tow API.
+** convert an integer to a wide character string
+**
+**
+**============================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ WCHAR *wpBuffer = NULL;
+ char *pChar = NULL;
+ unsigned long ul = 1234567890UL;
+ char *pChar10 = "1234567890";
+ char *pChar2 = "1001001100101100000001011010010";
+ char *pChar16 = "499602d2";
+
+ /*Initialize the PAL environment*/
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+ wpBuffer = malloc(64 * sizeof(WCHAR));
+ if(NULL == wpBuffer)
+ {
+ Fail("\nFail to allocate the buffer to save a converted "
+ "wide character string, error code=%d!\n",
+ GetLastError());
+ }
+
+ /*convert to a 10 base string*/
+ _ui64tow(ul, wpBuffer, 10);
+ pChar = convertC(wpBuffer);
+ if(strcmp(pChar10, pChar))
+ {
+ free(wpBuffer);
+ free(pChar);
+ Fail("\nFailed to call _ui64tow API to convert an interger "
+ "to a 10 base wide character string, error code=%d\n",
+ GetLastError());
+ }
+ free(pChar);
+ free(wpBuffer);
+
+ wpBuffer = malloc(64 * sizeof(WCHAR));
+ if(NULL == wpBuffer)
+ {
+ Fail("\nFail to allocate the buffer to save a converted "
+ "wide character string, error code=%d!\n",
+ GetLastError());
+ }
+
+ /*convert to a 16 base string*/
+ _ui64tow(ul, wpBuffer, 16);
+ pChar = convertC(wpBuffer);
+ if(strcmp(pChar16, pChar))
+ {
+ free(wpBuffer);
+ free(pChar);
+ Fail("\nFailed to call _ui64tow API to convert an interger "
+ "to a 16 base wide character string, error code = %d\n",
+ GetLastError());
+ }
+ free(pChar);
+ free(wpBuffer);
+
+ wpBuffer = malloc(64 * sizeof(WCHAR));
+ if(NULL == wpBuffer)
+ {
+ Fail("\nFail to allocate the buffer to save a converted "
+ "wide character string, error code=%d!\n",
+ GetLastError());
+ }
+ /*convert to a 2 base string*/
+ _ui64tow(ul, wpBuffer, 2);
+ pChar = convertC(wpBuffer);
+ if(strcmp(pChar2, pChar))
+ {
+ free(wpBuffer);
+ free(pChar);
+ Fail("\nFailed to call _ui64tow API to convert an interger "
+ "to a 2 base wide character string, error code=%d\n",
+ GetLastError());
+ }
+ free(pChar);
+ free(wpBuffer);
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/miscellaneous/_ui64tow/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/_ui64tow/test1/testinfo.dat
new file mode 100644
index 0000000000..a60f27a14a
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/_ui64tow/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = miscellaneous
+Function = _ui64tow
+Name = Positive test _ui64tow to convert an integer to a wide character string
+TYPE = DEFAULT
+EXE1 = _ui64tow
+Description
+=Test the _ui64tow API to convert an integer to a wide character string
diff --git a/src/pal/tests/palsuite/miscellaneous/_ui64tow/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/_ui64tow/test2/CMakeLists.txt
new file mode 100644
index 0000000000..b4feb4b8fd
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/_ui64tow/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ _ui64tow.c
+)
+
+add_executable(paltest_ui64tow_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_ui64tow_test2 coreclrpal)
+
+target_link_libraries(paltest_ui64tow_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/_ui64tow/test2/_ui64tow.c b/src/pal/tests/palsuite/miscellaneous/_ui64tow/test2/_ui64tow.c
new file mode 100644
index 0000000000..f13250578c
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/_ui64tow/test2/_ui64tow.c
@@ -0,0 +1,88 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: _ui64tow.c
+**
+** Purpose: Tests _ui64tow with normal values and different
+** radices,highest and lowest values.
+**
+**
+**============================================================*/
+
+#include <palsuite.h>
+
+typedef struct
+{
+ unsigned __int64 value;
+ int radix;
+ char* result;
+} testCase;
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR buffer[256];
+ WCHAR *testStr;
+ WCHAR *ret;
+ int i;
+ testCase testCases[] =
+ {
+ /* test limits */
+ {UI64(0xFFFFFFFFFFFFFFFF), 2,
+ "1111111111111111111111111111111111111111111111111111111111111111"},
+ {UI64(0xFFFFFFFFFFFFFFFF), 8, "1777777777777777777777"},
+ {UI64(0xFFFFFFFFFFFFFFFF), 10, "18446744073709551615"},
+ {UI64(0xFFFFFFFFFFFFFFFF), 16, "ffffffffffffffff"},
+ {47, 2, "101111"},
+ {47, 8, "57"},
+ {47, 10, "47"},
+ {47, 16, "2f"},
+ {12, 2, "1100"},
+ {12, 8, "14"},
+ {12, 10, "12"},
+ {12, 16, "c"},
+
+ /* test with 0. */
+ {0, 2, "0"},
+ {0, 8, "0"},
+ {0, 10, "0"},
+ {0, 16, "0"}
+ };
+
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ for (i=0; i<sizeof(testCases) / sizeof(testCase); i++)
+ {
+ ret = _ui64tow(testCases[i].value, buffer, testCases[i].radix);
+
+ if (ret != buffer)
+ {
+ Fail("Failed to call _ui64tow API: did not return a pointer "
+ "to string. Expected %p, got %p\n", buffer, ret);
+ }
+
+ testStr = convert(testCases[i].result);
+
+ if (wcscmp(testStr, buffer) != 0)
+ {
+ Trace("ERROR: _ui64tow test#%d. Expected <%S>, got <%S>.\n",
+ i,testStr, buffer);
+ free(testStr);
+ Fail("");
+ }
+
+ free(testStr);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/_ui64tow/test2/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/_ui64tow/test2/testinfo.dat
new file mode 100644
index 0000000000..0abbca2d11
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/_ui64tow/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = miscellaneous
+Function = _ui64tow
+Name = Positive test _ui64tow to convert an integer to a wide character string
+TYPE = DEFAULT
+EXE1 = _ui64tow
+Description
+=Test the _ui64tow API to convert an integer to a wide character string
+=Test the limits. and 0.
diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcatW/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/lstrcatW/CMakeLists.txt
new file mode 100644
index 0000000000..a3847f8ca9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/lstrcatW/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..aa5b0c2646
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_lstrcatw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_lstrcatw_test1 coreclrpal)
+
+target_link_libraries(paltest_lstrcatw_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test1/test.c b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test1/test.c
new file mode 100644
index 0000000000..ad1095e014
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test1/test.c
@@ -0,0 +1,59 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for lstrcatW() function
+**
+**
+**=========================================================*/
+
+#define UNICODE
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[]) {
+
+ WCHAR FirstString[10] = {'T','E','S','T','\0'};
+ const WCHAR SecondString[] = {'P','A','L','!','\0'};
+ WCHAR CorrectString[] = {'T','E','S','T','P','A','L','!','\0'};
+ WCHAR* ReturnedPointer = NULL;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ ReturnedPointer = lstrcat(FirstString,SecondString);
+
+ /* Check to see if the pointer returned points to the concat string */
+ if(ReturnedPointer != &FirstString[0])
+ {
+ Fail("ERROR: The function was supposed to return a pointer to "
+ "the concatentated string, but it did not.\n");
+ }
+
+ /* Check to make sure the Concat string is the same as the predetermined
+ 'CorrectString' */
+ if(memcmp(FirstString,CorrectString,
+ wcslen(FirstString)*sizeof(WCHAR)) != 0)
+ {
+ Fail("ERROR: The concatenated string should be %s but %s was the "
+ "result.\n",
+ convertC(CorrectString),
+ convertC(FirstString));
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test1/testinfo.dat
new file mode 100644
index 0000000000..006e83b882
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = lstrcatW
+Name = Positive test of lstrcatW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test to see that concatenating two strings works,
+= and also check return values in successful and failing situations.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test2/CMakeLists.txt
new file mode 100644
index 0000000000..8a11c8f154
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_lstrcatw_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_lstrcatw_test2 coreclrpal)
+
+target_link_libraries(paltest_lstrcatw_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test2/test2.c b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test2/test2.c
new file mode 100644
index 0000000000..6c66bc8976
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test2/test2.c
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test2.c
+**
+** Purpose: Negative test for lstrcatW() function
+**
+**
+**=========================================================*/
+
+#define UNICODE
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[]) {
+
+ WCHAR FirstString[10] = {'T','E','S','T','\0'};
+ const WCHAR SecondString[] = {'P','A','L','!','\0'};
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* If either of these is NULL, function should fail and return NULL. */
+ if(lstrcat(NULL,SecondString) != NULL)
+ {
+ Fail("ERROR: When NULL was passed to the first parameter of the "
+ "function, it should have returned "
+ "NULL as a result, but did not.\n");
+ }
+
+ if(lstrcat(FirstString,NULL) != NULL)
+ {
+ Fail("ERROR: When NULL was passed to the second parameter of the "
+ "function, it should have returned "
+ "NULL as a result, but did not.\n");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test2/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test2/testinfo.dat
new file mode 100644
index 0000000000..cc1ee644dc
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test2/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = lstrcatW
+Name = Negtive test of lstrcatW
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Test to see lstrcat reports error with failing situations.
diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test3/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test3/CMakeLists.txt
new file mode 100644
index 0000000000..1cdecedf1a
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_lstrcatw_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_lstrcatw_test3 coreclrpal)
+
+target_link_libraries(paltest_lstrcatw_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test3/test3.c b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test3/test3.c
new file mode 100644
index 0000000000..49a9c57555
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test3/test3.c
@@ -0,0 +1,46 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test3.c
+**
+** Purpose: Testing lstrcatw with two NULL strings passed on
+**
+**
+**=========================================================*/
+
+#define UNICODE
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+
+ /* testing the behaviour of lstrcatW with two NULL strings */
+ if( lstrcat(NULL,NULL) != NULL)
+ {
+
+ Fail("lstrcat:ERROR: the function should returned NULL\n");
+
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test3/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test3/testinfo.dat
new file mode 100644
index 0000000000..794bcdbff7
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test3/testinfo.dat
@@ -0,0 +1,26 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+
+Section = Miscellaneous
+
+Function = lstrcatW
+
+Name = Negative testing for lstrcatW
+
+TYPE = DEFAULT
+
+EXE1 = test3
+
+Description
+
+= Testing the behaviour after sending two strings contained NULL
+
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test4/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test4/CMakeLists.txt
new file mode 100644
index 0000000000..640c224f83
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_lstrcatw_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_lstrcatw_test4 coreclrpal)
+
+target_link_libraries(paltest_lstrcatw_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test4/test4.c b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test4/test4.c
new file mode 100644
index 0000000000..abc9021518
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test4/test4.c
@@ -0,0 +1,101 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test4.c
+**
+** Purpose: Testing the behaviour of lstrcatw when string2 contains
+** special characters, this test case depends on:
+** memcmp
+** wcslen
+** lstrcpyn
+**
+**
+**=========================================================*/
+
+#define UNICODE
+
+#include <palsuite.h>
+
+struct testCase
+{
+ WCHAR SecondString[5];
+ WCHAR CorrectString[10];
+};
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ WCHAR FirstString[10] = {'T','E','S','T','\0'};
+ WCHAR TestString[10] = {'T','E','S','T','\0'};
+ int i = 0;
+
+ /*
+ * this structure includes several strings to be tested with
+ * lstrcatW function and the expected results
+ */
+
+ struct testCase testCases[]=
+ {
+ {{'\t','T','A','B','\0'},
+ {'T','E','S','T','\t','T','A','B','\0'}},
+ {{'2','T','\?','B','\0'},
+ {'T','E','S','T','2','T','\?','B','\0'}},
+ {{'\v','T','E','\v','\0'},
+ {'T','E','S','T','\v','T','E','\v','\0'}},
+ {{'T','\a','E','\a','\0'},
+ {'T','E','S','T','T','\a','E','\a','\0'}},
+ {{'0','\f','Z','\f','\0'},
+ {'T','E','S','T','0','\f','Z','\f','\0'}},
+ {{'\r','H','I','\r','\0'},
+ {'T','E','S','T','\r','H','I','\r','\0'}},
+ {{'H','I','\"','\"','\0'},
+ {'T','E','S','T','H','I','\"','\"','\0'}},
+ {{'H','\b','I','\b','\0'},
+ {'T','E','S','T','H','\b','I','\b','\0'}},
+ {{'H','\n','I','\n','\0'},
+ {'T','E','S','T','H','\n','I','\n','\0'}}
+ };
+
+
+
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+
+ /* Loop through the struct and validate the resulted string */
+ for( i = 0; i < sizeof(testCases)/sizeof(struct testCase); i++)
+ {
+
+ lstrcat(FirstString, testCases[i].SecondString);
+
+ if(memcmp(FirstString,testCases[i].CorrectString,
+ wcslen(FirstString)*sizeof(WCHAR)))
+ {
+
+ Fail("ERROR: the function failed with a special character.\n");
+ }
+
+ /* reinitialize the first string */
+ lstrcpyn(FirstString,TestString,10);
+
+ }
+
+
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test4/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test4/testinfo.dat
new file mode 100644
index 0000000000..96235fb257
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test4/testinfo.dat
@@ -0,0 +1,28 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+
+Section = Miscellaneous
+
+Function = lstrcatW
+
+Name = Positive testing for lstrcatW
+
+TYPE = DEFAULT
+
+EXE1 = test4
+
+Description
+
+= Testing the behaviour of lstrcatw when string2 contains
+
+= special characters and validate the resulted string
+
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcpyW/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/lstrcpyW/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/lstrcpyW/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcpyW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/lstrcpyW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..e39c9a6098
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/lstrcpyW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_lstrcpyw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_lstrcpyw_test1 coreclrpal)
+
+target_link_libraries(paltest_lstrcpyw_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcpyW/test1/test.c b/src/pal/tests/palsuite/miscellaneous/lstrcpyW/test1/test.c
new file mode 100644
index 0000000000..881ba033e8
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/lstrcpyW/test1/test.c
@@ -0,0 +1,66 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for lstrcpyW() function
+**
+**
+**=========================================================*/
+
+#define UNICODE
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ WCHAR FirstString[5] = {'T','E','S','T','\0'};
+ WCHAR ResultBuffer[5];
+ WCHAR* ResultPointer = NULL;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ ResultPointer = lstrcpy(ResultBuffer,FirstString);
+
+ /* Check the return value */
+ if(ResultPointer != &ResultBuffer[0])
+ {
+ Fail("ERROR: The function did not return a pointer to the Result "
+ "Buffer after being called.\n");
+ }
+
+ /* A straight copy, the values should be equal. */
+ if(memcmp(ResultBuffer,FirstString,wcslen(ResultBuffer)*2+2) != 0)
+ {
+ Fail("ERROR: The result of the copy was '%s' when it should have "
+ "been '%s'.\n",convertC(ResultBuffer),convertC(FirstString));
+ }
+
+ /* If either param is NULL, it should return NULL. */
+ if(lstrcpy(ResultBuffer,NULL) != NULL)
+ {
+ Fail("ERROR: The second parameter was NULL, so the function should "
+ "fail and return NULL.\n");
+ }
+ if(lstrcpy(NULL,FirstString) != NULL)
+ {
+ Fail("ERROR: The first parameter was NULL, so the function should "
+ "fail and return NULL.\n");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcpyW/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/lstrcpyW/test1/testinfo.dat
new file mode 100644
index 0000000000..37c9835236
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/lstrcpyW/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = lstrcpyW
+Name = Positive test of lstrcpyW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Ensure that a copy of a string works, and that the return values
+= are correct for success and failure.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcpynW/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/lstrcpynW/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/lstrcpynW/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcpynW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/lstrcpynW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..4344b89402
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/lstrcpynW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_lstrcpynw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_lstrcpynw_test1 coreclrpal)
+
+target_link_libraries(paltest_lstrcpynw_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcpynW/test1/test.c b/src/pal/tests/palsuite/miscellaneous/lstrcpynW/test1/test.c
new file mode 100644
index 0000000000..1ae0c51474
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/lstrcpynW/test1/test.c
@@ -0,0 +1,73 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for lstrcpynW() function
+**
+**
+**=========================================================*/
+
+#define UNICODE
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[]) {
+
+ WCHAR FirstString[5] = {'T','E','S','T','\0'};
+ WCHAR CorrectBuffer[3] = {'T','E','\0'};
+ WCHAR ResultBuffer[5];
+ WCHAR* ResultPointer = NULL;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* A straight copy, the values should be equal. */
+ ResultPointer = lstrcpyn(ResultBuffer,FirstString,3);
+
+ /* Make sure the returned pointer is to the result buffer */
+ if(ResultPointer != &ResultBuffer[0])
+ {
+ Fail("ERROR: The function didn't return a pointer which points to the "
+ "location of the buffer which was copied into.\n");
+ }
+
+ /* Check to see that values are equal */
+ if(memcmp(ResultBuffer,
+ CorrectBuffer,
+ wcslen(ResultBuffer)*sizeof(WCHAR)) != 0)
+ {
+ Fail("ERROR: '%s' was the result and it should have been '%s' when "
+ "this copy was performed.\n",
+ convertC(ResultBuffer),convertC(CorrectBuffer));
+ }
+
+ /* Null values should get Null results */
+ if(lstrcpyn(ResultBuffer,NULL,3) != NULL)
+ {
+ Fail("ERROR: When the second parameter was set to NULL, the return "
+ "value should have been NULL, but it was not.\n");
+ }
+
+ if(lstrcpyn(NULL,FirstString,3) != NULL)
+ {
+ Fail("ERROR: When the first parameter was set to NULL, the return "
+ "value should have been NULL, but it was not.\n");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcpynW/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/lstrcpynW/test1/testinfo.dat
new file mode 100644
index 0000000000..111a57928a
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/lstrcpynW/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = lstrcpynW
+Name = Positive test of lstrcpynW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Ensure that a copy of a string works, and that the return values
+= are correct for success and failure.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/lstrlenA/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/lstrlenA/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/lstrlenA/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/lstrlenA/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/lstrlenA/test1/CMakeLists.txt
new file mode 100644
index 0000000000..807a5d83b9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/lstrlenA/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_lstrlena_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_lstrlena_test1 coreclrpal)
+
+target_link_libraries(paltest_lstrlena_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/lstrlenA/test1/test.c b/src/pal/tests/palsuite/miscellaneous/lstrlenA/test1/test.c
new file mode 100644
index 0000000000..13e935ba50
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/lstrlenA/test1/test.c
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for lstrlenA() function
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[]) {
+
+ char * FirstString = "Pal Testing"; /* 11 characters */
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* The string size should be 11 */
+ if(lstrlen(FirstString) != 11)
+ {
+ Fail("ERROR: The string size returned was %d but it should have "
+ "been 11 in this test.\n",lstrlen(FirstString));
+ }
+
+ /* A NULL pointer should return 0 length */
+ if(lstrlen(NULL) != 0)
+ {
+ Fail("ERROR: Checking the length of NULL pointer should return "
+ "a value of 0, but %d was returned.\n",lstrlen(NULL));
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/lstrlenA/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/lstrlenA/test1/testinfo.dat
new file mode 100644
index 0000000000..2c8b795f64
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/lstrlenA/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = lstrlenA
+Name = Positive test of lstrlenA
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test a standard NULL terminated string and a NULL pointer
+= to ensure values are correct.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/lstrlenW/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/lstrlenW/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/lstrlenW/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/lstrlenW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/lstrlenW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..fe6fc9691b
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/lstrlenW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_lstrlenw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_lstrlenw_test1 coreclrpal)
+
+target_link_libraries(paltest_lstrlenw_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/lstrlenW/test1/test.c b/src/pal/tests/palsuite/miscellaneous/lstrlenW/test1/test.c
new file mode 100644
index 0000000000..49bc6d8f67
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/lstrlenW/test1/test.c
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for lstrlenW() function
+**
+**
+**=========================================================*/
+
+#define UNICODE
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[]) {
+
+ WCHAR FirstString[] = {'T','E','S','T','\0'}; /* 4 characters */
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* The string size should be 4, as noted just above */
+ if(lstrlen(FirstString) != 4)
+ {
+ Fail("ERROR: The return value was %d when it should have shown the "
+ "size to be 4 characters.\n",lstrlen(FirstString));
+ }
+
+ /* A NULL pointer should return 0 length */
+ if(lstrlen(NULL) != 0)
+ {
+ Fail("ERROR: The return value was %d when it should have been 0, the "
+ "length of a NULL pointer.\n",lstrlen(NULL));
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/lstrlenW/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/lstrlenW/test1/testinfo.dat
new file mode 100644
index 0000000000..4e9a4eb2b7
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/lstrlenW/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = lstrlenW
+Name = Positive test of lstrlenW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test a standard NULL terminated string and
+= a NULL pointer to ensure values are correct.
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/queryperformancecounter/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/queryperformancecounter/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/queryperformancecounter/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/queryperformancecounter/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/queryperformancecounter/test1/CMakeLists.txt
new file mode 100644
index 0000000000..d76467aeab
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/queryperformancecounter/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_queryperformancecounter_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_queryperformancecounter_test1 coreclrpal)
+
+target_link_libraries(paltest_queryperformancecounter_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/queryperformancecounter/test1/test1.c b/src/pal/tests/palsuite/miscellaneous/queryperformancecounter/test1/test1.c
new file mode 100644
index 0000000000..55b173add7
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/queryperformancecounter/test1/test1.c
@@ -0,0 +1,107 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test1.c
+**
+** Purpose: Test for QueryPerformanceCounter function
+**
+**
+**=========================================================*/
+
+/* Depends on: QueryPerformanceFrequency. */
+
+#include <palsuite.h>
+
+/* Milliseconds of error which are acceptable Function execution time, etc.
+ FreeBSD has a "standard" resolution of 50ms for waiting operations, so we
+ must take that into account as well */
+DWORD AcceptableTimeError = 15;
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ int i;
+ int NumIterations = 100;
+ DWORD AvgTimeDiff;
+ DWORD TimeDiff[100];
+ DWORD TotalTimeDiff = 0;
+ DWORD SleepInterval = 50;
+ LARGE_INTEGER StartTime;
+ LARGE_INTEGER EndTime;
+ LARGE_INTEGER Freq;
+
+ /* Initialize the PAL.
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Get the frequency of the High-Performance Counter,
+ * in order to convert counter time to milliseconds.
+ */
+ if (!QueryPerformanceFrequency(&Freq))
+ {
+ Fail("ERROR:%u:Unable to retrieve the frequency of the "
+ "high-resolution performance counter.\n",
+ GetLastError());
+ }
+
+ /* Perform this set of sleep timings a number of times.
+ */
+ for(i=0; i < NumIterations; i++)
+ {
+
+ /* Get the current counter value.
+ */
+ if (!QueryPerformanceCounter(&StartTime))
+ {
+ Fail("ERROR:%u:Unable to retrieve the current value of the "
+ "high-resolution performance counter.\n",
+ GetLastError());
+ }
+
+ /* Sleep a predetermined interval.
+ */
+ Sleep(SleepInterval);
+
+ /* Get the new current counter value.
+ */
+ if (!QueryPerformanceCounter(&EndTime))
+ {
+ Fail("ERROR:%u:Unable to retrieve the current value of the "
+ "high-resolution performance counter.\n",
+ GetLastError());
+ }
+
+ /* Determine elapsed time, in milliseconds. Compare the elapsed time
+ * with the sleep interval, and add to counter.
+ */
+ TimeDiff[i] = (DWORD)(((EndTime.QuadPart - StartTime.QuadPart)*1000)/
+ (Freq.QuadPart));
+ TotalTimeDiff += TimeDiff[i] - SleepInterval;
+
+ }
+
+ /* Verify that the average of the difference between the performance
+ * counter and the sleep interval is within our acceptable range.
+ */
+ AvgTimeDiff = TotalTimeDiff / NumIterations;
+ if (AvgTimeDiff > AcceptableTimeError)
+ {
+ Fail("ERROR: average diff %u acceptable %u.\n",
+ AvgTimeDiff,
+ AcceptableTimeError);
+ }
+
+ /* Terminate the PAL.
+ */
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/queryperformancecounter/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/queryperformancecounter/test1/testinfo.dat
new file mode 100644
index 0000000000..56f11fc91b
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/queryperformancecounter/test1/testinfo.dat
@@ -0,0 +1,11 @@
+Version = 1.0
+Section = Miscellaneous
+Function = QueryPerformanceCounter
+Name = Positive Test for QueryPerformanceCounter
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= This test will verify with QueryPerformanceCounter
+= and QueryPerformanceFrequency that an API call of Sleep
+= of 100 milliseconds takes 100 milliseconds, taking into
+= account the error tolerance.
diff --git a/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/CMakeLists.txt
new file mode 100644
index 0000000000..352e51342d
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_queryperformancefrequency_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_queryperformancefrequency_test1 coreclrpal)
+
+target_link_libraries(paltest_queryperformancefrequency_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/test1.c b/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/test1.c
new file mode 100644
index 0000000000..de08063a74
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/test1.c
@@ -0,0 +1,59 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test1.c
+**
+** Purpose: Test for QueryPerformanceFrequency function
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ LARGE_INTEGER Freq;
+
+ /* Initialize the PAL.
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Check the return value of the performance
+ * frequency, a value of zero indicates that
+ * either the call has failed or the
+ * high-resolution performance counter is not
+ * installed.
+ */
+ if (!QueryPerformanceFrequency(&Freq))
+ {
+
+ Fail("ERROR:%u:Unable to retrieve the frequency of the "
+ "high-resolution performance counter.\n",
+ GetLastError());
+ }
+
+
+ /* Check the return value the frequency the
+ * value should be non-zero.
+ */
+ if (Freq.QuadPart == 0)
+ {
+
+ Fail("ERROR: The frequency has been determined to be 0 "
+ "the frequency should be non-zero.\n");
+
+ }
+
+ /* Terminate the PAL.
+ */
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/testinfo.dat
new file mode 100644
index 0000000000..ea561422c1
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/testinfo.dat
@@ -0,0 +1,12 @@
+Version = 1.0
+Section = Miscellaneous
+Function = QueryPerformanceFrequency
+Name = Positive Test for QueryPerformanceFrequency
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= This test will verify that QueryPerformanceFrequency
+= returns a valid return value.
+= The value of the count is processor dependent. On
+= some processors, for example, the count might be the
+= cycle rate of the processor clock.
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfA/CMakeLists.txt
new file mode 100644
index 0000000000..f40d4151d6
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfA/CMakeLists.txt
@@ -0,0 +1,13 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test11)
+add_subdirectory(test12)
+add_subdirectory(test13)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test6)
+add_subdirectory(test7)
+add_subdirectory(test8)
+add_subdirectory(test9)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test1/CMakeLists.txt
new file mode 100644
index 0000000000..ef589329f0
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_wsprintfa_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wsprintfa_test1 coreclrpal)
+
+target_link_libraries(paltest_wsprintfa_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test1/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test1/test.c
new file mode 100644
index 0000000000..722270965d
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test1/test.c
@@ -0,0 +1,58 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for wsprintfA() function
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+ char * ErrorMessage;
+ char buf[256];
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with strlen */
+
+int test1()
+{
+ char checkstr[] = "hello world";
+
+ wsprintf(buf, "hello world");
+
+ /* Error message */
+ ErrorMessage = "ERROR: (Test 1) Failed on 'hello world' test. The "
+ "correct string is 'hello world' and the result returned was ";
+
+ return (memcmp(checkstr, buf, strlen(checkstr)+1) != 0);
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ if(test1())
+ {
+ Fail("%s '%s'\n",ErrorMessage,buf);
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test1/testinfo.dat
new file mode 100644
index 0000000000..c06f4c01aa
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = wsprintfA
+Name = Positive test of wsprintfA
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test the very basic functionality of wsprintf.
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test11/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test11/CMakeLists.txt
new file mode 100644
index 0000000000..92c44b9341
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test11/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_wsprintfa_test11
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wsprintfa_test11 coreclrpal)
+
+target_link_libraries(paltest_wsprintfa_test11
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test11/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test11/test.c
new file mode 100644
index 0000000000..b43299a045
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test11/test.c
@@ -0,0 +1,128 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for wsprintfA() function
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with strlen */
+
+char * ErrorMessage;
+char buf[256];
+
+BOOL test1()
+{
+ int pos = 42;
+
+
+ /* Test 1 */
+ wsprintf(buf, "foo %u", pos);
+ if (memcmp(buf, "foo 42", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 1) Failed. The correct string is "
+ "'foo 42' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 2 */
+ wsprintf(buf, "foo %lu", 0xFFFF);
+ if (memcmp(buf, "foo 65535", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 2) Failed. The correct string is "
+ "'foo 65535' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 3 */
+ wsprintf(buf, "foo %hu", 0xFFFF);
+ if (memcmp(buf, "foo 65535", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 3) Failed. The correct string is "
+ "'foo 65535' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 4 */
+ wsprintf(buf, "foo %3u", pos);
+ if (memcmp(buf, "foo 42", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 4) Failed. The correct string is "
+ "'foo 42' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 5 */
+ wsprintf(buf, "foo %-3u", pos);
+ if (memcmp(buf, "foo 42 ", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 5) Failed. The correct string is "
+ "'foo 42' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 6 */
+ wsprintf(buf, "foo %.1u", pos);
+ if (memcmp(buf, "foo 42", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 6) Failed. The correct string is "
+ "'foo 42' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 7 */
+ wsprintf(buf, "foo %.3u", pos);
+ if (memcmp(buf, "foo 042", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 7) Failed. The correct string is "
+ "'foo 042' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 8 */
+ wsprintf(buf, "foo %03u", pos);
+ if (memcmp(buf, "foo 042", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 8) Failed. The correct string is "
+ "'foo 042' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 9 */
+ wsprintf(buf, "foo %#u", pos);
+ if (memcmp(buf, "foo 42", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 9) Failed. The correct string is "
+ "'foo 42' and the result returned was ";
+ return FAIL;
+ }
+ return PASS;
+}
+
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ if(test1())
+ {
+ Fail("%s'%s'\n",ErrorMessage,buf);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test11/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test11/testinfo.dat
new file mode 100644
index 0000000000..c5f1ec1975
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test11/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = wsprintfA
+Name = Positive test of wsprintfA
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test the %u formatter.
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test12/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test12/CMakeLists.txt
new file mode 100644
index 0000000000..e4013ad9e3
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test12/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_wsprintfa_test12
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wsprintfa_test12 coreclrpal)
+
+target_link_libraries(paltest_wsprintfa_test12
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test12/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test12/test.c
new file mode 100644
index 0000000000..dcc61019d4
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test12/test.c
@@ -0,0 +1,119 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for wsprintfA() function
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with strlen */
+
+char * ErrorMessage;
+char buf[256];
+
+BOOL test1()
+{
+ int pos = 0x1234ab;
+
+ /* Test 1 */
+ wsprintf(buf, "foo %x", pos);
+ if (memcmp(buf, "foo 1234ab", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 1) Failed. The correct "
+ "string is 'foo 1234ab' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 2 */
+ wsprintf(buf, "foo %lx", pos);
+ if (memcmp(buf, "foo 1234ab", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 2) Failed. The correct "
+ "string is 'foo 1234ab' and the result returned was ";
+ return FAIL;
+ }
+
+
+ /* Test 3 */
+ wsprintf(buf, "foo %7x", pos);
+ if (memcmp(buf, "foo 1234ab", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 3) Failed. The correct string is "
+ "'foo 1234ab' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 4 */
+ wsprintf(buf, "foo %-7x", pos);
+ if (memcmp(buf, "foo 1234ab ", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 4) Failed. The correct string is "
+ "'foo 1234ab' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 5 */
+ wsprintf(buf, "foo %.1x", pos);
+ if (memcmp(buf, "foo 1234ab", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 5) Failed. The correct string is "
+ "'foo 1234ab' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 6 */
+ wsprintf(buf, "foo %.7x", pos);
+ if (memcmp(buf, "foo 01234ab", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 6) Failed. The correct string is "
+ "'foo 01234ab' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 7 */
+ wsprintf(buf, "foo %07x", pos);
+ if (memcmp(buf, "foo 01234ab", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 7) Failed. The correct string is "
+ "'foo 01234ab' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 8 */
+ wsprintf(buf, "foo %#x", pos);
+ if (memcmp(buf, "foo 0x1234ab", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 8) Failed. The correct string is "
+ "'foo 0x1234ab' and the result returned was ";
+ return FAIL;
+ }
+
+ return PASS;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ if(test1())
+ {
+ Fail("%s '%s'\n",ErrorMessage,buf);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test12/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test12/testinfo.dat
new file mode 100644
index 0000000000..71c8386f27
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test12/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = wsprintfA
+Name = Positive test of wsprintfA
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test the %x formatter.
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test13/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test13/CMakeLists.txt
new file mode 100644
index 0000000000..423b05d8d9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test13/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_wsprintfa_test13
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wsprintfa_test13 coreclrpal)
+
+target_link_libraries(paltest_wsprintfa_test13
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test13/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test13/test.c
new file mode 100644
index 0000000000..e1f7d80a0f
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test13/test.c
@@ -0,0 +1,120 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for wsprintfA() function
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with strlen */
+
+char * ErrorMessage;
+char buf[256];
+
+BOOL test1()
+{
+ int pos = 0x1234ab;
+
+ /* Test 1 */
+ wsprintf(buf, "foo %X", pos);
+ if (memcmp(buf, "foo 1234AB", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 1) Failed. The correct string is "
+ " 'foo 1234AB' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 2 */
+ wsprintf(buf, "foo %lX", pos);
+ if (memcmp(buf, "foo 1234AB", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 2) Failed. The correct string is "
+ "'foo 1234AB' and the result returned was ";
+ return FAIL;
+ }
+
+
+ /* Test 3 */
+ wsprintf(buf, "foo %7X", pos);
+ if (memcmp(buf, "foo 1234AB", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 3) Failed. The correct string is "
+ "'foo 1234AB' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 4 */
+ wsprintf(buf, "foo %-7X", pos);
+ if (memcmp(buf, "foo 1234AB ", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 4) Failed. The correct string is "
+ "'foo 1234AB' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 5 */
+ wsprintf(buf, "foo %.1X", pos);
+ if (memcmp(buf, "foo 1234AB", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 5) Failed. The correct string is "
+ "'foo 1234AB' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 6 */
+ wsprintf(buf, "foo %.7X", pos);
+ if (memcmp(buf, "foo 01234AB", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 6) Failed. The correct string is "
+ "'foo 01234AB' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 7 */
+ wsprintf(buf, "foo %07X", pos);
+ if (memcmp(buf, "foo 01234AB", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 7) Failed. The correct string is "
+ "'foo 01234AB' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 8 */
+ wsprintf(buf, "foo %#X", pos);
+ if (memcmp(buf, "foo 0X1234AB", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 8) Failed. The correct string is "
+ "'foo 0X1234AB' and the result returned was ";
+ return FAIL;
+ }
+
+ return PASS;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ if(test1())
+ {
+ Fail("%s '%s'\n",ErrorMessage,buf);
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test13/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test13/testinfo.dat
new file mode 100644
index 0000000000..0e0d1b4633
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test13/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = wsprintfA
+Name = Positive test of wsprintfA
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test the %X formatter.
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test2/CMakeLists.txt
new file mode 100644
index 0000000000..546a1daa38
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_wsprintfa_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wsprintfa_test2 coreclrpal)
+
+target_link_libraries(paltest_wsprintfa_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test2/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test2/test.c
new file mode 100644
index 0000000000..b879e54043
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test2/test.c
@@ -0,0 +1,123 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for wsprintfA() function
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with strlen */
+
+char * ErrorMessage;
+char * BadResult;
+char buf[256];
+
+BOOL test1()
+{
+
+
+ /* Test 1 */
+ wsprintf(buf, "foo %s", "bar");
+ if (memcmp(buf, "foo bar", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 1) Failed. The correct string is "
+ "'foo bar' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ /* Test 2 */
+ wsprintf(buf, "foo %hs", "bar");
+ if (memcmp(buf, "foo bar", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 2) Failed. The correct string is "
+ "'foo bar' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+
+ /* Test 3 */
+ wsprintf(buf, "foo %5s", "bar");
+ if (memcmp(buf, "foo bar", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 3) Failed. The correct string is "
+ "'foo bar' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ /* Test 4 */
+ wsprintf(buf, "foo %.2s", "bar");
+ if (memcmp(buf, "foo ba", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 4) Failed. The correct string is "
+ "'foo ba' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ /* Test 5 */
+ wsprintf(buf, "foo %5.2s", "bar");
+ if (memcmp(buf, "foo ba", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 5) Failed. The correct string is "
+ "'foo ba' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ /* Test 6 */
+ wsprintf(buf, "foo %-5s", "bar");
+ if (memcmp(buf, "foo bar ", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 6) Failed. The correct string is "
+ "'foo bar' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ /* Test 7 */
+ wsprintf(buf, "foo %05s", "bar");
+ if (memcmp(buf, "foo 00bar", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 7) Failed. The correct string is "
+ "'foo 00bar' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+ return PASS;
+}
+
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ if(test1())
+ {
+ Fail("%s '%s'\n",ErrorMessage,BadResult);
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test2/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test2/testinfo.dat
new file mode 100644
index 0000000000..32e51df28b
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test2/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = wsprintfA
+Name = Positive test of wsprintfA
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test the %s and %ls formatters with various flags.
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test3/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test3/CMakeLists.txt
new file mode 100644
index 0000000000..8043ccd60b
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_wsprintfa_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wsprintfa_test3 coreclrpal)
+
+target_link_libraries(paltest_wsprintfa_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test3/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test3/test.c
new file mode 100644
index 0000000000..bb598d9d63
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test3/test.c
@@ -0,0 +1,121 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for wsprintfA() function
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with strlen */
+
+char * ErrorMessage;
+char buf[256];
+
+BOOL test1()
+{
+
+ /* Test 1 */
+ wsprintf(buf, "foo %S", convert("bar"));
+ if (memcmp(buf, "foo bar", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 1) Failed. The correct string is "
+ "'foo bar' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 2 */
+ wsprintf(buf, "foo %hS", "bar");
+ if (memcmp(buf, "foo bar", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 2) Failed. The correct string is "
+ "'foo bar' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 3 */
+ wsprintf(buf, "foo %lS", convert("bar"));
+ if (memcmp(buf, "foo bar", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 3) Failed. The correct string is '"
+ "foo bar' and the result returned was ";
+ return FAIL;
+ }
+
+
+ /* Test 4 */
+ wsprintf(buf, "foo %5S", convert("bar"));
+ if (memcmp(buf, "foo bar", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 4) Failed. The correct string is "
+ "'foo bar' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 5 */
+ wsprintf(buf, "foo %.2S", convert("bar"));
+ if (memcmp(buf, "foo ba", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 5) Failed. The correct string is "
+ "'foo ba' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 6 */
+ wsprintf(buf, "foo %5.2S", convert("bar"));
+ if (memcmp(buf, "foo ba", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 6) Failed. The correct string is "
+ "'foo ba' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 7 */
+ wsprintf(buf, "foo %-5S", convert("bar"));
+ if (memcmp(buf, "foo bar ", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 7) Failed. The correct string is "
+ "'foo bar ' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 8 */
+ wsprintf(buf, "foo %05S", convert("bar"));
+ if (memcmp(buf, "foo 00bar", strlen(buf) + 1) != 0) {
+ ErrorMessage = "ERROR: (Test 8) Failed. The correct string is "
+ "'foo 00bar' and the result returned was ";
+ return FAIL;
+ }
+ return PASS;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ if(test1()) {
+ Fail("%s '%s'\n",ErrorMessage,buf);
+
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test3/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test3/testinfo.dat
new file mode 100644
index 0000000000..0660aa17a3
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test3/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = wsprintfA
+Name = Positive test of wsprintfA
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test the %S and wide characters in general.
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test6/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test6/CMakeLists.txt
new file mode 100644
index 0000000000..6a5caf95c2
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_wsprintfa_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wsprintfa_test6 coreclrpal)
+
+target_link_libraries(paltest_wsprintfa_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test6/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test6/test.c
new file mode 100644
index 0000000000..08d97f467a
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test6/test.c
@@ -0,0 +1,114 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for wsprintfA() function
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with strlen */
+
+char * ErrorMessage;
+char buf[256];
+
+BOOL test1()
+{
+ WCHAR wc = 'c';
+
+ /* Test 1 */
+ wsprintf(buf, "foo %c", 'b');
+ if (memcmp(buf, "foo b", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 1) Failed. The correct string is "
+ "'foo b' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 2 */
+ wsprintf(buf, "foo %hc", 'b');
+ if (memcmp(buf, "foo b", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 2) Failed. The correct string is "
+ "'foo b' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 3 */
+ wsprintf(buf, "foo %lc", wc);
+ if (memcmp(buf, "foo c", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 3) Failed. The correct string is "
+ "'foo c' and the result returned was ";
+ return FAIL;
+ }
+
+
+ /* Test 4 */
+ wsprintf(buf, "foo %5c", 'b');
+ if (memcmp(buf, "foo b", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 4) Failed. The correct string is "
+ "'foo bar' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 5 */
+ wsprintf(buf, "foo %-5c", 'b');
+ if (memcmp(buf, "foo b ", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 5) Failed. The correct string is "
+ "'foo b ' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 6 */
+ wsprintf(buf, "foo %05c", 'b');
+ if (memcmp(buf, "foo 0000b", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 6) Failed. The correct string is "
+ "'foo 0000b' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 7 */
+ wsprintf(buf, "foo %#c", 'b');
+ if (memcmp(buf, "foo b", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 7) Failed. The correct string is "
+ "'foo b' and the result returned was ";
+ return FAIL;
+ }
+ return PASS;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ if(test1())
+ {
+ Fail("%s '%s'\n",ErrorMessage,buf);
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test6/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test6/testinfo.dat
new file mode 100644
index 0000000000..31b0f667b6
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test6/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = wsprintfA
+Name = Positive test of wsprintfA
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test the %c formatter.
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test7/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test7/CMakeLists.txt
new file mode 100644
index 0000000000..0885f0f21e
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test7/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_wsprintfa_test7
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wsprintfa_test7 coreclrpal)
+
+target_link_libraries(paltest_wsprintfa_test7
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test7/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test7/test.c
new file mode 100644
index 0000000000..6d380efaa9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test7/test.c
@@ -0,0 +1,112 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for wsprintfA() function
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with strlen */
+
+char * ErrorMessage;
+char buf[256];
+
+BOOL test1()
+{
+ WCHAR wb = 'b';
+
+ /* Test 1 */
+ wsprintf(buf, "foo %C", wb);
+ if (memcmp(buf, "foo b", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 1) Failed. The correct string is "
+ "'foo b' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 2 */
+ wsprintf(buf, "foo %hC", wb);
+ if (memcmp(buf, "foo b", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 2) Failed. The correct string is "
+ "'foo b' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 3 */
+ wsprintf(buf, "foo %lC", 'c');
+ if (memcmp(buf, "foo c", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 3) Failed. The correct string is "
+ "'foo c' and the result returned was ";
+ return FAIL;
+ }
+
+
+ /* Test 4 */
+ wsprintf(buf, "foo %5C", wb);
+ if (memcmp(buf, "foo b", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 4) Failed. The correct string is "
+ "'foo b' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 5 */
+ wsprintf(buf, "foo %-5C", wb);
+ if (memcmp(buf, "foo b ", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 5) Failed. The correct string is "
+ "'foo b ' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 6 */
+ wsprintf(buf, "foo %05C", wb);
+ if (memcmp(buf, "foo 0000b", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 6) Failed. The correct string is "
+ "'foo 0000b' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 7 */
+ wsprintf(buf, "foo %#C", wb);
+ if (memcmp(buf, "foo b", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 7) Failed. The correct string is "
+ "'foo b' and the result returned was ";
+ return FAIL;
+ }
+ return PASS;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ if(test1())
+ {
+ Fail("%s '%s'\n",ErrorMessage,buf);
+
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test7/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test7/testinfo.dat
new file mode 100644
index 0000000000..31b0f667b6
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test7/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = wsprintfA
+Name = Positive test of wsprintfA
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test the %c formatter.
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test8/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test8/CMakeLists.txt
new file mode 100644
index 0000000000..3c4b5ed36e
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test8/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_wsprintfa_test8
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wsprintfa_test8 coreclrpal)
+
+target_link_libraries(paltest_wsprintfa_test8
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test8/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test8/test.c
new file mode 100644
index 0000000000..7367461544
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test8/test.c
@@ -0,0 +1,120 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for wsprintfA() function
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with strlen */
+
+char * ErrorMessage;
+char buf[256];
+
+BOOL test1()
+{
+ int pos = 42;
+
+ /* Test 1 */
+ wsprintf(buf, "foo %d", pos);
+ if (memcmp(buf, "foo 42", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 1) Failed. The correct string is "
+ "'foo 42' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 2 */
+ wsprintf(buf, "foo %ld", 0xFFFF);
+ if (memcmp(buf, "foo 65535", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 2) Failed. The correct string is "
+ "'foo 65535' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 3 */
+ wsprintf(buf, "foo %3d", pos);
+ if (memcmp(buf, "foo 42", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 3) Failed. The correct string is "
+ "'foo 42' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 4 */
+ wsprintf(buf, "foo %-3d", pos);
+ if (memcmp(buf, "foo 42 ", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 4) Failed. The correct string is "
+ "'foo 42 ' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 5 */
+ wsprintf(buf, "foo %.1d", pos);
+ if (memcmp(buf, "foo 42", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 5) Failed. The correct string is "
+ "'foo 42' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 6 */
+ wsprintf(buf, "foo %.3d", pos);
+ if (memcmp(buf, "foo 042", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 6) Failed. The correct string is "
+ "'foo 042' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 7 */
+ wsprintf(buf, "foo %03d", pos);
+ if (memcmp(buf, "foo 042", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 7) Failed. The correct string is "
+ "'foo 042' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 8 */
+ wsprintf(buf, "foo %#d", pos);
+ if (memcmp(buf, "foo 42", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 8) Failed. The correct string is "
+ "'foo 42' and the result returned was ";
+ return FAIL;
+ }
+ return PASS;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ if(test1())
+ {
+ Fail("%s '%s'\n",ErrorMessage,buf);
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test8/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test8/testinfo.dat
new file mode 100644
index 0000000000..75f4fbf121
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test8/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = wsprintfA
+Name = Positive test of wsprintfA
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test the %d formatter.
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test9/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test9/CMakeLists.txt
new file mode 100644
index 0000000000..dcbb22ebb5
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test9/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_wsprintfa_test9
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wsprintfa_test9 coreclrpal)
+
+target_link_libraries(paltest_wsprintfa_test9
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test9/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test9/test.c
new file mode 100644
index 0000000000..9f123bcc6d
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test9/test.c
@@ -0,0 +1,122 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for wsprintfA() function
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with strlen */
+
+char * ErrorMessage;
+char buf[256];
+
+BOOL test1()
+{
+
+ int pos = 42;
+
+
+ /* Test 1 */
+ wsprintf(buf, "foo %i", pos);
+ if (memcmp(buf, "foo 42", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 1) Failed. The correct string is "
+ "'foo 42' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 2 */
+ wsprintf(buf, "foo %li", 0xFFFF);
+ if (memcmp(buf, "foo 65535", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 2) Failed. The correct string is "
+ "'foo 65535' and the result returned was ";
+ return FAIL;
+ }
+
+
+ /* Test 3 */
+ wsprintf(buf, "foo %3i", pos);
+ if (memcmp(buf, "foo 42", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 3) Failed. The correct string is "
+ "'foo 42' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 4 */
+ wsprintf(buf, "foo %-3i", pos);
+ if (memcmp(buf, "foo 42 ", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 4) Failed. The correct string is "
+ "'foo 42 ' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 5 */
+ wsprintf(buf, "foo %.1i", pos);
+ if (memcmp(buf, "foo 42", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 5) Failed. The correct string is "
+ "'foo 42' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 6 */
+ wsprintf(buf, "foo %.3i", pos);
+ if (memcmp(buf, "foo 042", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 6) Failed. The correct string is "
+ "'foo 042' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 7 */
+ wsprintf(buf, "foo %03i", pos);
+ if (memcmp(buf, "foo 042", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 7) Failed. The correct string is "
+ "'foo 042' and the result returned was ";
+ return FAIL;
+ }
+
+ /* Test 8 */
+ wsprintf(buf, "foo %#i", pos);
+ if (memcmp(buf, "foo 42", strlen(buf) + 1) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 8) Failed. The correct string is "
+ "'foo 42' and the result returned was ";
+ return FAIL;
+ }
+
+ return PASS;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ if(test1())
+ {
+ Fail("%s '%s'\n",ErrorMessage,buf);
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test9/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test9/testinfo.dat
new file mode 100644
index 0000000000..2a3689e4dd
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test9/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = wsprintfA
+Name = Positive test of wsprintfA
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test the %i formatter.
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfW/CMakeLists.txt
new file mode 100644
index 0000000000..f40d4151d6
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfW/CMakeLists.txt
@@ -0,0 +1,13 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test11)
+add_subdirectory(test12)
+add_subdirectory(test13)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test6)
+add_subdirectory(test7)
+add_subdirectory(test8)
+add_subdirectory(test9)
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..b1c0fb3d0b
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_wsprintfw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wsprintfw_test1 coreclrpal)
+
+target_link_libraries(paltest_wsprintfw_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test1/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test1/test.c
new file mode 100644
index 0000000000..700cb134bd
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test1/test.c
@@ -0,0 +1,64 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for wsprintfW() function
+**
+**
+**=========================================================*/
+
+#define UNICODE
+#include <palsuite.h>
+
+
+char * ErrorMessage = NULL;
+WCHAR * BadResult = NULL;
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with strlen */
+
+
+BOOL test1()
+{
+ char checkstr[] = "hello world";
+
+ WCHAR buf[256];
+
+ /* Test a simple string */
+ wsprintf(buf, convert("hello world"));
+
+ /* Error message */
+ ErrorMessage = "ERROR: (Test 1) Failed on 'hello world' test. "
+ "The correct string is 'hello world' and the result returned was ";
+ BadResult = buf;
+
+ return (memcmp(convert(checkstr), buf, wcslen(buf)*2+2) != 0);
+}
+
+int __cdecl main(int argc, char *argv[]) {
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ if(test1()) {
+ Fail("%s '%s'\n",ErrorMessage,convertC(BadResult));
+
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test1/testinfo.dat
new file mode 100644
index 0000000000..f36aced027
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = wsprintfW
+Name = Positive test of wsprintfW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test the very basic functionality of wsprintfW.
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test11/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test11/CMakeLists.txt
new file mode 100644
index 0000000000..a5d73ed413
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test11/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_wsprintfw_test11
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wsprintfw_test11 coreclrpal)
+
+target_link_libraries(paltest_wsprintfw_test11
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test11/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test11/test.c
new file mode 100644
index 0000000000..dc1e7a7758
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test11/test.c
@@ -0,0 +1,139 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for wsprintfW() function
+**
+**
+**=========================================================*/
+
+#define UNICODE
+#include <palsuite.h>
+
+
+
+char * ErrorMessage = NULL;
+WCHAR * BadResult = NULL;
+WCHAR buf[256];
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with strlen */
+
+
+BOOL test1()
+{
+
+ int pos = 42;
+
+ wsprintf(buf, convert("foo %u"), pos);
+ if (memcmp(buf, convert("foo 42"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 1) Failed. The correct string is"
+ " 'foo 42' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %lu"), 0xFFFF);
+ if (memcmp(buf, convert("foo 65535"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 2) Failed. The correct string is"
+ " 'foo 65535' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %hu"), 0xFFFF);
+ if (memcmp(buf, convert("foo 65535"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 3) Failed. The correct string is"
+ " 'foo 65535' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %3u"), pos);
+ if (memcmp(buf, convert("foo 42"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 4) Failed. The correct string is"
+ " 'foo 42' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %-3u"), pos);
+ if (memcmp(buf, convert("foo 42 "), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 5) Failed. The correct string is"
+ " 'foo 42 ' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %.1u"), pos);
+ if (memcmp(buf, convert("foo 42"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 6) Failed. The correct string is"
+ " 'foo 42' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %.3u"), pos);
+ if (memcmp(buf, convert("foo 042"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 7) Failed. The correct string is"
+ " 'foo 042' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %03u"), pos);
+ if (memcmp(buf, convert("foo 042"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 8) Failed. The correct string is"
+ " 'foo 042' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %#u"), pos);
+ if (memcmp(buf, convert("foo 42"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 9) Failed. The correct string is"
+ " 'foo 42' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ return PASS;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ if(test1())
+ {
+ Fail("%s '%s'\n",ErrorMessage,convertC(BadResult));
+
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test11/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test11/testinfo.dat
new file mode 100644
index 0000000000..bb85d63f1b
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test11/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = wsprintfW
+Name = Positive test of wsprintfW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test %u formatter with wsprintfW.
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test12/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test12/CMakeLists.txt
new file mode 100644
index 0000000000..3811fb07c9
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test12/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_wsprintfw_test12
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wsprintfw_test12 coreclrpal)
+
+target_link_libraries(paltest_wsprintfw_test12
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test12/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test12/test.c
new file mode 100644
index 0000000000..6ba456b3bc
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test12/test.c
@@ -0,0 +1,128 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for wsprintfW() function
+**
+**
+**=========================================================*/
+
+#define UNICODE
+#include <palsuite.h>
+
+
+char * ErrorMessage = NULL;
+WCHAR * BadResult = NULL;
+WCHAR buf[256];
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with strlen */
+
+BOOL test1()
+{
+ int pos = 0x1234ab;
+
+ wsprintf(buf, convert("foo %x"), pos);
+ if (memcmp(buf, convert("foo 1234ab"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 1) Failed. The correct string is"
+ " 'foo 1234ab' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %lx"), pos);
+ if (memcmp(buf, convert("foo 1234ab"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 2) Failed. The correct string is"
+ " 'foo 1234ab' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %7x"), pos);
+ if (memcmp(buf, convert("foo 1234ab"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 3) Failed. The correct string is"
+ " 'foo 1234ab' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %-7x"), pos);
+ if (memcmp(buf, convert("foo 1234ab "), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 4) Failed. The correct string is"
+ " 'foo 1234ab ' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %.1x"), pos);
+ if (memcmp(buf, convert("foo 1234ab"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 5) Failed. The correct string is"
+ " 'foo 1234ab' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %.7x"), pos);
+ if (memcmp(buf, convert("foo 01234ab"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 6) Failed. The correct string is"
+ " 'foo 01234ab' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %07x"), pos);
+ if (memcmp(buf, convert("foo 01234ab"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 7) Failed. The correct string is"
+ " 'foo 01234ab' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %#x"), pos);
+ if (memcmp(buf, convert("foo 0x1234ab"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 8) Failed. The correct string is"
+ " 'foo 0x1234ab' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ return PASS;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ if(test1())
+ {
+ Fail("%s '%s'\n",ErrorMessage,convertC(BadResult));
+
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test12/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test12/testinfo.dat
new file mode 100644
index 0000000000..0d38a20bcc
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test12/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = wsprintfW
+Name = Positive test of wsprintfW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test %x formatter with wsprintfW.
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test13/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test13/CMakeLists.txt
new file mode 100644
index 0000000000..617abb854c
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test13/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_wsprintfw_test13
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wsprintfw_test13 coreclrpal)
+
+target_link_libraries(paltest_wsprintfw_test13
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test13/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test13/test.c
new file mode 100644
index 0000000000..dd0daae0a0
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test13/test.c
@@ -0,0 +1,126 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for wsprintfW() function
+**
+**
+**=========================================================*/
+
+#define UNICODE
+#include <palsuite.h>
+
+char * ErrorMessage = NULL;
+WCHAR * BadResult = NULL;
+WCHAR buf[256];
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with strlen */
+
+BOOL test1()
+{
+ int pos = 0x1234ab;
+
+ wsprintf(buf, convert("foo %X"), pos);
+ if (memcmp(buf, convert("foo 1234AB"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 1) Failed. The correct string is"
+ " 'foo 1234AB' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %lX"), pos);
+ if (memcmp(buf, convert("foo 1234AB"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 2) Failed. The correct string is"
+ " 'foo 1234AB' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %7X"), pos);
+ if (memcmp(buf, convert("foo 1234AB"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 3) Failed. The correct string is"
+ " 'foo 1234AB' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %-7X"), pos);
+ if (memcmp(buf, convert("foo 1234AB "), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 4) Failed. The correct string is"
+ " 'foo 1234AB ' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %.1X"), pos);
+ if (memcmp(buf, convert("foo 1234AB"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 5) Failed. The correct string is"
+ " 'foo 1234AB' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %.7X"), pos);
+ if (memcmp(buf, convert("foo 01234AB"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 6) Failed. The correct string is"
+ " 'foo 01234AB' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %07X"), pos);
+ if (memcmp(buf, convert("foo 01234AB"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 7) Failed. The correct string is"
+ " 'foo 01234AB' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %#X"), pos);
+ if (memcmp(buf, convert("foo 0X1234AB"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 8) Failed. The correct string is"
+ " 'foo 0X1234AB' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ return PASS;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ if(test1())
+ {
+ Fail("%s '%s'\n",ErrorMessage,convertC(BadResult));
+
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test13/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test13/testinfo.dat
new file mode 100644
index 0000000000..c16a43f7b7
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test13/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = wsprintfW
+Name = Positive test of wsprintfW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test %X formatter with wsprintfW.
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test2/CMakeLists.txt
new file mode 100644
index 0000000000..00b26da2e6
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_wsprintfw_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wsprintfw_test2 coreclrpal)
+
+target_link_libraries(paltest_wsprintfw_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test2/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test2/test.c
new file mode 100644
index 0000000000..f25ab6c2f4
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test2/test.c
@@ -0,0 +1,108 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for wsprintfW() function
+**
+**
+**=========================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+
+char * ErrorMessage = NULL;
+WCHAR * BadResult = NULL;
+WCHAR buf[256];
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with strlen */
+
+
+BOOL test1()
+{
+
+ wsprintf(buf, convert("foo %s"), convert("bar"));
+ if (memcmp(buf, convert("foo bar"), wcslen(buf)*2+2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 1) Failed. The correct string is 'foo bar'"
+ " and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %ls"), convert("bar"));
+ if (memcmp(buf, convert("foo bar"), wcslen(buf)*2 + 2) != 0){
+ ErrorMessage = "ERROR: (Test 2) Failed. The correct string is 'foo bar'"
+ " and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %5s"), convert("bar"));
+ if (memcmp(buf, convert("foo bar"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 3) Failed. The correct string is"
+ " 'foo bar' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+ wsprintf(buf, convert("foo %.2s"), convert("bar"));
+ if (memcmp(buf, convert("foo ba"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 4) Failed. The correct string is 'foo ba'"
+ " and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+ wsprintf(buf, convert("foo %5.2s"), convert("bar"));
+ if (memcmp(buf, convert("foo ba"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 5) Failed. The correct string is"
+ " 'foo ba' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+ wsprintf(buf, convert("foo %-5s"), convert("bar"));
+ if (memcmp(buf, convert("foo bar "), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 6) Failed. The correct string is"
+ " 'foo bar ' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+ wsprintf(buf, convert("foo %05s"), convert("bar"));
+ if (memcmp(buf, convert("foo 00bar"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 7) Failed. The correct string is"
+ " 'foo 00bar' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ return PASS;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ if(test1())
+ {
+ Fail("%s '%s'\n",ErrorMessage,convertC(BadResult));
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test2/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test2/testinfo.dat
new file mode 100644
index 0000000000..a2a7bb2d39
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test2/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = wsprintfW
+Name = Positive test of wsprintfW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test %s formatter with wsprintfW.
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test3/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test3/CMakeLists.txt
new file mode 100644
index 0000000000..25c6185d12
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_wsprintfw_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wsprintfw_test3 coreclrpal)
+
+target_link_libraries(paltest_wsprintfw_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test3/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test3/test.c
new file mode 100644
index 0000000000..a52d617e47
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test3/test.c
@@ -0,0 +1,127 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for wsprintfW() function
+**
+**
+**=========================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+
+
+char * ErrorMessage = NULL;
+WCHAR * BadResult = NULL;
+WCHAR buf[256];
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with strlen */
+
+
+BOOL test1()
+{
+
+ wsprintf(buf, convert("foo %S"), "bar");
+ if (memcmp(buf, convert("foo bar"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 1) Failed. The correct string is"
+ " 'foo bar' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %hS"), "bar");
+ if (memcmp(buf, convert("foo bar"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 2) Failed. The correct string is"
+ " 'foo bar' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %lS"), convert("bar"));
+ if (memcmp(buf, convert("foo bar"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 3) Failed. The correct string is"
+ " 'foo bar' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %5S"), "bar");
+ if (memcmp(buf, convert("foo bar"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 4) Failed. The correct string is"
+ " 'foo bar' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %.2S"), "bar");
+ if (memcmp(buf, convert("foo ba"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 5) Failed. The correct string is"
+ " 'foo ba' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %5.2S"), "bar");
+ if (memcmp(buf, convert("foo ba"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 6) Failed. The correct string is"
+ " 'foo ba' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %-5S"), "bar");
+ if (memcmp(buf, convert("foo bar "), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 7) Failed. The correct string is"
+ " 'foo bar ' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %05S"), "bar");
+ if (memcmp(buf, convert("foo 00bar"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 8) Failed. The correct string is"
+ " 'foo 00bar' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ return PASS;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ if(test1())
+ {
+ Fail("%s '%s'\n",ErrorMessage,convertC(BadResult));
+
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test3/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test3/testinfo.dat
new file mode 100644
index 0000000000..46b7b7459d
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test3/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = wsprintfW
+Name = Positive test of wsprintfW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test %S formatter with wsprintfW.
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test6/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test6/CMakeLists.txt
new file mode 100644
index 0000000000..c63a4d5c82
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_wsprintfw_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wsprintfw_test6 coreclrpal)
+
+target_link_libraries(paltest_wsprintfw_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test6/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test6/test.c
new file mode 100644
index 0000000000..513f1f7941
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test6/test.c
@@ -0,0 +1,115 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for wsprintfW() function
+**
+**
+**=========================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+
+char * ErrorMessage = NULL;
+WCHAR * BadResult = NULL;
+WCHAR buf[256];
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with strlen */
+
+BOOL test1()
+{
+ WCHAR wc = 'b';
+
+ wsprintf(buf, convert("foo %c"), wc);
+ if (memcmp(buf, convert("foo b"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 1) Failed. The correct string is"
+ " 'foo b' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %hc"), wc);
+ if (memcmp(buf, convert("foo b"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 2) Failed. The correct string is 'foo b'"
+ " and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %lc"), wc);
+ if (memcmp(buf, convert("foo b"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 3) Failed. The correct string is 'foo b'"
+ " and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %5c"), wc);
+ if (memcmp(buf, convert("foo b"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 4) Failed. The correct string is"
+ " 'foo b' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %-5c"), wc);
+ if (memcmp(buf, convert("foo b "), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 5) Failed. The correct string is"
+ " 'foo b ' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %05c"), wc);
+ if (memcmp(buf, convert("foo 0000b"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 6) Failed. The correct string is"
+ " 'foo 0000b' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %#c"), wc);
+ if (memcmp(buf, convert("foo b"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 7) Failed. The correct string is 'foo b'"
+ " and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+ return PASS;
+}
+int __cdecl main(int argc, char *argv[])
+{
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ if(test1())
+ {
+ Fail("%s '%s'\n",ErrorMessage,convertC(BadResult));
+
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test6/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test6/testinfo.dat
new file mode 100644
index 0000000000..627b76f602
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test6/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = wsprintfW
+Name = Positive test of wsprintfW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test %c formatter with wsprintfW.
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test7/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test7/CMakeLists.txt
new file mode 100644
index 0000000000..25e43107ff
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test7/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_wsprintfw_test7
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wsprintfw_test7 coreclrpal)
+
+target_link_libraries(paltest_wsprintfw_test7
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test7/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test7/test.c
new file mode 100644
index 0000000000..99e73b13ce
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test7/test.c
@@ -0,0 +1,117 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for wsprintfW() function
+**
+**
+**=========================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+
+
+char * ErrorMessage = NULL;
+WCHAR * BadResult = NULL;
+WCHAR buf[256];
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with strlen */
+
+
+BOOL test1()
+{
+ WCHAR wb = 'b';
+
+ wsprintf(buf, convert("foo %C"), 'b');
+ if (memcmp(buf, convert("foo b"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 1) Failed. The correct string is"
+ " 'foo b' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %hC"), 'b');
+ if (memcmp(buf, convert("foo b"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 2) Failed. The correct string is"
+ " 'foo b' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %lC"), wb);
+ if (memcmp(buf, convert("foo b"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 3) Failed. The correct string is"
+ " 'foo b' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %5C"), 'b');
+ if (memcmp(buf, convert("foo b"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 4) Failed. The correct string is"
+ " 'foo b' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %-5C"), 'b');
+ if (memcmp(buf, convert("foo b "), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 5) Failed. The correct string is"
+ " 'foo b ' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %05C"), 'b');
+ if (memcmp(buf, convert("foo 0000b"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 6) Failed. The correct string is"
+ " 'foo 0000b' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %#C"), 'b');
+ if (memcmp(buf, convert("foo b"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 7) Failed. The correct string is"
+ " 'foo b' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+ return PASS;
+}
+int __cdecl main(int argc, char *argv[])
+{
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ if(test1())
+ {
+ Fail("%s '%s'\n",ErrorMessage,convertC(BadResult));
+
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test7/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test7/testinfo.dat
new file mode 100644
index 0000000000..ffcb47a37f
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test7/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = wsprintfW
+Name = Positive test of wsprintfW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test %C formatter with wsprintfW.
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test8/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test8/CMakeLists.txt
new file mode 100644
index 0000000000..a6478a2af0
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test8/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_wsprintfw_test8
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wsprintfw_test8 coreclrpal)
+
+target_link_libraries(paltest_wsprintfw_test8
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test8/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test8/test.c
new file mode 100644
index 0000000000..63c296eb22
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test8/test.c
@@ -0,0 +1,128 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for wsprintfW() function
+**
+**
+**=========================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+
+
+char * ErrorMessage = NULL;
+WCHAR * BadResult = NULL;
+WCHAR buf[256];
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with strlen */
+
+
+BOOL test1()
+{
+ int pos = 42;
+
+ wsprintf(buf, convert("foo %d"), pos);
+ if (memcmp(buf, convert("foo 42"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 1) Failed. The correct string is"
+ " 'foo 42' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %ld"), 0xFFFF);
+ if (memcmp(buf, convert("foo 65535"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 2) Failed. The correct string is"
+ " 'foo 65535' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %3d"), pos);
+ if (memcmp(buf, convert("foo 42"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 3) Failed. The correct string is"
+ " 'foo 42' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %-3d"), pos);
+ if (memcmp(buf, convert("foo 42 "), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 4) Failed. The correct string is"
+ " 'foo 42 ' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %.1d"), pos);
+ if (memcmp(buf, convert("foo 42"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 5) Failed. The correct string is"
+ " 'foo 42' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %.3d"), pos);
+ if (memcmp(buf, convert("foo 042"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 6) Failed. The correct string is"
+ " 'foo 042' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %03d"), pos);
+ if (memcmp(buf, convert("foo 042"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 7) Failed. The correct string is"
+ " 'foo 042' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %#d"), pos);
+ if (memcmp(buf, convert("foo 42"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 8) Failed. The correct string is"
+ " 'foo 42' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ return PASS;
+}
+int __cdecl main(int argc, char *argv[])
+{
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ if(test1())
+ {
+ Fail("%s '%s'\n",ErrorMessage,convertC(BadResult));
+
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test8/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test8/testinfo.dat
new file mode 100644
index 0000000000..4238671918
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test8/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = wsprintfW
+Name = Positive test of wsprintfW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test %d formatter with wsprintfW.
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test9/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test9/CMakeLists.txt
new file mode 100644
index 0000000000..e09867b1a7
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test9/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_wsprintfw_test9
+ ${SOURCES}
+)
+
+add_dependencies(paltest_wsprintfw_test9 coreclrpal)
+
+target_link_libraries(paltest_wsprintfw_test9
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test9/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test9/test.c
new file mode 100644
index 0000000000..0a49d9c2c5
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test9/test.c
@@ -0,0 +1,128 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test.c
+**
+** Purpose: Test for wsprintfW() function
+**
+**
+**=========================================================*/
+
+#define UNICODE
+#include <palsuite.h>
+
+
+char * ErrorMessage = NULL;
+WCHAR * BadResult = NULL;
+WCHAR buf[256];
+
+/* memcmp is used to verify the results, so this test is dependent on it. */
+/* ditto with strlen */
+
+
+BOOL test1()
+{
+ int pos = 42;
+
+ wsprintf(buf, convert("foo %i"), pos);
+ if (memcmp(buf, convert("foo 42"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 1) Failed. The correct string is"
+ " 'foo 42' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %li"), 0xFFFF);
+ if (memcmp(buf, convert("foo 65535"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 2) Failed. The correct string is"
+ " 'foo 65535' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %3i"), pos);
+ if (memcmp(buf, convert("foo 42"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 3) Failed. The correct string is"
+ " 'foo 42' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %-3i"), pos);
+ if (memcmp(buf, convert("foo 42 "), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 4) Failed. The correct string is"
+ " 'foo 42 ' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %.1i"), pos);
+ if (memcmp(buf, convert("foo 42"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 5) Failed. The correct string is"
+ " 'foo 42' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %.3i"), pos);
+ if (memcmp(buf, convert("foo 042"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 6) Failed. The correct string is"
+ " 'foo 042' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %03i"), pos);
+ if (memcmp(buf, convert("foo 042"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 7) Failed. The correct string is"
+ " 'foo 042' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ wsprintf(buf, convert("foo %#i"), pos);
+ if (memcmp(buf, convert("foo 42"), wcslen(buf)*2 + 2) != 0)
+ {
+ ErrorMessage = "ERROR: (Test 8) Failed. The correct string is"
+ " 'foo 42' and the result returned was ";
+ BadResult = buf;
+ return FAIL;
+ }
+
+ return PASS;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ if(test1())
+ {
+ Fail("%s '%s'\n",ErrorMessage,convertC(BadResult));
+
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test9/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test9/testinfo.dat
new file mode 100644
index 0000000000..3006aa87bc
--- /dev/null
+++ b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test9/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Miscellaneous
+Function = wsprintfW
+Name = Positive test of wsprintfW
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Test %i formatter with wsprintfW.
+
+
diff --git a/src/pal/tests/palsuite/pal_specific/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/CMakeLists.txt
new file mode 100644
index 0000000000..aaf1f27182
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/CMakeLists.txt
@@ -0,0 +1,13 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+# TODO: make these tests compile
+# add_subdirectory(PAL_get_stderr)
+# add_subdirectory(PAL_get_stdin)
+# add_subdirectory(PAL_get_stdout)
+
+add_subdirectory(pal_entrypoint)
+add_subdirectory(PAL_errno)
+add_subdirectory(PAL_GetPALDirectoryW)
+add_subdirectory(pal_initializedebug)
+add_subdirectory(PAL_Initialize_Terminate)
+
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..bf1d3a91e7
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ PAL_GetPALDirectoryW.c
+)
+
+add_executable(paltest_pal_getpaldirectoryw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_getpaldirectoryw_test1 coreclrpal)
+
+target_link_libraries(paltest_pal_getpaldirectoryw_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/PAL_GetPALDirectoryW.c b/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/PAL_GetPALDirectoryW.c
new file mode 100644
index 0000000000..2c67aa4954
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/PAL_GetPALDirectoryW.c
@@ -0,0 +1,78 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: pal_getpaldirectoryw.c
+**
+** Purpose: Positive test the PAL_GetPALDirectoryW API.
+** Call this API to retrieve a fully-qualified
+** directory name where the PAL DLL is loaded from.
+**
+**
+**============================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ BOOL bValue;
+ DWORD dwFileAttribute;
+ WCHAR *wpDirectoryName = NULL;
+ char *pDirectoryName = NULL;
+
+ /*Initialize the PAL environment*/
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+ /*allocate momory to store the directory name*/
+ wpDirectoryName = malloc(MAX_PATH*sizeof(WCHAR));
+ if(NULL == wpDirectoryName)
+ {
+ Fail("\nFailed to allocate memory for storing directory name!\n");
+ }
+
+ UINT size = MAX_PATH;
+ /*retrieve the machine configuration directory*/
+ bValue = PAL_GetPALDirectoryW(wpDirectoryName, &size);
+ if(FALSE == bValue)
+ {
+ free(wpDirectoryName);
+ Fail("Failed to call PAL_GetPALDirectoryW API, "
+ "error code =%u\n", GetLastError());
+ }
+
+
+ /*convert wide char string to a standard one*/
+ pDirectoryName = convertC(wpDirectoryName);
+ if(0 == strlen(pDirectoryName))
+ {
+ free(wpDirectoryName);
+ free(pDirectoryName);
+ Fail("The retrieved directory name string is empty!\n");
+ }
+
+ /*free the memory*/
+ free(pDirectoryName);
+
+ /*retrieve the attribute of a file or directory*/
+ dwFileAttribute = GetFileAttributesW(wpDirectoryName);
+
+ /*free the memory*/
+ free(wpDirectoryName);
+
+ /*check if the attribute indicates a directory*/
+ if(FILE_ATTRIBUTE_DIRECTORY !=
+ (dwFileAttribute & FILE_ATTRIBUTE_DIRECTORY))
+ {
+ Fail("The retrieved directory name is not a valid directory!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/testinfo.dat b/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/testinfo.dat
new file mode 100644
index 0000000000..dca92b0462
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = PAL_Specific
+Function = PAL_GetPALDirectoryW
+Name = Positive test for PAL_GetPALDirectoryW to retrieve fully-qualified directory name.
+TYPE = DEFAULT
+EXE1 = pal_getpaldirectoryw
+Description
+=Retrieve the fully-qualified directory name where the PAL DLL is loaded from
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..e8d3c40565
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ PAL_GetUserTempDirectoryW.c
+)
+
+add_executable(paltest_pal_getusertempdirectoryw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_getusertempdirectoryw_test1 coreclrpal)
+
+target_link_libraries(paltest_pal_getusertempdirectoryw_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/PAL_GetUserTempDirectoryW.c b/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/PAL_GetUserTempDirectoryW.c
new file mode 100644
index 0000000000..65cc426c74
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/PAL_GetUserTempDirectoryW.c
@@ -0,0 +1,58 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: pal_getusertempdirectoryw.c
+**
+** Purpose: Positive test the PAL_GetUserTempDirectoryW API.
+** Call PAL_GetUserTempDirectoryW to retrieve the user
+** temp directory.
+**
+**
+**============================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+#define DIRECTORYLENGTH 1024
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ DWORD dwFileAttribute;
+ DWORD cch = DIRECTORYLENGTH;
+ WCHAR wDirectoryName[DIRECTORYLENGTH];
+
+ //Initialize the PAL environment
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ ExitProcess(FAIL);
+ }
+
+ //retrieve the user temp directory
+ err = PAL_GetUserTempDirectory(ddtInstallationDependentDirectory, wDirectoryName, &cch);
+
+ if(0 == err || 0 == strlen(convertC(wDirectoryName)))
+ {
+ Fail("Failed to call PAL_GetUserTempDirectoryW API!\n");
+ }
+
+
+ //retrieve the attributes of a file or directory
+ dwFileAttribute = GetFileAttributesW(wDirectoryName);
+
+
+ //check if the retrieved attribute indicates a directory
+ if( FILE_ATTRIBUTE_DIRECTORY != (FILE_ATTRIBUTE_DIRECTORY & dwFileAttribute))
+ {
+ Fail("PAL_GetUserTempDirectoryW API returned a non-directory name!\n");
+ }
+
+ printf ("PAL_GetUserTempDirectoryW returns %S\n", wDirectoryName);
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/testinfo.dat b/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/testinfo.dat
new file mode 100644
index 0000000000..d530ca5fc7
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = pal_specific
+Function = PAL_GetUserTempDirectoryW
+Name = Positive test for PAL_GetUserTempDirectoryW API
+TYPE = DEFAULT
+EXE1 = pal_getusertempdirectoryw
+Description
+=Test the PAL_GetUserTempDirectoryW to retrieve the user temp
+=directory name
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/CMakeLists.txt
new file mode 100644
index 0000000000..416439d650
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ PAL_Initialize_Terminate.c
+)
+
+add_executable(paltest_pal_initialize_terminate_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_initialize_terminate_test1 coreclrpal)
+
+target_link_libraries(paltest_pal_initialize_terminate_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/PAL_Initialize_Terminate.c b/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/PAL_Initialize_Terminate.c
new file mode 100644
index 0000000000..29bb2c3b4f
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/PAL_Initialize_Terminate.c
@@ -0,0 +1,33 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: pal_initialize_terminate.c
+**
+** Purpose: Positive test the PAL_Initialize and PAL_Terminate API.
+** Call PAL_Initialize to initialize the PAL
+** environment and call PAL_Terminate to clean up the PAL
+** environment.
+**
+
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+
+ /* Initialize the PAL environment */
+ err = PAL_Initialize(argc, argv);
+
+ if(0 != err)
+ {
+ ExitProcess(1);
+ }
+
+ PAL_Terminate();
+ return 0;
+}
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/testinfo.dat b/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/testinfo.dat
new file mode 100644
index 0000000000..8ffe3bb7c7
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = PAL_Specific
+Function = PAL_Initialize and PAL_Terminate
+Name = Positive test for PAL_Initialize and PAL_Terminate
+TYPE = DEFAULT
+EXE1 = pal_initialize_terminate
+Description
+=Test the PAL_Initialize to initialize the PAL environment
+=Test the PAL_Terminate to clean up the PAL environment
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/CMakeLists.txt
new file mode 100644
index 0000000000..b7661fd240
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ pal_initialize_twice.c
+)
+
+add_executable(paltest_pal_initialize_terminate_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_initialize_terminate_test2 coreclrpal)
+
+target_link_libraries(paltest_pal_initialize_terminate_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/pal_initialize_twice.c b/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/pal_initialize_twice.c
new file mode 100644
index 0000000000..fc460bc1ad
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/pal_initialize_twice.c
@@ -0,0 +1,41 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: pal_initialize_twice.c
+**
+** Purpose: Positive test of PAL_Initialize and PAL_Terminate APIs.
+** Calls PAL_Initialize twice to ensure that doing so
+** will not cause unexpected failures in the PAL.
+** Calls PAL_Terminate twice to clean up the PAL.
+**
+
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ /* Initialize the PAL environment */
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Try calling PAL_Initialize again - should just increment the init_count. */
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ // Call terminate due to the first PAL initialization.
+ PAL_TerminateEx(FAIL);
+ return FAIL;
+ }
+
+ /* If both calls to PAL_Initialize succeed, then PAL_Terminate must be
+ called twice. The first call just decrements the init_count to 1. */
+
+ PAL_Terminate();
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/testinfo.dat b/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/testinfo.dat
new file mode 100644
index 0000000000..31ceaf054d
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = PAL_Specific
+Function = PAL_Initialize and PAL_Terminate
+Name = Positive test for calling PAL_Initialize twice
+TYPE = DEFAULT
+EXE1 = pal_initialize_twice
+Description
+=Test calling PAL_Initialize twice to initialize the PAL environment
+=and increment the init_count.
+=Test calling PAL_Terminate twice to decrement the init_count
+=and then clean up the PAL environment.
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/CMakeLists.txt
new file mode 100644
index 0000000000..37b29c0d6d
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2_neg)
+
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..2379694b24
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ PAL_RegisterLibraryW_UnregisterLibraryW.c
+)
+
+add_executable(paltest_pal_registerlibraryw_unregisterlibraryw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_registerlibraryw_unregisterlibraryw_test1 coreclrpal)
+
+target_link_libraries(paltest_pal_registerlibraryw_unregisterlibraryw_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/PAL_RegisterLibraryW_UnregisterLibraryW.c b/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/PAL_RegisterLibraryW_UnregisterLibraryW.c
new file mode 100644
index 0000000000..ff0d33879c
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/PAL_RegisterLibraryW_UnregisterLibraryW.c
@@ -0,0 +1,64 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: pal_registerlibrary_unregisterlibrary
+**
+** Purpose: Positive test the PAL_RegisterLibrary API and
+** PAL_UnRegisterLibrary.
+** Call PAL_RegisterLibrary to map a module into the calling
+** process address space and call PAL_UnRegisterLibrary
+** to unmap this module.
+**
+**
+**============================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ HMODULE ModuleHandle;
+ char ModuleName[64];
+ WCHAR *wpModuleName = NULL;
+ int err;
+
+ /*Initialize the PAL environment*/
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+ /*zero the buffer*/
+ memset(ModuleName,0,64);
+ sprintf(ModuleName, "%s", "rotor_pal");
+
+ /*convert a normal string to a wide one*/
+ wpModuleName = convert(ModuleName);
+
+ /*load a module*/
+ ModuleHandle = PAL_RegisterLibrary(wpModuleName);
+
+ /*free the memory*/
+ free(wpModuleName);
+
+ if(!ModuleHandle)
+ {
+ Fail("Failed to call PAL_RegisterLibrary API to map a module "
+ "into calling process, error code=%u!\n", GetLastError());
+ }
+
+ /*decrement the reference count of the loaded DLL*/
+ err = PAL_UnregisterLibrary(ModuleHandle);
+ if(0 == err)
+ {
+ Fail("\nFailed to call PAL_UnregisterLibrary API to "
+ "decrement the count of the loaded DLL module, "
+ "error code=%u!\n", GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/testinfo.dat b/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/testinfo.dat
new file mode 100644
index 0000000000..abbd28c238
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = pal_specific
+Function = PAL_RegisterLibraryW and PAL_UnregisterLibraryW API
+Name = Positive test PAL_RegisterLibraryW and PAL_UnregisterLibaryW API
+TYPE = DEFAULT
+EXE1 = pal_registerlibraryw_unregisterlibraryw
+Description
+=Test the PAL_RegisterLibraryW and PAL_UnregisterLibraryW to map an executable
+=module into calling process address space and unmap this module
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/CMakeLists.txt
new file mode 100644
index 0000000000..bbcb35933e
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ reg_unreg_libraryw_neg.c
+)
+
+add_executable(paltest_reg_unreg_libraryw_neg
+ ${SOURCES}
+)
+
+add_dependencies(paltest_reg_unreg_libraryw_neg coreclrpal)
+
+target_link_libraries(paltest_reg_unreg_libraryw_neg
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/reg_unreg_libraryw_neg.c b/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/reg_unreg_libraryw_neg.c
new file mode 100644
index 0000000000..a15ff5745b
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/reg_unreg_libraryw_neg.c
@@ -0,0 +1,62 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: pal_registerlibraryw_unregisterlibraryw_neg.c
+**
+** Purpose: Negative test the PAL_RegisterLibrary API.
+** Call PAL_RegisterLibrary to map a non-existant module
+** into the calling process address space.
+**
+**
+**============================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ HMODULE ModuleHandle;
+ char ModuleName[64];
+ WCHAR *wpModuleName = NULL;
+ int err;
+
+ /*Initialize the PAL environment*/
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+ memset(ModuleName, 0, 64);
+ sprintf(ModuleName, "%s", "not_exist_module_name");
+
+ /*convert a normal string to a wide one*/
+ wpModuleName = convert(ModuleName);
+
+ /*load a not exist module*/
+ ModuleHandle = PAL_RegisterLibrary(wpModuleName);
+
+ /*free the memory*/
+ free(wpModuleName);
+
+ if(NULL != ModuleHandle)
+ {
+ Trace("ERROR: PAL_RegisterLibrary successfully mapped "
+ "a module that does not exist into the calling process\n");
+
+ /*decrement the reference count of the loaded DLL*/
+ err = PAL_UnregisterLibrary(ModuleHandle);
+ if(0 == err)
+ {
+ Trace("\nFailed to call PAL_UnregisterLibrary API to decrement the "
+ "count of the loaded DLL module!\n");
+ }
+ Fail("");
+
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/testinfo.dat b/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/testinfo.dat
new file mode 100644
index 0000000000..3322633291
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = pal_specific
+Function = PAL_RegisterLibraryW and PAL_UnregisterLibraryW API
+Name = Negative test for PAL_RegisterLibraryW and PAL_UnregisterLibaryW API to map and unmap a non-existant module
+TYPE = DEFAULT
+EXE1 = pal_registerlibraryw_unregisterlibraryw_neg
+Description
+=Test the PAL_RegisterLibraryW and PAL_UnregisterLibraryW to map a non-existant
+=module into calling process address space
+
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_errno/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/PAL_errno/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_errno/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_errno/test1/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/PAL_errno/test1/CMakeLists.txt
new file mode 100644
index 0000000000..59922b194b
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_errno/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ PAL_errno.c
+)
+
+add_executable(paltest_pal_errno_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_errno_test1 coreclrpal)
+
+target_link_libraries(paltest_pal_errno_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_errno/test1/PAL_errno.c b/src/pal/tests/palsuite/pal_specific/PAL_errno/test1/PAL_errno.c
new file mode 100644
index 0000000000..32e8487d07
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_errno/test1/PAL_errno.c
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: pal_errno.c
+**
+** Purpose: Positive test the PAL_errno API.
+** call PAL_errno to retrieve the pointer to
+** the per-thread errno value.
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ FILE *pFile = NULL;
+
+ /*Initialize the PAL environment*/
+ err = PAL_Initialize(argc, argv);
+ if( 0 != err)
+ {
+ return FAIL;
+ }
+
+ /*Try to open a not-exist file to read to generate an error*/
+ pFile = fopen( "no_exist_file_name", "r" );
+
+ if( NULL != pFile )
+ {
+ Trace("\nFailed to call fopen to open a not exist for reading, "
+ "an error is expected, but no error occurred\n");
+
+ if( EOF == fclose( pFile ) )
+ {
+ Trace("\nFailed to call fclose to close a file stream\n");
+ }
+ Fail( "Test failed! fopen() Should not have worked!" );
+ }
+
+ /*retrieve the per-thread error value pointer*/
+ if( 2 != errno )
+ {
+ Fail("\nFailed to call PAL_errno API, this value is not correct."
+ " The correct value is ENOENT[2] ( No such file or directory.).\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_errno/test1/testinfo.dat b/src/pal/tests/palsuite/pal_specific/PAL_errno/test1/testinfo.dat
new file mode 100644
index 0000000000..a35e1d23fc
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_errno/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = PAL_Specific
+Function = PAL_errno
+Name = Positive test PAL_errno API to retrieve the pre-thread errno value
+TYPE = DEFAULT
+EXE1 = pal_errno
+Description
+=Test the PAL_errno to retrieve a pointer to per-thread errno value
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/CMakeLists.txt
new file mode 100644
index 0000000000..3436a2dfdb
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ PAL_get_stderr.c
+)
+
+add_executable(paltest_pal_get_stderr_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_get_stderr_test1 coreclrpal)
+
+target_link_libraries(paltest_pal_get_stderr_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/PAL_get_stderr.c b/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/PAL_get_stderr.c
new file mode 100644
index 0000000000..da53460101
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/PAL_get_stderr.c
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: pal_get_stderr.c
+**
+** Purpose: Positive test the PAL_get_stderr API.
+** Call PAL_get_stderr to retrieve the PAL standard error
+** output stream pointer.
+** This test case should be run manually and automatically.
+**
+
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ FILE *pPAL_stderr = NULL;
+ const char *pMsg = "\nThis is a PAL_get_stderr test message, "
+ "not an error message!\n";
+
+ /*Initialize the PAL environment*/
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+ /*retrieve the PAL standard error output stream pointer*/
+ pPAL_stderr = PAL_get_stderr();
+
+ if(NULL == pPAL_stderr)
+ {
+ Fail("\nFailed to call PAL_get_stderr API, error code = %u\n",
+ GetLastError());
+ }
+
+ /*output a test message through PAL standard error stream*/
+ err = fputs(pMsg, pPAL_stderr);
+ if(EOF == err)
+ {
+ Fail("\nFailed to call fputs to output message to PAL stdandard "
+ "error stream, error code=%u\n", GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/testinfo.dat b/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/testinfo.dat
new file mode 100644
index 0000000000..a633c68e34
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = PAL_Specific
+Function = PAL_get_stderr
+Name = Positive test PAL_get_stderr to retrieve the PAL standard error stream pointer
+TYPE = DEFAULT
+EXE1 = pal_get_stderr
+Description
+=Test the PAL_get_stderr to retrieve the PAL standard error output stream pointer and
+=output a test message to this error stream
+=this test case will be run both manually and automatically
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/CMakeLists.txt
new file mode 100644
index 0000000000..592895b18c
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ PAL_get_stdin.c
+)
+
+add_executable(paltest_pal_get_stdin_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_get_stdin_test1 coreclrpal)
+
+target_link_libraries(paltest_pal_get_stdin_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/PAL_get_stdin.c b/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/PAL_get_stdin.c
new file mode 100644
index 0000000000..5d1fd23f92
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/PAL_get_stdin.c
@@ -0,0 +1,68 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: pal_get_stdin.c
+**
+** Purpose: Positive test the PAL_get_stdout API.
+** Call PAL_get_stdin to retrieve the PAL standard input
+** stream pointer.
+** This test case should be run manually.
+**
+
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ FILE *pPAL_stdin = NULL;
+ char Buffer[256];
+
+ /*Initialize the PAL environment*/
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+ /*retrieve the PAL standard input stream pointer*/
+ pPAL_stdin = PAL_get_stdin();
+ if(NULL == pPAL_stdin)
+ {
+ Fail("\nFailed to call PAL_get_stdin API to retrieve the "
+ "PAL standard input stream pointer, "
+ "error code = %u\n", GetLastError());
+ }
+
+ /*zero the buffer*/
+ memset(Buffer, 0, 256);
+
+ printf("\nPlease input some words: (less than 255 characters)\n");
+
+ /*further test the input stream*/
+ /*read message from the PAL standard input stream*/
+ if(NULL == fgets(Buffer, 255, pPAL_stdin))
+ {
+ Fail( "Failed to call fgets to get a string from PAL standard "
+ "input stream, error code=%u\n", GetLastError());
+ }
+ else
+ {
+ if(1 == strlen(Buffer) && Buffer[0] == '\n')
+ {
+ printf("\nEmpty input!\n");
+ }
+ else
+ {
+ printf("\nYour input words are:\n%s\n", Buffer);
+ }
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/testinfo.dat b/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/testinfo.dat
new file mode 100644
index 0000000000..d1c5723236
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = PAL_Specific
+Function = PAL_get_stdin
+Name = Positive test PAL_get_stdin to retrieve the PAL standard stdin stream pointer
+TYPE = DEFAULT
+EXE1 = pal_get_stdin
+Description
+=Test the PAL_get_stdin to retrieve the PAL standard input stream pointer
+=if success, display the input string to screen
+=this test case should be run manually
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/CMakeLists.txt
new file mode 100644
index 0000000000..865dd52f16
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ PAL_get_stdout.c
+)
+
+add_executable(paltest_pal_get_stdout_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_get_stdout_test1 coreclrpal)
+
+target_link_libraries(paltest_pal_get_stdout_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/PAL_get_stdout.c b/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/PAL_get_stdout.c
new file mode 100644
index 0000000000..ebfee47ae9
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/PAL_get_stdout.c
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: pal_get_stdout.c
+**
+** Purpose: Positive test the PAL_get_stdout API.
+** Call PAL_get_stdout to retrieve the PAL standard output
+** stream pointer.
+** This test case should be run manually and automatically.
+**
+
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ FILE *pPAL_stdout = NULL;
+ const char *pMsg = "\nThis is a PAL_get_stdout test output message, "
+ "not an error message!\n";
+
+ /*Initialize the PAL environment*/
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+ /*retrieve the PAL output stream pointer*/
+ pPAL_stdout = PAL_get_stdout();
+ if(NULL == pPAL_stdout)
+ {
+ Fail("\nFailed to call PAL_get_stdout API to retrieve the "
+ "standard PAL output stream pointer, error code=%u\n",
+ GetLastError());
+ }
+
+ /*output a test message through PAL standard output stream*/
+ err = fputs(pMsg, pPAL_stdout);
+ if(EOF == err)
+ {
+ Fail("\nFailed to call fputs to output message to PAL stdandard "
+ "output stream, error code=%u\n", GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/testinfo.dat b/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/testinfo.dat
new file mode 100644
index 0000000000..ed370981aa
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = PAL_Specific
+Function = PAL_get_stdout
+Name = Positive test PAL_get_stdout to retrieve PAL standard output stream pointer
+TYPE = DEFAULT
+EXE1 = pal_get_stdout
+Description
+=Test the PAL_get_stdout to retrieve the PAL standard output stream pointer
+=This test case will be run both manually and automatically
diff --git a/src/pal/tests/palsuite/pal_specific/pal_entrypoint/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/pal_entrypoint/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/pal_entrypoint/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/pal_specific/pal_entrypoint/test1/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/pal_entrypoint/test1/CMakeLists.txt
new file mode 100644
index 0000000000..cd18b76958
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/pal_entrypoint/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ pal_entrypoint.c
+)
+
+add_executable(paltest_pal_entrypoint_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_entrypoint_test1 coreclrpal)
+
+target_link_libraries(paltest_pal_entrypoint_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/pal_specific/pal_entrypoint/test1/pal_entrypoint.c b/src/pal/tests/palsuite/pal_specific/pal_entrypoint/test1/pal_entrypoint.c
new file mode 100644
index 0000000000..c1b66944aa
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/pal_entrypoint/test1/pal_entrypoint.c
@@ -0,0 +1,54 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: pal_entrypoint.c
+**
+** Purpose: Positive test the PAL_EntryPoint API.
+**
+** Test the PAL_EntryPoint, Call a PAL function, and let main return
+** as expected..
+**
+
+**
+**============================================================*/
+
+#include "palstartup.h"
+
+/* Test case copied and stream lined from isalpha\test1*/
+struct testCase
+{
+ int CorrectResult;
+ int character;
+};
+
+int __cdecl main(int argc, char *argv[])
+{
+ int result;
+ int i;
+
+ struct testCase testCases[] =
+ {
+ {1, 'a'}
+ };
+
+
+ i = 0;
+ result = isalpha(testCases[i].character);
+ /* The return value is 'non-zero' for success. This if condition
+ * will still work if that non-zero isn't just 1
+ */
+ if ( ((testCases[i].CorrectResult == 1) && (result == 0)) ||
+ ( (testCases[i].CorrectResult == 0) && (result != 0) ))
+ {
+ Fail("ERROR: isalpha returned %i instead of %i for character "
+ "%c.\n",
+ result,
+ testCases[i].CorrectResult,
+ testCases[i].character);
+ }
+
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/pal_specific/pal_entrypoint/test1/palstartup.h b/src/pal/tests/palsuite/pal_specific/pal_entrypoint/test1/palstartup.h
new file mode 100644
index 0000000000..862870be99
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/pal_entrypoint/test1/palstartup.h
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+// ===========================================================================
+// File: palstartup.h
+//
+// An implementation of startup code for Rotor's Unix PAL. This file should
+// be included by any file in a PAL application that defines main.
+// we have added palsuite.h to include test related macros etc...
+// ===========================================================================
+
+#ifndef __PALSTARTUP_H__
+#define __PALSTARTUP_H__
+
+#include <palsuite.h>
+
+int __cdecl PAL_startup_main(int argc, char **argv);
+
+struct _mainargs
+{
+ int argc;
+ char ** argv;
+};
+
+static DWORD PALAPI run_main(struct _mainargs *args)
+{
+ return (DWORD) PAL_startup_main(args->argc, args->argv);
+}
+
+int __cdecl main(int argc, char **argv) {
+ struct _mainargs mainargs;
+
+ if (PAL_Initialize(argc, argv)) {
+ return FAIL;;
+ }
+
+ // PAL_Terminate is a stdcall function, but it takes no parameters
+ // so the difference doesn't matter.
+ atexit((void (__cdecl *)(void)) PAL_Terminate);
+
+ mainargs.argc = argc;
+ mainargs.argv = argv;
+ exit((int)PAL_EntryPoint((PTHREAD_START_ROUTINE)run_main, &mainargs));
+ return 0; // Quiet a compiler warning
+}
+
+#define main PAL_startup_main
+
+#endif // __PALSTARTUP_H__
diff --git a/src/pal/tests/palsuite/pal_specific/pal_entrypoint/test1/testinfo.dat b/src/pal/tests/palsuite/pal_specific/pal_entrypoint/test1/testinfo.dat
new file mode 100644
index 0000000000..01ac3d6f9f
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/pal_entrypoint/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = PAL_Specific
+Function = PAL_entrypoint
+Name = Positive test entrypoint API
+TYPE = DEFAULT
+EXE1 = pal_errno
+Description
+=Test the PAL_entrypoint to call a PAL api
diff --git a/src/pal/tests/palsuite/pal_specific/pal_initializedebug/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/pal_initializedebug/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/pal_initializedebug/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/pal_specific/pal_initializedebug/test1/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/pal_initializedebug/test1/CMakeLists.txt
new file mode 100644
index 0000000000..f6e243d0c4
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/pal_initializedebug/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ pal_initializedebug.c
+)
+
+add_executable(paltest_pal_initializedebug_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_initializedebug_test1 coreclrpal)
+
+target_link_libraries(paltest_pal_initializedebug_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/pal_specific/pal_initializedebug/test1/pal_initializedebug.c b/src/pal/tests/palsuite/pal_specific/pal_initializedebug/test1/pal_initializedebug.c
new file mode 100644
index 0000000000..d14c316013
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/pal_initializedebug/test1/pal_initializedebug.c
@@ -0,0 +1,36 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: pal_initializedebug.c
+**
+** Purpose: Positive test the PAL_InitializeDebug API.
+**
+** Test the PAL_InitializeDebug, it will be NOPs for all
+** platforms other than Mac. There is no other way of testing it
+** currently
+**
+
+**
+**============================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+
+ /* Initialize the PAL environment */
+ err = PAL_Initialize(argc, argv);
+
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+ PAL_InitializeDebug();
+
+ PAL_Terminate();
+ return 0;
+}
diff --git a/src/pal/tests/palsuite/pal_specific/pal_initializedebug/test1/testinfo.dat b/src/pal/tests/palsuite/pal_specific/pal_initializedebug/test1/testinfo.dat
new file mode 100644
index 0000000000..45c40e50d2
--- /dev/null
+++ b/src/pal/tests/palsuite/pal_specific/pal_initializedebug/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = PAL_Specific
+Function = PAL_InitializeDebug
+Name = Positive test for PAL_InitializeDebug
+TYPE = DEFAULT
+EXE1 = pal_initializedebug
+Description
+=Test the PAL_InitializeDebug, it will be NOPs for all
+=platforms other than Mac
diff --git a/src/pal/tests/palsuite/paltestlist.txt b/src/pal/tests/palsuite/paltestlist.txt
new file mode 100644
index 0000000000..d0a76e9573
--- /dev/null
+++ b/src/pal/tests/palsuite/paltestlist.txt
@@ -0,0 +1,808 @@
+c_runtime/abs/test1/paltest_abs_test1
+c_runtime/acos/test1/paltest_acos_test1
+c_runtime/asin/test1/paltest_asin_test1
+c_runtime/atan/test1/paltest_atan_test1
+c_runtime/atan2/test1/paltest_atan2_test1
+c_runtime/atof/test1/paltest_atof_test1
+c_runtime/atoi/test1/paltest_atoi_test1
+c_runtime/atol/test1/paltest_atol_test1
+c_runtime/bsearch/test1/paltest_bsearch_test1
+c_runtime/bsearch/test2/paltest_bsearch_test2
+c_runtime/ceil/test1/paltest_ceil_test1
+c_runtime/cos/test1/paltest_cos_test1
+c_runtime/cosh/test1/paltest_cosh_test1
+c_runtime/errno/test1/paltest_errno_test1
+c_runtime/errno/test2/paltest_errno_test2
+c_runtime/exit/test1/paltest_exit_test1
+c_runtime/exp/test1/paltest_exp_test1
+c_runtime/fabs/test1/paltest_fabs_test1
+c_runtime/fabsf/test1/paltest_fabsf_test1
+c_runtime/fclose/test1/paltest_fclose_test1
+c_runtime/fclose/test2/paltest_fclose_test2
+c_runtime/fflush/test1/paltest_fflush_test1
+c_runtime/fgets/test1/paltest_fgets_test1
+c_runtime/fgets/test2/paltest_fgets_test2
+c_runtime/fgets/test3/paltest_fgets_test3
+c_runtime/floor/test1/paltest_floor_test1
+c_runtime/fmod/test1/paltest_fmod_test1
+c_runtime/fmodf/test1/paltest_fmodf_test1
+c_runtime/fopen/test1/paltest_fopen_test1
+c_runtime/fopen/test2/paltest_fopen_test2
+c_runtime/fopen/test3/paltest_fopen_test3
+c_runtime/fopen/test4/paltest_fopen_test4
+c_runtime/fopen/test5/paltest_fopen_test5
+c_runtime/fopen/test6/paltest_fopen_test6
+c_runtime/fopen/test7/paltest_fopen_test7
+c_runtime/fprintf/test1/paltest_fprintf_test1
+c_runtime/fprintf/test10/paltest_fprintf_test10
+c_runtime/fprintf/test11/paltest_fprintf_test11
+c_runtime/fprintf/test12/paltest_fprintf_test12
+c_runtime/fprintf/test13/paltest_fprintf_test13
+c_runtime/fprintf/test14/paltest_fprintf_test14
+c_runtime/fprintf/test15/paltest_fprintf_test15
+c_runtime/fprintf/test16/paltest_fprintf_test16
+c_runtime/fprintf/test17/paltest_fprintf_test17
+c_runtime/fprintf/test18/paltest_fprintf_test18
+c_runtime/fprintf/test19/paltest_fprintf_test19
+c_runtime/fprintf/test2/paltest_fprintf_test2
+c_runtime/fprintf/test3/paltest_fprintf_test3
+c_runtime/fprintf/test4/paltest_fprintf_test4
+c_runtime/fprintf/test5/paltest_fprintf_test5
+c_runtime/fprintf/test6/paltest_fprintf_test6
+c_runtime/fprintf/test7/paltest_fprintf_test7
+c_runtime/fprintf/test8/paltest_fprintf_test8
+c_runtime/fprintf/test9/paltest_fprintf_test9
+c_runtime/fputs/test1/paltest_fputs_test1
+c_runtime/free/test1/paltest_free_test1
+c_runtime/fseek/test1/paltest_fseek_test1
+c_runtime/fwprintf/test1/paltest_fwprintf_test1
+c_runtime/fwprintf/test10/paltest_fwprintf_test10
+c_runtime/fwprintf/test11/paltest_fwprintf_test11
+c_runtime/fwprintf/test12/paltest_fwprintf_test12
+c_runtime/fwprintf/test13/paltest_fwprintf_test13
+c_runtime/fwprintf/test14/paltest_fwprintf_test14
+c_runtime/fwprintf/test15/paltest_fwprintf_test15
+c_runtime/fwprintf/test16/paltest_fwprintf_test16
+c_runtime/fwprintf/test17/paltest_fwprintf_test17
+c_runtime/fwprintf/test18/paltest_fwprintf_test18
+c_runtime/fwprintf/test3/paltest_fwprintf_test3
+c_runtime/fwprintf/test4/paltest_fwprintf_test4
+c_runtime/fwprintf/test5/paltest_fwprintf_test5
+c_runtime/fwprintf/test6/paltest_fwprintf_test6
+c_runtime/fwprintf/test8/paltest_fwprintf_test8
+c_runtime/fwprintf/test9/paltest_fwprintf_test9
+c_runtime/fwrite/test1/paltest_fwrite_test1
+c_runtime/getc/test1/paltest_getc_test1
+c_runtime/getenv/test1/paltest_getenv_test1
+c_runtime/getenv/test2/paltest_getenv_test2
+c_runtime/getenv/test3/paltest_getenv_test3
+c_runtime/isalnum/test1/paltest_isalnum_test1
+c_runtime/isalpha/test1/paltest_isalpha_test1
+c_runtime/isdigit/test1/paltest_isdigit_test1
+c_runtime/islower/test1/paltest_islower_test1
+c_runtime/isprint/test1/paltest_isprint_test1
+c_runtime/isprint/test2/paltest_isprint_test2
+c_runtime/isspace/test1/paltest_isspace_test1
+c_runtime/isupper/test1/paltest_isupper_test1
+c_runtime/iswdigit/test1/paltest_iswdigit_test1
+c_runtime/iswspace/test1/paltest_iswspace_test1
+c_runtime/iswupper/test1/paltest_iswupper_test1
+c_runtime/iswxdigit/test1/paltest_iswxdigit_test1
+c_runtime/isxdigit/test1/paltest_isxdigit_test1
+c_runtime/labs/test1/paltest_labs_test1
+c_runtime/llabs/test1/paltest_llabs_test1
+c_runtime/localtime/test1/paltest_localtime_test1
+c_runtime/log/test1/paltest_log_test1
+c_runtime/log10/test1/paltest_log10_test1
+c_runtime/malloc/test1/paltest_malloc_test1
+c_runtime/malloc/test2/paltest_malloc_test2
+c_runtime/memchr/test1/paltest_memchr_test1
+c_runtime/memcmp/test1/paltest_memcmp_test1
+c_runtime/memcpy/test1/paltest_memcpy_test1
+c_runtime/memmove/test1/paltest_memmove_test1
+c_runtime/memset/test1/paltest_memset_test1
+c_runtime/modf/test1/paltest_modf_test1
+c_runtime/modff/test1/paltest_modff_test1
+c_runtime/pow/test1/paltest_pow_test1
+c_runtime/printf/test1/paltest_printf_test1
+c_runtime/printf/test10/paltest_printf_test10
+c_runtime/printf/test11/paltest_printf_test11
+c_runtime/printf/test12/paltest_printf_test12
+c_runtime/printf/test13/paltest_printf_test13
+c_runtime/printf/test14/paltest_printf_test14
+c_runtime/printf/test15/paltest_printf_test15
+c_runtime/printf/test16/paltest_printf_test16
+c_runtime/printf/test17/paltest_printf_test17
+c_runtime/printf/test18/paltest_printf_test18
+c_runtime/printf/test19/paltest_printf_test19
+c_runtime/printf/test2/paltest_printf_test2
+c_runtime/printf/test3/paltest_printf_test3
+c_runtime/printf/test4/paltest_printf_test4
+c_runtime/printf/test5/paltest_printf_test5
+c_runtime/printf/test6/paltest_printf_test6
+c_runtime/printf/test7/paltest_printf_test7
+c_runtime/printf/test8/paltest_printf_test8
+c_runtime/printf/test9/paltest_printf_test9
+c_runtime/qsort/test1/paltest_qsort_test1
+c_runtime/qsort/test2/paltest_qsort_test2
+c_runtime/rand_srand/test1/paltest_rand_srand_test1
+c_runtime/realloc/test1/paltest_realloc_test1
+c_runtime/sin/test1/paltest_sin_test1
+c_runtime/sinh/test1/paltest_sinh_test1
+c_runtime/sprintf/test1/paltest_sprintf_test1
+c_runtime/sprintf/test10/paltest_sprintf_test10
+c_runtime/sprintf/test11/paltest_sprintf_test11
+c_runtime/sprintf/test12/paltest_sprintf_test12
+c_runtime/sprintf/test13/paltest_sprintf_test13
+c_runtime/sprintf/test14/paltest_sprintf_test14
+c_runtime/sprintf/test15/paltest_sprintf_test15
+c_runtime/sprintf/test16/paltest_sprintf_test16
+c_runtime/sprintf/test17/paltest_sprintf_test17
+c_runtime/sprintf/test18/paltest_sprintf_test18
+c_runtime/sprintf/test19/paltest_sprintf_test19
+c_runtime/sprintf/test2/paltest_sprintf_test2
+c_runtime/sprintf/test3/paltest_sprintf_test3
+c_runtime/sprintf/test4/paltest_sprintf_test4
+c_runtime/sprintf/test5/paltest_sprintf_test5
+c_runtime/sprintf/test6/paltest_sprintf_test6
+c_runtime/sprintf/test7/paltest_sprintf_test7
+c_runtime/sprintf/test8/paltest_sprintf_test8
+c_runtime/sprintf/test9/paltest_sprintf_test9
+c_runtime/sqrt/test1/paltest_sqrt_test1
+c_runtime/sscanf/test1/paltest_sscanf_test1
+c_runtime/sscanf/test10/paltest_sscanf_test10
+c_runtime/sscanf/test11/paltest_sscanf_test11
+c_runtime/sscanf/test12/paltest_sscanf_test12
+c_runtime/sscanf/test13/paltest_sscanf_test13
+c_runtime/sscanf/test14/paltest_sscanf_test14
+c_runtime/sscanf/test15/paltest_sscanf_test15
+c_runtime/sscanf/test16/paltest_sscanf_test16
+c_runtime/sscanf/test17/paltest_sscanf_test17
+c_runtime/sscanf/test2/paltest_sscanf_test2
+c_runtime/sscanf/test3/paltest_sscanf_test3
+c_runtime/sscanf/test4/paltest_sscanf_test4
+c_runtime/sscanf/test5/paltest_sscanf_test5
+c_runtime/sscanf/test6/paltest_sscanf_test6
+c_runtime/sscanf/test7/paltest_sscanf_test7
+c_runtime/sscanf/test8/paltest_sscanf_test8
+c_runtime/sscanf/test9/paltest_sscanf_test9
+c_runtime/strcat/test1/paltest_strcat_test1
+c_runtime/strchr/test1/paltest_strchr_test1
+c_runtime/strcmp/test1/paltest_strcmp_test1
+c_runtime/strcpy/test1/paltest_strcpy_test1
+c_runtime/strcspn/test1/paltest_strcspn_test1
+c_runtime/strlen/test1/paltest_strlen_test1
+c_runtime/strncat/test1/paltest_strncat_test1
+c_runtime/strncmp/test1/paltest_strncmp_test1
+c_runtime/strncpy/test1/paltest_strncpy_test1
+c_runtime/strpbrk/test1/paltest_strpbrk_test1
+c_runtime/strrchr/test1/paltest_strrchr_test1
+c_runtime/strspn/test1/paltest_strspn_test1
+c_runtime/strstr/test1/paltest_strstr_test1
+c_runtime/strtod/test1/paltest_strtod_test1
+c_runtime/strtod/test2/paltest_strtod_test2
+c_runtime/strtok/test1/paltest_strtok_test1
+c_runtime/strtoul/test1/paltest_strtoul_test1
+c_runtime/swprintf/test1/paltest_swprintf_test1
+c_runtime/swprintf/test10/paltest_swprintf_test10
+c_runtime/swprintf/test11/paltest_swprintf_test11
+c_runtime/swprintf/test12/paltest_swprintf_test12
+c_runtime/swprintf/test13/paltest_swprintf_test13
+c_runtime/swprintf/test14/paltest_swprintf_test14
+c_runtime/swprintf/test15/paltest_swprintf_test15
+c_runtime/swprintf/test16/paltest_swprintf_test16
+c_runtime/swprintf/test17/paltest_swprintf_test17
+c_runtime/swprintf/test18/paltest_swprintf_test18
+c_runtime/swprintf/test19/paltest_swprintf_test19
+c_runtime/swprintf/test3/paltest_swprintf_test3
+c_runtime/swprintf/test4/paltest_swprintf_test4
+c_runtime/swprintf/test5/paltest_swprintf_test5
+c_runtime/swprintf/test6/paltest_swprintf_test6
+c_runtime/swprintf/test8/paltest_swprintf_test8
+c_runtime/swprintf/test9/paltest_swprintf_test9
+c_runtime/swscanf/test1/paltest_swscanf_test1
+c_runtime/swscanf/test10/paltest_swscanf_test10
+c_runtime/swscanf/test11/paltest_swscanf_test11
+c_runtime/swscanf/test12/paltest_swscanf_test12
+c_runtime/swscanf/test13/paltest_swscanf_test13
+c_runtime/swscanf/test14/paltest_swscanf_test14
+c_runtime/swscanf/test15/paltest_swscanf_test15
+c_runtime/swscanf/test16/paltest_swscanf_test16
+c_runtime/swscanf/test17/paltest_swscanf_test17
+c_runtime/swscanf/test2/paltest_swscanf_test2
+c_runtime/swscanf/test3/paltest_swscanf_test3
+c_runtime/swscanf/test4/paltest_swscanf_test4
+c_runtime/swscanf/test5/paltest_swscanf_test5
+c_runtime/swscanf/test6/paltest_swscanf_test6
+c_runtime/swscanf/test7/paltest_swscanf_test7
+c_runtime/swscanf/test8/paltest_swscanf_test8
+c_runtime/swscanf/test9/paltest_swscanf_test9
+c_runtime/tan/test1/paltest_tan_test1
+c_runtime/tanh/test1/paltest_tanh_test1
+c_runtime/time/test1/paltest_time_test1
+c_runtime/tolower/test1/paltest_tolower_test1
+c_runtime/toupper/test1/paltest_toupper_test1
+c_runtime/towlower/test1/paltest_towlower_test1
+c_runtime/towupper/test1/paltest_towupper_test1
+c_runtime/ungetc/test1/paltest_ungetc_test1
+c_runtime/vfprintf/test1/paltest_vfprintf_test1
+c_runtime/vfprintf/test10/paltest_vfprintf_test10
+c_runtime/vfprintf/test11/paltest_vfprintf_test11
+c_runtime/vfprintf/test12/paltest_vfprintf_test12
+c_runtime/vfprintf/test13/paltest_vfprintf_test13
+c_runtime/vfprintf/test14/paltest_vfprintf_test14
+c_runtime/vfprintf/test15/paltest_vfprintf_test15
+c_runtime/vfprintf/test16/paltest_vfprintf_test16
+c_runtime/vfprintf/test17/paltest_vfprintf_test17
+c_runtime/vfprintf/test18/paltest_vfprintf_test18
+c_runtime/vfprintf/test19/paltest_vfprintf_test19
+c_runtime/vfprintf/test2/paltest_vfprintf_test2
+c_runtime/vfprintf/test3/paltest_vfprintf_test3
+c_runtime/vfprintf/test4/paltest_vfprintf_test4
+c_runtime/vfprintf/test5/paltest_vfprintf_test5
+c_runtime/vfprintf/test6/paltest_vfprintf_test6
+c_runtime/vfprintf/test7/paltest_vfprintf_test7
+c_runtime/vfprintf/test8/paltest_vfprintf_test8
+c_runtime/vfprintf/test9/paltest_vfprintf_test9
+c_runtime/vprintf/test10/paltest_vprintf_test10
+c_runtime/vprintf/test11/paltest_vprintf_test11
+c_runtime/vprintf/test12/paltest_vprintf_test12
+c_runtime/vprintf/test13/paltest_vprintf_test13
+c_runtime/vprintf/test14/paltest_vprintf_test14
+c_runtime/vprintf/test15/paltest_vprintf_test15
+c_runtime/vprintf/test16/paltest_vprintf_test16
+c_runtime/vprintf/test17/paltest_vprintf_test17
+c_runtime/vprintf/test18/paltest_vprintf_test18
+c_runtime/vprintf/test19/paltest_vprintf_test19
+c_runtime/vprintf/test2/paltest_vprintf_test2
+c_runtime/vprintf/test3/paltest_vprintf_test3
+c_runtime/vprintf/test4/paltest_vprintf_test4
+c_runtime/vprintf/test5/paltest_vprintf_test5
+c_runtime/vprintf/test6/paltest_vprintf_test6
+c_runtime/vprintf/test7/paltest_vprintf_test7
+c_runtime/vprintf/test8/paltest_vprintf_test8
+c_runtime/vprintf/test9/paltest_vprintf_test9
+c_runtime/vsprintf/test1/paltest_vsprintf_test1
+c_runtime/vsprintf/test10/paltest_vsprintf_test10
+c_runtime/vsprintf/test11/paltest_vsprintf_test11
+c_runtime/vsprintf/test12/paltest_vsprintf_test12
+c_runtime/vsprintf/test13/paltest_vsprintf_test13
+c_runtime/vsprintf/test14/paltest_vsprintf_test14
+c_runtime/vsprintf/test15/paltest_vsprintf_test15
+c_runtime/vsprintf/test16/paltest_vsprintf_test16
+c_runtime/vsprintf/test17/paltest_vsprintf_test17
+c_runtime/vsprintf/test18/paltest_vsprintf_test18
+c_runtime/vsprintf/test19/paltest_vsprintf_test19
+c_runtime/vsprintf/test2/paltest_vsprintf_test2
+c_runtime/vsprintf/test3/paltest_vsprintf_test3
+c_runtime/vsprintf/test4/paltest_vsprintf_test4
+c_runtime/vsprintf/test5/paltest_vsprintf_test5
+c_runtime/vsprintf/test6/paltest_vsprintf_test6
+c_runtime/vsprintf/test7/paltest_vsprintf_test7
+c_runtime/vsprintf/test8/paltest_vsprintf_test8
+c_runtime/vsprintf/test9/paltest_vsprintf_test9
+c_runtime/vswprintf/test1/paltest_vswprintf_test1
+c_runtime/vswprintf/test10/paltest_vswprintf_test10
+c_runtime/vswprintf/test11/paltest_vswprintf_test11
+c_runtime/vswprintf/test12/paltest_vswprintf_test12
+c_runtime/vswprintf/test13/paltest_vswprintf_test13
+c_runtime/vswprintf/test14/paltest_vswprintf_test14
+c_runtime/vswprintf/test15/paltest_vswprintf_test15
+c_runtime/vswprintf/test16/paltest_vswprintf_test16
+c_runtime/vswprintf/test17/paltest_vswprintf_test17
+c_runtime/vswprintf/test18/paltest_vswprintf_test18
+c_runtime/vswprintf/test19/paltest_vswprintf_test19
+c_runtime/vswprintf/test3/paltest_vswprintf_test3
+c_runtime/vswprintf/test4/paltest_vswprintf_test4
+c_runtime/vswprintf/test5/paltest_vswprintf_test5
+c_runtime/vswprintf/test6/paltest_vswprintf_test6
+c_runtime/vswprintf/test8/paltest_vswprintf_test8
+c_runtime/vswprintf/test9/paltest_vswprintf_test9
+c_runtime/wcscat/test1/paltest_wcscat_test1
+c_runtime/wcschr/test1/paltest_wcschr_test1
+c_runtime/wcscmp/test1/paltest_wcscmp_test1
+c_runtime/wcscpy/test1/paltest_wcscpy_test1
+c_runtime/wcslen/test1/paltest_wcslen_test1
+c_runtime/wcsncat/test1/paltest_wcsncat_test1
+c_runtime/wcsncmp/test1/paltest_wcsncmp_test1
+c_runtime/wcsncpy/test1/paltest_wcsncpy_test1
+c_runtime/wcspbrk/test1/paltest_wcspbrk_test1
+c_runtime/wcsrchr/test1/paltest_wcsrchr_test1
+c_runtime/wcsstr/test1/paltest_wcsstr_test1
+c_runtime/wcstod/test1/paltest_wcstod_test1
+c_runtime/wcstod/test2/paltest_wcstod_test2
+c_runtime/wcstok/test1/paltest_wcstok_test1
+c_runtime/wcstol/test1/paltest_wcstol_test1
+c_runtime/wcstol/test2/paltest_wcstol_test2
+c_runtime/wcstol/test3/paltest_wcstol_test3
+c_runtime/wcstol/test4/paltest_wcstol_test4
+c_runtime/wcstol/test5/paltest_wcstol_test5
+c_runtime/wcstol/test6/paltest_wcstol_test6
+c_runtime/wcstoul/test1/paltest_wcstoul_test1
+c_runtime/wcstoul/test2/paltest_wcstoul_test2
+c_runtime/wcstoul/test3/paltest_wcstoul_test3
+c_runtime/wcstoul/test4/paltest_wcstoul_test4
+c_runtime/wcstoul/test5/paltest_wcstoul_test5
+c_runtime/wcstoul/test6/paltest_wcstoul_test6
+c_runtime/wprintf/test1/paltest_wprintf_test1
+c_runtime/_alloca/test1/paltest_alloca_test1
+c_runtime/_fdopen/test1/paltest_fdopen_test1
+c_runtime/_finite/test1/paltest_finite_test1
+c_runtime/_fullpath/test1/paltest_fullpath_test1
+c_runtime/_isnan/test1/paltest_isnan_test1
+c_runtime/_itow/test1/paltest_itow_test1
+c_runtime/_makepath/test1/paltest_makepath_test1
+c_runtime/_mbsdec/test1/paltest_mbsdec_test1
+c_runtime/_mbsinc/test1/paltest_mbsinc_test1
+c_runtime/_mbslen/test1/paltest_mbslen_test1
+c_runtime/_mbsninc/test1/paltest_mbsninc_test1
+c_runtime/_open_osfhandle/test1/paltest_open_osfhandle_test1
+c_runtime/_open_osfhandle/test2/paltest_open_osfhandle_test2
+c_runtime/_putenv/test1/paltest_putenv_test1
+c_runtime/_putenv/test2/paltest_putenv_test2
+c_runtime/_putenv/test3/paltest_putenv_test3
+c_runtime/_putenv/test4/paltest_putenv_test4
+c_runtime/_putw/test1/paltest_putw_test1
+c_runtime/_rotl/test1/paltest_rotl_test1
+c_runtime/_rotr/test1/paltest_rotr_test1
+c_runtime/_snprintf/test1/paltest_snprintf_test1
+c_runtime/_snprintf/test10/paltest_snprintf_test10
+c_runtime/_snprintf/test11/paltest_snprintf_test11
+c_runtime/_snprintf/test12/paltest_snprintf_test12
+c_runtime/_snprintf/test13/paltest_snprintf_test13
+c_runtime/_snprintf/test14/paltest_snprintf_test14
+c_runtime/_snprintf/test15/paltest_snprintf_test15
+c_runtime/_snprintf/test16/paltest_snprintf_test16
+c_runtime/_snprintf/test17/paltest_snprintf_test17
+c_runtime/_snprintf/test18/paltest_snprintf_test18
+c_runtime/_snprintf/test19/paltest_snprintf_test19
+c_runtime/_snprintf/test2/paltest_snprintf_test2
+c_runtime/_snprintf/test3/paltest_snprintf_test3
+c_runtime/_snprintf/test4/paltest_snprintf_test4
+c_runtime/_snprintf/test5/paltest_snprintf_test5
+c_runtime/_snprintf/test6/paltest_snprintf_test6
+c_runtime/_snprintf/test7/paltest_snprintf_test7
+c_runtime/_snprintf/test8/paltest_snprintf_test8
+c_runtime/_snprintf/test9/paltest_snprintf_test9
+c_runtime/_snwprintf/test1/paltest_snwprintf_test1
+c_runtime/_snwprintf/test10/paltest_snwprintf_test10
+c_runtime/_snwprintf/test11/paltest_snwprintf_test11
+c_runtime/_snwprintf/test12/paltest_snwprintf_test12
+c_runtime/_snwprintf/test13/paltest_snwprintf_test13
+c_runtime/_snwprintf/test14/paltest_snwprintf_test14
+c_runtime/_snwprintf/test15/paltest_snwprintf_test15
+c_runtime/_snwprintf/test16/paltest_snwprintf_test16
+c_runtime/_snwprintf/test17/paltest_snwprintf_test17
+c_runtime/_snwprintf/test18/paltest_snwprintf_test18
+c_runtime/_snwprintf/test19/paltest_snwprintf_test19
+c_runtime/_snwprintf/test3/paltest_snwprintf_test3
+c_runtime/_snwprintf/test4/paltest_snwprintf_test4
+c_runtime/_snwprintf/test5/paltest_snwprintf_test5
+c_runtime/_snwprintf/test6/paltest_snwprintf_test6
+c_runtime/_snwprintf/test8/paltest_snwprintf_test8
+c_runtime/_snwprintf/test9/paltest_snwprintf_test9
+c_runtime/_splitpath/test1/paltest_splitpath_test1
+c_runtime/_stricmp/test1/paltest_stricmp_test1
+c_runtime/_strlwr/test1/paltest_strlwr_test1
+c_runtime/_strnicmp/test1/paltest_strnicmp_test1
+c_runtime/_swab/test1/paltest_swab_test1
+c_runtime/_vsnprintf/test1/paltest_vsnprintf_test1
+c_runtime/_vsnprintf/test10/paltest_vsnprintf_test10
+c_runtime/_vsnprintf/test11/paltest_vsnprintf_test11
+c_runtime/_vsnprintf/test12/paltest_vsnprintf_test12
+c_runtime/_vsnprintf/test13/paltest_vsnprintf_test13
+c_runtime/_vsnprintf/test14/paltest_vsnprintf_test14
+c_runtime/_vsnprintf/test15/paltest_vsnprintf_test15
+c_runtime/_vsnprintf/test16/paltest_vsnprintf_test16
+c_runtime/_vsnprintf/test17/paltest_vsnprintf_test17
+c_runtime/_vsnprintf/test18/paltest_vsnprintf_test18
+c_runtime/_vsnprintf/test19/paltest_vsnprintf_test19
+c_runtime/_vsnprintf/test2/paltest_vsnprintf_test2
+c_runtime/_vsnprintf/test3/paltest_vsnprintf_test3
+c_runtime/_vsnprintf/test4/paltest_vsnprintf_test4
+c_runtime/_vsnprintf/test5/paltest_vsnprintf_test5
+c_runtime/_vsnprintf/test6/paltest_vsnprintf_test6
+c_runtime/_vsnprintf/test7/paltest_vsnprintf_test7
+c_runtime/_vsnprintf/test8/paltest_vsnprintf_test8
+c_runtime/_vsnprintf/test9/paltest_vsnprintf_test9
+c_runtime/_vsnwprintf/test1/paltest_vsnwprintf_test1
+c_runtime/_vsnwprintf/test10/paltest_vsnwprintf_test10
+c_runtime/_vsnwprintf/test11/paltest_vsnwprintf_test11
+c_runtime/_vsnwprintf/test12/paltest_vsnwprintf_test12
+c_runtime/_vsnwprintf/test13/paltest_vsnwprintf_test13
+c_runtime/_vsnwprintf/test14/paltest_vsnwprintf_test14
+c_runtime/_vsnwprintf/test15/paltest_vsnwprintf_test15
+c_runtime/_vsnwprintf/test16/paltest_vsnwprintf_test16
+c_runtime/_vsnwprintf/test17/paltest_vsnwprintf_test17
+c_runtime/_vsnwprintf/test18/paltest_vsnwprintf_test18
+c_runtime/_vsnwprintf/test19/paltest_vsnwprintf_test19
+c_runtime/_vsnwprintf/test3/paltest_vsnwprintf_test3
+c_runtime/_vsnwprintf/test4/paltest_vsnwprintf_test4
+c_runtime/_vsnwprintf/test5/paltest_vsnwprintf_test5
+c_runtime/_vsnwprintf/test6/paltest_vsnwprintf_test6
+c_runtime/_vsnwprintf/test8/paltest_vsnwprintf_test8
+c_runtime/_vsnwprintf/test9/paltest_vsnwprintf_test9
+c_runtime/_wcsicmp/test1/paltest_wcsicmp_test1
+c_runtime/_wcslwr/test1/paltest_wcslwr_test1
+c_runtime/_wcsnicmp/test1/paltest_wcsnicmp_test1
+c_runtime/_wfopen/test1/paltest_wfopen_test1
+c_runtime/_wfopen/test2/paltest_wfopen_test2
+c_runtime/_wfopen/test3/paltest_wfopen_test3
+c_runtime/_wfopen/test4/paltest_wfopen_test4
+c_runtime/_wfopen/test5/paltest_wfopen_test5
+c_runtime/_wfopen/test6/paltest_wfopen_test6
+c_runtime/_wfopen/test7/paltest_wfopen_test7
+c_runtime/_wsplitpath/test1/paltest_wsplitpath_test1
+c_runtime/_wtoi/test1/paltest_wtoi_test1
+c_runtime/__iscsym/test1/paltest_iscsym_test1
+debug_api/OutputDebugStringW/test1/paltest_outputdebugstringw_test1
+exception_handling/RaiseException/test1/paltest_raiseexception_test1
+exception_handling/RaiseException/test2/paltest_raiseexception_test2
+exception_handling/RaiseException/test3/paltest_raiseexception_test3
+exception_handling/pal_sxs/test1/paltest_pal_sxs_test1
+filemapping_memmgt/CreateFileMappingA/test1/paltest_createfilemappinga_test1
+filemapping_memmgt/CreateFileMappingA/test3/paltest_createfilemappinga_test3
+filemapping_memmgt/CreateFileMappingA/test4/paltest_createfilemappinga_test4
+filemapping_memmgt/CreateFileMappingA/test8/paltest_createfilemappinga_test8
+filemapping_memmgt/CreateFileMappingA/test9/paltest_createfilemappinga_test9
+filemapping_memmgt/CreateFileMappingW/test1/paltest_createfilemappingw_test1
+filemapping_memmgt/CreateFileMappingW/test3/paltest_createfilemappingw_test3
+filemapping_memmgt/CreateFileMappingW/test4/paltest_createfilemappingw_test4
+filemapping_memmgt/CreateFileMappingW/test8/paltest_createfilemappingw_test8
+filemapping_memmgt/CreateFileMappingW/test9/paltest_createfilemappingw_test9
+filemapping_memmgt/FreeLibrary/test2/paltest_freelibrary_test2
+filemapping_memmgt/GetModuleFileNameA/test2/paltest_getmodulefilenamea_test2
+filemapping_memmgt/GetModuleFileNameW/test2/paltest_getmodulefilenamew_test2
+filemapping_memmgt/GetProcessHeap/test1/paltest_getprocessheap_test1
+filemapping_memmgt/HeapAlloc/test1/paltest_heapalloc_test1
+filemapping_memmgt/HeapAlloc/test2/paltest_heapalloc_test2
+filemapping_memmgt/HeapAlloc/test3/paltest_heapalloc_test3
+filemapping_memmgt/HeapFree/test1/paltest_heapfree_test1
+filemapping_memmgt/HeapReAlloc/test1/paltest_heaprealloc_test1
+filemapping_memmgt/HeapReAlloc/test2/paltest_heaprealloc_test2
+filemapping_memmgt/HeapReAlloc/test3/paltest_heaprealloc_test3
+filemapping_memmgt/HeapReAlloc/test4/paltest_heaprealloc_test4
+filemapping_memmgt/HeapReAlloc/test5/paltest_heaprealloc_test5
+filemapping_memmgt/LocalAlloc/test1/paltest_localalloc_test1
+filemapping_memmgt/LocalFree/test1/paltest_localfree_test1
+filemapping_memmgt/LocalFree/test2/paltest_localfree_test2
+filemapping_memmgt/LockFile/test2/paltest_lockfile_test2
+filemapping_memmgt/LockFile/test7/paltest_lockfile_test7
+filemapping_memmgt/MapViewOfFile/test2/paltest_mapviewoffile_test2
+filemapping_memmgt/MapViewOfFile/test3/paltest_mapviewoffile_test3
+filemapping_memmgt/MapViewOfFile/test4/paltest_mapviewoffile_test4
+filemapping_memmgt/MapViewOfFile/test5/paltest_mapviewoffile_test5
+filemapping_memmgt/MapViewOfFile/test6/paltest_mapviewoffile_test6
+filemapping_memmgt/RtlMoveMemory/test1/paltest_rtlmovememory_test1
+filemapping_memmgt/RtlMoveMemory/test3/paltest_rtlmovememory_test3
+filemapping_memmgt/RtlMoveMemory/test4/paltest_rtlmovememory_test4
+filemapping_memmgt/RtlMoveMemory/test5/paltest_rtlmovememory_test5
+filemapping_memmgt/UnlockFile/test2/paltest_unlockfile_test2
+filemapping_memmgt/UnlockFile/test4/paltest_unlockfile_test4
+filemapping_memmgt/UnmapViewOfFile/test1/paltest_unmapviewoffile_test1
+filemapping_memmgt/UnmapViewOfFile/test2/paltest_unmapviewoffile_test2
+filemapping_memmgt/VirtualAlloc/test1/paltest_virtualalloc_test1
+filemapping_memmgt/VirtualAlloc/test10/paltest_virtualalloc_test10
+filemapping_memmgt/VirtualAlloc/test11/paltest_virtualalloc_test11
+filemapping_memmgt/VirtualAlloc/test12/paltest_virtualalloc_test12
+filemapping_memmgt/VirtualAlloc/test13/paltest_virtualalloc_test13
+filemapping_memmgt/VirtualAlloc/test14/paltest_virtualalloc_test14
+filemapping_memmgt/VirtualAlloc/test15/paltest_virtualalloc_test15
+filemapping_memmgt/VirtualAlloc/test16/paltest_virtualalloc_test16
+filemapping_memmgt/VirtualAlloc/test17/paltest_virtualalloc_test17
+filemapping_memmgt/VirtualAlloc/test18/paltest_virtualalloc_test18
+filemapping_memmgt/VirtualAlloc/test19/paltest_virtualalloc_test19
+filemapping_memmgt/VirtualAlloc/test2/paltest_virtualalloc_test2
+filemapping_memmgt/VirtualAlloc/test20/paltest_virtualalloc_test20
+filemapping_memmgt/VirtualAlloc/test21/paltest_virtualalloc_test21
+filemapping_memmgt/VirtualAlloc/test3/paltest_virtualalloc_test3
+filemapping_memmgt/VirtualAlloc/test4/paltest_virtualalloc_test4
+filemapping_memmgt/VirtualAlloc/test5/paltest_virtualalloc_test5
+filemapping_memmgt/VirtualAlloc/test6/paltest_virtualalloc_test6
+filemapping_memmgt/VirtualAlloc/test7/paltest_virtualalloc_test7
+filemapping_memmgt/VirtualAlloc/test8/paltest_virtualalloc_test8
+filemapping_memmgt/VirtualAlloc/test9/paltest_virtualalloc_test9
+filemapping_memmgt/VirtualFree/test1/paltest_virtualfree_test1
+filemapping_memmgt/VirtualFree/test2/paltest_virtualfree_test2
+filemapping_memmgt/VirtualFree/test3/paltest_virtualfree_test3
+filemapping_memmgt/VirtualProtect/test1/paltest_virtualprotect_test1
+filemapping_memmgt/VirtualProtect/test2/paltest_virtualprotect_test2
+filemapping_memmgt/VirtualProtect/test3/paltest_virtualprotect_test3
+filemapping_memmgt/VirtualProtect/test4/paltest_virtualprotect_test4
+filemapping_memmgt/VirtualProtect/test6/paltest_virtualprotect_test6
+filemapping_memmgt/VirtualProtect/test7/paltest_virtualprotect_test7
+filemapping_memmgt/VirtualQuery/test1/paltest_virtualquery_test1
+file_io/AreFileApisANSI/test1/paltest_arefileapisansi_test1
+file_io/CompareFileTime/test1/paltest_comparefiletime_test1
+file_io/CopyFileA/test1/paltest_copyfilea_test1
+file_io/CopyFileA/test2/paltest_copyfilea_test2
+file_io/CopyFileA/test3/paltest_copyfilea_test3
+file_io/CopyFileA/test4/paltest_copyfilea_test4
+file_io/CopyFileW/test2/paltest_copyfilew_test2
+file_io/CopyFileW/test3/paltest_copyfilew_test3
+file_io/CreateDirectoryA/test1/paltest_createdirectorya_test1
+file_io/CreateDirectoryW/test1/paltest_createdirectoryw_test1
+file_io/DeleteFileA/test1/paltest_deletefilea_test1
+file_io/DeleteFileW/test1/paltest_deletefilew_test1
+file_io/errorpathnotfound/test2/paltest_errorpathnotfound_test2
+file_io/errorpathnotfound/test3/paltest_errorpathnotfound_test3
+file_io/FILECanonicalizePath/paltest_filecanonicalizepath_test1
+file_io/FileTimeToDosDateTime/test1/paltest_filetimetodosdatetime_test1
+file_io/FindClose/test1/paltest_findclose_test1
+file_io/FindFirstFileA/test1/paltest_findfirstfilea_test1
+file_io/FindFirstFileW/test1/paltest_findfirstfilew_test1
+file_io/FindNextFileA/test1/paltest_findnextfilea_test1
+file_io/FindNextFileA/test2/paltest_findnextfilea_test2
+file_io/FindNextFileW/test1/paltest_findnextfilew_test1
+file_io/FindNextFileW/test2/paltest_findnextfilew_test2
+file_io/FlushFileBuffers/test1/paltest_flushfilebuffers_test1
+file_io/GetConsoleCP/test1/paltest_getconsolecp_test1
+file_io/GetConsoleOutputCP/test1/paltest_getconsoleoutputcp_test1
+file_io/GetCurrentDirectoryA/test1/paltest_getcurrentdirectorya_test1
+file_io/GetCurrentDirectoryW/test1/paltest_getcurrentdirectoryw_test1
+file_io/GetDiskFreeSpaceW/test1/paltest_getdiskfreespacew_test1
+file_io/GetDiskFreeSpaceW/test2/paltest_getdiskfreespacew_test2
+file_io/GetFileAttributesA/test1/paltest_getfileattributesa_test1
+file_io/GetFileAttributesExW/test2/paltest_getfileattributesexw_test2
+file_io/GetFileAttributesW/test1/paltest_getfileattributesw_test1
+file_io/GetFileSize/test1/paltest_getfilesize_test1
+file_io/GetFileSizeEx/test1/paltest_getfilesizeex_test1
+file_io/GetFileTime/test1/paltest_getfiletime_test1
+file_io/GetFileTime/test2/paltest_getfiletime_test2
+file_io/GetFileTime/test3/paltest_getfiletime_test3
+file_io/GetFileTime/test4/paltest_getfiletime_test4
+file_io/GetFileTime/test5/paltest_getfiletime_test5
+file_io/GetFileTime/test6/paltest_getfiletime_test6
+file_io/GetFileTime/test7/paltest_getfiletime_test7
+file_io/GetFileType/test1/paltest_getfiletype_test1
+file_io/GetFileType/test2/paltest_getfiletype_test2
+file_io/GetFileType/test3/paltest_getfiletype_test3
+file_io/GetFullPathNameA/test1/paltest_getfullpathnamea_test1
+file_io/GetFullPathNameA/test3/paltest_getfullpathnamea_test3
+file_io/GetFullPathNameA/test4/paltest_getfullpathnamea_test4
+file_io/GetFullPathNameW/test1/paltest_getfullpathnamew_test1
+file_io/GetFullPathNameW/test3/paltest_getfullpathnamew_test3
+file_io/GetFullPathNameW/test4/paltest_getfullpathnamew_test4
+file_io/GetLongPathNameW/test1/paltest_getlongpathnamew_test1
+file_io/GetLongPathNameW/test2/paltest_getlongpathnamew_test2
+file_io/GetStdHandle/test2/paltest_getstdhandle_test2
+file_io/GetSystemTime/test1/paltest_getsystemtime_test1
+file_io/GetSystemTimeAsFileTime/test1/paltest_getsystemtimeasfiletime_test1
+file_io/GetTempFileNameA/test1/paltest_gettempfilenamea_test1
+file_io/GetTempFileNameA/test2/paltest_gettempfilenamea_test2
+file_io/GetTempFileNameA/test3/paltest_gettempfilenamea_test3
+file_io/GetTempFileNameW/test3/paltest_gettempfilenamew_test3
+file_io/gettemppatha/test1/paltest_gettemppatha_test1
+file_io/GetTempPathW/test1/paltest_gettemppathw_test1
+file_io/ReadFile/test2/paltest_readfile_test2
+file_io/ReadFile/test3/paltest_readfile_test3
+file_io/ReadFile/test4/paltest_readfile_test4
+file_io/RemoveDirectoryA/test1/paltest_removedirectorya_test1
+file_io/RemoveDirectoryW/test1/paltest_removedirectoryw_test1
+file_io/SearchPathA/test1/paltest_searchpatha_test1
+file_io/SearchPathW/test1/paltest_searchpathw_test1
+file_io/SetCurrentDirectoryA/test1/paltest_setcurrentdirectorya_test1
+file_io/SetCurrentDirectoryA/test2/paltest_setcurrentdirectorya_test2
+file_io/SetCurrentDirectoryA/test3/paltest_setcurrentdirectorya_test3
+file_io/SetCurrentDirectoryW/test1/paltest_setcurrentdirectoryw_test1
+file_io/SetCurrentDirectoryW/test2/paltest_setcurrentdirectoryw_test2
+file_io/SetCurrentDirectoryW/test3/paltest_setcurrentdirectoryw_test3
+file_io/SetEndOfFile/test1/paltest_setendoffile_test1
+file_io/SetEndOfFile/test2/paltest_setendoffile_test2
+file_io/SetEndOfFile/test3/paltest_setendoffile_test3
+file_io/SetEndOfFile/test4/paltest_setendoffile_test4
+file_io/SetEndOfFile/test5/paltest_setendoffile_test5
+file_io/SetFileAttributesA/test2/paltest_setfileattributesa_test2
+file_io/SetFileAttributesA/test3/paltest_setfileattributesa_test3
+file_io/SetFileAttributesW/test2/paltest_setfileattributesw_test2
+file_io/SetFileAttributesW/test3/paltest_setfileattributesw_test3
+file_io/SetFilePointer/test1/paltest_setfilepointer_test1
+file_io/SetFilePointer/test2/paltest_setfilepointer_test2
+file_io/SetFilePointer/test3/paltest_setfilepointer_test3
+file_io/SetFilePointer/test4/paltest_setfilepointer_test4
+file_io/SetFilePointer/test5/paltest_setfilepointer_test5
+file_io/SetFilePointer/test6/paltest_setfilepointer_test6
+file_io/SetFilePointer/test7/paltest_setfilepointer_test7
+file_io/SetFileTime/test1/paltest_setfiletime_test1
+file_io/SetFileTime/test2/paltest_setfiletime_test2
+file_io/SetFileTime/test3/paltest_setfiletime_test3
+file_io/SetFileTime/test4/paltest_setfiletime_test4
+file_io/WriteFile/test1/paltest_writefile_test1
+file_io/WriteFile/test3/paltest_writefile_test3
+file_io/WriteFile/test4/paltest_writefile_test4
+file_io/WriteFile/test5/paltest_writefile_test5
+loader/LoadLibraryA/test2/paltest_loadlibrarya_test2
+loader/LoadLibraryA/test3/paltest_loadlibrarya_test3
+loader/LoadLibraryA/test5/paltest_loadlibrarya_test5
+loader/LoadLibraryW/test2/paltest_loadlibraryw_test2
+loader/LoadLibraryW/test3/paltest_loadlibraryw_test3
+loader/LoadLibraryW/test5/paltest_loadlibraryw_test5
+locale_info/GetACP/test1/paltest_getacp_test1
+locale_info/GetCPInfo/test1/paltest_getcpinfo_test1
+locale_info/GetCPInfo/test3/paltest_getcpinfo_test3
+locale_info/IsDBCSLeadByte/test1/paltest_isdbcsleadbyte_test1
+locale_info/IsDBCSLeadByteEx/test1/paltest_isdbcsleadbyteex_test1
+locale_info/IsValidCodePage/test1/paltest_isvalidcodepage_test1
+locale_info/MultiByteToWideChar/test1/paltest_multibytetowidechar_test1
+locale_info/MultiByteToWideChar/test2/paltest_multibytetowidechar_test2
+locale_info/MultiByteToWideChar/test3/paltest_multibytetowidechar_test3
+locale_info/MultiByteToWideChar/test4/paltest_multibytetowidechar_test4
+locale_info/WideCharToMultiByte/test1/paltest_widechartomultibyte_test1
+locale_info/WideCharToMultiByte/test2/paltest_widechartomultibyte_test2
+locale_info/WideCharToMultiByte/test3/paltest_widechartomultibyte_test3
+locale_info/WideCharToMultiByte/test5/paltest_widechartomultibyte_test5
+miscellaneous/CharNextA/test1/paltest_charnexta_test1
+miscellaneous/CharNextA/test2/paltest_charnexta_test2
+miscellaneous/CharNextExA/test1/paltest_charnextexa_test1
+miscellaneous/CharNextExA/test2/paltest_charnextexa_test2
+miscellaneous/CloseHandle/test1/paltest_closehandle_test1
+miscellaneous/CloseHandle/test2/paltest_closehandle_test2
+miscellaneous/CreatePipe/test1/paltest_createpipe_test1
+miscellaneous/FlushInstructionCache/test1/paltest_flushinstructioncache_test1
+miscellaneous/FormatMessageW/test1/paltest_formatmessagew_test1
+miscellaneous/FormatMessageW/test2/paltest_formatmessagew_test2
+miscellaneous/FormatMessageW/test3/paltest_formatmessagew_test3
+miscellaneous/FreeEnvironmentStringsW/test1/paltest_freeenvironmentstringsw_test1
+miscellaneous/FreeEnvironmentStringsW/test2/paltest_freeenvironmentstringsw_test2
+miscellaneous/GetCommandLineW/test1/paltest_getcommandlinew_test1
+miscellaneous/GetComputerNameW/test1/paltest_getcomputernamew_test1
+miscellaneous/GetEnvironmentStringsW/test1/paltest_getenvironmentstringsw_test1
+miscellaneous/GetEnvironmentVariableA/test1/paltest_getenvironmentvariablea_test1
+miscellaneous/GetEnvironmentVariableA/test2/paltest_getenvironmentvariablea_test2
+miscellaneous/GetEnvironmentVariableA/test3/paltest_getenvironmentvariablea_test3
+miscellaneous/GetEnvironmentVariableA/test4/paltest_getenvironmentvariablea_test4
+miscellaneous/GetEnvironmentVariableA/test5/paltest_getenvironmentvariablea_test5
+miscellaneous/GetEnvironmentVariableA/test6/paltest_getenvironmentvariablea_test6
+miscellaneous/GetEnvironmentVariableW/test1/paltest_getenvironmentvariablew_test1
+miscellaneous/GetEnvironmentVariableW/test2/paltest_getenvironmentvariablew_test2
+miscellaneous/GetEnvironmentVariableW/test3/paltest_getenvironmentvariablew_test3
+miscellaneous/GetEnvironmentVariableW/test4/paltest_getenvironmentvariablew_test4
+miscellaneous/GetEnvironmentVariableW/test5/paltest_getenvironmentvariablew_test5
+miscellaneous/GetEnvironmentVariableW/test6/paltest_getenvironmentvariablew_test6
+miscellaneous/GetLastError/test1/paltest_getlasterror_test1
+miscellaneous/GetSystemInfo/test1/paltest_getsysteminfo_test1
+miscellaneous/GetTickCount/test1/paltest_gettickcount_test1
+miscellaneous/InterlockedCompareExchange/test1/paltest_interlockedcompareexchange_test1
+miscellaneous/InterlockedCompareExchange/test2/paltest_interlockedcompareexchange_test2
+miscellaneous/InterlockedCompareExchange64/test1/paltest_interlockedcompareexchange64_test1
+miscellaneous/InterlockedCompareExchange64/test2/paltest_interlockedcompareexchange64_test2
+miscellaneous/InterlockedCompareExchangePointer/test1/paltest_interlockedcompareexchangepointer_test1
+miscellaneous/InterlockedDecrement/test1/paltest_interlockeddecrement_test1
+miscellaneous/InterlockedDecrement/test2/paltest_interlockeddecrement_test2
+miscellaneous/InterlockedDecrement64/test1/paltest_interlockeddecrement64_test1
+miscellaneous/InterlockedDecrement64/test2/paltest_interlockeddecrement64_test2
+miscellaneous/InterlockedExchange/test1/paltest_interlockedexchange_test1
+miscellaneous/InterlockedExchange64/test1/paltest_interlockedexchange64_test1
+miscellaneous/InterlockedExchangePointer/test1/paltest_interlockedexchangepointer_test1
+miscellaneous/InterlockedIncrement/test1/paltest_interlockedincrement_test1
+miscellaneous/InterlockedIncrement/test2/paltest_interlockedincrement_test2
+miscellaneous/InterlockedIncrement64/test1/paltest_interlockedincrement64_test1
+miscellaneous/InterlockedIncrement64/test2/paltest_interlockedincrement64_test2
+miscellaneous/lstrcatW/test1/paltest_lstrcatw_test1
+miscellaneous/lstrcatW/test2/paltest_lstrcatw_test2
+miscellaneous/lstrcatW/test3/paltest_lstrcatw_test3
+miscellaneous/lstrcatW/test4/paltest_lstrcatw_test4
+miscellaneous/lstrcpynW/test1/paltest_lstrcpynw_test1
+miscellaneous/lstrcpyW/test1/paltest_lstrcpyw_test1
+miscellaneous/lstrlenA/test1/paltest_lstrlena_test1
+miscellaneous/lstrlenW/test1/paltest_lstrlenw_test1
+miscellaneous/queryperformancecounter/test1/paltest_queryperformancecounter_test1
+miscellaneous/queryperformancefrequency/test1/paltest_queryperformancefrequency_test1
+miscellaneous/SetEnvironmentVariableA/test1/paltest_setenvironmentvariablea_test1
+miscellaneous/SetEnvironmentVariableA/test2/paltest_setenvironmentvariablea_test2
+miscellaneous/SetEnvironmentVariableA/test3/paltest_setenvironmentvariablea_test3
+miscellaneous/SetEnvironmentVariableA/test4/paltest_setenvironmentvariablea_test4
+miscellaneous/SetEnvironmentVariableW/test1/paltest_setenvironmentvariablew_test1
+miscellaneous/SetEnvironmentVariableW/test2/paltest_setenvironmentvariablew_test2
+miscellaneous/SetEnvironmentVariableW/test3/paltest_setenvironmentvariablew_test3
+miscellaneous/SetEnvironmentVariableW/test4/paltest_setenvironmentvariablew_test4
+miscellaneous/SetLastError/test1/paltest_setlasterror_test1
+miscellaneous/wsprintfA/test1/paltest_wsprintfa_test1
+miscellaneous/wsprintfA/test11/paltest_wsprintfa_test11
+miscellaneous/wsprintfA/test12/paltest_wsprintfa_test12
+miscellaneous/wsprintfA/test13/paltest_wsprintfa_test13
+miscellaneous/wsprintfA/test2/paltest_wsprintfa_test2
+miscellaneous/wsprintfA/test3/paltest_wsprintfa_test3
+miscellaneous/wsprintfA/test6/paltest_wsprintfa_test6
+miscellaneous/wsprintfA/test7/paltest_wsprintfa_test7
+miscellaneous/wsprintfA/test8/paltest_wsprintfa_test8
+miscellaneous/wsprintfA/test9/paltest_wsprintfa_test9
+miscellaneous/wsprintfW/test1/paltest_wsprintfw_test1
+miscellaneous/wsprintfW/test11/paltest_wsprintfw_test11
+miscellaneous/wsprintfW/test12/paltest_wsprintfw_test12
+miscellaneous/wsprintfW/test13/paltest_wsprintfw_test13
+miscellaneous/wsprintfW/test3/paltest_wsprintfw_test3
+miscellaneous/wsprintfW/test6/paltest_wsprintfw_test6
+miscellaneous/wsprintfW/test8/paltest_wsprintfw_test8
+miscellaneous/wsprintfW/test9/paltest_wsprintfw_test9
+miscellaneous/_i64tow/test1/paltest_i64tow_test1
+miscellaneous/_ui64tow/test1/paltest_ui64tow_test1
+miscellaneous/_ui64tow/test2/paltest_ui64tow_test2
+pal_specific/pal_entrypoint/test1/paltest_pal_entrypoint_test1
+pal_specific/PAL_errno/test1/paltest_pal_errno_test1
+pal_specific/pal_initializedebug/test1/paltest_pal_initializedebug_test1
+pal_specific/PAL_Initialize_Terminate/test1/paltest_pal_initialize_terminate_test1
+pal_specific/PAL_Initialize_Terminate/test2/paltest_pal_initialize_terminate_test2
+samples/test1/paltest_samples_test1
+threading/CreateEventA/test1/paltest_createeventa_test1
+threading/CreateEventA/test2/paltest_createeventa_test2
+threading/CreateEventW/test1/paltest_createeventw_test1
+threading/CreateEventW/test2/paltest_createeventw_test2
+threading/CreateMutexA_ReleaseMutex/test1/paltest_createmutexa_releasemutex_test1
+threading/CreateMutexW_ReleaseMutex/test1/paltest_createmutexw_releasemutex_test1
+threading/CreateProcessA/test1/paltest_createprocessa_test1
+threading/CreateProcessA/test2/paltest_createprocessa_test2
+threading/CreateProcessW/test1/paltest_createprocessw_test1
+threading/CreateProcessW/test2/paltest_createprocessw_test2
+threading/CreateSemaphoreA_ReleaseSemaphore/test1/paltest_createsemaphorea_releasesemaphore_test1
+threading/CreateSemaphoreA_ReleaseSemaphore/test2/paltest_createsemaphorea_releasesemaphore_test2
+threading/CreateSemaphoreW_ReleaseSemaphore/test1/paltest_createsemaphorew_releasesemaphore_test1
+threading/CreateSemaphoreW_ReleaseSemaphore/test2/paltest_createsemaphorew_releasesemaphore_test2
+threading/CreateThread/test1/paltest_createthread_test1
+threading/CreateThread/test3/paltest_createthread_test3
+threading/CriticalSectionFunctions/test1/paltest_criticalsectionfunctions_test1
+threading/CriticalSectionFunctions/test2/paltest_criticalsectionfunctions_test2
+threading/CriticalSectionFunctions/test3/paltest_criticalsectionfunctions_test3
+threading/CriticalSectionFunctions/test4/paltest_criticalsectionfunctions_test4
+threading/CriticalSectionFunctions/test7/paltest_criticalsectionfunctions_test7
+threading/CriticalSectionFunctions/test8/paltest_criticalsectionfunctions_test8
+threading/DuplicateHandle/test10/paltest_duplicatehandle_test10
+threading/DuplicateHandle/test2/paltest_duplicatehandle_test2
+threading/DuplicateHandle/test4/paltest_duplicatehandle_test4
+threading/DuplicateHandle/test5/paltest_duplicatehandle_test5
+threading/DuplicateHandle/test6/paltest_duplicatehandle_test6
+threading/DuplicateHandle/test7/paltest_duplicatehandle_test7
+threading/DuplicateHandle/test8/paltest_duplicatehandle_test8
+threading/ExitProcess/test1/paltest_exitprocess_test1
+threading/ExitProcess/test2/paltest_exitprocess_test2
+threading/ExitProcess/test3/paltest_exitprocess_test3
+threading/ExitThread/test1/paltest_exitthread_test1
+threading/GetCurrentProcessId/test1/paltest_getcurrentprocessid_test1
+threading/GetCurrentThread/test1/paltest_getcurrentthread_test1
+threading/GetCurrentThread/test2/paltest_getcurrentthread_test2
+threading/GetProcessTimes/test2/paltest_getprocesstimes_test2
+threading/GetThreadTimes/test1/paltest_getthreadtimes_test1
+threading/NamedMutex/test1/paltest_namedmutex_test1
+threading/QueryThreadCycleTime/test1/paltest_querythreadcycletime_test1
+threading/QueueUserAPC/test2/paltest_queueuserapc_test2
+threading/QueueUserAPC/test3/paltest_queueuserapc_test3
+threading/QueueUserAPC/test4/paltest_queueuserapc_test4
+threading/QueueUserAPC/test5/paltest_queueuserapc_test5
+threading/QueueUserAPC/test6/paltest_queueuserapc_test6
+threading/QueueUserAPC/test7/paltest_queueuserapc_test7
+threading/ReleaseMutex/test3/paltest_releasemutex_test3
+threading/releasesemaphore/test1/paltest_releasesemaphore_test1
+threading/ResetEvent/test1/paltest_resetevent_test1
+threading/ResetEvent/test2/paltest_resetevent_test2
+threading/ResetEvent/test3/paltest_resetevent_test3
+threading/ResetEvent/test4/paltest_resetevent_test4
+threading/ResumeThread/test1/paltest_resumethread_test1
+threading/SetErrorMode/test1/paltest_seterrormode_test1
+threading/SetEvent/test1/paltest_setevent_test1
+threading/SetEvent/test2/paltest_setevent_test2
+threading/SetEvent/test3/paltest_setevent_test3
+threading/SetEvent/test4/paltest_setevent_test4
+threading/Sleep/test1/paltest_sleep_test1
+threading/SleepEx/test1/paltest_sleepex_test1
+threading/SleepEx/test2/paltest_sleepex_test2
+threading/SwitchToThread/test1/paltest_switchtothread_test1
+threading/ThreadPriority/test1/paltest_threadpriority_test1
+threading/TLS/test1/paltest_tls_test1
+threading/TLS/test2/paltest_tls_test2
+threading/TLS/test3/paltest_tls_test3
+threading/TLS/test4/paltest_tls_test4
+threading/TLS/test5/paltest_tls_test5
+threading/WaitForMultipleObjects/test1/paltest_waitformultipleobjects_test1
+threading/WaitForMultipleObjectsEx/test1/paltest_waitformultipleobjectsex_test1
+threading/WaitForMultipleObjectsEx/test2/paltest_waitformultipleobjectsex_test2
+threading/WaitForMultipleObjectsEx/test3/paltest_waitformultipleobjectsex_test3
+threading/WaitForMultipleObjectsEx/test4/paltest_waitformultipleobjectsex_test4
+threading/WaitForSingleObject/test1/paltest_waitforsingleobject_test1
+threading/WaitForSingleObject/WFSOExMutexTest/paltest_waitforsingleobject_wfsoexmutextest
+threading/WaitForSingleObject/WFSOExSemaphoreTest/paltest_waitforsingleobject_wfsoexsemaphoretest
+threading/WaitForSingleObject/WFSOExThreadTest/paltest_waitforsingleobject_wfsoexthreadtest
+threading/WaitForSingleObject/WFSOMutexTest/paltest_waitforsingleobject_wfsomutextest
+threading/WaitForSingleObject/WFSOSemaphoreTest/paltest_waitforsingleobject_wfsosemaphoretest
+threading/WaitForSingleObject/WFSOThreadTest/paltest_waitforsingleobject_wfsothreadtest
+threading/YieldProcessor/test1/paltest_yieldprocessor_test1
+eventprovider/eventprovidertest
diff --git a/src/pal/tests/palsuite/paltestlist_to_be_reviewed.txt b/src/pal/tests/palsuite/paltestlist_to_be_reviewed.txt
new file mode 100644
index 0000000000..ac0a2ee4eb
--- /dev/null
+++ b/src/pal/tests/palsuite/paltestlist_to_be_reviewed.txt
@@ -0,0 +1,201 @@
+This is a list of failing PAL tests that need to be reviewed because.
+They should either be fixed or deleted if they are no longer applicable.
+
+c_runtime/ctime/test1/paltest_ctime_test1
+c_runtime/exit/test2/paltest_exit_test2
+c_runtime/feof/test1/paltest_feof_test1
+c_runtime/ferror/test1/paltest_ferror_test1
+c_runtime/ferror/test2/paltest_ferror_test2
+c_runtime/fputs/test2/paltest_fputs_test2
+c_runtime/fread/test1/paltest_fread_test1
+c_runtime/fread/test2/paltest_fread_test2
+c_runtime/fread/test3/paltest_fread_test3
+c_runtime/ftell/test1/paltest_ftell_test1
+c_runtime/fwprintf/test19/paltest_fwprintf_test19
+c_runtime/fwprintf/test2/paltest_fwprintf_test2
+c_runtime/fwprintf/test7/paltest_fwprintf_test7
+c_runtime/iswprint/test1/paltest_iswprint_test1
+c_runtime/swprintf/test2/paltest_swprintf_test2
+c_runtime/swprintf/test7/paltest_swprintf_test7
+c_runtime/ungetc/test2/paltest_ungetc_test2
+c_runtime/vprintf/test1/paltest_vprintf_test1
+c_runtime/vswprintf/test2/paltest_vswprintf_test2
+c_runtime/vswprintf/test7/paltest_vswprintf_test7
+c_runtime/wprintf/test2/paltest_wprintf_test2
+c_runtime/_ecvt/test1/paltest_ecvt_test1
+c_runtime/_gcvt/test1/paltest_gcvt_test1
+c_runtime/_gcvt/test2/paltest_gcvt_test2
+c_runtime/_getw/test1/paltest_getw_test1
+c_runtime/_snwprintf/test2/paltest_snwprintf_test2
+c_runtime/_snwprintf/test7/paltest_snwprintf_test7
+c_runtime/_vsnwprintf/test2/paltest_vsnwprintf_test2
+c_runtime/_vsnwprintf/test7/paltest_vsnwprintf_test7
+c_runtime/_wmakepath/test1/paltest_wmakepath_test1
+debug_api/DebugBreak/test1/paltest_debugbreak_test1
+debug_api/OutputDebugStringA/test1/paltest_outputdebugstringa_test1
+debug_api/WriteProcessMemory/test1/paltest_writeprocessmemory_test1
+debug_api/WriteProcessMemory/test3/paltest_writeprocessmemory_test3
+debug_api/WriteProcessMemory/test4/paltest_writeprocessmemory_test4
+exception_handling/pal_except/test1/paltest_pal_except_test1
+exception_handling/pal_except/test2/paltest_pal_except_test2
+exception_handling/pal_except/test3/paltest_pal_except_test3
+exception_handling/pal_except/test4/paltest_pal_except_test4
+exception_handling/pal_except/test5/paltest_pal_except_test5
+exception_handling/pal_except/test6/paltest_pal_except_test6
+exception_handling/pal_except/test7/paltest_pal_except_test7
+exception_handling/PAL_EXCEPT_FILTER/test1/paltest_pal_except_filter_test1
+exception_handling/PAL_EXCEPT_FILTER/test2/paltest_pal_except_filter_test2
+exception_handling/PAL_EXCEPT_FILTER/test3/paltest_pal_except_filter_test3
+exception_handling/PAL_EXCEPT_FILTER_EX/test1/paltest_pal_except_filter_ex_test1
+exception_handling/PAL_EXCEPT_FILTER_EX/test2/paltest_pal_except_filter_ex_test2
+exception_handling/PAL_EXCEPT_FILTER_EX/test3/paltest_pal_except_filter_ex_test3
+exception_handling/pal_finally/test1/paltest_pal_finally_test1
+exception_handling/PAL_GetBottommostRegistration/test1/paltest_pal_getbottommostregistration_test1
+exception_handling/PAL_GetBottommostRegistration/test2/paltest_pal_getbottommostregistration_test2
+exception_handling/PAL_TRY_EXCEPT/test1/paltest_pal_try_except_test1
+exception_handling/PAL_TRY_EXCEPT/test2/paltest_pal_try_except_test2
+exception_handling/PAL_TRY_EXCEPT_EX/test1/paltest_pal_try_except_ex_test1
+exception_handling/PAL_TRY_EXCEPT_EX/test2/paltest_pal_try_except_ex_test2
+exception_handling/PAL_TRY_EXCEPT_EX/test3/paltest_pal_try_except_ex_test3
+exception_handling/PAL_TRY_LEAVE_FINALLY/test1/paltest_pal_try_leave_finally_test1
+exception_handling/SetUnhandledExceptionFilter/test1/paltest_setunhandledexceptionfilter_test1
+filemapping_memmgt/CreateFileMappingA/test5/paltest_createfilemappinga_test5
+filemapping_memmgt/CreateFileMappingA/test6/paltest_createfilemappinga_test6
+filemapping_memmgt/CreateFileMappingA/test7/paltest_createfilemappinga_test7
+filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/paltest_createfilemappingw_createfilemapping_neg1
+filemapping_memmgt/CreateFileMappingW/test2/paltest_createfilemappingw_test2
+filemapping_memmgt/CreateFileMappingW/test5/paltest_createfilemappingw_test5
+filemapping_memmgt/CreateFileMappingW/test6/paltest_createfilemappingw_test6
+filemapping_memmgt/CreateFileMappingW/test7/paltest_createfilemappingw_test7
+filemapping_memmgt/FreeLibrary/test1/paltest_freelibrary_test1
+filemapping_memmgt/FreeLibraryAndExitThread/test1/paltest_freelibraryandexitthread_test1
+filemapping_memmgt/GetModuleFileNameA/test1/paltest_getmodulefilenamea_test1
+filemapping_memmgt/GetModuleFileNameW/test1/paltest_getmodulefilenamew_test1
+filemapping_memmgt/GetProcAddress/test1/paltest_getprocaddress_test1
+filemapping_memmgt/GetProcAddress/test2/paltest_getprocaddress_test2
+filemapping_memmgt/LockFile/test1/paltest_lockfile_test1
+filemapping_memmgt/LockFile/test3/paltest_lockfile_test3
+filemapping_memmgt/LockFile/test4/paltest_lockfile_test4
+filemapping_memmgt/LockFile/test5/paltest_lockfile_test5
+filemapping_memmgt/LockFile/test6/paltest_lockfile_test6
+filemapping_memmgt/OpenFileMappingA/test1/paltest_openfilemappinga_test1
+filemapping_memmgt/OpenFileMappingA/test2/paltest_openfilemappinga_test2
+filemapping_memmgt/OpenFileMappingA/test3/paltest_openfilemappinga_test3
+filemapping_memmgt/OpenFileMappingW/test1/paltest_openfilemappingw_test1
+filemapping_memmgt/OpenFileMappingW/test2/paltest_openfilemappingw_test2
+filemapping_memmgt/OpenFileMappingW/test3/paltest_openfilemappingw_test3
+filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/paltest_readprocessmemory_readprocessmemory_neg1
+filemapping_memmgt/ReadProcessMemory/test1/paltest_readprocessmemory_test1
+filemapping_memmgt/ReadProcessMemory/test2/paltest_readprocessmemory_test2
+filemapping_memmgt/UnlockFile/test1/paltest_unlockfile_test1
+filemapping_memmgt/UnlockFile/test3/paltest_unlockfile_test3
+file_io/CopyFileW/test1/paltest_copyfilew_test1
+file_io/CreateDirectoryA/test2/paltest_createdirectorya_test2
+file_io/CreateDirectoryW/test2/paltest_createdirectoryw_test2
+file_io/CreateFileA/test1/paltest_createfilea_test1
+file_io/CreateFileW/test1/paltest_createfilew_test1
+file_io/errorpathnotfound/test1/paltest_errorpathnotfound_test1
+file_io/errorpathnotfound/test4/paltest_errorpathnotfound_test4
+file_io/GetFileAttributesExW/test1/paltest_getfileattributesexw_test1
+file_io/GetFullPathNameA/test2/paltest_getfullpathnamea_test2
+file_io/GetFullPathNameW/test2/paltest_getfullpathnamew_test2
+file_io/GetStdHandle/test1/paltest_getstdhandle_test1
+file_io/GetTempFileNameW/test1/paltest_gettempfilenamew_test1
+file_io/GetTempFileNameW/test2/paltest_gettempfilenamew_test2
+file_io/gettemppatha/test1/paltest_gettemppatha_test1
+file_io/GetTempPathW/test1/paltest_gettemppathw_test1
+file_io/MoveFileA/test1/paltest_movefilea_test1
+file_io/MoveFileExA/test1/paltest_movefileexa_test1
+file_io/MoveFileExW/test1/paltest_movefileexw_test1
+file_io/MoveFileW/test1/paltest_movefilew_test1
+file_io/ReadFile/test1/paltest_readfile_test1
+file_io/SetFileAttributesA/test1/paltest_setfileattributesa_test1
+file_io/SetFileAttributesA/test4/paltest_setfileattributesa_test4
+file_io/SetFileAttributesW/test1/paltest_setfileattributesw_test1
+file_io/SetFileAttributesW/test4/paltest_setfileattributesw_test4
+file_io/WriteFile/test2/paltest_writefile_test2
+loader/LoadLibraryA/test1/paltest_loadlibrarya_test1
+loader/LoadLibraryA/test6/paltest_loadlibrarya_test6
+loader/LoadLibraryA/test7/paltest_loadlibrarya_test7
+loader/LoadLibraryA/test8/paltest_loadlibrarya_test8
+loader/LoadLibraryW/test1/paltest_loadlibraryw_test1
+locale_info/CompareStringA/test1/paltest_comparestringa_test1
+locale_info/CompareStringW/test1/paltest_comparestringw_test1
+locale_info/GetCPInfo/test2/paltest_getcpinfo_test2
+locale_info/GetLocaleInfoW/test1/paltest_getlocaleinfow_test1
+locale_info/GetLocaleInfoW/test2/paltest_getlocaleinfow_test2
+locale_info/GetStringTypeExW/test1/paltest_getstringtypeexw_test1
+locale_info/GetStringTypeExW/test2/paltest_getstringtypeexw_test2
+locale_info/GetSystemDefaultLangID/test1/paltest_getsystemdefaultlangid_test1
+locale_info/GetThreadLocale/test1/paltest_getthreadlocale_test1
+locale_info/GetTimeZoneInformation/test1/paltest_gettimezoneinformation_test1
+locale_info/GetUserDefaultLangID/test1/paltest_getuserdefaultlangid_test1
+locale_info/GetUserDefaultLCID/test1/paltest_getuserdefaultlcid_test1
+locale_info/IsValidCodePage/test2/paltest_isvalidcodepage_test2
+locale_info/IsValidLocale/test1/paltest_isvalidlocale_test1
+locale_info/SetThreadLocale/test1/paltest_setthreadlocale_test1
+locale_info/WideCharToMultiByte/test4/paltest_widechartomultibyte_test4
+miscellaneous/FormatMessageW/test4/paltest_formatmessagew_test4
+miscellaneous/FormatMessageW/test5/paltest_formatmessagew_test5
+miscellaneous/FormatMessageW/test6/paltest_formatmessagew_test6
+miscellaneous/GetCalendarInfoW/test1/paltest_getcalendarinfow_test1
+miscellaneous/GetCalendarInfoW/test2/paltest_getcalendarinfow_test2
+miscellaneous/GetComputerNameW/test1/paltest_getcomputernamew_test1
+miscellaneous/GetDateFormatW/GetDateFormatW_neg1/paltest_getdateformatw_getdateformatw_neg1
+miscellaneous/GetDateFormatW/GetDateFormatW_neg2/paltest_getdateformatw_getdateformatw_neg2
+miscellaneous/GetDateFormatW/test1/paltest_getdateformatw_test1
+miscellaneous/GetUserNameW/test1/paltest_getusernamew_test1
+miscellaneous/GetVersionExA/test1/paltest_getversionexa_test1
+miscellaneous/GetVersionExW/test1/paltest_getversionexw_test1
+miscellaneous/InterLockedExchangeAdd/test1/paltest_interlockedexchangeadd_test1
+miscellaneous/IsBadCodePtr/test1/paltest_isbadcodeptr_test1
+miscellaneous/IsBadReadPtr/test1/paltest_isbadreadptr_test1
+miscellaneous/IsBadWritePtr/test1/paltest_isbadwriteptr_test1
+miscellaneous/IsBadWritePtr/test2/paltest_isbadwriteptr_test2
+miscellaneous/IsBadWritePtr/test3/paltest_isbadwriteptr_test3
+miscellaneous/MessageBoxW/test1/paltest_messageboxw_test1
+miscellaneous/MessageBoxW/test2/paltest_messageboxw_test2
+miscellaneous/wsprintfW/test2/paltest_wsprintfw_test2
+miscellaneous/wsprintfW/test7/paltest_wsprintfw_test7
+pal_specific/PAL_GetMachineConfigurationDirectoryW/test1/paltest_pal_getmachineconfigurationdirectoryw_test1
+pal_specific/PAL_GetPALDirectoryW/test1/paltest_pal_getpaldirectoryw_test1
+pal_specific/PAL_GetUserConfigurationDirectoryW/test1/paltest_pal_getuserconfigurationdirectoryw_test1
+pal_specific/PAL_GetUserTempDirectoryW/test1/paltest_pal_getusertempdirectoryw_test1
+pal_specific/PAL_get_stderr/test1/paltest_pal_get_stderr_test1
+pal_specific/PAL_get_stdin/test1/paltest_pal_get_stdin_test1
+pal_specific/PAL_get_stdout/test1/paltest_pal_get_stdout_test1
+pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/paltest_pal_registerlibraryw_unregisterlibraryw_test1
+samples/test2/paltest_samples_test2
+threading/CreateEventA/test3/paltest_createeventa_test3
+threading/CreateEventW/test3/paltest_createeventw_test3
+threading/CreateMutexA_ReleaseMutex/test2/paltest_createmutexa_releasemutex_test2
+threading/CreateMutexW_ReleaseMutex/test2/paltest_createmutexw_releasemutex_test2
+threading/CreateSemaphoreA_ReleaseSemaphore/test3/paltest_createsemaphorea_releasesemaphore_test3
+threading/CreateSemaphoreW_ReleaseSemaphore/test3/paltest_createsemaphorew_releasesemaphore_test3
+threading/CreateThread/test2/paltest_createthread_test2
+threading/CriticalSectionFunctions/test5/paltest_criticalsectionfunctions_test5
+threading/CriticalSectionFunctions/test6/paltest_criticalsectionfunctions_test6
+threading/DuplicateHandle/test1/paltest_duplicatehandle_test1
+threading/DuplicateHandle/test11/paltest_duplicatehandle_test11
+threading/DuplicateHandle/test12/paltest_duplicatehandle_test12
+threading/DuplicateHandle/test3/paltest_duplicatehandle_test3
+threading/DuplicateHandle/test9/paltest_duplicatehandle_test9
+threading/ExitThread/test2/paltest_exitthread_test2
+threading/GetCurrentProcess/test1/paltest_getcurrentprocess_test1
+threading/GetCurrentThreadId/test1/paltest_getcurrentthreadid_test1
+threading/GetExitCodeProcess/test1/paltest_getexitcodeprocess_test1
+threading/OpenEventW/test1/paltest_openeventw_test1
+threading/OpenEventW/test2/paltest_openeventw_test2
+threading/OpenEventW/test3/paltest_openeventw_test3
+threading/OpenEventW/test4/paltest_openeventw_test4
+threading/OpenEventW/test5/paltest_openeventw_test5
+threading/OpenProcess/test1/paltest_openprocess_test1
+threading/QueueUserAPC/test1/paltest_queueuserapc_test1
+threading/setthreadcontext/test1/paltest_setthreadcontext_test1
+threading/SuspendThread/test2/paltest_suspendthread_test2
+threading/SuspendThread/test3/paltest_suspendthread_test3
+threading/TerminateProcess/test1/paltest_terminateprocess_test1
+threading/TLS/test6_optimizedtls/paltest_tls_test6_optimizedtls
+threading/WaitForMultipleObjectsEx/test5/paltest_waitformultipleobjectsex_test5
+threading/WaitForMultipleObjectsEx/test6/paltest_waitformultipleobjectsex_test6
+threading/WaitForSingleObject/WFSOProcessTest/paltest_waitforsingleobject_wfsoprocesstest
diff --git a/src/pal/tests/palsuite/palverify.dat b/src/pal/tests/palsuite/palverify.dat
new file mode 100644
index 0000000000..36b48d66e8
--- /dev/null
+++ b/src/pal/tests/palsuite/palverify.dat
@@ -0,0 +1,889 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+c_runtime/__iscsym/test1,1
+c_runtime/_alloca/test1,1
+c_runtime/_ecvt/test1,1
+c_runtime/_fdopen/test1,1
+c_runtime/_finite/test1,1
+c_runtime/_fullpath/test1,1
+c_runtime/_gcvt/test1,1
+c_runtime/_gcvt/test2,1
+c_runtime/_getw/test1,1
+c_runtime/_isnan/test1,1
+c_runtime/_itow/test1,1
+c_runtime/_makepath/test1,1
+c_runtime/_mbsdec/test1,1
+c_runtime/_mbsinc/test1,1
+c_runtime/_mbslen/test1,1
+c_runtime/_mbsninc/test1,1
+c_runtime/_open_osfhandle/test1,1
+c_runtime/_open_osfhandle/test2,1
+c_runtime/_putenv/test1,1
+c_runtime/_putenv/test2,1
+c_runtime/_putenv/test3,1
+c_runtime/_putenv/test4,1
+c_runtime/_putw/test1,1
+c_runtime/_rotl/test1,1
+c_runtime/_rotr/test1,1
+c_runtime/_snprintf/test1,1
+c_runtime/_snprintf/test2,1
+c_runtime/_snprintf/test3,1
+c_runtime/_snprintf/test4,1
+c_runtime/_snprintf/test5,1
+c_runtime/_snprintf/test6,1
+c_runtime/_snprintf/test7,1
+c_runtime/_snprintf/test8,1
+c_runtime/_snprintf/test9,1
+c_runtime/_snprintf/test10,1
+c_runtime/_snprintf/test11,1
+c_runtime/_snprintf/test12,1
+c_runtime/_snprintf/test13,1
+c_runtime/_snprintf/test14,1
+c_runtime/_snprintf/test15,1
+c_runtime/_snprintf/test16,1
+c_runtime/_snprintf/test17,1
+c_runtime/_snprintf/test18,1
+c_runtime/_snprintf/test19,1
+c_runtime/_snwprintf/test1,1
+c_runtime/_snwprintf/test2,1
+c_runtime/_snwprintf/test3,1
+c_runtime/_snwprintf/test4,1
+c_runtime/_snwprintf/test5,1
+c_runtime/_snwprintf/test6,1
+c_runtime/_snwprintf/test7,1
+c_runtime/_snwprintf/test8,1
+c_runtime/_snwprintf/test9,1
+c_runtime/_snwprintf/test10,1
+c_runtime/_snwprintf/test11,1
+c_runtime/_snwprintf/test12,1
+c_runtime/_snwprintf/test13,1
+c_runtime/_snwprintf/test14,1
+c_runtime/_snwprintf/test15,1
+c_runtime/_snwprintf/test16,1
+c_runtime/_snwprintf/test17,1
+c_runtime/_snwprintf/test18,1
+c_runtime/_snwprintf/test19,1
+c_runtime/_splitpath/test1,1
+c_runtime/_stricmp/test1,1
+c_runtime/_strlwr/test1,1
+c_runtime/_strnicmp/test1,1
+c_runtime/_swab/test1,1
+c_runtime/_vsnprintf/test1,1
+c_runtime/_vsnprintf/test2,1
+c_runtime/_vsnprintf/test3,1
+c_runtime/_vsnprintf/test4,1
+c_runtime/_vsnprintf/test5,1
+c_runtime/_vsnprintf/test6,1
+c_runtime/_vsnprintf/test7,1
+c_runtime/_vsnprintf/test8,1
+c_runtime/_vsnprintf/test9,1
+c_runtime/_vsnprintf/test10,1
+c_runtime/_vsnprintf/test11,1
+c_runtime/_vsnprintf/test12,1
+c_runtime/_vsnprintf/test13,1
+c_runtime/_vsnprintf/test14,1
+c_runtime/_vsnprintf/test15,1
+c_runtime/_vsnprintf/test16,1
+c_runtime/_vsnprintf/test17,1
+c_runtime/_vsnprintf/test18,1
+c_runtime/_vsnprintf/test19,1
+c_runtime/_vsnwprintf/test1,1
+c_runtime/_vsnwprintf/test2,1
+c_runtime/_vsnwprintf/test3,1
+c_runtime/_vsnwprintf/test4,1
+c_runtime/_vsnwprintf/test5,1
+c_runtime/_vsnwprintf/test6,1
+c_runtime/_vsnwprintf/test7,1
+c_runtime/_vsnwprintf/test8,1
+c_runtime/_vsnwprintf/test9,1
+c_runtime/_vsnwprintf/test10,1
+c_runtime/_vsnwprintf/test11,1
+c_runtime/_vsnwprintf/test12,1
+c_runtime/_vsnwprintf/test13,1
+c_runtime/_vsnwprintf/test14,1
+c_runtime/_vsnwprintf/test15,1
+c_runtime/_vsnwprintf/test16,1
+c_runtime/_vsnwprintf/test17,1
+c_runtime/_vsnwprintf/test18,1
+c_runtime/_vsnwprintf/test19,1
+c_runtime/_wcsicmp/test1,1
+c_runtime/_wcslwr/test1,1
+c_runtime/_wcsnicmp/test1,1
+c_runtime/_wfopen/test1,1
+c_runtime/_wfopen/test2,1
+c_runtime/_wfopen/test3,1
+c_runtime/_wfopen/test4,1
+c_runtime/_wfopen/test5,1
+c_runtime/_wfopen/test6,1
+c_runtime/_wfopen/test7,1
+c_runtime/_wmakepath/test1,1
+c_runtime/_wsplitpath/test1,1
+c_runtime/_wtoi/test1,1
+c_runtime/abs/test1,1
+c_runtime/acos/test1,1
+c_runtime/asin/test1,1
+c_runtime/atan/test1,1
+c_runtime/atan2/test1,1
+c_runtime/atof/test1,1
+c_runtime/atoi/test1,1
+c_runtime/atol/test1,1
+c_runtime/bsearch/test1,1
+c_runtime/bsearch/test2,1
+c_runtime/ceil/test1,1
+c_runtime/cos/test1,1
+c_runtime/cosh/test1,1
+c_runtime/ctime/test1,1
+c_runtime/errno/test1,1
+c_runtime/errno/test2,1
+c_runtime/exit/test1,1
+c_runtime/exp/test1,1
+c_runtime/fabs/test1,1
+c_runtime/fabsf/test1,1
+c_runtime/fclose/test1,1
+c_runtime/fclose/test2,1
+c_runtime/feof/test1,1
+c_runtime/ferror/test1,1
+c_runtime/ferror/test2,1
+c_runtime/fflush/test1,1
+c_runtime/fgets/test1,1
+c_runtime/fgets/test2,1
+c_runtime/fgets/test3,1
+c_runtime/floor/test1,1
+c_runtime/fmod/test1,1
+c_runtime/fmodf/test1,1
+c_runtime/fopen/test1,1
+c_runtime/fopen/test2,1
+c_runtime/fopen/test3,1
+c_runtime/fopen/test4,1
+c_runtime/fopen/test5,1
+c_runtime/fopen/test6,1
+c_runtime/fopen/test7,1
+c_runtime/fprintf/test1,1
+c_runtime/fprintf/test2,1
+c_runtime/fprintf/test3,1
+c_runtime/fprintf/test4,1
+c_runtime/fprintf/test5,1
+c_runtime/fprintf/test6,1
+c_runtime/fprintf/test7,1
+c_runtime/fprintf/test8,1
+c_runtime/fprintf/test9,1
+c_runtime/fprintf/test10,1
+c_runtime/fprintf/test11,1
+c_runtime/fprintf/test12,1
+c_runtime/fprintf/test13,1
+c_runtime/fprintf/test14,1
+c_runtime/fprintf/test15,1
+c_runtime/fprintf/test16,1
+c_runtime/fprintf/test17,1
+c_runtime/fprintf/test18,1
+c_runtime/fprintf/test19,1
+c_runtime/fputs/test1,1
+c_runtime/fputs/test2,1
+c_runtime/fread/test1,1
+c_runtime/fread/test2,1
+c_runtime/fread/test3,1
+c_runtime/free/test1,1
+c_runtime/fseek/test1,1
+c_runtime/ftell/test1,1
+c_runtime/fwprintf/test1,1
+c_runtime/fwprintf/test2,1
+c_runtime/fwprintf/test3,1
+c_runtime/fwprintf/test4,1
+c_runtime/fwprintf/test5,1
+c_runtime/fwprintf/test6,1
+c_runtime/fwprintf/test7,1
+c_runtime/fwprintf/test8,1
+c_runtime/fwprintf/test9,1
+c_runtime/fwprintf/test10,1
+c_runtime/fwprintf/test11,1
+c_runtime/fwprintf/test12,1
+c_runtime/fwprintf/test13,1
+c_runtime/fwprintf/test14,1
+c_runtime/fwprintf/test15,1
+c_runtime/fwprintf/test16,1
+c_runtime/fwprintf/test17,1
+c_runtime/fwprintf/test18,1
+c_runtime/fwprintf/test19,1
+c_runtime/fwrite/test1,1
+c_runtime/getc/test1,1
+c_runtime/getenv/test1,0
+c_runtime/getenv/test2,1
+c_runtime/getenv/test3,1
+c_runtime/isalnum/test1,1
+c_runtime/isalpha/test1,1
+c_runtime/isdigit/test1,1
+c_runtime/islower/test1,1
+c_runtime/isprint/test1,1
+c_runtime/isprint/test2,1
+c_runtime/isspace/test1,1
+c_runtime/isupper/test1,1
+c_runtime/iswdigit/test1,1
+c_runtime/iswprint/test1,1
+c_runtime/iswspace/test1,1
+c_runtime/iswupper/test1,1
+c_runtime/iswxdigit/test1,1
+c_runtime/isxdigit/test1,1
+c_runtime/labs/test1,1
+c_runtime/llabs/test1,1
+c_runtime/localtime/test1,1
+c_runtime/log/test1,1
+c_runtime/log10/test1,1
+c_runtime/malloc/test1,1
+c_runtime/memchr/test1,1
+c_runtime/memcmp/test1,1
+c_runtime/memcpy/test1,1
+c_runtime/memmove/test1,1
+c_runtime/memset/test1,1
+c_runtime/modf/test1,1
+c_runtime/pow/test1,1
+c_runtime/printf/test1,1
+c_runtime/printf/test2,1
+c_runtime/printf/test3,1
+c_runtime/printf/test4,1
+c_runtime/printf/test5,1
+c_runtime/printf/test6,1
+c_runtime/printf/test7,1
+c_runtime/printf/test8,1
+c_runtime/printf/test9,1
+c_runtime/printf/test10,1
+c_runtime/printf/test11,1
+c_runtime/printf/test12,1
+c_runtime/printf/test13,1
+c_runtime/printf/test14,1
+c_runtime/printf/test15,1
+c_runtime/printf/test16,1
+c_runtime/printf/test17,1
+c_runtime/printf/test18,1
+c_runtime/printf/test19,1
+c_runtime/qsort/test1,1
+c_runtime/qsort/test2,1
+c_runtime/rand_srand/test1,1
+c_runtime/realloc/test1,1
+c_runtime/sin/test1,1
+c_runtime/sinh/test1,1
+c_runtime/sprintf/test1,1
+c_runtime/sprintf/test2,1
+c_runtime/sprintf/test3,1
+c_runtime/sprintf/test4,1
+c_runtime/sprintf/test5,1
+c_runtime/sprintf/test6,1
+c_runtime/sprintf/test7,1
+c_runtime/sprintf/test8,1
+c_runtime/sprintf/test9,1
+c_runtime/sprintf/test10,1
+c_runtime/sprintf/test11,1
+c_runtime/sprintf/test12,1
+c_runtime/sprintf/test13,1
+c_runtime/sprintf/test14,1
+c_runtime/sprintf/test15,1
+c_runtime/sprintf/test16,1
+c_runtime/sprintf/test17,1
+c_runtime/sprintf/test18,1
+c_runtime/sprintf/test19,1
+c_runtime/sqrt/test1,1
+c_runtime/sscanf/test1,1
+c_runtime/sscanf/test2,1
+c_runtime/sscanf/test3,1
+c_runtime/sscanf/test4,1
+c_runtime/sscanf/test5,1
+c_runtime/sscanf/test6,1
+c_runtime/sscanf/test7,1
+c_runtime/sscanf/test8,1
+c_runtime/sscanf/test9,1
+c_runtime/sscanf/test10,1
+c_runtime/sscanf/test11,1
+c_runtime/sscanf/test12,1
+c_runtime/sscanf/test13,1
+c_runtime/sscanf/test14,1
+c_runtime/sscanf/test15,1
+c_runtime/sscanf/test16,1
+c_runtime/sscanf/test17,1
+c_runtime/strcat/test1,1
+c_runtime/strchr/test1,1
+c_runtime/strcmp/test1,1
+c_runtime/strcpy/test1,1
+c_runtime/strcspn/test1,1
+c_runtime/strlen/test1,1
+c_runtime/strncat/test1,1
+c_runtime/strncmp/test1,1
+c_runtime/strncpy/test1,1
+c_runtime/strpbrk/test1,1
+c_runtime/strrchr/test1,1
+c_runtime/strspn/test1,1
+c_runtime/strstr/test1,1
+c_runtime/strtod/test1,1
+c_runtime/strtod/test2,1
+c_runtime/strtok/test1,1
+c_runtime/strtoul/test1,1
+c_runtime/swprintf/test1,1
+c_runtime/swprintf/test2,1
+c_runtime/swprintf/test3,1
+c_runtime/swprintf/test4,1
+c_runtime/swprintf/test5,1
+c_runtime/swprintf/test6,1
+c_runtime/swprintf/test7,1
+c_runtime/swprintf/test8,1
+c_runtime/swprintf/test9,1
+c_runtime/swprintf/test10,1
+c_runtime/swprintf/test11,1
+c_runtime/swprintf/test12,1
+c_runtime/swprintf/test13,1
+c_runtime/swprintf/test14,1
+c_runtime/swprintf/test15,1
+c_runtime/swprintf/test16,1
+c_runtime/swprintf/test17,1
+c_runtime/swprintf/test18,1
+c_runtime/swprintf/test19,1
+c_runtime/swscanf/test1,1
+c_runtime/swscanf/test2,1
+c_runtime/swscanf/test3,1
+c_runtime/swscanf/test4,1
+c_runtime/swscanf/test5,1
+c_runtime/swscanf/test6,1
+c_runtime/swscanf/test7,1
+c_runtime/swscanf/test8,1
+c_runtime/swscanf/test9,1
+c_runtime/swscanf/test10,1
+c_runtime/swscanf/test11,1
+c_runtime/swscanf/test12,1
+c_runtime/swscanf/test13,1
+c_runtime/swscanf/test14,1
+c_runtime/swscanf/test15,1
+c_runtime/swscanf/test16,1
+c_runtime/swscanf/test17,1
+c_runtime/tan/test1,1
+c_runtime/tanh/test1,1
+c_runtime/time/test1,1
+c_runtime/tolower/test1,1
+c_runtime/toupper/test1,1
+c_runtime/towlower/test1,1
+c_runtime/towupper/test1,1
+c_runtime/ungetc/test1,1
+c_runtime/vfprintf/test1,1
+c_runtime/vfprintf/test2,1
+c_runtime/vfprintf/test3,1
+c_runtime/vfprintf/test4,1
+c_runtime/vfprintf/test5,1
+c_runtime/vfprintf/test6,1
+c_runtime/vfprintf/test7,1
+c_runtime/vfprintf/test8,1
+c_runtime/vfprintf/test9,1
+c_runtime/vfprintf/test10,1
+c_runtime/vfprintf/test11,1
+c_runtime/vfprintf/test12,1
+c_runtime/vfprintf/test13,1
+c_runtime/vfprintf/test14,1
+c_runtime/vfprintf/test15,1
+c_runtime/vfprintf/test16,1
+c_runtime/vfprintf/test17,1
+c_runtime/vfprintf/test18,1
+c_runtime/vfprintf/test19,1
+c_runtime/vprintf/test1,1
+c_runtime/vprintf/test2,1
+c_runtime/vprintf/test3,1
+c_runtime/vprintf/test4,1
+c_runtime/vprintf/test5,1
+c_runtime/vprintf/test6,1
+c_runtime/vprintf/test7,1
+c_runtime/vprintf/test8,1
+c_runtime/vprintf/test9,1
+c_runtime/vprintf/test10,1
+c_runtime/vprintf/test11,1
+c_runtime/vprintf/test12,1
+c_runtime/vprintf/test13,1
+c_runtime/vprintf/test14,1
+c_runtime/vprintf/test15,1
+c_runtime/vprintf/test16,1
+c_runtime/vprintf/test17,1
+c_runtime/vprintf/test18,1
+c_runtime/vprintf/test19,1
+c_runtime/vsprintf/test1,1
+c_runtime/vsprintf/test2,1
+c_runtime/vsprintf/test3,1
+c_runtime/vsprintf/test4,1
+c_runtime/vsprintf/test5,1
+c_runtime/vsprintf/test6,1
+c_runtime/vsprintf/test7,1
+c_runtime/vsprintf/test8,1
+c_runtime/vsprintf/test9,1
+c_runtime/vsprintf/test10,1
+c_runtime/vsprintf/test11,1
+c_runtime/vsprintf/test12,1
+c_runtime/vsprintf/test13,1
+c_runtime/vsprintf/test14,1
+c_runtime/vsprintf/test15,1
+c_runtime/vsprintf/test16,1
+c_runtime/vsprintf/test17,1
+c_runtime/vsprintf/test18,1
+c_runtime/vsprintf/test19,1
+c_runtime/vswprintf/test1,1
+c_runtime/vswprintf/test2,1
+c_runtime/vswprintf/test3,1
+c_runtime/vswprintf/test4,1
+c_runtime/vswprintf/test5,1
+c_runtime/vswprintf/test6,1
+c_runtime/vswprintf/test7,1
+c_runtime/vswprintf/test8,1
+c_runtime/vswprintf/test9,1
+c_runtime/vswprintf/test10,1
+c_runtime/vswprintf/test11,1
+c_runtime/vswprintf/test12,1
+c_runtime/vswprintf/test13,1
+c_runtime/vswprintf/test14,1
+c_runtime/vswprintf/test15,1
+c_runtime/vswprintf/test16,1
+c_runtime/vswprintf/test17,1
+c_runtime/vswprintf/test18,1
+c_runtime/vswprintf/test19,1
+c_runtime/wcscat/test1,1
+c_runtime/wcschr/test1,1
+c_runtime/wcscmp/test1,1
+c_runtime/wcscpy/test1,1
+c_runtime/wcslen/test1,1
+c_runtime/wcsncat/test1,1
+c_runtime/wcsncmp/test1,1
+c_runtime/wcsncpy/test1,1
+c_runtime/wcspbrk/test1,1
+c_runtime/wcsrchr/test1,1
+c_runtime/wcsstr/test1,1
+c_runtime/wcstod/test1,1
+c_runtime/wcstod/test2,1
+c_runtime/wcstok/test1,1
+c_runtime/wcstol/test1,1
+c_runtime/wcstol/test2,1
+c_runtime/wcstol/test3,1
+c_runtime/wcstol/test4,1
+c_runtime/wcstol/test5,1
+c_runtime/wcstol/test6,1
+c_runtime/wcstoul/test1,1
+c_runtime/wcstoul/test2,1
+c_runtime/wcstoul/test3,1
+c_runtime/wcstoul/test4,1
+c_runtime/wcstoul/test5,1
+c_runtime/wcstoul/test6,1
+debug_api/writeprocessmemory/test1,1
+exception_handling/pal_except/test1,1
+exception_handling/pal_except/test2,1
+exception_handling/pal_except/test3,1
+exception_handling/pal_except/test4,1
+exception_handling/pal_except/test5,1
+exception_handling/pal_except/test6,1
+exception_handling/pal_except/test7,1
+exception_handling/pal_except_filter/test1,1
+exception_handling/pal_except_filter/test2,1
+exception_handling/pal_except_filter/test3,1
+exception_handling/pal_except_filter_ex/test1,1
+exception_handling/pal_except_filter_ex/test2,1
+exception_handling/pal_except_filter_ex/test3,1
+exception_handling/pal_getbottommostregistration/test1,1
+exception_handling/pal_getbottommostregistration/test2,1
+exception_handling/pal_finally/test1,1
+exception_handling/pal_try_except/test1,1
+exception_handling/pal_try_except/test2,1
+exception_handling/pal_try_except_ex/test1,1
+exception_handling/pal_try_except_ex/test2,1
+exception_handling/pal_try_except_ex/test3,1
+exception_handling/pal_try_leave_finally/test1,1
+exception_handling/raiseexception/test1,1
+exception_handling/raiseexception/test2,1
+exception_handling/raiseexception/test3,1
+file_io/arefileapisansi/test1,1
+file_io/comparefiletime/test1,1
+file_io/copyfilea/test1,1
+file_io/copyfilea/test2,1
+file_io/copyfilea/test3,1
+file_io/copyfilea/test4,1
+file_io/copyfilew/test1,1
+file_io/copyfilew/test2,1
+file_io/createdirectorya/test1,1
+file_io/createdirectoryw/test1,1
+file_io/createfilea/test1,1
+file_io/createfilew/test1,1
+file_io/deletefilea/test1,1
+file_io/deletefilew/test1,1
+file_io/errorpathnotfound/test1,1
+file_io/errorpathnotfound/test2,1
+file_io/errorpathnotfound/test3,1
+#file_io/errorpathnotfound/test4,1
+file_io/filetimetodosdatetime/test1,1
+file_io/findclose/test1,1
+file_io/findfirstfilea/test1,1
+#file_io/findfirstfilew/test1,1
+file_io/findnextfilea/test1,1
+file_io/findnextfilew/test1,1
+file_io/flushfilebuffers/test1,1
+file_io/getconsolecp/test1,1
+file_io/getconsoleoutputcp/test1,1
+file_io/getcurrentdirectorya/test1,1
+file_io/getcurrentdirectoryw/test1,1
+file_io/getdiskfreespacew/test1,1
+#file_io/getfileattributesa/test1,1
+#file_io/getfileattributesexw/test1,1
+file_io/getfileattributesexw/test2,1
+#file_io/getfileattributesw/test1,1
+file_io/getfiletime/test1,1
+file_io/getfiletime/test2,1
+file_io/getfiletime/test3,1
+file_io/getfiletime/test4,1
+file_io/getfiletime/test6,1
+file_io/getfiletime/test7,1
+file_io/getfiletype/test1,1
+file_io/getfiletype/test2,1
+file_io/getfiletype/test3,1
+file_io/getfullpathnamea/test1,1
+file_io/getfullpathnamea/test2,1
+file_io/getfullpathnamea/test3,1
+file_io/getfullpathnamea/test4,1
+file_io/getfullpathnamew/test1,1
+file_io/getfullpathnamew/test2,1
+#file_io/getfullpathnamew/test3,1
+#file_io/getfullpathnamew/test4,1
+file_io/getlongpathnamew/test1,1
+file_io/getlongpathnamew/test2,1
+file_io/getsystemtime/test1,1
+file_io/getsystemtimeasfiletime/test1,1
+file_io/gettempfilenamea/test1,1
+file_io/gettempfilenamea/test3,1
+file_io/gettempfilenamew/test1,1
+file_io/gettempfilenamew/test3,1
+file_io/gettemppatha/test1,1
+file_io/gettemppathw/test1,1
+file_io/movefileexw/test1,1
+file_io/movefilew/test1,1
+#file_io/readfile/test1,1
+file_io/readfile/test2,1
+file_io/readfile/test3,1
+file_io/readfile/test4,1
+file_io/removedirectoryw/test1,1
+file_io/setcurrentdirectorya/test1,1
+file_io/setcurrentdirectorya/test2,1
+file_io/setcurrentdirectorya/test3,1
+file_io/setcurrentdirectoryw/test1,1
+file_io/setcurrentdirectoryw/test2,1
+#file_io/setcurrentdirectoryw/test3,1
+file_io/setendoffile/test1,1
+file_io/setendoffile/test2,1
+file_io/setendoffile/test3,1
+file_io/setendoffile/test4,1
+file_io/setendoffile/test5,1
+file_io/setfileattributesa/test2,1
+file_io/setfileattributesa/test3,1
+file_io/setfileattributesw/test2,1
+file_io/setfileattributesw/test3,1
+file_io/setfilepointer/test1,1
+file_io/setfilepointer/test2,1
+file_io/setfilepointer/test3,1
+file_io/setfilepointer/test4,1
+file_io/setfiletime/test1,1
+file_io/setfiletime/test2,1
+file_io/setfiletime/test3,1
+file_io/setfiletime/test4,1
+file_io/writefile/test1,1
+file_io/writefile/test2,1
+file_io/writefile/test3,1
+file_io/writefile/test4,1
+file_io/writefile/test5,1
+filemapping_memmgt/createfilemappinga/test1,1
+filemapping_memmgt/createfilemappinga/test3,1
+filemapping_memmgt/createfilemappinga/test4,1
+filemapping_memmgt/createfilemappinga/test5,1
+filemapping_memmgt/createfilemappinga/test6,1
+filemapping_memmgt/createfilemappinga/test7,1
+filemapping_memmgt/createfilemappinga/test8,1
+filemapping_memmgt/createfilemappinga/test9,1
+filemapping_memmgt/createfilemappingw/test1,1
+filemapping_memmgt/createfilemappingw/test3,1
+filemapping_memmgt/createfilemappingw/test4,1
+filemapping_memmgt/createfilemappingw/test5,1
+filemapping_memmgt/createfilemappingw/test6,1
+filemapping_memmgt/createfilemappingw/test7,1
+filemapping_memmgt/createfilemappingw/test8,1
+filemapping_memmgt/createfilemappingw/test9,1
+filemapping_memmgt/freelibrary/test1,1
+filemapping_memmgt/freelibrary/test2,1
+filemapping_memmgt/freelibraryandexitthread/test1,1
+filemapping_memmgt/getmodulefilenamea/test1,1
+filemapping_memmgt/getmodulefilenamea/test2,1
+filemapping_memmgt/getmodulefilenamew/test1,1
+filemapping_memmgt/getmodulefilenamew/test2,1
+filemapping_memmgt/getprocaddress/test1,1
+filemapping_memmgt/getprocaddress/test2,1
+filemapping_memmgt/getprocessheap/test1,1
+filemapping_memmgt/heapalloc/test1,1
+filemapping_memmgt/heapalloc/test2,1
+filemapping_memmgt/heapfree/test1,1
+filemapping_memmgt/heaprealloc/test1,1
+filemapping_memmgt/heaprealloc/test2,1
+filemapping_memmgt/heaprealloc/test3,1
+filemapping_memmgt/heaprealloc/test4,1
+filemapping_memmgt/heaprealloc/test5,1
+filemapping_memmgt/localalloc/test1,1
+filemapping_memmgt/localfree/test1,1
+filemapping_memmgt/localfree/test2,1
+filemapping_memmgt/lockfile/test1,1
+filemapping_memmgt/lockfile/test2,1
+filemapping_memmgt/lockfile/test3,1
+filemapping_memmgt/lockfile/test4,1
+filemapping_memmgt/lockfile/test5,1
+filemapping_memmgt/lockfile/test6,1
+filemapping_memmgt/lockfile/test7,1
+filemapping_memmgt/mapviewoffile/test1,1
+filemapping_memmgt/mapviewoffile/test2,1
+filemapping_memmgt/mapviewoffile/test3,1
+filemapping_memmgt/mapviewoffile/test4,1
+filemapping_memmgt/mapviewoffile/test5,1
+filemapping_memmgt/mapviewoffile/test6,1
+filemapping_memmgt/openfilemappinga/test1,1
+filemapping_memmgt/openfilemappinga/test2,1
+filemapping_memmgt/openfilemappinga/test3,1
+filemapping_memmgt/openfilemappingw/test1,1
+filemapping_memmgt/openfilemappingw/test2,1
+filemapping_memmgt/openfilemappingw/test3,1
+filemapping_memmgt/readprocessmemory/readprocessmemory_neg1,1
+filemapping_memmgt/readprocessmemory/test1,1
+filemapping_memmgt/rtlmovememory/test1,1
+filemapping_memmgt/rtlmovememory/test3,1
+filemapping_memmgt/rtlmovememory/test4,1
+filemapping_memmgt/rtlmovememory/test5,1
+filemapping_memmgt/unlockfile/test1,1
+filemapping_memmgt/unlockfile/test2,1
+filemapping_memmgt/unlockfile/test3,1
+filemapping_memmgt/unlockfile/test4,1
+filemapping_memmgt/unmapviewoffile/test1,1
+filemapping_memmgt/virtualalloc/test1,1
+filemapping_memmgt/virtualalloc/test2,1
+filemapping_memmgt/virtualalloc/test3,1
+filemapping_memmgt/virtualalloc/test4,1
+filemapping_memmgt/virtualalloc/test5,1
+filemapping_memmgt/virtualalloc/test6,1
+filemapping_memmgt/virtualalloc/test7,1
+filemapping_memmgt/virtualalloc/test8,1
+filemapping_memmgt/virtualalloc/test9,1
+filemapping_memmgt/virtualalloc/test10,1
+filemapping_memmgt/virtualalloc/test11,1
+filemapping_memmgt/virtualalloc/test12,1
+filemapping_memmgt/virtualalloc/test13,1
+filemapping_memmgt/virtualalloc/test14,1
+filemapping_memmgt/virtualalloc/test15,1
+filemapping_memmgt/virtualalloc/test16,1
+filemapping_memmgt/virtualalloc/test17,1
+filemapping_memmgt/virtualalloc/test18,1
+filemapping_memmgt/virtualalloc/test19,1
+filemapping_memmgt/virtualalloc/test20,1
+filemapping_memmgt/virtualalloc/test21,1
+filemapping_memmgt/virtualfree/test1,1
+filemapping_memmgt/virtualfree/test2,1
+filemapping_memmgt/virtualfree/test3,1
+filemapping_memmgt/virtualprotect/test1,1
+filemapping_memmgt/virtualprotect/test2,1
+filemapping_memmgt/virtualprotect/test3,1
+filemapping_memmgt/virtualprotect/test4,1
+filemapping_memmgt/virtualprotect/test6,1
+filemapping_memmgt/virtualprotect/test7,1
+filemapping_memmgt/virtualquery/test1,1
+loader/loadlibrarya/test1,1
+loader/loadlibrarya/test2,1
+loader/loadlibrarya/test3,0
+loader/loadlibrarya/test5,1
+loader/loadlibrarya/test6,1
+loader/loadlibraryw/test1,1
+loader/loadlibraryw/test2,1
+loader/loadlibraryw/test3,1
+loader/loadlibraryw/test5,1
+locale_info/comparestringw/test1,1
+locale_info/getacp/test1,1
+locale_info/getcpinfo/test1,1
+locale_info/getlocaleinfow/test1,1
+locale_info/getlocaleinfow/test2,1
+locale_info/getstringtypeexw/test1,1
+locale_info/getstringtypeexw/test2,0
+locale_info/getsystemdefaultlangid/test1,1
+locale_info/getthreadlocale/test1,1
+locale_info/gettimezoneinformation/test1,1
+locale_info/getuserdefaultlangid/test1,1
+locale_info/getuserdefaultlcid/test1,1
+locale_info/isdbcsleadbyteex/test1,1
+locale_info/isvalidcodepage/test1,1
+locale_info/isvalidlocale/test1,1
+locale_info/multibytetowidechar/test1,1
+locale_info/multibytetowidechar/test2,1
+locale_info/multibytetowidechar/test3,1
+locale_info/setthreadlocale/test1,1
+locale_info/widechartomultibyte/test1,1
+locale_info/widechartomultibyte/test2,1
+locale_info/widechartomultibyte/test3,1
+miscellaneous/_i64tow/test1,1
+miscellaneous/_ui64tow/test1,1
+miscellaneous/_ui64tow/test2,1
+miscellaneous/charnexta/test1,1
+miscellaneous/charnexta/test2,1
+miscellaneous/charnextexa/test1,1
+miscellaneous/charnextexa/test2,1
+miscellaneous/closehandle/test1,1
+miscellaneous/closehandle/test2,1
+miscellaneous/createpipe/test1,1
+miscellaneous/flushinstructioncache/test1,1
+miscellaneous/formatmessagew/test1,1
+miscellaneous/formatmessagew/test2,1
+miscellaneous/formatmessagew/test3,1
+miscellaneous/formatmessagew/test4,1
+miscellaneous/formatmessagew/test5,1
+miscellaneous/formatmessagew/test6,1
+miscellaneous/freeenvironmentstringsw/test1,1
+miscellaneous/freeenvironmentstringsw/test2,1
+miscellaneous/getcalendarinfow/test1,1
+miscellaneous/getcommandlinew/test1,1
+miscellaneous/getenvironmentstringsw/test1,1
+miscellaneous/getenvironmentvariablea/test1,1
+miscellaneous/getenvironmentvariablea/test2,1
+miscellaneous/getenvironmentvariablea/test3,1
+miscellaneous/getenvironmentvariablea/test4,1
+miscellaneous/getenvironmentvariablew/test1,1
+miscellaneous/getenvironmentvariablew/test2,1
+miscellaneous/getenvironmentvariablew/test3,1
+miscellaneous/getenvironmentvariablew/test4,1
+miscellaneous/getlasterror/test1,1
+miscellaneous/getsysteminfo/test1,1
+miscellaneous/gettickcount/test1,1
+miscellaneous/getversionexa/test1,1
+miscellaneous/getversionexw/test1,1
+miscellaneous/interlockedcompareexchange/test1,1
+miscellaneous/interlockedcompareexchangepointer/test1,1
+miscellaneous/interlockeddecrement/test1,1
+miscellaneous/interlockedexchange/test1,1
+miscellaneous/interlockedexchangepointer/test1,1
+miscellaneous/interlockedincrement/test1,1
+miscellaneous/isbadcodeptr/test1,1
+miscellaneous/isbadreadptr/test1,1
+miscellaneous/isbadwriteptr/test1,1
+miscellaneous/isbadwriteptr/test2,1
+miscellaneous/isbadwriteptr/test3,1
+miscellaneous/lstrcatw/test1,1
+miscellaneous/lstrcatw/test2,1
+miscellaneous/lstrcatw/test3,1
+miscellaneous/lstrcatw/test4,1
+miscellaneous/lstrcpynw/test1,1
+miscellaneous/lstrcpyw/test1,1
+miscellaneous/lstrlena/test1,1
+miscellaneous/lstrlenw/test1,1
+miscellaneous/queryperformancecounter/test1,1
+miscellaneous/queryperformancefrequency/test1,1
+miscellaneous/setenvironmentvariablea/test1,1
+miscellaneous/setenvironmentvariablea/test2,1
+miscellaneous/setenvironmentvariablew/test1,1
+miscellaneous/setenvironmentvariablew/test2,1
+miscellaneous/setlasterror/test1,1
+miscellaneous/wsprintfa/test1,1
+miscellaneous/wsprintfa/test2,1
+miscellaneous/wsprintfa/test3,1
+miscellaneous/wsprintfa/test6,1
+miscellaneous/wsprintfa/test7,1
+miscellaneous/wsprintfa/test8,1
+miscellaneous/wsprintfa/test9,1
+miscellaneous/wsprintfa/test11,1
+miscellaneous/wsprintfa/test12,1
+miscellaneous/wsprintfa/test13,1
+miscellaneous/wsprintfw/test1,1
+miscellaneous/wsprintfw/test2,1
+miscellaneous/wsprintfw/test3,1
+miscellaneous/wsprintfw/test6,1
+miscellaneous/wsprintfw/test7,1
+miscellaneous/wsprintfw/test8,1
+miscellaneous/wsprintfw/test9,1
+miscellaneous/wsprintfw/test11,1
+miscellaneous/wsprintfw/test12,1
+miscellaneous/wsprintfw/test13,1
+pal_specific/pal_errno/test1,1
+pal_specific/pal_getpaldirectoryw/test1,1
+pal_specific/pal_getuserconfigurationdirectoryw/test1,1
+pal_specific/pal_initialize_terminate/test1,1
+threading/createeventa/test1,1
+threading/createeventa/test2,1
+threading/createeventa/test3,1
+threading/createeventw/test1,1
+threading/createeventw/test2,1
+threading/createeventw/test3,1
+threading/createmutexw_releasemutex/test1,1
+threading/createmutexw_releasemutex/test2,1
+threading/createprocessa/test1,1
+threading/createprocessa/test2,1
+threading/createprocessw/test1,1
+threading/createprocessw/test2,1
+threading/createsemaphorea_releasesemaphore/test1,1
+threading/createsemaphorea_releasesemaphore/test2,1
+threading/createsemaphorea_releasesemaphore/test3,1
+threading/createsemaphorew_releasesemaphore/test1,1
+threading/createsemaphorew_releasesemaphore/test2,1
+threading/createsemaphorew_releasesemaphore/test3,1
+threading/createthread/test1,1
+threading/createthread/test2,1
+threading/createthread/test3,1
+threading/criticalsectionfunctions/test1,1
+threading/criticalsectionfunctions/test2,1
+threading/criticalsectionfunctions/test3,1
+threading/criticalsectionfunctions/test4,1
+threading/criticalsectionfunctions/test5,1
+threading/criticalsectionfunctions/test6,1
+threading/criticalsectionfunctions/test7,1
+threading/disablethreadlibrarycalls/test1,1
+threading/disablethreadlibrarycalls/test2,1
+threading/duplicatehandle/test1,1
+threading/duplicatehandle/test2,1
+threading/duplicatehandle/test3,1
+threading/duplicatehandle/test4,1
+threading/duplicatehandle/test5,1
+threading/duplicatehandle/test6,1
+threading/duplicatehandle/test7,1
+threading/duplicatehandle/test8,1
+threading/duplicatehandle/test9,1
+threading/duplicatehandle/test10,1
+threading/duplicatehandle/test11,1
+threading/exitprocess/test1,1
+threading/exitthread/test1,1
+#threading/exitthread/test2,1
+threading/exitthread/test3,1
+threading/getcurrentprocess/test1,1
+threading/getcurrentprocessid/test1,1
+threading/getcurrentthread/test1,1
+threading/getcurrentthread/test2,1
+threading/getcurrentthreadid/test1,1
+threading/getexitcodeprocess/test1,1
+threading/getprocesstimes/test2,1
+threading/openeventw/test1,1
+threading/openeventw/test2,1
+threading/openeventw/test3,1
+threading/openeventw/test4,1
+threading/openeventw/test5,1
+threading/openprocess/test1,1
+threading/queueuserapc/test1,1
+threading/queueuserapc/test2,1
+threading/queueuserapc/test3,1
+threading/queueuserapc/test4,1
+threading/queueuserapc/test5,0
+threading/queueuserapc/test6,0
+threading/queueuserapc/test7,1
+threading/releasemutex/test3,1
+threading/releasesemaphore/test1,1
+threading/resetevent/test1,1
+threading/resumethread/test1,1
+threading/seterrormode/test1,1
+threading/setevent/test1,1
+threading/setthreadcontext/test1,1
+threading/sleepex/test2,1
+threading/suspendthread/test1,1
+threading/terminateprocess/test1,1
+threading/tls/test1,1
+threading/tls/test2,1
+threading/tls/test3,1
+threading/tls/test4,1
+threading/tls/test5,1
+threading/waitformultipleobjects/test1,1
+threading/waitformultipleobjectsex/test1,1
+threading/waitformultipleobjectsex/test2,1
+threading/waitformultipleobjectsex/test3,1
+threading/waitformultipleobjectsex/test4,1
+threading/waitformultipleobjectsex/test5,1
+
+
diff --git a/src/pal/tests/palsuite/runpaltests.sh b/src/pal/tests/palsuite/runpaltests.sh
new file mode 100755
index 0000000000..cc8ffd6b91
--- /dev/null
+++ b/src/pal/tests/palsuite/runpaltests.sh
@@ -0,0 +1,213 @@
+#!/usr/bin/env bash
+#
+# This script executes PAL tests from the specified build location.
+#
+
+if [ $# -lt 1 -o $# -gt 3 ]
+then
+ echo "Usage..."
+ echo "runpaltests.sh <path to root build directory> [<path to temp folder for PAL tests>]"
+ echo
+ echo "For example:"
+ echo "runpaltests.sh /projectk/build/debug"
+ echo
+ exit 1
+fi
+
+echo
+echo "***** Testing PAL *****"
+echo
+
+# Store the location of the root of build directory
+BUILD_ROOD_DIR=$1
+# Create path to the compiled PAL tets in the build directory
+PAL_TEST_BUILD=$BUILD_ROOD_DIR/src/pal/tests/palsuite
+echo Running PAL tests from $PAL_TEST_BUILD
+
+# Create absolute path to the file that contains a list of PAL tests to execute.
+# This file is located next to this script in the source tree
+RELATIVE_PATH_TO_PAL_TESTS=$0
+# Remove the name of this script from the path
+RELATIVE_PATH_TO_PAL_TESTS=${RELATIVE_PATH_TO_PAL_TESTS%/*.*}
+# Change current directory to the location of this script
+cd $RELATIVE_PATH_TO_PAL_TESTS
+# Environment variable PWD contains absolute path to the current folder
+# so use it to create absolute path to the file with a list of tests.
+PAL_TEST_LIST=$PWD/paltestlist.txt
+# Change current directory back to the original location
+cd $OLDPWD
+echo The list of PAL tests to run will be read from $PAL_TEST_LIST
+
+# Create the test output root directory
+mkdir -p /tmp/PalTestOutput
+if [ ! -d /tmp/PalTestOutput ]; then
+ rm -f -r /tmp/PalTestOutput
+ mkdir -p /tmp/PalTestOutput
+fi
+
+# Determine the folder to use for PAL test output during the run, and the folder where output files were requested to be copied.
+# First check if the output folder was passed as a parameter to the script. It is supposed be the second parameter so check if
+# we have more than 1 argument.
+PAL_TEST_OUTPUT_DIR=/tmp/PalTestOutput/default
+if [ $# -gt 1 ]
+then
+ COPY_TO_TEST_OUTPUT_DIR=$2
+else
+ COPY_TO_TEST_OUTPUT_DIR=$PAL_TEST_OUTPUT_DIR
+fi
+
+# Determine the folder to use for PAL test output during the run
+if [ "$COPY_TO_TEST_OUTPUT_DIR" != "$PAL_TEST_OUTPUT_DIR" ]; then
+ # Output files were requested to be copied to a specific folder. In this mode, we need to support parallel runs of PAL tests
+ # on the same machine. Make a unique temp folder for working output inside /tmp/PalTestOutput.
+ PAL_TEST_OUTPUT_DIR=$(mktemp -d /tmp/PalTestOutput/tmp.XXXXXXXX)
+fi
+
+echo PAL tests will store their temporary files and output in $PAL_TEST_OUTPUT_DIR.
+if [ "$COPY_TO_TEST_OUTPUT_DIR" != "$PAL_TEST_OUTPUT_DIR" ]; then
+ echo Output files will be copied to $COPY_TO_TEST_OUTPUT_DIR at the end.
+fi
+
+# Path to a file that will contains a list PAL tests that failed during the test run.
+PAL_FAILED_TEST_LIST=$PAL_TEST_OUTPUT_DIR/palfailedtests.txt
+
+# Path to a file that will contain the XUnit style test result for Jenkins
+# We use a temp file as at the end we have to prepend with the number of tests
+# and failures
+PAL_XUNIT_TEST_LIST_TMP=$PAL_TEST_OUTPUT_DIR/pal_tests.xml.tmp
+PAL_XUNIT_TEST_LIST=$PAL_TEST_OUTPUT_DIR/pal_tests.xml
+
+# Capturing stdout and stderr
+PAL_OUT_FILE=$PAL_TEST_OUTPUT_DIR/pal_test_out
+
+# Remove and recreate the temporary test output directory, and the directory where output files were requested to be copied.
+if [ "$COPY_TO_TEST_OUTPUT_DIR" == "$PAL_TEST_OUTPUT_DIR" ]; then
+ if [ -e $PAL_TEST_OUTPUT_DIR ]; then
+ rm -f -r $PAL_TEST_OUTPUT_DIR
+ fi
+ mkdir -p $PAL_TEST_OUTPUT_DIR
+else
+ # No need to recreate the temp output directory, as mktemp would have created a unique empty directory
+ if [ -e $COPY_TO_TEST_OUTPUT_DIR ]; then
+ rm -f -r $COPY_TO_TEST_OUTPUT_DIR
+ fi
+ mkdir -p $COPY_TO_TEST_OUTPUT_DIR
+ if [ ! -d $COPY_TO_TEST_OUTPUT_DIR ]; then
+ echo Failed to create $COPY_TO_TEST_OUTPUT_DIR.
+ COPY_TO_TEST_OUTPUT_DIR=$PAL_TEST_OUTPUT_DIR
+ fi
+fi
+cd $PAL_TEST_OUTPUT_DIR
+
+echo
+echo "Running tests..."
+echo
+
+NUMBER_OF_PASSED_TESTS=0
+NUMBER_OF_FAILED_TESTS=0
+
+# Read PAL tests names from the $PAL_TEST_LIST file and run them one by one.
+while read TEST_NAME
+do
+ # Remove stdout/stderr file if it exists
+ rm -f $PAL_OUT_FILE
+
+ # Create a folder with the test name, and use that as the working directory for the test. Many PAL tests don't clean up after
+ # themselves and may leave files/directories around, but even to handle test failures that result in a dirty state, run each
+ # test in its own folder.
+ TEST_WORKING_DIR=$(basename $TEST_NAME)
+ if [ -e $TEST_WORKING_DIR ]; then
+ rm -f -r $TEST_WORKING_DIR
+ fi
+ mkdir $TEST_WORKING_DIR
+ cd $TEST_WORKING_DIR
+
+ # Create path to a test executable to run
+ TEST_COMMAND="$PAL_TEST_BUILD/$TEST_NAME"
+ echo -n .
+ # Redirect to temp file
+ $TEST_COMMAND 2>&1 | tee ${PAL_OUT_FILE} ; ( exit ${PIPESTATUS[0]} )
+
+ # Get exit code of the test process.
+ TEST_EXIT_CODE=$?
+
+ # Change back to the output directory, and remove the test's working directory if it's empty
+ cd $PAL_TEST_OUTPUT_DIR
+ rmdir $TEST_WORKING_DIR 2>/dev/null
+
+ TEST_XUNIT_NAME=$(dirname $TEST_NAME)
+ TEST_XUNIT_CLASSNAME=$(dirname $TEST_XUNIT_NAME)
+ TEST_XUNIT_NAME=${TEST_XUNIT_NAME#*/}
+ TEST_XUNIT_NAME=${TEST_XUNIT_NAME#*/}
+
+ TEST_XUNIT_NAME=$(echo $TEST_XUNIT_NAME | tr / .)
+ TEST_XUNIT_CLASSNAME=$(echo $TEST_XUNIT_CLASSNAME | tr / .)
+
+ echo -n "<test name=\"$TEST_XUNIT_CLASSNAME.$TEST_XUNIT_NAME\" type=\"$TEST_XUNIT_CLASSNAME\" method=\"$TEST_XUNIT_NAME\" result=\"" >> $PAL_XUNIT_TEST_LIST_TMP
+
+ # If the exit code is 0 then the test passed, otherwise record a failure.
+ if [ "$TEST_EXIT_CODE" -eq "0" ]; then
+ NUMBER_OF_PASSED_TESTS=$(($NUMBER_OF_PASSED_TESTS + 1))
+ echo "Pass\" />" >> $PAL_XUNIT_TEST_LIST_TMP
+ else
+ echo "Fail\" >" >> $PAL_XUNIT_TEST_LIST_TMP
+ echo "<failure exception-type=\"Exit code: $TEST_EXIT_CODE\">" >> $PAL_XUNIT_TEST_LIST_TMP
+ echo "<message><![CDATA[$(cat $PAL_OUT_FILE)]]></message>" >> $PAL_XUNIT_TEST_LIST_TMP
+ echo "</failure>" >> $PAL_XUNIT_TEST_LIST_TMP
+ echo "</test>" >> $PAL_XUNIT_TEST_LIST_TMP
+ FAILED_TEST="$TEST_NAME. Exit code: $TEST_EXIT_CODE"
+ echo
+ echo FAILED: $FAILED_TEST
+ echo
+
+ # Store the name of the failed test in the list of failed tests.
+ echo $FAILED_TEST >> $PAL_FAILED_TEST_LIST
+
+ NUMBER_OF_FAILED_TESTS=$(($NUMBER_OF_FAILED_TESTS + 1))
+ fi
+done < $PAL_TEST_LIST
+
+# We are done running tests.
+echo
+echo Finished running PAL tests.
+echo
+
+# Finish XUnit file, output to finished file with the number of failures, tests etc
+NUMBER_OF_TESTS=$(($NUMBER_OF_PASSED_TESTS + $NUMBER_OF_FAILED_TESTS))
+
+XUNIT_SUFFIX="</collection>\n"
+XUNIT_SUFFIX+="</assembly>\n"
+XUNIT_SUFFIX+="</assemblies>"
+
+XUNIT_PREFIX="<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+XUNIT_PREFIX+="<assemblies>\n"
+XUNIT_PREFIX+="<assembly name=\"PAL\" total=\"$NUMBER_OF_TESTS\" passed=\"$NUMBER_OF_PASSED_TESTS\" failed=\"$NUMBER_OF_FAILED_TESTS\" skipped=\"0\">\n"
+XUNIT_PREFIX+="<collection total=\"$NUMBER_OF_TESTS\" passed=\"$NUMBER_OF_PASSED_TESTS\" failed=\"$NUMBER_OF_FAILED_TESTS\" skipped=\"0\" name=\"palsuite\">"
+
+printf "$XUNIT_SUFFIX" >> $PAL_XUNIT_TEST_LIST_TMP
+printf "$XUNIT_PREFIX" | cat - $PAL_XUNIT_TEST_LIST_TMP > $PAL_XUNIT_TEST_LIST
+
+# If there were tests failures then print the list of failed tests
+if [ $NUMBER_OF_FAILED_TESTS -gt "0" ]; then
+ echo "The following test(s) failed:"
+ while read FAILED_TEST_NAME
+ do
+ echo $FAILED_TEST_NAME
+ done < $PAL_FAILED_TEST_LIST
+ echo
+fi
+
+echo PAL Test Results:
+echo " Passed: $NUMBER_OF_PASSED_TESTS"
+echo " Failed: $NUMBER_OF_FAILED_TESTS"
+echo
+
+if [ "$COPY_TO_TEST_OUTPUT_DIR" != "$PAL_TEST_OUTPUT_DIR" ]; then
+ mv -f $PAL_TEST_OUTPUT_DIR/* $COPY_TO_TEST_OUTPUT_DIR/
+ rm -f -r $PAL_TEST_OUTPUT_DIR
+ echo Copied PAL test output files to $COPY_TO_TEST_OUTPUT_DIR.
+fi
+
+# Set exit code to be equal to the number PAL tests that have failed.
+# Exit code 0 indicates success.
+exit $NUMBER_OF_FAILED_TESTS
diff --git a/src/pal/tests/palsuite/samples/CMakeLists.txt b/src/pal/tests/palsuite/samples/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/samples/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/samples/test1/CMakeLists.txt b/src/pal/tests/palsuite/samples/test1/CMakeLists.txt
new file mode 100644
index 0000000000..da5892cfa6
--- /dev/null
+++ b/src/pal/tests/palsuite/samples/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_samples_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_samples_test1 coreclrpal)
+
+target_link_libraries(paltest_samples_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/samples/test1/test.c b/src/pal/tests/palsuite/samples/test1/test.c
new file mode 100644
index 0000000000..2eed6f6f44
--- /dev/null
+++ b/src/pal/tests/palsuite/samples/test1/test.c
@@ -0,0 +1,41 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test.c
+**
+** Purpose: This test is an example of the basic structure of a PAL test
+** suite test case.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ /* Initialize the PAL.
+ */
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ Trace("\nTest #1...\n");
+
+#ifdef WIN32
+ Trace("\nWe are testing under Win32 environment.\n");
+#else
+ Trace("\nWe are testing under Non-Win32 environment.\n");
+#endif
+
+ Trace("\nThis test has passed.\n");
+
+ /* Shutdown the PAL.
+ */
+ PAL_Terminate();
+
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/samples/test1/testinfo.dat b/src/pal/tests/palsuite/samples/test1/testinfo.dat
new file mode 100644
index 0000000000..0459d24d63
--- /dev/null
+++ b/src/pal/tests/palsuite/samples/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Samples
+Function = sample
+Name = Sample Test #1
+TYPE = DEFAULT
+EXE1 = test
+Description
+=This is a sample test case. It will always pass.
+
+
diff --git a/src/pal/tests/palsuite/samples/test2/CMakeLists.txt b/src/pal/tests/palsuite/samples/test2/CMakeLists.txt
new file mode 100644
index 0000000000..fdef2aac6b
--- /dev/null
+++ b/src/pal/tests/palsuite/samples/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_samples_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_samples_test2 coreclrpal)
+
+target_link_libraries(paltest_samples_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/samples/test2/test.c b/src/pal/tests/palsuite/samples/test2/test.c
new file mode 100644
index 0000000000..53d4158b9d
--- /dev/null
+++ b/src/pal/tests/palsuite/samples/test2/test.c
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test.c
+**
+** Purpose: A sample to show how to structure a test case.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ int exampleInt = 9;
+
+ /* Initialize the PAL.
+ */
+ if(0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ Trace("\nTest #2...\n");
+
+#ifdef WIN32
+ Trace("\nWe are testing under Win32 environment.\n");
+#else
+ Trace("\nWe are testing under Non-Win32 environment.\n");
+#endif
+
+ if (exampleInt == 9)
+ {
+ Fail("This is an example to how to code a failure. "
+ "This failure was caused by exampleInt equalling %d\n",
+ exampleInt);
+ }
+
+ /* Shutdown the PAL.
+ */
+ PAL_Terminate();
+
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/samples/test2/testinfo.dat b/src/pal/tests/palsuite/samples/test2/testinfo.dat
new file mode 100644
index 0000000000..eb6e38db87
--- /dev/null
+++ b/src/pal/tests/palsuite/samples/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Samples
+Function = sample
+Name = Sample Test #2
+TYPE = DEFAULT
+EXE1 = test
+Description
+=This is a sample test case. It will always fail.
+
diff --git a/src/pal/tests/palsuite/smoketest.script b/src/pal/tests/palsuite/smoketest.script
new file mode 100644
index 0000000000..19bb8cd6dc
--- /dev/null
+++ b/src/pal/tests/palsuite/smoketest.script
@@ -0,0 +1,100 @@
+#!/bin/csh
+
+# Smoketest v1.1
+#
+# This smoketest is intended to stress briefly every part of PAL,
+# and is to be run before submitting or approving a patch, to ensure
+# that it is not breaking the PAL. It should run in about 30 seconds
+#
+# Installation:
+# smoketest.dat and this script should be placed in xxx/xport/tests/palsuite.
+# Execute smoketest with the location of rotor as a commandline arg
+# with no trailing
+#
+# Be sure that xrun and testharness are built. (in xport/tests/harness,
+# cd test_harness, gmake, cd ../xrun, gmake)
+#
+if ($#argv != 1) then
+ echo smoketest v1.1
+ echo " "
+ echo Usage: smoketest location-of-xport
+ echo " "
+ echo "where location-of-xport is the location of your xport checkout"
+ echo "ie. xxxx/xport (with NO TRAILING /)"
+ echo " (For example: smoketest ~/xport)"
+ exit
+endif
+
+setenv ROTOR_DIR $argv[1]
+setenv TH_BIN $argv[1]/tests/harness/test_harness/testharness
+setenv TH_CONFIG $argv[1]/tests/palsuite/smoketest.dat
+setenv TH_RESULTS $argv[1]/tests/palsuite/smoketest.log
+setenv TH_DIR $argv[1]/tests/palsuite
+setenv TH_XRUN $argv[1]/tests/harness/xrun/xrun
+setenv PAL_DBG_CHANNELS ""
+
+
+# Let's check to make sure that the developer has built xrun
+# and testharness for us and/or that the variables above were set
+# properly
+if ((-e $TH_BIN) != 1) then
+ echo $TH_BIN was not found.
+ echo Did you forget to build the test harness\?
+ exit
+endif
+
+if ((-e $TH_XRUN) != 1) then
+ echo $TH_XRUN was not found.
+ echo Did you forget to build Xrun\?
+ exit
+endif
+
+
+$TH_BIN 2>&1 /dev/null
+
+
+set FAILING = `grep EXEC,FAIL $TH_RESULTS | wc -l`
+set PASSING = `grep EXEC,PASS $TH_RESULTS | wc -l`
+set DISABLED = `grep EXEC,DISABLED $TH_RESULTS | wc -l`
+set TOTAL_TESTS = `grep BUILD $TH_RESULTS | wc -l`
+set OTHERS = $TOTAL_TESTS
+@ OTHERS = ((($OTHERS - $FAILING) - $PASSING ) - $DISABLED)
+
+clear
+echo Summary:
+echo ========
+echo Total Number of Tests: $TOTAL_TESTS
+echo Total Passing: $PASSING / $TOTAL_TESTS
+echo Total Failing: $FAILING / $TOTAL_TESTS
+echo Total Disabled: $DISABLED / $TOTAL_TESTS
+echo Other Problems: $OTHERS / $TOTAL_TESTS
+
+if ($FAILING > 0) then
+ echo " "
+ echo "*******************************************"
+ echo "*******************************************"
+ echo "*******************************************"
+ echo "*******************************************"
+ echo "WARNING WARNING WARNING WARNING WARNING"
+ echo " "
+
+ if ($FAILING > 1) then
+ echo There are now $FAILING tests failing.
+ else
+ echo There is now 1 test failing.
+ endif
+
+ echo Please run:
+ echo " "
+ echo grep \"EXEC,FAIL\" $TH_RESULTS
+ echo " "
+ echo to figure out what is going wrong.
+ echo "*******************************************"
+ echo "*******************************************"
+ echo "*******************************************"
+ echo "*******************************************"
+else
+ echo " "
+ echo "Smoketest executed OK."
+ rm $TH_RESULTS
+endif
diff --git a/src/pal/tests/palsuite/tests-manual.dat b/src/pal/tests/palsuite/tests-manual.dat
new file mode 100644
index 0000000000..402e819cea
--- /dev/null
+++ b/src/pal/tests/palsuite/tests-manual.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+c_runtime/exit/test2,1
+pal_specific/pal_get_stderr/test1,1
+pal_specific/pal_get_stdin/test1,1
+pal_specific/pal_get_stdout/test1,1
+threading/setconsolectrlhandler/test1,1
+threading/setconsolectrlhandler/test2,1
+threading/setconsolectrlhandler/test3,1
+threading/setconsolectrlhandler/test4,1
diff --git a/src/pal/tests/palsuite/threading/CMakeLists.txt b/src/pal/tests/palsuite/threading/CMakeLists.txt
new file mode 100644
index 0000000000..bd31d17579
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CMakeLists.txt
@@ -0,0 +1,44 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(CreateEventA)
+add_subdirectory(CreateEventW)
+add_subdirectory(CreateMutexA_ReleaseMutex)
+add_subdirectory(CreateMutexW_ReleaseMutex)
+add_subdirectory(CreateProcessA)
+add_subdirectory(CreateProcessW)
+add_subdirectory(CreateSemaphoreA_ReleaseSemaphore)
+add_subdirectory(CreateSemaphoreW_ReleaseSemaphore)
+add_subdirectory(CreateThread)
+add_subdirectory(CriticalSectionFunctions)
+add_subdirectory(DuplicateHandle)
+add_subdirectory(ExitProcess)
+add_subdirectory(ExitThread)
+add_subdirectory(GetCurrentProcess)
+add_subdirectory(GetCurrentProcessId)
+add_subdirectory(GetCurrentThread)
+add_subdirectory(GetCurrentThreadId)
+add_subdirectory(GetExitCodeProcess)
+add_subdirectory(GetProcessTimes)
+add_subdirectory(GetThreadTimes)
+add_subdirectory(NamedMutex)
+add_subdirectory(OpenEventW)
+add_subdirectory(OpenProcess)
+add_subdirectory(QueryThreadCycleTime)
+add_subdirectory(QueueUserAPC)
+add_subdirectory(ReleaseMutex)
+add_subdirectory(releasesemaphore)
+add_subdirectory(ResetEvent)
+add_subdirectory(ResumeThread)
+add_subdirectory(SetErrorMode)
+add_subdirectory(SetEvent)
+add_subdirectory(Sleep)
+add_subdirectory(SleepEx)
+add_subdirectory(SwitchToThread)
+add_subdirectory(TerminateProcess)
+add_subdirectory(ThreadPriority)
+add_subdirectory(TLS)
+add_subdirectory(WaitForMultipleObjects)
+add_subdirectory(WaitForMultipleObjectsEx)
+add_subdirectory(WaitForSingleObject)
+add_subdirectory(YieldProcessor)
+
diff --git a/src/pal/tests/palsuite/threading/CreateEventA/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateEventA/CMakeLists.txt
new file mode 100644
index 0000000000..1962ade358
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateEventA/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+
diff --git a/src/pal/tests/palsuite/threading/CreateEventA/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateEventA/test1/CMakeLists.txt
new file mode 100644
index 0000000000..da1232eea4
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateEventA/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_createeventa_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createeventa_test1 coreclrpal)
+
+target_link_libraries(paltest_createeventa_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/CreateEventA/test1/test1.c b/src/pal/tests/palsuite/threading/CreateEventA/test1/test1.c
new file mode 100644
index 0000000000..d8ef0f58a3
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateEventA/test1/test1.c
@@ -0,0 +1,95 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test1.c
+**
+** Purpose: Test for CreateEvent. Create an event, ensure the
+** HANDLE is valid. Then check to ensure that the object is in the
+** signaled state. Close the HANDLE and done.
+**
+**
+**=========================================================*/
+
+/*
+ Note: From the rotor_pal documentation:
+
+ lpEventAttributes will always be NULL, bManualReset can be either
+ TRUE or FALSE, bInitialState can be either TRUE or FALSE, the lpName
+ may be non-NULL
+
+*/
+
+
+#include <palsuite.h>
+
+BOOL CreateEventTest()
+{
+ BOOL bRet = FALSE;
+ DWORD dwRet = 0;
+
+ LPSECURITY_ATTRIBUTES lpEventAttributes = NULL;
+ BOOL bManualReset = TRUE;
+ BOOL bInitialState = TRUE;
+
+ /* Call CreateEvent, and check to ensure the returned HANDLE is a
+ valid event HANDLE
+ */
+
+ HANDLE hEvent = CreateEvent( lpEventAttributes,
+ bManualReset,
+ bInitialState,
+ NULL);
+
+ if (hEvent != NULL)
+ {
+ /* Wait for the Object (for 0 time) and ensure that it returns
+ the value indicating that the event is signaled.
+ */
+ dwRet = WaitForSingleObject(hEvent,0);
+
+ if (dwRet != WAIT_OBJECT_0)
+ {
+ Trace("CreateEventTest:WaitForSingleObject failed (%x)\n", GetLastError());
+ }
+ else
+ {
+ /* If we make it here, and CloseHandle succeeds, then the
+ entire test has passed. Otherwise bRet will still show
+ failure
+ */
+ bRet = CloseHandle(hEvent);
+
+ if (!bRet)
+ {
+ Trace("CreateEventTest:CloseHandle failed (%x)\n", GetLastError());
+ }
+ }
+ }
+ else
+ {
+ Trace("CreateEventTest:CreateEvent failed (%x)\n", GetLastError());
+ }
+
+ return bRet;
+}
+
+int __cdecl main(int argc, char **argv)
+{
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ if(!CreateEventTest())
+ {
+ Fail ("Test failed\n");
+ }
+
+ PAL_Terminate();
+ return ( PASS );
+
+}
diff --git a/src/pal/tests/palsuite/threading/CreateEventA/test1/testinfo.dat b/src/pal/tests/palsuite/threading/CreateEventA/test1/testinfo.dat
new file mode 100644
index 0000000000..c0d169ccdc
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateEventA/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = CreateEvent
+Name = Positive Test for CreateEvent
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Test for CreateEvent. Create an event, ensure the
+= HANDLE is valid. Then check to ensure that the object is in the
+= signaled state. Close the HANDLE and done.
diff --git a/src/pal/tests/palsuite/threading/CreateEventA/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateEventA/test2/CMakeLists.txt
new file mode 100644
index 0000000000..f87e5bea87
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateEventA/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_createeventa_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createeventa_test2 coreclrpal)
+
+target_link_libraries(paltest_createeventa_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/CreateEventA/test2/test2.c b/src/pal/tests/palsuite/threading/CreateEventA/test2/test2.c
new file mode 100644
index 0000000000..a24d20eeea
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateEventA/test2/test2.c
@@ -0,0 +1,84 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test2.c
+**
+** Purpose: Test for CreateEvent. Create the event with the
+** initial state being not signaled. Check to ensure that it
+** times out when the event is triggered.
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+BOOL CreateEventTest()
+{
+ BOOL bRet = FALSE;
+ DWORD dwRet = 0;
+
+ LPSECURITY_ATTRIBUTES lpEventAttributes = 0;
+ BOOL bManualReset = TRUE;
+ BOOL bInitialState = FALSE;
+
+ /* Create an event with the Initial State set to FALSE */
+
+ HANDLE hEvent = CreateEvent( lpEventAttributes,
+ bManualReset,
+ bInitialState,
+ NULL);
+
+ if (hEvent != NULL)
+ {
+ /* This should ensure that the object is reset, or
+ non-signaled.
+ */
+
+ dwRet = WaitForSingleObject(hEvent,0);
+
+ if (dwRet != WAIT_TIMEOUT)
+ {
+ Trace("CloseEventTest:WaitForSingleObject failed (%x)\n", GetLastError());
+ }
+ else
+ {
+ /* At this point, we've tested the function with success.
+ So long as the HANDLE can be closed, this test should
+ pass.
+ */
+
+ bRet = CloseHandle(hEvent);
+
+ if (!bRet)
+ {
+ Trace("CloseEventTest:CloseHandle failed (%x)\n", GetLastError());
+ }
+ }
+ }
+ else
+ {
+ Trace("CloseEventTest:CreateEvent failed (%x)\n", GetLastError());
+ }
+
+ return bRet;
+}
+
+int __cdecl main(int argc, char **argv)
+{
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ if(!CreateEventTest())
+ {
+ Fail ("Test failed\n");
+ }
+
+ PAL_Terminate();
+ return ( PASS );
+
+}
diff --git a/src/pal/tests/palsuite/threading/CreateEventA/test2/testinfo.dat b/src/pal/tests/palsuite/threading/CreateEventA/test2/testinfo.dat
new file mode 100644
index 0000000000..4af65f18d8
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateEventA/test2/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = CreateEvent
+Name = Positive Test for CreateEvent
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Test for CreateEvent. Create the event with the
+= initial state being not signaled. Check to ensure that it
+= times out when the event is triggered.
diff --git a/src/pal/tests/palsuite/threading/CreateEventA/test3/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateEventA/test3/CMakeLists.txt
new file mode 100644
index 0000000000..e33c404a79
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateEventA/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_createeventa_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createeventa_test3 coreclrpal)
+
+target_link_libraries(paltest_createeventa_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/CreateEventA/test3/test3.c b/src/pal/tests/palsuite/threading/CreateEventA/test3/test3.c
new file mode 100644
index 0000000000..56d107b22d
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateEventA/test3/test3.c
@@ -0,0 +1,219 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test3.c
+**
+** Purpose: Tests for CreateEventA. Create an event with an empty name,
+** create an event with the same name as an already created event
+** object.
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+#define SWAPPTR ((VOID *)(-1))
+
+struct testCase
+{
+ LPSECURITY_ATTRIBUTES lpEventAttributes;
+ BOOL bManualReset;
+ BOOL bInitialState;
+ char lpName[MAX_PATH + 2];
+ DWORD dwNameLen;
+ DWORD lastError;
+ BOOL bResult;
+};
+
+struct testCase testCases[]=
+{
+ {0, TRUE, FALSE, "", 0, ERROR_SUCCESS, PASS},
+ {0, TRUE, FALSE, "", 5, ERROR_SUCCESS, PASS},
+ {0, TRUE, FALSE, "", 5, ERROR_ALREADY_EXISTS, PASS},
+ {0, TRUE, FALSE, "", 6, ERROR_INVALID_HANDLE, PASS},
+ {0, TRUE, FALSE, "", MAX_PATH - 1 - 60, ERROR_SUCCESS, PASS},
+ {0, TRUE, FALSE, "", MAX_PATH + 1, ERROR_FILENAME_EXCED_RANGE, PASS}
+};
+
+static HANDLE hEvent[sizeof(testCases)/sizeof(struct testCase)];
+
+DWORD result[sizeof(testCases)/sizeof(struct testCase)];
+
+int __cdecl main(int argc, char **argv)
+{
+
+ BOOL bRet = TRUE;
+ const char *nonEventName = "aaaaaa";
+ HANDLE hUnnamedEvent;
+ HANDLE hFMap;
+ DWORD dwRet;
+ int i;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ hUnnamedEvent = CreateEventA(0, TRUE, FALSE, NULL);
+
+ if ( NULL == hUnnamedEvent )
+ {
+ bRet = FALSE;
+ Trace ( "PALSUITE ERROR: CreateEventA (%d, %d, %d, NULL) call "
+ "returned NULL.\nGetLastError returned %u.\n", 0, TRUE, FALSE,
+ GetLastError());
+ }
+
+ if (!CloseHandle(hUnnamedEvent))
+ {
+ bRet = FALSE;
+ Trace("PALSUITE ERROR: CreateEventA: CloseHandle(%lp); call "
+ "failed\nGetLastError returned '%u'.\n", hUnnamedEvent,
+ GetLastError());
+ }
+
+ /* Create non-event with the same name as one of the testCases */
+ hFMap = CreateFileMappingA( SWAPPTR, NULL, PAGE_READONLY, 0, 1,
+ nonEventName );
+
+ if ( NULL == hFMap )
+ {
+ bRet = FALSE;
+ Trace ( "PALSUITE ERROR: CreateFileMapping (%p, %p, %d, %d, %d, %s)"
+ " call returned NULL.\nGetLastError returned %u.\n",
+ SWAPPTR, NULL, PAGE_READONLY, 0, 0, nonEventName,
+ GetLastError());
+ goto done;
+ }
+
+ /* Create Events */
+ for (i = 0; i < sizeof(testCases)/sizeof(struct testCase); i++)
+ {
+ /* create name */
+ memset (testCases[i].lpName, '\0', (MAX_PATH + 2));
+ memset (testCases[i].lpName, 'a', testCases[i].dwNameLen );
+
+ SetLastError(ERROR_SUCCESS);
+
+ hEvent[i] = CreateEventA( testCases[i].lpEventAttributes,
+ testCases[i].bManualReset,
+ testCases[i].bInitialState,
+ testCases[i].lpName);
+
+ if (hEvent[i] != INVALID_HANDLE_VALUE)
+ {
+ DWORD dwError = GetLastError();
+
+ if (dwError != testCases[i].lastError)
+ {
+ bRet = FALSE;
+ Trace ("PALSUITE ERROR:\nCreateEventA(%lp, %d, %d, %s)"
+ "\nGetLastError returned '%u', it should have returned"
+ "'%d' at index '%d'.\n", testCases[i].lpEventAttributes,
+ testCases[i].bManualReset, testCases[i].bInitialState,
+ testCases[i].lpName, dwError,
+ testCases[i].lastError, i);
+ }
+ if ( ERROR_FILENAME_EXCED_RANGE == testCases[i].lastError )
+ {
+ result [i] = 1;
+ }
+ if ( ERROR_INVALID_HANDLE == testCases[i].lastError )
+ {
+ result [i] = 1;
+ }
+ /*
+ * If we expected the testcase to FAIL and it passed,
+ * report an error.
+ */
+ if (testCases[i].bResult == FAIL)
+ {
+ bRet = FALSE;
+ Trace ("PALSUITE ERROR:\nCreateEventA(%lp, %d, %d, %s)"
+ "\nShould have returned INVALID_HANDLE_VALUE but "
+ "didn't at index '%d'.\n",
+ testCases[i].lpEventAttributes,
+ testCases[i].bManualReset,
+ testCases[i].bInitialState,
+ testCases[i].lpName, i);
+ }
+ /*
+ * If result hasn't been set already set it to 0 so all the
+ * resources will be freed.
+ */
+ if (!result[i] )
+ {
+ result[i] = 0;
+ }
+ }
+ else
+ {
+ /*
+ * If we get an INVALID_HANDLE_VALUE and we expected the
+ * test case to pass, report an error.
+ */
+ result[i] = 1;
+
+ if (testCases[i].bResult == PASS)
+ {
+ bRet = FALSE;
+ Trace ("PALSUITE ERROR:\nCreateEventA(%lp, %d, %d, %s);"
+ "\nReturned INVALID_HANDLE_VALUE at index '%d'.\n",
+ testCases[i].lpEventAttributes,
+ testCases[i].bManualReset, testCases[i].bInitialState,
+ testCases[i].lpName, i);
+ }
+ }
+ }
+
+ /* cleanup */
+ for (i = 0; i < sizeof(testCases)/sizeof(struct testCase); i++)
+ {
+ if (result[i])
+ {
+ continue;
+ }
+ dwRet = WaitForSingleObject ( hEvent[i], 0 );
+
+ if (dwRet != WAIT_TIMEOUT)
+ {
+ bRet = FALSE;
+ Trace("PALSUITE ERROR: CreateEventA:\nWaitForSingleObject (%lp, "
+ "%d) call failed at index %d .\nGetLastError returned "
+ "'%u'.\n", hEvent[i], 0, i, GetLastError());
+ }
+
+ if (!CloseHandle(hEvent[i]))
+ {
+ bRet = FALSE;
+ Trace("PALSUITE ERROR: CreateEventA: CloseHandle(%lp) call "
+ "failed at index %d\nGetLastError returned '%u'.\n",
+ hEvent[i], i, GetLastError());
+ }
+ }
+
+done:
+ if (!CloseHandle(hFMap))
+ {
+ bRet = FALSE;
+ Trace("PALSUITE ERROR: CreateEventW: CloseHandle(%p) call "
+ "failed\nGetLastError returned '%u'.\n", hFMap,
+ GetLastError());
+ }
+
+ if (FALSE == bRet)
+ {
+ bRet = FAIL;
+ }
+ else
+ {
+ bRet = PASS;
+ }
+
+ PAL_TerminateEx(bRet);
+
+ return(bRet);
+}
diff --git a/src/pal/tests/palsuite/threading/CreateEventA/test3/testinfo.dat b/src/pal/tests/palsuite/threading/CreateEventA/test3/testinfo.dat
new file mode 100644
index 0000000000..c3a344a2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateEventA/test3/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = CreateEventA
+Name = Positive Test for CreateEventA
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Tests for CreateEventA. Create an unnamed event, create
+= an event with an empty name, create an event with a name longer than
+= MAX_PATH, MAX_PATH + 1, create an event with a name already taken
+= by a non-event object, create an event with a name already taken
+= by an event object.
diff --git a/src/pal/tests/palsuite/threading/CreateEventW/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateEventW/CMakeLists.txt
new file mode 100644
index 0000000000..1962ade358
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateEventW/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+
diff --git a/src/pal/tests/palsuite/threading/CreateEventW/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateEventW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..0e8ba5bc2a
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateEventW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_createeventw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createeventw_test1 coreclrpal)
+
+target_link_libraries(paltest_createeventw_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/CreateEventW/test1/test1.c b/src/pal/tests/palsuite/threading/CreateEventW/test1/test1.c
new file mode 100644
index 0000000000..8d99e41934
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateEventW/test1/test1.c
@@ -0,0 +1,93 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test1.c
+**
+** Purpose: Test for CreateEventW
+**
+**
+**=========================================================*/
+
+/*
+ * Note: From the rotor_pal documentation: lpEventAttributes will
+ * always be NULL, bManualReset can be either TRUE or FALSE,
+ * bInitialState can be either TRUE or FALSE, the lpName may be
+ * non-NULL.
+*/
+#define UNICODE
+#include <palsuite.h>
+
+BOOL CreateEventTest()
+{
+ BOOL bRet = FALSE;
+ DWORD dwRet = 0;
+
+ LPSECURITY_ATTRIBUTES lpEventAttributes = NULL;
+ BOOL bManualReset = TRUE;
+ BOOL bInitialState = TRUE;
+
+ /*
+ * Call CreateEvent, and check to ensure the returned HANDLE is a
+ * valid event HANDLE
+ */
+
+ HANDLE hEvent = CreateEventW(lpEventAttributes,
+ bManualReset,
+ bInitialState,
+ NULL);
+
+ if (hEvent != NULL)
+ {
+ /*
+ * Wait for the Object (for 0 time) and ensure that it returns
+ * the value indicating that the event is signaled.
+ */
+ dwRet = WaitForSingleObject(hEvent,0);
+
+ if (dwRet != WAIT_OBJECT_0)
+ {
+ Trace("CreateEventTest:WaitForSingleObject failed (%x)\n", GetLastError());
+ }
+ else
+ {
+ /*
+ * If we make it here, and CloseHandle succeeds, then the
+ * entire test has passed. Otherwise bRet will still show
+ * failure
+ */
+ bRet = CloseHandle(hEvent);
+
+ if (!bRet)
+ {
+ Trace("CreateEventTest:CloseHandle failed (%x)\n", GetLastError());
+ }
+ }
+ }
+ else
+ {
+ Trace("CreateEventTest:CreateEvent failed (%x)\n", GetLastError());
+ }
+
+ return bRet;
+}
+
+int __cdecl main(int argc, char **argv)
+{
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ if(!CreateEventTest())
+ {
+ Fail ("Test failed\n");
+ }
+
+ PAL_Terminate();
+ return ( PASS );
+
+}
diff --git a/src/pal/tests/palsuite/threading/CreateEventW/test1/testinfo.dat b/src/pal/tests/palsuite/threading/CreateEventW/test1/testinfo.dat
new file mode 100644
index 0000000000..204ad1f4d4
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateEventW/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = CreateEventW
+Name = Positive Test for CreateEventW
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Test for CreateEventW. Create an event, ensure the
+= HANDLE is valid. Then check to ensure that the object is in the
+= signaled state. Close the HANDLE and done.
diff --git a/src/pal/tests/palsuite/threading/CreateEventW/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateEventW/test2/CMakeLists.txt
new file mode 100644
index 0000000000..f624377474
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateEventW/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_createeventw_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createeventw_test2 coreclrpal)
+
+target_link_libraries(paltest_createeventw_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/CreateEventW/test2/test2.c b/src/pal/tests/palsuite/threading/CreateEventW/test2/test2.c
new file mode 100644
index 0000000000..4df218995a
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateEventW/test2/test2.c
@@ -0,0 +1,85 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test2.c
+**
+** Purpose: Test for CreateEventW. Create the event with the
+** initial state being not signaled. Check to ensure that it
+** times out when the event is triggered.
+**
+**
+**=========================================================*/
+#define UNICODE
+#include <palsuite.h>
+
+BOOL CreateEventTest()
+{
+ BOOL bRet = FALSE;
+ DWORD dwRet = 0;
+
+ LPSECURITY_ATTRIBUTES lpEventAttributes = 0;
+ BOOL bManualReset = TRUE;
+ BOOL bInitialState = FALSE;
+
+
+ /* Create an event with the Initial State set to FALSE */
+
+ HANDLE hEvent = CreateEventW(lpEventAttributes,
+ bManualReset,
+ bInitialState,
+ NULL);
+
+ if (hEvent != NULL)
+ {
+ /* This should ensure that the object is reset, or
+ non-signaled.
+ */
+
+ dwRet = WaitForSingleObject(hEvent,0);
+
+ if (dwRet != WAIT_TIMEOUT)
+ {
+ Trace("CloseEventTest:WaitForSingleObject failed (%x)\n", GetLastError());
+ }
+ else
+ {
+ /* At this point, we've tested the function with success.
+ So long as the HANDLE can be closed, this test should
+ pass.
+ */
+
+ bRet = CloseHandle(hEvent);
+
+ if (!bRet)
+ {
+ Trace("CloseEventTest:CloseHandle failed (%x)\n", GetLastError());
+ }
+ }
+ }
+ else
+ {
+ Trace("CloseEventTest:CreateEvent failed (%x)\n", GetLastError());
+ }
+
+ return bRet;
+}
+
+int __cdecl main(int argc, char **argv)
+{
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ if(!CreateEventTest())
+ {
+ Fail ("Test failed\n");
+ }
+
+ PAL_Terminate();
+ return ( PASS );
+
+}
diff --git a/src/pal/tests/palsuite/threading/CreateEventW/test2/testinfo.dat b/src/pal/tests/palsuite/threading/CreateEventW/test2/testinfo.dat
new file mode 100644
index 0000000000..01f7519ae3
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateEventW/test2/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = CreateEventW
+Name = Positive Test for CreateEventW
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Test for CreateEvent. Create the event with the
+= initial state being not signaled. Check to ensure that it
+= times out when the event is triggered.
diff --git a/src/pal/tests/palsuite/threading/CreateEventW/test3/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateEventW/test3/CMakeLists.txt
new file mode 100644
index 0000000000..4493ba3872
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateEventW/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_createeventw_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createeventw_test3 coreclrpal)
+
+target_link_libraries(paltest_createeventw_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/CreateEventW/test3/test3.c b/src/pal/tests/palsuite/threading/CreateEventW/test3/test3.c
new file mode 100644
index 0000000000..22f0fcfc49
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateEventW/test3/test3.c
@@ -0,0 +1,233 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test3.c
+**
+** Purpose: Tests for CreateEvent. Create an unnamed event, create
+** an event with an empty name, create an event with a name longer than
+** MAX_PATH, MAX_PATH + 1, create an event with a name already taken
+** by a non-event object, create an event with a name already taken
+** by an event object.
+**
+**
+**=========================================================*/
+#include <palsuite.h>
+
+#define SWAPPTR ((VOID *) (-1))
+
+struct testCase
+{
+ LPSECURITY_ATTRIBUTES lpEventAttributes;
+ BOOL bManualReset;
+ BOOL bInitialState;
+ WCHAR lpName[MAX_PATH + 2];
+ DWORD dwNameLen;
+ DWORD lastError;
+ BOOL bResult;
+};
+
+struct testCase testCases[]=
+{
+ {0, TRUE, FALSE, {'\0'}, 0, ERROR_SUCCESS, PASS},
+ {0, TRUE, FALSE, {'\0'}, 5, ERROR_SUCCESS, PASS},
+ {0, TRUE, FALSE, {'\0'}, 5, ERROR_ALREADY_EXISTS, PASS},
+ {0, TRUE, FALSE, {'\0'}, 6, ERROR_INVALID_HANDLE, PASS},
+ {0, TRUE, FALSE, {'\0'}, MAX_PATH - 1 - 60, ERROR_SUCCESS, PASS},
+ {0, TRUE, FALSE, {'\0'}, MAX_PATH - 60, ERROR_SUCCESS, PASS},
+};
+
+static HANDLE hEvent[sizeof(testCases)/sizeof(struct testCase)];
+
+DWORD result[sizeof(testCases)/sizeof(struct testCase)];
+
+int __cdecl main(int argc, char **argv)
+{
+
+ BOOL bRet = TRUE;
+ WCHAR nonEventName[] = {'a','a','a','a','a','a','\0'};
+ char name[MAX_PATH + 2];
+ WCHAR *wName;
+ HANDLE hFMap = NULL;
+ HANDLE hUnnamedEvent;
+ DWORD dwRet;
+ int i;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ hUnnamedEvent = CreateEventW(0, TRUE, FALSE, NULL);
+
+ if ( NULL == hUnnamedEvent )
+ {
+ bRet = FALSE;
+ Trace ( "PALSUITE ERROR: CreateEventW (%d, %d, %d, NULL) call "
+ "returned NULL.\nGetLastError returned %u.\n", 0, TRUE, FALSE,
+ GetLastError());
+ goto done;
+ }
+
+ if (!CloseHandle(hUnnamedEvent))
+ {
+ bRet = FALSE;
+ Trace("PALSUITE ERROR: CreateEventW: CloseHandle(%lp); call "
+ "failed\nGetLastError returned '%u'.\n", hUnnamedEvent,
+ GetLastError());
+ }
+
+ /* Create non-event with the same name as one of the testCases */
+ hFMap = CreateFileMappingW( SWAPPTR, NULL, PAGE_READONLY, 0, 1,
+ nonEventName );
+
+ if ( NULL == hFMap )
+ {
+ bRet = FALSE;
+ Trace ( "PALSUITE ERROR: CreateFileMapping (%p, %p, %d, %d, %d, %S)"
+ " call returned NULL.\nGetLastError returned %u\n",
+ SWAPPTR, NULL, PAGE_READONLY, 0, 0, nonEventName,
+ GetLastError());
+ }
+
+ /* Create Events */
+ for (i = 0; i < sizeof(testCases)/sizeof(struct testCase); i++)
+ {
+ /* create name */
+ memset (name, '\0', MAX_PATH + 2);
+ memset (name, 'a', testCases[i].dwNameLen );
+
+ wName = convert(name);
+
+ wcsncpy(testCases[i].lpName, wName,
+ testCases[i].dwNameLen);
+
+ free(wName);
+
+ SetLastError(ERROR_SUCCESS);
+
+ hEvent[i] = CreateEventW( testCases[i].lpEventAttributes,
+ testCases[i].bManualReset,
+ testCases[i].bInitialState,
+ testCases[i].lpName);
+
+ if (hEvent[i] != INVALID_HANDLE_VALUE)
+ {
+ DWORD dwError = GetLastError();
+
+ if (dwError != testCases[i].lastError)
+ {
+ bRet = FALSE;
+ Trace ("PALSUITE ERROR:\nCreateEvent(%lp, %d, %d, %S)"
+ "\nGetLastError returned '%u', it should have returned"
+ "'%d' at index '%d'.\n", testCases[i].lpEventAttributes,
+ testCases[i].bManualReset, testCases[i].bInitialState,
+ testCases[i].lpName, dwError,
+ testCases[i].lastError, i);
+ }
+ if ( ERROR_FILENAME_EXCED_RANGE == testCases[i].lastError )
+ {
+ result [i] = 1;
+ }
+ if ( ERROR_INVALID_HANDLE == testCases[i].lastError )
+ {
+ result [i] = 1;
+ }
+ /*
+ * If we expected the testcase to FAIL and it passed,
+ * report an error.
+ */
+ if (testCases[i].bResult == FAIL)
+ {
+ bRet = FALSE;
+ Trace ("PALSUITE ERROR:\nCreateEvent(%lp, %d, %d, %S)"
+ "\nShould have returned INVALID_HANDLE_VALUE but "
+ "didn't at index '%d'.\n",
+ testCases[i].lpEventAttributes,
+ testCases[i].bManualReset,
+ testCases[i].bInitialState,
+ testCases[i].lpName, i);
+ }
+ /*
+ * If result hasn't been set already set it to 0 so all the
+ * resources will be freed.
+ */
+ if (!result[i])
+ {
+ result[i] = 0;
+ }
+ }
+ else
+ {
+ /*
+ * If we get an INVALID_HANDLE_VALUE and we expected the
+ * test case to pass, report an error.
+ */
+ result[i] = 1;
+
+ if (testCases[i].bResult == PASS)
+ {
+ bRet = FALSE;
+ Trace ("PALSUITE ERROR:\nCreateEvent(%lp, %d, %d, %S);"
+ "\nReturned INVALID_HANDLE_VALUE at index '%d'.\n",
+ testCases[i].lpEventAttributes,
+ testCases[i].bManualReset, testCases[i].bInitialState,
+ testCases[i].lpName, i);
+ }
+ }
+ }
+
+ /* cleanup */
+ for (i = 0; i < sizeof(testCases)/sizeof(struct testCase); i++)
+ {
+ if (result[i])
+ {
+ continue;
+ }
+ dwRet = WaitForSingleObject ( hEvent[i], 0 );
+
+ if (dwRet != WAIT_TIMEOUT)
+ {
+ bRet = FALSE;
+ Trace("PALSUITE ERROR: CreateEventW:\nWaitForSingleObject (%lp, "
+ "%d) call failed at index %d .\nGetLastError returned "
+ "'%u'.\n", hEvent[i], 0, i, GetLastError());
+ }
+
+ if (!CloseHandle(hEvent[i]))
+ {
+ bRet = FALSE;
+ Trace("PALSUITE ERROR: CreateEventW: CloseHandle(%lp) call "
+ "failed at index %d\nGetLastError returned '%u'.\n",
+ hEvent[i], i, GetLastError());
+ }
+ }
+
+done:
+ if (hFMap != NULL && !CloseHandle(hFMap))
+ {
+ bRet = FALSE;
+ Trace("PALSUITE ERROR: CreateEventW: CloseHandle(%p) call "
+ "failed\nGetLastError returned '%u'.\n", hFMap,
+ GetLastError());
+ }
+
+ if (FALSE == bRet)
+ {
+ bRet = FAIL;
+ }
+ else
+ {
+ bRet = PASS;
+ }
+
+ PAL_TerminateEx(bRet);
+
+ return(bRet);
+
+}
+
+
+
diff --git a/src/pal/tests/palsuite/threading/CreateEventW/test3/testinfo.dat b/src/pal/tests/palsuite/threading/CreateEventW/test3/testinfo.dat
new file mode 100644
index 0000000000..4776ed239f
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateEventW/test3/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = CreateEventW
+Name = Positive Test for CreateEventW
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Tests for CreateEventW. Create an unnamed event, create
+= an event with an empty name, create an event with a name longer than
+= MAX_PATH, MAX_PATH + 1, create an event with a name already taken
+= by a non-event object, create an event with a name already taken
+= by an event object.
diff --git a/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test1/CMakeLists.txt
new file mode 100644
index 0000000000..ffdf13228e
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ CreateMutexA.c
+)
+
+add_executable(paltest_createmutexa_releasemutex_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createmutexa_releasemutex_test1 coreclrpal)
+
+target_link_libraries(paltest_createmutexa_releasemutex_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test1/CreateMutexA.c b/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test1/CreateMutexA.c
new file mode 100644
index 0000000000..52bab351fb
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test1/CreateMutexA.c
@@ -0,0 +1,345 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: CreateMutexA_ReleaseMutex/test1/CreateMutexA.c
+**
+** Purpose: This test case tests whether a Mutex object created
+** with CreateMutex really works by mutually excluding
+** threads from accessing a data structure at the same
+** time. Here we have a buffer that can be filled or
+** emptied, we use a Mutex object to ensure that one
+** operation cannot be started until the other is
+** finished. If one operation detects that the other
+** has not finished, it fails. There is a Producer
+** thread which will try to fill the buffer 25 times,
+** and a consumer thread which try to empty the buffer
+** 25 times. If either the fill or empty operations
+** fails because the Mutex failed to mutually exclude
+** them, the corresponding thread will set an error
+** flag and return. This will cause the test case to
+** fail.
+**
+** To increase the probability of identifying problems,
+** the Fill opeartion has been slowed down with a call
+** to Sleep. This ensures that one operation will try
+** to access the shared buffer while the other is in
+** progress.
+**
+** NOTE: this test case also serves as a test case for
+** WaitForSingleObject.
+**
+**
+** Dependencies: CreateThread
+** ReleaseMutex
+** WaitForSingleObject
+** WaitForMultipleObjects
+** Sleep
+** memset
+**
+
+**
+**=========================================================*/
+
+#define UNICODE
+#include <palsuite.h>
+
+/* Define some values that we will using many times */
+#define MAIN_BUF_SIZE 40
+#define NUM_OF_CYCLES 40
+
+/* Buffer Operation return codes */
+#define OP_OK 0
+#define OP_ERR 1
+#define OP_NONE 2
+
+
+HANDLE hMutex; /* handle to mutex */
+
+BOOL bProdErr; /* Producer error Flag */
+BOOL bConErr; /* Consumer error Flag */
+
+/* Test Buffer */
+char Buffer[MAIN_BUF_SIZE];
+
+/*
+ * EmptyBuffer implements the empty operation for test buffer.
+ */
+int
+EmptyBuffer()
+{
+ int i;
+
+ if ( WaitForSingleObject(hMutex, INFINITE) == WAIT_FAILED)
+ {
+ Fail("ERROR: WaitForSingleObject failed.\n");
+ }
+
+ /* Check to see if the buffer is already completely empty */
+ for (i=0; i<MAIN_BUF_SIZE && Buffer[i] == 0; i++);
+ if (i == MAIN_BUF_SIZE)
+ {
+ /* Its empty so just return */
+ if (ReleaseMutex(hMutex) == FALSE)
+ {
+ Fail("ERROR: ReleaseMutex Failed.\n");
+ }
+ return OP_NONE;
+ }
+
+ /* Its not empty so we must empty it. */
+ for (i=0; i<MAIN_BUF_SIZE; i++)
+ {
+ /* Check for empty slots if we find one then the */
+ /* fill operation did no finish. return an error */
+ if (Buffer[i] == 0)
+ {
+ if (ReleaseMutex(hMutex) == FALSE)
+ {
+ Fail("ERROR: ReleaseMutex Failed.\n");
+ }
+ return OP_ERR;
+ }
+
+ Buffer[i] = 0;
+ }
+
+ if (ReleaseMutex(hMutex) == FALSE)
+ {
+ Fail("ERROR: ReleaseMutex Failed.\n");
+ }
+ return OP_OK;
+}
+
+/*
+ * FillBuffer implements the fill operation for test buffer.
+ */
+int
+FillBuffer()
+{
+ int i;
+
+ if ( WaitForSingleObject(hMutex, INFINITE) == WAIT_FAILED)
+ {
+ Fail("ERROR: WaitForSingleObject failed.\n");
+ }
+
+ /* Check to see if the buffer is already completely full */
+ for (i=0; i<MAIN_BUF_SIZE && Buffer[i] != 0; i++);
+ if (i == MAIN_BUF_SIZE)
+ {
+ /* Its full so just return */
+ if (ReleaseMutex(hMutex) == FALSE)
+ {
+ Fail("ERROR: ReleaseMutex Failed.\n");
+ }
+ return OP_NONE;
+ }
+
+ /* Its not full so we must fill it. */
+ for (i=0; i<MAIN_BUF_SIZE; i++)
+ {
+ /* Check for filled slots if we find one then the */
+ /* empty operation did not finish. return an error */
+ if (Buffer[i] == 1)
+ {
+ if (ReleaseMutex(hMutex) == FALSE)
+ {
+ Fail("ERROR: ReleaseMutex Failed.\n");
+ }
+ return OP_ERR;
+ }
+
+ Buffer[i] = 1;
+ Sleep(10);
+ }
+
+ if (ReleaseMutex(hMutex) == FALSE)
+ {
+ Fail("ERROR: ReleaseMutex Failed.\n");
+ }
+ return OP_OK;
+}
+
+
+
+
+/*
+ * Producer thread function.
+ */
+DWORD
+Producer(LPVOID lpParam)
+{
+ int n = 0;
+ int ret;
+
+ while (n < NUM_OF_CYCLES)
+ {
+ if (bConErr == TRUE)
+ {
+ /* The consumer ran into an error so we'll stop */
+ return 0;
+ }
+
+ ret = FillBuffer();
+
+ if (ret == OP_OK)
+ {
+ n++;
+ }
+ else if (ret == OP_ERR)
+ {
+ bProdErr = TRUE;
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Consumer thread function.
+ */
+DWORD Consumer( LPVOID lpParam )
+{
+ int n = 0;
+ int ret;
+
+ while (n < NUM_OF_CYCLES)
+ {
+ if (bProdErr == TRUE)
+ {
+ /* The consumer ran into an error so we'll stop */
+ return 0;
+ }
+
+ ret = EmptyBuffer();
+
+ if (ret == OP_OK)
+ {
+ n++;
+ }
+ else if (ret == OP_ERR)
+ {
+ bConErr = TRUE;
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+
+int __cdecl main (int argc, char **argv)
+{
+ DWORD dwThreadId;
+ DWORD dwWaitRet;
+
+ HANDLE hThread1; /* handle to consumer thread */
+ HANDLE hThread2; /* handle to producer thread */
+ HANDLE handleArray[2];
+
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ /* Initialize our error flags */
+ bProdErr = FALSE;
+ bConErr = FALSE;
+
+ /*
+ * Initialize the Buffer to be empty
+ */
+ memset(Buffer, 0, MAIN_BUF_SIZE);
+
+ /*
+ * Create Mutex
+ */
+ hMutex = CreateMutexA (NULL, FALSE, NULL);
+
+ if (NULL == hMutex)
+ {
+ Fail("hMutex = CreateMutexA() - returned NULL\n"
+ "Failing Test.\nGetLastError returned %u\n", GetLastError());
+ }
+
+
+ /*
+ * Create the Producer thread
+ */
+ hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Producer,
+ 0, 0, &dwThreadId);
+
+ if ( NULL == hThread1 )
+ {
+ CloseHandle(hMutex);
+
+ Fail("CreateThread() returned NULL. Failing test.\n"
+ "GetLastError returned %u\n", GetLastError());
+ }
+
+ /*
+ * Create the Consumer thread
+ */
+ hThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Consumer,
+ 0, 0, &dwThreadId);
+
+ if ( NULL == hThread2 )
+ {
+ CloseHandle(hMutex);
+
+ /* Set the error flag and give thread1 some time to exit */
+ bConErr = FALSE;
+ Sleep(250);
+
+ Fail("CreateThread() returned NULL. Failing test.\n"
+ "GetLastError returned %u\n", GetLastError());
+ }
+
+ /*
+ * Wait for both threads to complete (Max 45 Seconds)
+ */
+ handleArray[0] = hThread1;
+ handleArray[1] = hThread2;
+ dwWaitRet = WaitForMultipleObjects (2, handleArray, TRUE, 450000);
+ if (dwWaitRet == WAIT_FAILED)
+ {
+ Fail("ERROR: WaitForMultipleObjects failed.\n");
+ }
+ else if (dwWaitRet == WAIT_TIMEOUT)
+ {
+ /* Set the error flags and give the threads some time to exit */
+ bProdErr = FALSE;
+ bConErr = FALSE;
+ Sleep(250);
+
+ Fail("ERROR: Timeout interval exceeded.\n");
+ }
+
+ /*
+ * Clean up
+ */
+ if (CloseHandle(hThread1) == FALSE ||
+ CloseHandle(hThread2) == FALSE ||
+ CloseHandle(hMutex) == FALSE)
+ {
+ Fail("ERROR: CloseHandle failed.\n");
+ }
+
+
+ /*
+ * Check our error flags
+ */
+ if (bProdErr == TRUE || bConErr == TRUE)
+ {
+ Fail("ERROR: A collision occurred, so the mutex failed.\n");
+ }
+
+ PAL_Terminate();
+ return ( PASS );
+
+}
diff --git a/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test1/testinfo.dat b/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test1/testinfo.dat
new file mode 100644
index 0000000000..829b7159ac
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test1/testinfo.dat
@@ -0,0 +1,33 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = CreateMutexA / ReleaseMutex
+Name = Positive Test for CreateMutexA and ReleaseMutex
+TYPE = DEFAULT
+EXE1 = createmutexa
+Description
+= This test cases test whether a Mutex object created
+= with CreateMutexA really works by mutually excluding
+= threads from accessing a data structure at the same
+= time. Here we have a buffer that can be filled or
+= emptied, we use a Mutex object to ensure that one
+= operation cannot be started until the other is
+= finished. If one operation detects that the other
+= has not finished, it fails. There is a Producer
+= thread which will try to fill the buffer 25 times,
+= and a consumer thread which try to empty the buffer
+= 25 times. If either the fill or empty operations
+= fails because the Mutex failed to mutually exclude
+= then, the corresponding thread will set an error
+= flag and return. This will cause the test case to
+= fail.
+= To increase the probability of identifying problems,
+= the Fill opeartion has been slowed dowm with a call
+= to Sleep. This ensures that one operation will try
+= to access the shared buffer while the other is in
+= progress.
+= NOTE: this test case also serves as a test case for
+= WaitForSingleObject.
diff --git a/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test2/CMakeLists.txt
new file mode 100644
index 0000000000..925c5d41f6
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ CreateMutexA.c
+)
+
+add_executable(paltest_createmutexa_releasemutex_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createmutexa_releasemutex_test2 coreclrpal)
+
+target_link_libraries(paltest_createmutexa_releasemutex_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test2/CreateMutexA.c b/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test2/CreateMutexA.c
new file mode 100644
index 0000000000..3b83ba9674
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test2/CreateMutexA.c
@@ -0,0 +1,331 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: CreateMutexA_ReleaseMutex/test2/CreateMutexA.c
+**
+** Purpose: This test case tests the following things
+** - Creation of named Mutexes
+** - Creating multiple handles to a single named Mutex
+** - Ensuring that these handles work interchangeably
+** - Setting bInitialOwnerFlag to TRUE will cause the
+** initial call to a Wait function on the same Mutex
+** to actually wait.
+** - Waiting on a Mutex that a thread already owns does
+** not block.
+** - Create Named mutex with empty string ("")
+** - Create Named mutex with string of MAX_LONGPATH length
+** - Calling RelaseMutex with invalid Mutex handles and
+** valid but unowned Mutexes.
+**
+** Dependencies: CreateThread
+** ReleaseMutex
+** WaitForSingleObject
+** CloseHandle
+** Sleep
+** memset
+**
+
+**
+**=========================================================*/
+
+#define UNICODE
+#include <palsuite.h>
+
+const char *szMutex = "MyMutex";
+const char *szEmpty = "";
+
+/* Function Prototypes */
+BOOL TestNamedMutex(const char *szMutexName);
+DWORD NamedMutexThread(LPVOID lpParam);
+BOOL NegativeReleaseMutexTests();
+
+struct ThreadData
+{
+ HANDLE hMutex;
+ BOOL bReturnCode;
+};
+typedef struct ThreadData THREADDATA;
+
+
+int __cdecl main (int argc, char **argv)
+{
+ BOOL bFailures = FALSE;
+ char *szMaxPath;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+
+ /*
+ * Test named Mutexes with ordinary string
+ */
+
+ if (!TestNamedMutex(szMutex))
+ {
+ bFailures = TRUE;
+ }
+
+
+ /*
+ * Test named Mutexes with empty ("") string
+ */
+
+ if (!TestNamedMutex(szEmpty))
+ {
+ bFailures = TRUE;
+ }
+
+
+ /*
+ * Test named Mutexes with string of length MAX_LONGPATHPATH
+ */
+
+ szMaxPath = (char *)malloc(MAX_LONGPATH+2);
+ memset(szMaxPath, 'A', MAX_LONGPATH-60);
+ szMaxPath[MAX_LONGPATH-60] = 0;
+
+ if (!TestNamedMutex(szMaxPath))
+ {
+ bFailures = TRUE;
+ }
+
+ free(szMaxPath);
+
+
+ /*
+ * Run some negative tests on ReleaseMutex
+ */
+
+ if (!NegativeReleaseMutexTests())
+ {
+ bFailures = TRUE;
+ }
+
+
+ /*
+ * If there were any failures, then abort with a call to Fail
+ */
+
+ if (bFailures == TRUE)
+ {
+ Fail("ERROR: There some failures in the Mutex tests.\n");
+ }
+
+ PAL_Terminate();
+ return ( PASS );
+}
+
+
+/*
+ * Testing Function
+ *
+ * Try to get multiple handles to a named Mutex and test
+ * to make sure they actually refer to same Mutex object.
+ */
+BOOL TestNamedMutex(const char *szMutexName)
+{
+ DWORD dwData;
+ HANDLE hMutex1;
+ HANDLE hMutex2;
+ HANDLE hThread;
+ THREADDATA threadData;
+
+ /* Create a mutex and take ownership immediately */
+ hMutex1 = CreateMutexA (NULL, TRUE, szMutexName);
+
+ if (NULL == hMutex1)
+ {
+ Trace("ERROR: CreateMutexA #1 failed. GetLastError returned %u\n",
+ GetLastError());
+ return FALSE;
+ }
+
+ /* Try to wait on the Mutex we just created. We should not block. */
+ if (WaitForSingleObject(hMutex1, 1000) == WAIT_TIMEOUT)
+ {
+ Trace("WaitForSingleObject blocked on a Mutex that we owned.\n");
+ return FALSE;
+ }
+ /* We have to call ReleaseMutex here because of the Wait */
+ if (ReleaseMutex(hMutex1) == FALSE)
+ {
+ Trace("ReleaseMutex Failed.\n");
+ return FALSE;
+ }
+
+ /* Get a second handle to the same mutex */
+ hMutex2 = CreateMutexA (NULL, FALSE, szMutexName);
+
+ if (NULL == hMutex2)
+ {
+ Trace("ERROR: CreateMutex #2 failed. GetLastError returned %u\n",
+ GetLastError());
+ free(szMutexName);
+ return FALSE;
+ }
+
+ /*
+ * Create a thread that will Wait on the second handle.
+ */
+ threadData.hMutex = hMutex2;
+ hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)NamedMutexThread,
+ (LPVOID)&threadData, 0, &dwData);
+
+ if (NULL == hThread)
+ {
+ Trace("ERROR: CreateThread failed. GetLastError returned %u\n",
+ GetLastError());
+ return FALSE;
+ }
+
+ /* Give the thread a little time to execute & wait*/
+ Sleep(500);
+
+ /* Signal the the first handle */
+ if (ReleaseMutex(hMutex1) == FALSE)
+ {
+ Trace("ReleaseMutex Failed.\n");
+ return FALSE;
+ }
+
+ /* Give the thread some time to finish */
+ Sleep(2000);
+
+ /* Clean Up */
+ if (CloseHandle(hMutex1) == FALSE ||
+ CloseHandle(hMutex2) == FALSE ||
+ CloseHandle(hThread) == FALSE)
+ {
+ Trace("ERROR: CloseHandle failed.\n");
+ return FALSE;
+ }
+
+ /* Check the return code to see if signalling the first */
+ /* Mutex handle woke up the thread which was Waiting on */
+ /* the second handle. */
+ if (threadData.bReturnCode != FALSE)
+ {
+ Trace("ERROR: The handles did not refer to the same Mutex object.\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Thread function used with above testing function.
+ */
+DWORD NamedMutexThread(LPVOID lpParam)
+{
+ BOOL bTimedOut = FALSE;
+ THREADDATA *lpThreadData = (THREADDATA *)lpParam;
+
+ /* Wait on the Mutex that was passed to us */
+ if (WaitForSingleObject(lpThreadData->hMutex, 10000) == WAIT_TIMEOUT)
+ {
+ /* The Mutex was not signaled in the allotted time */
+ bTimedOut = TRUE;
+ }
+ if (ReleaseMutex(lpThreadData->hMutex) == FALSE)
+ {
+ Trace("ERROR: ReleaseMutex failed.\n");
+ lpThreadData->bReturnCode = FALSE;
+ return 0;
+ }
+
+ /* Indicate whether we timed out Waiting on the Mutex */
+ lpThreadData->bReturnCode = bTimedOut;
+
+ return 0;
+}
+
+
+/*
+ * Testing Function
+ *
+ * Try some negative tests on ReleaseMutex
+ */
+BOOL NegativeReleaseMutexTests()
+{
+ HANDLE hMutex;
+ BOOL bRet;
+ BOOL bResults = TRUE;
+
+
+ /*
+ * Try calling ReleaseMutex on a null handle
+ */
+ hMutex = 0;
+ bRet = ReleaseMutex(hMutex);
+
+ if (bRet != 0)
+ {
+ Trace("Error: ReleaseMutex accepted null handle.\n");
+ bResults = FALSE;
+ }
+
+
+ /*
+ * Try calling ReleaseMutex on an handle that we don't own
+ */
+ hMutex = CreateMutexA (NULL, TRUE, NULL);
+ if (hMutex == 0)
+ {
+ Trace("Error: CreateMutex failed.\n");
+ bResults = FALSE;
+ }
+
+ bRet = ReleaseMutex(hMutex);
+ bRet = ReleaseMutex(hMutex);
+
+ if (bRet != FALSE)
+ {
+ Trace("Error: ReleaseMutex accepted unowned handle.\n");
+ bResults = FALSE;
+ }
+
+ if (CloseHandle(hMutex) == FALSE)
+ {
+ Trace("Error: CloseHandle failed.\n");
+ bResults = FALSE;
+ }
+
+
+
+ /*
+ * Try calling ReleaseMutex on an handle that has been closed
+ */
+ hMutex = CreateMutexA (NULL, TRUE, NULL);
+ if (hMutex == 0)
+ {
+ Trace("Error: CreateMutex failed.\n");
+ bResults = FALSE;
+ }
+
+ if (ReleaseMutex(hMutex) == FALSE)
+ {
+ Trace("Error: ReleaseMutex failed.\n");
+ bResults = FALSE;
+ }
+ if (CloseHandle(hMutex) == FALSE)
+ {
+ Trace("Error: CloseHandle failed.\n");
+ bResults = FALSE;
+ }
+
+ bRet = ReleaseMutex(hMutex);
+
+ if (bRet != FALSE)
+ {
+ Trace("Error: ReleaseMutex accepted invalid handle.\n");
+ bResults = FALSE;
+ }
+
+ return bResults;
+}
diff --git a/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test2/testinfo.dat b/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test2/testinfo.dat
new file mode 100644
index 0000000000..7e37528c15
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test2/testinfo.dat
@@ -0,0 +1,24 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = CreateMutexA / ReleaseMutex
+Name = Basic validity Tests for CreateMutexA / ReleaseMutex
+TYPE = DEFAULT
+EXE1 = createmutexa
+Description
+= This test case tests the following things
+= - Creation of named Mutexes
+= - Creating multiple handles to a single named Mutex
+= - Ensuring that these handles work interchangeably
+= - Setting bInitialOwnerFlag to TRUE will cause the
+= initial call to a Wait function on the same Mutex
+= to actually wait.
+= - Waiting on a Mutex that a thread already owns should
+= not block.
+= - Create Named mutex with empty string ("")
+= - Create Named mutex with string of MAX_PATH length
+= - Calling RelaseMutex with invalid Mutex handles and
+= valid but unowned Mutexes.
diff --git a/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test1/CMakeLists.txt
new file mode 100644
index 0000000000..a73ee045a3
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ CreateMutexW.c
+)
+
+add_executable(paltest_createmutexw_releasemutex_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createmutexw_releasemutex_test1 coreclrpal)
+
+target_link_libraries(paltest_createmutexw_releasemutex_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test1/CreateMutexW.c b/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test1/CreateMutexW.c
new file mode 100644
index 0000000000..c21bfb6a50
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test1/CreateMutexW.c
@@ -0,0 +1,345 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: CreateMutexW_ReleaseMutex/test1/CreateMutexW.c
+**
+** Purpose: This test case tests whether a Mutex object created
+** with CreateMutex really works by mutually excluding
+** threads from accessing a data structure at the same
+** time. Here we have a buffer that can be filled or
+** emptied, we use a Mutex object to ensure that one
+** operation cannot be started until the other is
+** finished. If one operation detects that the other
+** has not finished, it fails. There is a Producer
+** thread which will try to fill the buffer 25 times,
+** and a consumer thread which try to empty the buffer
+** 25 times. If either the fill or empty operations
+** fails because the Mutex failed to mutually exclude
+** them, the corresponding thread will set an error
+** flag and return. This will cause the test case to
+** fail.
+**
+** To increase the probability of identifying problems,
+** the Fill opeartion has been slowed dowm with a call
+** to Sleep. This ensures that one operation will try
+** to access the shared buffer while the other is in
+** progress.
+**
+** NOTE: this test case also serves as a test case for
+** WaitForSingleObject.
+**
+**
+** Dependencies: CreateThread
+** ReleaseMutex
+** WaitForSingleObject
+** WaitForMultipleObjects
+** Sleep
+** memset
+**
+
+**
+**=========================================================*/
+
+#define UNICODE
+#include <palsuite.h>
+
+/* Define some values that we will using many times */
+#define MAIN_BUF_SIZE 40
+#define NUM_OF_CYCLES 40
+
+/* Buffer Operation return codes */
+#define OP_OK 0
+#define OP_ERR 1
+#define OP_NONE 2
+
+
+HANDLE hMutex; /* handle to mutex */
+
+BOOL bProdErr; /* Producer error Flag */
+BOOL bConErr; /* Consumer error Flag */
+
+/* Test Buffer */
+char Buffer[MAIN_BUF_SIZE];
+
+/*
+ * EmptyBuffer implements the empty operation for test buffer.
+ */
+int
+EmptyBuffer()
+{
+ int i;
+
+ if ( WaitForSingleObject(hMutex, INFINITE) == WAIT_FAILED)
+ {
+ Fail("ERROR: WaitForSingleObject failed.\n");
+ }
+
+ /* Check to see if the buffer is already completely empty */
+ for (i=0; i<MAIN_BUF_SIZE && Buffer[i] == 0; i++);
+ if (i == MAIN_BUF_SIZE)
+ {
+ /* Its empty so just return */
+ if (ReleaseMutex(hMutex) == FALSE)
+ {
+ Fail("ERROR: ReleaseMutex Failed.\n");
+ }
+ return OP_NONE;
+ }
+
+ /* Its not empty so we must empty it. */
+ for (i=0; i<MAIN_BUF_SIZE; i++)
+ {
+ /* Check for empty slots if we find one then the */
+ /* fill operation did no finish. return an error */
+ if (Buffer[i] == 0)
+ {
+ if (ReleaseMutex(hMutex) == FALSE)
+ {
+ Fail("ERROR: ReleaseMutex Failed.\n");
+ }
+ return OP_ERR;
+ }
+
+ Buffer[i] = 0;
+ }
+
+ if (ReleaseMutex(hMutex) == FALSE)
+ {
+ Fail("ERROR: ReleaseMutex Failed.\n");
+ }
+ return OP_OK;
+}
+
+/*
+ * FillBuffer implements the fill operation for test buffer.
+ */
+int
+FillBuffer()
+{
+ int i;
+
+ if ( WaitForSingleObject(hMutex, INFINITE) == WAIT_FAILED)
+ {
+ Fail("ERROR: WaitForSingleObject failed.\n");
+ }
+
+ /* Check to see if the buffer is already completely full */
+ for (i=0; i<MAIN_BUF_SIZE && Buffer[i] != 0; i++);
+ if (i == MAIN_BUF_SIZE)
+ {
+ /* Its full so just return */
+ if (ReleaseMutex(hMutex) == FALSE)
+ {
+ Fail("ERROR: ReleaseMutex Failed.\n");
+ }
+ return OP_NONE;
+ }
+
+ /* Its not full so we must fill it. */
+ for (i=0; i<MAIN_BUF_SIZE; i++)
+ {
+ /* Check for filled slots if we find one then the */
+ /* empty operation did not finish. return an error */
+ if (Buffer[i] == 1)
+ {
+ if (ReleaseMutex(hMutex) == FALSE)
+ {
+ Fail("ERROR: ReleaseMutex Failed.\n");
+ }
+ return OP_ERR;
+ }
+
+ Buffer[i] = 1;
+ Sleep(10);
+ }
+
+ if (ReleaseMutex(hMutex) == FALSE)
+ {
+ Fail("ERROR: ReleaseMutex Failed.\n");
+ }
+ return OP_OK;
+}
+
+
+
+
+/*
+ * Producer thread function.
+ */
+DWORD
+Producer(LPVOID lpParam)
+{
+ int n = 0;
+ int ret;
+
+ while (n < NUM_OF_CYCLES)
+ {
+ if (bConErr == TRUE)
+ {
+ /* The consumer ran into an error so we'll stop */
+ return 0;
+ }
+
+ ret = FillBuffer();
+
+ if (ret == OP_OK)
+ {
+ n++;
+ }
+ else if (ret == OP_ERR)
+ {
+ bProdErr = TRUE;
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Consumer thread function.
+ */
+DWORD Consumer( LPVOID lpParam )
+{
+ int n = 0;
+ int ret;
+
+ while (n < NUM_OF_CYCLES)
+ {
+ if (bProdErr == TRUE)
+ {
+ /* The consumer ran into an error so we'll stop */
+ return 0;
+ }
+
+ ret = EmptyBuffer();
+
+ if (ret == OP_OK)
+ {
+ n++;
+ }
+ else if (ret == OP_ERR)
+ {
+ bConErr = TRUE;
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+
+int __cdecl main (int argc, char **argv)
+{
+ DWORD dwThreadId;
+ DWORD dwWaitRet;
+
+ HANDLE hThread1; /* handle to consumer thread */
+ HANDLE hThread2; /* handle to producer thread */
+ HANDLE handleArray[2];
+
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ /* Initialize our error flags */
+ bProdErr = FALSE;
+ bConErr = FALSE;
+
+ /*
+ * Initialize the Buffer to be empty
+ */
+ memset(Buffer, 0, MAIN_BUF_SIZE);
+
+ /*
+ * Create Mutex
+ */
+ hMutex = CreateMutexW (NULL, FALSE, NULL);
+
+ if (NULL == hMutex)
+ {
+ Fail("hMutex = CreateMutexW() - returned NULL\n"
+ "Failing Test.\nGetLastError returned %u\n", GetLastError());
+ }
+
+
+ /*
+ * Create the Producer thread
+ */
+ hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Producer,
+ 0, 0, &dwThreadId);
+
+ if ( NULL == hThread1 )
+ {
+ CloseHandle(hMutex);
+
+ Fail("CreateThread() returned NULL. Failing test.\n"
+ "GetLastError returned %u\n", GetLastError());
+ }
+
+ /*
+ * Create the Consumer thread
+ */
+ hThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Consumer,
+ 0, 0, &dwThreadId);
+
+ if ( NULL == hThread2 )
+ {
+ CloseHandle(hMutex);
+
+ /* Set the error flag and give thread1 some time to exit */
+ bConErr = FALSE;
+ Sleep(250);
+
+ Fail("CreateThread() returned NULL. Failing test.\n"
+ "GetLastError returned %u\n", GetLastError());
+ }
+
+ /*
+ * Wait for both threads to complete (Max 45 Seconds)
+ */
+ handleArray[0] = hThread1;
+ handleArray[1] = hThread2;
+ dwWaitRet = WaitForMultipleObjects (2, handleArray, TRUE, 450000);
+ if (dwWaitRet == WAIT_FAILED)
+ {
+ Fail("ERROR: WaitForMultipleObjects failed.\n");
+ }
+ else if (dwWaitRet == WAIT_TIMEOUT)
+ {
+ /* Set the error flags and give the threads some time to exit */
+ bProdErr = FALSE;
+ bConErr = FALSE;
+ Sleep(250);
+
+ Fail("ERROR: Timeout interval exceeded.\n");
+ }
+
+ /*
+ * Clean up
+ */
+ if (CloseHandle(hThread1) == FALSE ||
+ CloseHandle(hThread2) == FALSE ||
+ CloseHandle(hMutex) == FALSE)
+ {
+ Fail("ERROR: CloseHandle failed.\n");
+ }
+
+
+ /*
+ * Check our error flags
+ */
+ if (bProdErr == TRUE || bConErr == TRUE)
+ {
+ Fail("ERROR: A collision occurred, so the mutex failed.\n");
+ }
+
+ PAL_Terminate();
+ return ( PASS );
+
+}
diff --git a/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test1/testinfo.dat b/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test1/testinfo.dat
new file mode 100644
index 0000000000..19ea934dff
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test1/testinfo.dat
@@ -0,0 +1,33 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = CreateMutexW / ReleaseMutex
+Name = Positive Test for CreateMutexW and ReleaseMutex
+TYPE = DEFAULT
+EXE1 = createmutexw
+Description
+= This test cases test whether a Mutex object created
+= with CreateMutexW really works by mutually excluding
+= threads from accessing a data structure at the same
+= time. Here we have a buffer that can be filled or
+= emptied, we use a Mutex object to ensure that one
+= operation cannot be started until the other is
+= finished. If one operation detects that the other
+= has not finished, it fails. There is a Producer
+= thread which will try to fill the buffer 25 times,
+= and a consumer thread which try to empty the buffer
+= 25 times. If either the fill or empty operations
+= fails because the Mutex failed to mutually exclude
+= then, the corresponding thread will set an error
+= flag and return. This will cause the test case to
+= fail.
+= To increase the probability of identifying problems,
+= the Fill opeartion has been slowed dowm with a call
+= to Sleep. This ensures that one operation will try
+= to access the shared buffer while the other is in
+= progress.
+= NOTE: this test case also serves as a test case for
+= WaitForSingleObject.
diff --git a/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test2/CMakeLists.txt
new file mode 100644
index 0000000000..b40569b3f5
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ CreateMutexW.c
+)
+
+add_executable(paltest_createmutexw_releasemutex_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createmutexw_releasemutex_test2 coreclrpal)
+
+target_link_libraries(paltest_createmutexw_releasemutex_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test2/CreateMutexW.c b/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test2/CreateMutexW.c
new file mode 100644
index 0000000000..41b7798a6e
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test2/CreateMutexW.c
@@ -0,0 +1,340 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: CreateMutexW_ReleaseMutex/test2/CreateMutexW.c
+**
+** Purpose: This test case tests the following things
+** - Creation of named Mutexes
+** - Creating multiple handles to a single named Mutex
+** - Ensuring that these handles work interchangeably
+** - Setting bInitialOwnerFlag to TRUE will cause the
+** initial call to a Wait function on the same Mutex
+** to actually wait.
+** - Waiting on a Mutex that a thread already owns does
+** not block.
+** - Create Named mutex with empty string ("")
+** - Create Named mutex with string of MAX_LONGPATH length
+** - Calling RelaseMutex with invalid Mutex handles and
+** valid but unowned Mutexes.
+**
+** Dependencies: CreateThread
+** ReleaseMutex
+** WaitForSingleObject
+** CloseHandle
+** Sleep
+** memset
+**
+
+**
+**=========================================================*/
+
+#define UNICODE
+#include <palsuite.h>
+
+const char *szMutex = "MyMutex";
+const char *szEmpty = "";
+
+/* Function Prototypes */
+BOOL TestNamedMutex(const char *szMutexName);
+DWORD NamedMutexThread(LPVOID lpParam);
+BOOL NegativeReleaseMutexTests();
+
+struct ThreadData
+{
+ HANDLE hMutex;
+ BOOL bReturnCode;
+};
+typedef struct ThreadData THREADDATA;
+
+
+int __cdecl main (int argc, char **argv)
+{
+ BOOL bFailures = FALSE;
+ char *szMaxPath;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+
+ /*
+ * Test named Mutexes with ordinary string
+ */
+
+ if (!TestNamedMutex(szMutex))
+ {
+ bFailures = TRUE;
+ }
+
+
+ /*
+ * Test named Mutexes with empty ("") string
+ */
+
+ if (!TestNamedMutex(szEmpty))
+ {
+ bFailures = TRUE;
+ }
+
+
+ /*
+ * Test named Mutexes with string of length MAX_LONGPATH
+ */
+
+ szMaxPath = (char *)malloc(MAX_LONGPATH+2);
+ memset(szMaxPath, 'A', MAX_LONGPATH-60);
+ szMaxPath[MAX_LONGPATH-60] = 0;
+
+ if (!TestNamedMutex(szMaxPath))
+ {
+ bFailures = TRUE;
+ }
+
+ free(szMaxPath);
+
+
+ /*
+ * Run some negative tests on ReleaseMutex
+ */
+
+ if (!NegativeReleaseMutexTests())
+ {
+ bFailures = TRUE;
+ }
+
+
+ /*
+ * If there were any failures, then abort with a call to Fail
+ */
+
+ if (bFailures == TRUE)
+ {
+ Fail("ERROR: There some failures in the Mutex tests.\n");
+ }
+
+ PAL_Terminate();
+ return ( PASS );
+}
+
+
+/*
+ * Testing Function
+ *
+ * Try to get multiple handles to a named Mutex and test
+ * to make sure they actually refer to same Mutex object.
+ */
+BOOL TestNamedMutex(const char *szMutexName)
+{
+ DWORD dwData;
+ HANDLE hMutex1;
+ HANDLE hMutex2;
+ HANDLE hThread;
+ WCHAR *swzMutexName;
+ THREADDATA threadData;
+
+ /* Convert the Mutex name to wide characters */
+ swzMutexName = convert((char *)szMutexName);
+
+ /* Create a mutex and take ownership immediately */
+ hMutex1 = CreateMutexW (NULL, TRUE, swzMutexName);
+
+ if (NULL == hMutex1)
+ {
+ Trace("ERROR: CreateMutex #1 failed. GetLastError returned %u\n",
+ GetLastError());
+ free(swzMutexName);
+ return FALSE;
+ }
+
+ /* Try to wait on the Mutex we just created. We should not block. */
+ if (WaitForSingleObject(hMutex1, 1000) == WAIT_TIMEOUT)
+ {
+ Trace("WaitForSingleObject blocked on a Mutex that we owned.\n");
+ free(swzMutexName);
+ return FALSE;
+ }
+ /* We have to call ReleaseMutex here because of the Wait */
+ if (ReleaseMutex(hMutex1) == FALSE)
+ {
+ Trace("ReleaseMutex Failed.\n");
+ return FALSE;
+ }
+
+ /* Get a second handle to the same mutex */
+ hMutex2 = CreateMutexW (NULL, FALSE, swzMutexName);
+
+ if (NULL == hMutex2)
+ {
+ Trace("ERROR: CreateMutex #2 failed. GetLastError returned %u\n",
+ GetLastError());
+ free(swzMutexName);
+ return FALSE;
+ }
+
+ /* Get rid of the wide character string */
+ free(swzMutexName);
+
+ /*
+ * Create a thread that will Wait on the second handle.
+ */
+ threadData.hMutex = hMutex2;
+ hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)NamedMutexThread,
+ (LPVOID)&threadData, 0, &dwData);
+
+ if (NULL == hThread)
+ {
+ Trace("ERROR: CreateThread failed. GetLastError returned %u\n",
+ GetLastError());
+ return FALSE;
+ }
+
+ /* Give the thread a little time to execute & wait*/
+ Sleep(500);
+
+ /* Signal the the first handle */
+ if (ReleaseMutex(hMutex1) == FALSE)
+ {
+ Trace("ReleaseMutex Failed.\n");
+ return FALSE;
+ }
+
+ /* Give the thread some time to finish */
+ Sleep(2000);
+
+ /* Clean Up */
+ if (CloseHandle(hMutex1) == FALSE ||
+ CloseHandle(hMutex2) == FALSE ||
+ CloseHandle(hThread) == FALSE)
+ {
+ Trace("ERROR: CloseHandle failed.\n");
+ return FALSE;
+ }
+
+ /* Check the return code to see if signalling the first */
+ /* Mutex handle woke up the thread which was Waiting on */
+ /* the second handle. */
+ if (threadData.bReturnCode != FALSE)
+ {
+ Trace("ERROR: The handles did not refer to the same Mutex object.\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Thread function used with above testing function.
+ */
+DWORD NamedMutexThread(LPVOID lpParam)
+{
+ BOOL bTimedOut = FALSE;
+ THREADDATA *lpThreadData = (THREADDATA *)lpParam;
+
+ /* Wait on the Mutex that was passed to us */
+ if (WaitForSingleObject(lpThreadData->hMutex, 10000) == WAIT_TIMEOUT)
+ {
+ /* The Mutex was not signaled in the allotted time */
+ bTimedOut = TRUE;
+ }
+ if (ReleaseMutex(lpThreadData->hMutex) == FALSE)
+ {
+ Trace("ERROR: ReleaseMutex failed.\n");
+ lpThreadData->bReturnCode = FALSE;
+ return 0;
+ }
+
+ /* Indicate whether we timed out Waiting on the Mutex */
+ lpThreadData->bReturnCode = bTimedOut;
+
+ return 0;
+}
+
+
+/*
+ * Testing Function
+ *
+ * Try some negative tests on ReleaseMutex
+ */
+BOOL NegativeReleaseMutexTests()
+{
+ HANDLE hMutex;
+ BOOL bRet;
+ BOOL bResults = TRUE;
+
+
+ /*
+ * Try calling ReleaseMutex on a null handle
+ */
+ hMutex = 0;
+ bRet = ReleaseMutex(hMutex);
+
+ if (bRet != 0)
+ {
+ Trace("Error: ReleaseMutex accepted null handle.\n");
+ bResults = FALSE;
+ }
+
+
+ /*
+ * Try calling ReleaseMutex on an handle that we don't own
+ */
+ hMutex = CreateMutexW (NULL, TRUE, NULL);
+ if (hMutex == 0)
+ {
+ Trace("Error: CreateMutex failed.\n");
+ bResults = FALSE;
+ }
+
+ bRet = ReleaseMutex(hMutex);
+ bRet = ReleaseMutex(hMutex);
+
+ if (bRet != FALSE)
+ {
+ Trace("Error: ReleaseMutex accepted unowned handle.\n");
+ bResults = FALSE;
+ }
+
+ if (CloseHandle(hMutex) == FALSE)
+ {
+ Trace("Error: CloseHandle failed.\n");
+ bResults = FALSE;
+ }
+
+
+
+ /*
+ * Try calling ReleaseMutex on an handle that has been closed
+ */
+ hMutex = CreateMutexW (NULL, TRUE, NULL);
+ if (hMutex == 0)
+ {
+ Trace("Error: CreateMutex failed.\n");
+ bResults = FALSE;
+ }
+
+ if (ReleaseMutex(hMutex) == FALSE)
+ {
+ Trace("Error: ReleaseMutex failed.\n");
+ bResults = FALSE;
+ }
+ if (CloseHandle(hMutex) == FALSE)
+ {
+ Trace("Error: CloseHandle failed.\n");
+ bResults = FALSE;
+ }
+
+ bRet = ReleaseMutex(hMutex);
+
+ if (bRet != FALSE)
+ {
+ Trace("Error: ReleaseMutex accepted invalid handle.\n");
+ bResults = FALSE;
+ }
+
+ return bResults;
+}
diff --git a/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test2/testinfo.dat b/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test2/testinfo.dat
new file mode 100644
index 0000000000..c5769e3ad3
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test2/testinfo.dat
@@ -0,0 +1,24 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = CreateMutexW / ReleaseMutex
+Name = Basic validity Tests for CreateMutexW / ReleaseMutex
+TYPE = DEFAULT
+EXE1 = createmutexw
+Description
+= This test case tests the following things
+= - Creation of named Mutexes
+= - Creating multiple handles to a single named Mutex
+= - Ensuring that these handles work interchangeably
+= - Setting bInitialOwnerFlag to TRUE will cause the
+= initial call to a Wait function on the same Mutex
+= to actually wait.
+= - Waiting on a Mutex that a thread already owns should
+= not block.
+= - Create Named mutex with empty string ("")
+= - Create Named mutex with string of MAX_PATH length
+= - Calling RelaseMutex with invalid Mutex handles and
+= valid but unowned Mutexes.
diff --git a/src/pal/tests/palsuite/threading/CreateProcessA/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateProcessA/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateProcessA/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/threading/CreateProcessA/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateProcessA/test1/CMakeLists.txt
new file mode 100644
index 0000000000..67e53edccd
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateProcessA/test1/CMakeLists.txt
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(TESTSOURCES
+ parentProcess.c
+)
+
+add_executable(paltest_createprocessa_test1
+ ${TESTSOURCES}
+)
+
+add_dependencies(paltest_createprocessa_test1 coreclrpal)
+
+target_link_libraries(paltest_createprocessa_test1
+ pthread
+ m
+ coreclrpal
+)
+
+
+set(HELPERSOURCES
+ childProcess.c
+)
+
+add_executable(paltest_createprocessa_test1_child
+ ${HELPERSOURCES}
+)
+
+add_dependencies(paltest_createprocessa_test1_child coreclrpal)
+
+target_link_libraries(paltest_createprocessa_test1_child
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/CreateProcessA/test1/childProcess.c b/src/pal/tests/palsuite/threading/CreateProcessA/test1/childProcess.c
new file mode 100644
index 0000000000..ccbb050c04
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateProcessA/test1/childProcess.c
@@ -0,0 +1,131 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: CreateProcessA/test1/childprocess.c
+**
+** Purpose: Test to ensure CreateProcessA starts a new process. This test
+** launches a child process, and examines a file written by the child.
+** This code is the child code.
+**
+** Dependencies: GetCurrentDirectory
+** strlen
+** fopen
+** fclose
+** fprintf
+**
+
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+const char *szCommonFileA = "childdata.tmp";
+
+const char *szPathDelimA = "\\";
+
+const char *szCommonStringA = "058d2d057111a313aa82401c2e856002\0";
+
+/*
+ * Take two wide strings representing file and directory names
+ * (dirName, fileName), join the strings with the appropriate path
+ * delimiter and populate a wide character buffer (absPathName) with
+ * the resulting string.
+ *
+ * Returns: The number of wide characters in the resulting string.
+ * 0 is returned on Error.
+ */
+int
+mkAbsoluteFilenameA (
+ LPSTR dirName,
+ DWORD dwDirLength,
+ LPCSTR fileName,
+ DWORD dwFileLength,
+ LPSTR absPathName )
+{
+ extern const char *szPathDelimA;
+
+ DWORD sizeDN, sizeFN, sizeAPN;
+
+ sizeDN = strlen( dirName );
+ sizeFN = strlen( fileName );
+ sizeAPN = (sizeDN + 1 + sizeFN + 1);
+
+ /* insure ((dirName + DELIM + fileName + \0) =< _MAX_PATH ) */
+ if ( sizeAPN > _MAX_PATH )
+ {
+ return ( 0 );
+ }
+
+ strncpy(absPathName, dirName, dwDirLength +1);
+ strncpy(absPathName, szPathDelimA, 2);
+ strncpy(absPathName, fileName, dwFileLength +1);
+
+ return (sizeAPN);
+
+}
+
+int __cdecl main( int argc, char **argv )
+{
+
+ static FILE * fp;
+
+ DWORD dwFileLength;
+ DWORD dwDirLength;
+ DWORD dwSize;
+
+ char szDirNameA[_MAX_DIR];
+ char szAbsPathNameA[_MAX_PATH];
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ dwDirLength = GetCurrentDirectory( _MAX_PATH, szDirNameA );
+
+ if (0 == dwDirLength)
+ {
+ Fail ("GetCurrentDirectory call failed. Could not get "
+ "current working directory\n. Exiting.\n");
+ }
+
+ dwFileLength = strlen( szCommonFileA );
+
+ dwSize = mkAbsoluteFilenameA( szDirNameA, dwDirLength, szCommonFileA,
+ dwFileLength, szAbsPathNameA );
+
+ if (0 == dwSize)
+ {
+ Fail ("Palsuite Code: mkAbsoluteFilename() call failed. Could "
+ "not build absolute path name to file\n. Exiting.\n");
+ }
+
+ if ( NULL == ( fp = fopen ( szAbsPathNameA , "w+" ) ) )
+ {
+ /*
+ * A return value of NULL indicates an error condition or an
+ * EOF condition
+ */
+ Fail ("%s unable to open %s for writing. Exiting.\n", argv[0]
+ , szAbsPathNameA );
+ }
+
+ if ( 0 >= ( fprintf ( fp, "%s", szCommonStringA )))
+ {
+ Fail("%s unable to write to %s. Exiting.\n", argv[0]
+ , szAbsPathNameA );
+ }
+
+ if (0 != (fclose ( fp )))
+ {
+ Fail ("%s unable to close file %s. Pid may not be "
+ "written to file. Exiting.\n", argv[0], szAbsPathNameA );
+ }
+
+ PAL_Terminate();
+ return ( PASS );
+
+}
diff --git a/src/pal/tests/palsuite/threading/CreateProcessA/test1/parentProcess.c b/src/pal/tests/palsuite/threading/CreateProcessA/test1/parentProcess.c
new file mode 100644
index 0000000000..b0c5808a7e
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateProcessA/test1/parentProcess.c
@@ -0,0 +1,201 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: CreateProcessA/test1/parentprocess.c
+**
+** Purpose: Test to ensure CreateProcessA starts a new process. This test
+** launches a child process, and examines a file written by the child.
+** This process (the parent process) reads the file created by the child and
+** compares the value the child wrote to the file. (a const char *)
+**
+** Dependencies: GetCurrentDirectory
+** strlen
+** WaitForSingleObject
+** fopen
+** fclose
+** Fail
+**
+
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+const char *szCommonFileA = "childdata.tmp";
+
+const char *szChildFileA = "paltest_createprocessa_test1_child";
+
+const char *szPathDelimA = "\\";
+
+const char *szCommonStringA = "058d2d057111a313aa82401c2e856002\0";
+
+/*
+ * Take two wide strings representing file and directory names
+ * (dirName, fileName), join the strings with the appropriate path
+ * delimiter and populate a wide character buffer (absPathName) with
+ * the resulting string.
+ *
+ * Returns: The number of wide characters in the resulting string.
+ * 0 is returned on Error.
+ */
+int
+mkAbsoluteFilenameA (
+ LPSTR dirName,
+ DWORD dwDirLength,
+ LPCSTR fileName,
+ DWORD dwFileLength,
+ LPSTR absPathName )
+{
+ extern const char *szPathDelimA;
+
+ DWORD sizeDN, sizeFN, sizeAPN;
+
+ sizeDN = strlen( dirName );
+ sizeFN = strlen( fileName );
+ sizeAPN = (sizeDN + 1 + sizeFN + 1);
+
+ /* insure ((dirName + DELIM + fileName + \0) =< _MAX_PATH ) */
+ if ( sizeAPN > _MAX_PATH )
+ {
+ return ( 0 );
+ }
+
+ strncpy(absPathName, dirName, dwDirLength +1);
+ strncpy(absPathName, szPathDelimA, 2);
+ strncpy(absPathName, fileName, dwFileLength +1);
+
+ return (sizeAPN);
+
+}
+
+int __cdecl main( int argc, char **argv )
+
+{
+
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+
+ static FILE * fp;
+
+ DWORD dwFileLength;
+ DWORD dwDirLength;
+ DWORD dwSize;
+
+ size_t cslen;
+
+ char szReadStringA[256];
+
+ char szDirNameA[_MAX_DIR];
+ char absPathBuf[_MAX_PATH];
+ char *szAbsPathNameA;
+
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ ZeroMemory ( &si, sizeof(si) );
+ si.cb = sizeof(si);
+ ZeroMemory ( &pi, sizeof(pi) );
+
+ szAbsPathNameA=&absPathBuf[0];
+ dwFileLength = strlen( szChildFileA );
+
+ dwDirLength = GetCurrentDirectory(_MAX_PATH, szDirNameA);
+
+ if (0 == dwDirLength)
+ {
+ Fail ("GetCurrentDirectory call failed. Could not get "
+ "current working directory\n. Exiting.\n");
+ }
+
+ dwSize = mkAbsoluteFilenameA( szDirNameA, dwDirLength, szChildFileA,
+ dwFileLength, szAbsPathNameA );
+
+ if (0 == dwSize)
+ {
+ Fail ("Palsuite Code: mkAbsoluteFilename() call failed. Could "
+ "not build absolute path name to file\n. Exiting.\n");
+ }
+
+ if ( !CreateProcessA ( NULL,
+ szAbsPathNameA,
+ NULL,
+ NULL,
+ FALSE,
+ CREATE_NEW_CONSOLE,
+ NULL,
+ NULL,
+ &si,
+ &pi )
+ )
+ {
+ Fail ( "CreateProcess call failed. GetLastError returned %d\n",
+ GetLastError() );
+ }
+
+ WaitForSingleObject ( pi.hProcess, INFINITE );
+
+ szAbsPathNameA=&absPathBuf[0];
+
+ dwFileLength = strlen( szCommonFileA );
+
+ dwSize = mkAbsoluteFilenameA( szDirNameA, dwDirLength, szCommonFileA,
+ dwFileLength, szAbsPathNameA );
+
+ /* set the string length for the open call*/
+
+ if (0 == dwSize)
+ {
+ Fail ("Palsuite Code: mkAbsoluteFilename() call failed. Could "
+ "not build absolute path name to file\n. Exiting.\n");
+ }
+
+ if ( NULL == ( fp = fopen ( szAbsPathNameA , "r" ) ) )
+ {
+ Fail ("%s\nunable to open %s\nfor reading. Exiting.\n", argv[0],
+ szAbsPathNameA );
+ }
+
+ cslen = strlen ( szCommonStringA );
+
+ if ( NULL == fgets( szReadStringA, (cslen + 1), fp ))
+ {
+ /*
+ * A return value of NULL indicates an error condition or an
+ * EOF condition
+ */
+ Fail ("%s\nunable to read file\n%s\nszReadStringA is %s\n"
+ "Exiting.\n", argv[0], szAbsPathNameA,
+ szReadStringA );
+
+ }
+ if ( 0 != strncmp( szReadStringA, szCommonStringA, cslen ))
+ {
+ Fail ("string comparison failed.\n szReadStringA is %s and\n"
+ "szCommonStringA is %s\n", szReadStringA,
+ szCommonStringA );
+ }
+ else
+ {
+ Trace ("string comparison passed.\n");
+ }
+
+ if (0 != (fclose ( fp )))
+ {
+ Trace ("%s unable to close file %s. This may cause a file pointer "
+ "leak. Continuing.\n", argv[0], szAbsPathNameA );
+ }
+
+ /* Close process and thread handle */
+ CloseHandle ( pi.hProcess );
+ CloseHandle ( pi.hThread );
+
+ PAL_Terminate();
+ return ( PASS );
+
+}
diff --git a/src/pal/tests/palsuite/threading/CreateProcessA/test1/testinfo.dat b/src/pal/tests/palsuite/threading/CreateProcessA/test1/testinfo.dat
new file mode 100644
index 0000000000..02c25444fe
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateProcessA/test1/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = CreateProcessA
+Name = Positive Test for CreateProcessA
+TYPE = DEFAULT
+EXE1 = parentprocess
+EXE2 = childprocess
+Description
+= Test the CreateProcessA function. The test executes the childprocess
+= program. The childprocess program launches and writes a const char string
+= to a file childdata. The parent waits for the completion of childprocess
+= and then reads the string from the childdata file. If the string in the
+= file matches it's copy of the const char string, then the test succeeds.
diff --git a/src/pal/tests/palsuite/threading/CreateProcessA/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateProcessA/test2/CMakeLists.txt
new file mode 100644
index 0000000000..b81ea2e978
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateProcessA/test2/CMakeLists.txt
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(TESTSOURCES
+ parentprocess.c
+)
+
+add_executable(paltest_createprocessa_test2
+ ${TESTSOURCES}
+)
+
+add_dependencies(paltest_createprocessa_test2 coreclrpal)
+
+target_link_libraries(paltest_createprocessa_test2
+ pthread
+ m
+ coreclrpal
+)
+
+
+set(HELPERSOURCES
+ childprocess.c
+)
+
+add_executable(paltest_createprocessa_test2_child
+ ${HELPERSOURCES}
+)
+
+add_dependencies(paltest_createprocessa_test2_child coreclrpal)
+
+target_link_libraries(paltest_createprocessa_test2_child
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/CreateProcessA/test2/childprocess.c b/src/pal/tests/palsuite/threading/CreateProcessA/test2/childprocess.c
new file mode 100644
index 0000000000..baa20c2d3c
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateProcessA/test2/childprocess.c
@@ -0,0 +1,69 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: createprocessa/test2/childprocess.c
+**
+** Purpose: This child process reads a string from stdin
+** and writes it out to stdout & stderr
+**
+** Dependencies: memset
+** fgets
+** gputs
+**
+
+**
+**=========================================================*/
+
+#include <palsuite.h>
+#include "test2.h"
+
+
+
+int __cdecl main( int argc, char **argv )
+{
+ int iRetCode = EXIT_OK_CODE; /* preset exit code to OK */
+ char szBuf[BUF_LEN];
+
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ if (argc != 4)
+ {
+ return EXIT_ERR_CODE3;
+ }
+
+ if (strcmp(argv[1], szArg1) != 0
+ || strcmp(argv[2], szArg2) != 0
+ || strcmp(argv[3], szArg3) != 0)
+ {
+ return EXIT_ERR_CODE4;
+ }
+
+
+ memset(szBuf, 0, BUF_LEN);
+
+ /* Read the string that was written by the parent */
+ if (fgets(szBuf, BUF_LEN, stdin) == NULL)
+ {
+ return EXIT_ERR_CODE1;
+ }
+
+ /* Write the string out to the stdout & stderr pipes */
+ if (fputs(szBuf, stdout) == EOF
+ || fputs(szBuf, stderr) == EOF)
+ {
+ return EXIT_ERR_CODE2;
+ }
+
+ /* The exit code will indicate success or failure */
+ PAL_TerminateEx(iRetCode);
+
+ /* Return special exit code to indicate success or failure */
+ return iRetCode;
+}
diff --git a/src/pal/tests/palsuite/threading/CreateProcessA/test2/parentprocess.c b/src/pal/tests/palsuite/threading/CreateProcessA/test2/parentprocess.c
new file mode 100644
index 0000000000..ef3340c5d9
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateProcessA/test2/parentprocess.c
@@ -0,0 +1,243 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: createprocessa/test2/parentprocess.c
+**
+** Purpose: Test the following features of CreateProcessA:
+** - Check to see if hProcess & hThread are set in
+** return PROCESS_INFORMATION structure
+** - Check to see if stdin, stdout, & stderr handles
+** are used when STARTF_USESTDHANDLES is specified
+** in STARUPINFO flags and bInheritHandles = TRUE
+** - Check to see that proper arguments are passed to
+** child process
+**
+** Dependencies: CreatePipe
+** strcpy, strlen, strncmp, memset
+** WaitForSingleObject
+** WriteFile, ReadFile
+** GetExitCodeProcess
+**
+
+**
+**=========================================================*/
+
+#include <palsuite.h>
+#include "test2.h"
+
+
+
+int __cdecl main( int argc, char **argv )
+{
+
+ /*******************************************
+ * Declarations
+ *******************************************/
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+
+ HANDLE hTestStdInR = NULL;
+ HANDLE hTestStdInW = NULL;
+ HANDLE hTestStdOutR = NULL;
+ HANDLE hTestStdOutW = NULL;
+ HANDLE hTestStdErrR = NULL;
+ HANDLE hTestStdErrW = NULL;
+
+ BOOL bRetVal = FALSE;
+ DWORD dwBytesWritten = 0;
+ DWORD dwBytesRead = 0;
+ DWORD dwExitCode = 0;
+
+ SECURITY_ATTRIBUTES pipeAttributes;
+
+ char szStdOutBuf[BUF_LEN];
+ char szStdErrBuf[BUF_LEN];
+ char szFullPathNameA[_MAX_PATH];
+
+
+ /*******************************************
+ * Initialization
+ *******************************************/
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ /*Setup SECURITY_ATTRIBUTES structure for CreatePipe*/
+ pipeAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
+ pipeAttributes.lpSecurityDescriptor = NULL;
+ pipeAttributes.bInheritHandle = TRUE;
+
+
+ /*Create a StdIn pipe for child*/
+ bRetVal = CreatePipe(&hTestStdInR, /* read handle*/
+ &hTestStdInW, /* write handle */
+ &pipeAttributes, /* security attributes*/
+ 1024); /* pipe size*/
+
+ if (bRetVal == FALSE)
+ {
+ Fail("ERROR: %ld :Unable to create stdin pipe\n", GetLastError());
+ }
+
+
+ /*Create a StdOut pipe for child*/
+ bRetVal = CreatePipe(&hTestStdOutR, /* read handle*/
+ &hTestStdOutW, /* write handle */
+ &pipeAttributes, /* security attributes*/
+ 0); /* pipe size*/
+
+ if (bRetVal == FALSE)
+ {
+ Fail("ERROR: %ld :Unable to create stdout pipe\n", GetLastError());
+ }
+
+
+ /*Create a StdErr pipe for child*/
+ bRetVal = CreatePipe(&hTestStdErrR, /* read handle*/
+ &hTestStdErrW, /* write handle */
+ &pipeAttributes, /* security attributes*/
+ 0); /* pipe size*/
+
+ if (bRetVal == FALSE)
+ {
+ Fail("ERROR: %ld :Unable to create stderr pipe\n", GetLastError());
+ }
+
+ /* Zero the data structure space */
+ ZeroMemory ( &pi, sizeof(pi) );
+ ZeroMemory ( &si, sizeof(si) );
+
+ /* Set the process flags and standard io handles */
+ si.cb = sizeof(si);
+ si.dwFlags = STARTF_USESTDHANDLES;
+ si.hStdInput = hTestStdInR;
+ si.hStdOutput = hTestStdOutW;
+ si.hStdError = hTestStdErrW;
+
+ strcpy(szFullPathNameA, szChildFileA);
+ strcat(szFullPathNameA, szArgs);
+
+ /*******************************************
+ * Start Testing
+ *******************************************/
+
+ /* Launch the child */
+ if ( !CreateProcessA (NULL, szFullPathNameA, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi ))
+ {
+ Fail("ERROR: CreateProcess call failed. GetLastError returned %d\n",
+ GetLastError() );
+ }
+
+ /* Check the returned process information for validity */
+ if (pi.hProcess == 0 || pi.hThread == 0)
+ {
+ Fail("ERROR: CreateProcess Error: Process Handle = %u, Thread Handle = %u\n",
+ pi.hProcess, pi.hThread);
+ }
+
+ /* Write the Constructed string to stdin pipe for the child process */
+ if (WriteFile(hTestStdInW, szTestString, strlen(szTestString), &dwBytesWritten, NULL) == FALSE
+ || WriteFile(hTestStdInW, "\n", strlen("\n"), &dwBytesWritten, NULL) == FALSE)
+ {
+ Fail("ERROR: %ld :unable to write to write pipe handle "
+ "hTestStdInW=0x%lx\n", GetLastError(), hTestStdInW);
+ }
+
+ /* Wait for the child to finish, Max 20 seconds */
+ dwExitCode = WaitForSingleObject(pi.hProcess, 20000);
+
+ /* If the child failed then whole thing fails */
+ if (dwExitCode != WAIT_OBJECT_0)
+ {
+ TerminateProcess(pi.hProcess, 0);
+ Fail("ERROR: The child failed to run properly.\n");
+ }
+
+ /* Check for problems in the child process */
+ if (GetExitCodeProcess(pi.hProcess, &dwExitCode) == FALSE)
+ {
+ Fail("ERROR: Call to GetExitCodeProcess failed.\n");
+ }
+ else if (dwExitCode == EXIT_ERR_CODE1)
+ {
+ Fail("ERROR: The Child process could not reead the string "
+ "written to the stdin pipe.\n");
+ }
+ else if (dwExitCode == EXIT_ERR_CODE2)
+ {
+ Fail("ERROR: The Child process could not write the string "
+ "the stdout pipe or stderr pipe.\n");
+ }
+ else if (dwExitCode == EXIT_ERR_CODE3)
+ {
+ Fail("ERROR: The Child received the wrong number of "
+ "command line arguments.\n");
+ }
+ else if (dwExitCode == EXIT_ERR_CODE4)
+ {
+ Fail("ERROR: The Child received the wrong "
+ "command line arguments.\n");
+ }
+ else if (dwExitCode != EXIT_OK_CODE)
+ {
+ Fail("ERROR: Unexpected exit code returned: %u. Child process "
+ "did not complete its part of the test.\n", dwExitCode);
+ }
+
+
+ /* The child ran ok, so check to see if we received the proper */
+ /* strings through the pipes. */
+
+ /* clear our buffers */
+ memset(szStdOutBuf, 0, BUF_LEN);
+ memset(szStdErrBuf, 0, BUF_LEN);
+
+ /* Read the data back from the child process stdout */
+ bRetVal = ReadFile(hTestStdOutR, /* handle to read pipe*/
+ szStdOutBuf, /* buffer to write to*/
+ BUF_LEN, /* number of bytes to read*/
+ &dwBytesRead, /* number of bytes read*/
+ NULL); /* overlapped buffer*/
+
+ /*Read the data back from the child process stderr */
+ bRetVal = ReadFile(hTestStdErrR, /* handle to read pipe*/
+ szStdErrBuf, /* buffer to write to*/
+ BUF_LEN, /* number of bytes to read*/
+ &dwBytesRead, /* number of bytes read*/
+ NULL); /* overlapped buffer*/
+
+
+ /* Confirm that we recieved the same string that we originally */
+ /* wrote to the child and was received on both stdout & stderr.*/
+ if (strncmp(szTestString, szStdOutBuf, strlen(szTestString)) != 0
+ || strncmp(szTestString, szStdErrBuf, strlen(szTestString)) != 0)
+ {
+ Fail("ERROR: The data read back from child does not match "
+ "what was written. STDOUT: %s STDERR: %s\n",
+ szStdOutBuf, szStdErrBuf);
+ }
+
+
+ /*******************************************
+ * Clean Up
+ *******************************************/
+
+ /* Close process and thread handle */
+ CloseHandle ( pi.hProcess );
+ CloseHandle ( pi.hThread );
+
+ CloseHandle(hTestStdInR);
+ CloseHandle(hTestStdInW);
+ CloseHandle(hTestStdOutR);
+ CloseHandle(hTestStdOutW);
+ CloseHandle(hTestStdErrR);
+ CloseHandle(hTestStdErrW);
+
+ PAL_Terminate();
+ return ( PASS );
+}
diff --git a/src/pal/tests/palsuite/threading/CreateProcessA/test2/test2.h b/src/pal/tests/palsuite/threading/CreateProcessA/test2/test2.h
new file mode 100644
index 0000000000..8cdff3b939
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateProcessA/test2/test2.h
@@ -0,0 +1,72 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test2.h
+**
+
+**
+**===========================================================*/
+
+
+const char *szChildFileA = "paltest_createprocessa_test2_child";
+const char *szArgs = " A B C";
+const char *szArg1 = "A";
+const char *szArg2 = "B";
+const char *szArg3 = "C";
+
+const char *szPathDelimA = "\\";
+
+const char *szTestString = "Copyright (c) Microsoft";
+
+const DWORD EXIT_OK_CODE = 100;
+const DWORD EXIT_ERR_CODE1 = 101;
+const DWORD EXIT_ERR_CODE2 = 102;
+const DWORD EXIT_ERR_CODE3 = 103;
+const DWORD EXIT_ERR_CODE4 = 104;
+const DWORD EXIT_ERR_CODE5 = 105;
+
+#define BUF_LEN 64
+
+/*
+ * Take two wide strings representing file and directory names
+ * (dirName, fileName), join the strings with the appropriate path
+ * delimiter and populate a wide character buffer (absPathName) with
+ * the resulting string.
+ *
+ * Returns: The number of wide characters in the resulting string.
+ * 0 is returned on Error.
+ */
+int
+mkAbsoluteFilenameA (
+ LPSTR dirName,
+ DWORD dwDirLength,
+ LPCSTR fileName,
+ DWORD dwFileLength,
+ LPSTR absPathName )
+{
+ extern const char *szPathDelimA;
+
+ DWORD sizeDN;
+ DWORD sizeFN;
+ DWORD sizeAPN;
+
+ sizeDN = strlen( dirName );
+ sizeFN = strlen( fileName );
+ sizeAPN = (sizeDN + 1 + sizeFN + 1);
+
+ /* insure ((dirName + DELIM + fileName + \0) =< _MAX_PATH ) */
+ if ( sizeAPN > _MAX_PATH )
+ {
+ return ( 0 );
+ }
+
+ strncpy(absPathName, dirName, dwDirLength +1);
+ strcat(absPathName, szPathDelimA);
+ strcat(absPathName, fileName);
+
+ return (sizeAPN);
+
+}
diff --git a/src/pal/tests/palsuite/threading/CreateProcessA/test2/testinfo.dat b/src/pal/tests/palsuite/threading/CreateProcessA/test2/testinfo.dat
new file mode 100644
index 0000000000..23fcdf93ae
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateProcessA/test2/testinfo.dat
@@ -0,0 +1,20 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = CreateProcessA
+Name = PROCESS_INFORMATION and HANDLE Inheritance
+TYPE = DEFAULT
+EXE1 = parentprocess
+EXE2 = childprocess
+Description
+= Test the following features of CreateProcessA:
+= - Check to see if hProcess & hThread are set in
+= return PROCESS_INFORMATION structure
+= - Check to see if stdin, stdout, & stderr handles
+= are used when STARTF_USESTDHANDLES is specified
+= in STARUPINFO flags and bInheritHandles = TRUE
+= - Check to see that proper arguments are passed to
+= child process
diff --git a/src/pal/tests/palsuite/threading/CreateProcessW/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateProcessW/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateProcessW/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/threading/CreateProcessW/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateProcessW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..394b124526
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateProcessW/test1/CMakeLists.txt
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(TESTSOURCES
+ parentProcess.c
+)
+
+add_executable(paltest_createprocessw_test1
+ ${TESTSOURCES}
+)
+
+add_dependencies(paltest_createprocessw_test1 coreclrpal)
+
+target_link_libraries(paltest_createprocessw_test1
+ pthread
+ m
+ coreclrpal
+)
+
+
+set(HELPERSOURCES
+ childProcess.c
+)
+
+add_executable(paltest_createprocessw_test1_child
+ ${HELPERSOURCES}
+)
+
+add_dependencies(paltest_createprocessw_test1_child coreclrpal)
+
+target_link_libraries(paltest_createprocessw_test1_child
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/CreateProcessW/test1/childProcess.c b/src/pal/tests/palsuite/threading/CreateProcessW/test1/childProcess.c
new file mode 100644
index 0000000000..c71f967b65
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateProcessW/test1/childProcess.c
@@ -0,0 +1,150 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: CreateProcessW/test1/childprocess.c
+**
+** Purpose: Test to ensure CreateProcessW starts a new process. This test
+** launches a child process, and examines a file written by the child.
+** This code is the child code.
+**
+** Dependencies: GetCurrentDirectory
+** MultiByteToWideChar
+** wcslen
+** strlen
+** WideCharToMultiByte
+** fopen
+** fclose
+** fprintf
+**
+
+**
+**=========================================================*/
+
+#define UNICODE
+#include <palsuite.h>
+
+const WCHAR szCommonFileW[] =
+ {'c','h','i','l','d','d','a','t','a','.','t','m','p','\0'};
+
+const WCHAR szPathDelimW[] = {'\\','\0'};
+
+const char *szCommonStringA = "058d2d057111a313aa82401c2e856002\0";
+
+/*
+ * Take two wide strings representing file and directory names
+ * (dirName, fileName), join the strings with the appropriate path
+ * delimiter and populate a wide character buffer (absPathName) with
+ * the resulting string.
+ *
+ * Returns: The number of wide characters in the resulting string.
+ * 0 is returned on Error.
+ */
+int
+mkAbsoluteFilenameW (
+ LPWSTR dirName,
+ DWORD dwDirLength,
+ LPCWSTR fileName,
+ DWORD dwFileLength,
+ LPWSTR absPathName )
+{
+ extern const WCHAR szPathDelimW[];
+
+ DWORD sizeDN, sizeFN, sizeAPN;
+
+ sizeDN = wcslen( dirName );
+ sizeFN = wcslen( fileName );
+ sizeAPN = (sizeDN + 1 + sizeFN + 1);
+
+ /* insure ((dirName + DELIM + fileName + \0) =< _MAX_PATH ) */
+ if ( sizeAPN > _MAX_PATH )
+ {
+ return ( 0 );
+ }
+
+ wcsncpy(absPathName, dirName, dwDirLength +1);
+ wcsncpy(absPathName, szPathDelimW, 2);
+ wcsncpy(absPathName, fileName, dwFileLength +1);
+
+ return (sizeAPN);
+
+}
+
+int __cdecl main( int argc, char **argv )
+{
+
+ static FILE * fp;
+
+ DWORD dwFileLength;
+ DWORD dwDirLength;
+ DWORD dwSize;
+
+ char *szAbsPathNameA;
+ WCHAR szDirNameW[_MAX_DIR];
+ WCHAR szAbsPathNameW[_MAX_PATH];
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ dwDirLength = GetCurrentDirectory( _MAX_PATH, szDirNameW );
+
+ if (0 == dwDirLength)
+ {
+ Fail ("GetCurrentDirectory call failed. Could not get "
+ "current working directory\n. Exiting.\n");
+ }
+
+ dwFileLength = wcslen( szCommonFileW );
+
+ dwSize = mkAbsoluteFilenameW( szDirNameW, dwDirLength, szCommonFileW,
+ dwFileLength, szAbsPathNameW );
+
+ if (0 == dwSize)
+ {
+ Fail ("Palsuite Code: mkAbsoluteFilename() call failed. Could "
+ "not build absolute path name to file\n. Exiting.\n");
+ }
+
+ /* set the string length for the open call */
+ szAbsPathNameA = malloc (dwSize +1);
+
+ if (NULL == szAbsPathNameA)
+ {
+ Fail ("Unable to malloc (%d) bytes. Exiting\n", (dwSize +1) );
+ }
+
+ WideCharToMultiByte (CP_ACP, 0, szAbsPathNameW, -1, szAbsPathNameA,
+ (dwSize + 1), NULL, NULL);
+
+ if ( NULL == ( fp = fopen ( szAbsPathNameA , "w+" ) ) )
+ {
+ /*
+ * A return value of NULL indicates an error condition or an
+ * EOF condition
+ */
+ Fail ("%s unable to open %s for writing. Exiting.\n", argv[0]
+ , szAbsPathNameA );
+ }
+
+ free (szAbsPathNameA);
+
+ if ( 0 >= ( fprintf ( fp, "%s", szCommonStringA )))
+ {
+ Fail("%s unable to write to %s. Exiting.\n", argv[0]
+ , szAbsPathNameA );
+ }
+
+ if (0 != (fclose ( fp )))
+ {
+ Fail ("%s unable to close file %s. Pid may not be "
+ "written to file. Exiting.\n", argv[0], szAbsPathNameA );
+ }
+
+ PAL_Terminate();
+ return ( PASS );
+
+}
diff --git a/src/pal/tests/palsuite/threading/CreateProcessW/test1/parentProcess.c b/src/pal/tests/palsuite/threading/CreateProcessW/test1/parentProcess.c
new file mode 100644
index 0000000000..db1fb6356d
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateProcessW/test1/parentProcess.c
@@ -0,0 +1,210 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: CreateProcessW/test1/parentprocess.c
+**
+** Purpose: Test to ensure CreateProcessW starts a new process. This test
+** launches a child process, and examines a file written by the child.
+** This process (the parent process) reads the file created by the child and
+** compares the value the child wrote to the file. (a const char *)
+**
+** Dependencies: GetCurrentDirectory
+** MultiByteToWideChar
+** wcslen
+** strlen
+** WideCharToMultiByte
+** WaitForSingleObject
+** fopen
+** fclose
+** Fail
+**
+
+**
+**=========================================================*/
+
+#define UNICODE
+#include <palsuite.h>
+
+const WCHAR szCommonFileW[] =
+ {'c','h','i','l','d','d','a','t','a','.','t','m','p','\0'};
+
+const WCHAR szChildFileW[] = u"paltest_createprocessw_test1_child";
+
+const WCHAR szPathDelimW[] = {'\\','\0'};
+
+const char *szCommonStringA = "058d2d057111a313aa82401c2e856002\0";
+
+/*
+ * Take two wide strings representing file and directory names
+ * (dirName, fileName), join the strings with the appropriate path
+ * delimiter and populate a wide character buffer (absPathName) with
+ * the resulting string.
+ *
+ * Returns: The number of wide characters in the resulting string.
+ * 0 is returned on Error.
+ */
+int
+mkAbsoluteFilenameW (
+ LPWSTR dirName,
+ DWORD dwDirLength,
+ LPCWSTR fileName,
+ DWORD dwFileLength,
+ LPWSTR absPathName )
+{
+ extern const WCHAR szPathDelimW[];
+
+ DWORD sizeDN, sizeFN, sizeAPN;
+
+ sizeDN = wcslen( dirName );
+ sizeFN = wcslen( fileName );
+ sizeAPN = (sizeDN + 1 + sizeFN + 1);
+
+ /* insure ((dirName + DELIM + fileName + \0) =< _MAX_PATH ) */
+ if ( sizeAPN > _MAX_PATH )
+ {
+ return ( 0 );
+ }
+
+ wcsncpy(absPathName, dirName, dwDirLength +1);
+ wcsncpy(absPathName, szPathDelimW, 2);
+ wcsncpy(absPathName, fileName, dwFileLength +1);
+
+ return (sizeAPN);
+
+}
+
+int __cdecl main( int argc, char **argv )
+
+{
+
+ STARTUPINFOW si;
+ PROCESS_INFORMATION pi;
+
+ static FILE * fp;
+
+ DWORD dwFileLength;
+ DWORD dwDirLength;
+ DWORD dwSize;
+
+ size_t cslen;
+
+ char szReadStringA[256];
+
+ char szAbsPathNameA[_MAX_PATH];
+ WCHAR szDirNameW[_MAX_DIR];
+ WCHAR absPathBuf[_MAX_PATH];
+ WCHAR *szAbsPathNameW;
+
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ ZeroMemory ( &si, sizeof(si) );
+ si.cb = sizeof(si);
+ ZeroMemory ( &pi, sizeof(pi) );
+
+ szAbsPathNameW=&absPathBuf[0];
+ dwFileLength = wcslen( szChildFileW );
+
+ dwDirLength = GetCurrentDirectory(_MAX_PATH, szDirNameW);
+
+ if (0 == dwDirLength)
+ {
+ Fail ("GetCurrentDirectory call failed. Could not get "
+ "current working directory\n. Exiting.\n");
+ }
+
+ dwSize = mkAbsoluteFilenameW( szDirNameW, dwDirLength, szChildFileW,
+ dwFileLength, szAbsPathNameW );
+
+ if (0 == dwSize)
+ {
+ Fail ("Palsuite Code: mkAbsoluteFilename() call failed. Could "
+ "not build absolute path name to file\n. Exiting.\n");
+ }
+
+ if ( !CreateProcessW ( NULL,
+ szAbsPathNameW,
+ NULL,
+ NULL,
+ FALSE,
+ CREATE_NEW_CONSOLE,
+ NULL,
+ NULL,
+ &si,
+ &pi )
+ )
+ {
+ Fail ( "CreateProcess call failed. GetLastError returned %d\n",
+ GetLastError() );
+ }
+
+ WaitForSingleObject ( pi.hProcess, INFINITE );
+
+ szAbsPathNameW=&absPathBuf[0];
+
+ dwFileLength = wcslen( szCommonFileW );
+
+ dwSize = mkAbsoluteFilenameW( szDirNameW, dwDirLength, szCommonFileW,
+ dwFileLength, szAbsPathNameW );
+
+ /* set the string length for the open call*/
+
+ if (0 == dwSize)
+ {
+ Fail ("Palsuite Code: mkAbsoluteFilename() call failed. Could "
+ "not build absolute path name to file\n. Exiting.\n");
+ }
+
+ WideCharToMultiByte (CP_ACP, 0, szAbsPathNameW, -1, szAbsPathNameA,
+ (dwSize + 1), NULL, NULL);
+
+ if ( NULL == ( fp = fopen ( szAbsPathNameA , "r" ) ) )
+ {
+ Fail ("%s\nunable to open %s\nfor reading. Exiting.\n", argv[0],
+ szAbsPathNameA );
+ }
+
+ cslen = strlen ( szCommonStringA );
+
+ if ( NULL == fgets( szReadStringA, (cslen + 1), fp ))
+ {
+ /*
+ * A return value of NULL indicates an error condition or an
+ * EOF condition
+ */
+ Fail ("%s\nunable to read file\n%s\nszReadStringA is %s\n"
+ "Exiting.\n", argv[0], szAbsPathNameA,
+ szReadStringA );
+ }
+
+ if ( 0 != strncmp( szReadStringA, szCommonStringA, cslen ))
+ {
+ Fail ("string comparison failed.\n szReadStringA is %s and\n"
+ "szCommonStringA is %s\n", szReadStringA,
+ szCommonStringA );
+ }
+ else
+ {
+ Trace ("string comparison passed.\n");
+ }
+
+ if (0 != (fclose ( fp )))
+ {
+ Trace ("%s unable to close file %s. This may cause a file pointer "
+ "leak. Continuing.\n", argv[0], szAbsPathNameA );
+ }
+
+ /* Close process and thread handle */
+ CloseHandle ( pi.hProcess );
+ CloseHandle ( pi.hThread );
+
+ PAL_Terminate();
+ return ( PASS );
+
+}
diff --git a/src/pal/tests/palsuite/threading/CreateProcessW/test1/testinfo.dat b/src/pal/tests/palsuite/threading/CreateProcessW/test1/testinfo.dat
new file mode 100644
index 0000000000..2acf2c9289
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateProcessW/test1/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = CreateProcessW
+Name = Positive Test for CreateProcessW
+TYPE = DEFAULT
+EXE1 = parentprocess
+EXE2 = childprocess
+Description
+= Test the CreateProcessW function. The test executes the childprocess
+= program. The childprocess program launches and writes a const char string
+= to a file childdata. The parent waits for the completion of childprocess
+= and then reads the string from the childdata file. If the string in the
+= file matches it's copy of the const char string, then the test succeeds.
diff --git a/src/pal/tests/palsuite/threading/CreateProcessW/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateProcessW/test2/CMakeLists.txt
new file mode 100644
index 0000000000..3feef213c4
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateProcessW/test2/CMakeLists.txt
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(TESTSOURCES
+ parentprocess.c
+)
+
+add_executable(paltest_createprocessw_test2
+ ${TESTSOURCES}
+)
+
+add_dependencies(paltest_createprocessw_test2 coreclrpal)
+
+target_link_libraries(paltest_createprocessw_test2
+ pthread
+ m
+ coreclrpal
+)
+
+
+set(HELPERSOURCES
+ childprocess.c
+)
+
+add_executable(paltest_createprocessw_test2_child
+ ${HELPERSOURCES}
+)
+
+add_dependencies(paltest_createprocessw_test2_child coreclrpal)
+
+target_link_libraries(paltest_createprocessw_test2_child
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/CreateProcessW/test2/childprocess.c b/src/pal/tests/palsuite/threading/CreateProcessW/test2/childprocess.c
new file mode 100644
index 0000000000..b4ab9366d9
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateProcessW/test2/childprocess.c
@@ -0,0 +1,78 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: createprocessw/test2/childprocess.c
+**
+** Purpose: This child process reads a string from stdin
+** and writes it out to stdout & stderr
+**
+** Dependencies: memset
+** fgets
+** gputs
+**
+
+**
+**=========================================================*/
+
+#define UNICODE
+#include <palsuite.h>
+#include "test2.h"
+
+
+int __cdecl main( int argc, char **argv )
+{
+ int iRetCode = EXIT_OK_CODE; /* preset exit code to OK */
+ char szBuf[BUF_LEN];
+
+ WCHAR *swzParam1, *swzParam2, *swzParam3 = NULL;
+
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+ if (argc != 4)
+ {
+ return EXIT_ERR_CODE3;
+ }
+
+ swzParam1 = convert(argv[1]);
+ swzParam2 = convert(argv[2]);
+ swzParam3 = convert(argv[3]);
+
+ if (wcscmp(swzParam1, szArg1) != 0
+ || wcscmp(swzParam2, szArg2) != 0
+ || wcscmp(swzParam3, szArg3) != 0)
+ {
+ return EXIT_ERR_CODE4;
+ }
+
+ free(swzParam1);
+ free(swzParam2);
+ free(swzParam3);
+
+ memset(szBuf, 0, BUF_LEN);
+
+ /* Read the string that was written by the parent */
+ if (fgets(szBuf, BUF_LEN, stdin) == NULL)
+ {
+ return EXIT_ERR_CODE1;
+ }
+
+
+ /* Write the string out to the stdout & stderr pipes */
+ if (fputs(szBuf, stdout) == EOF
+ || fputs(szBuf, stderr) == EOF)
+ {
+ return EXIT_ERR_CODE2;
+ }
+
+ /* The exit code will indicate success or failure */
+ PAL_TerminateEx(iRetCode);
+
+ /* Return special exit code to indicate success or failure */
+ return iRetCode;
+}
diff --git a/src/pal/tests/palsuite/threading/CreateProcessW/test2/parentprocess.c b/src/pal/tests/palsuite/threading/CreateProcessW/test2/parentprocess.c
new file mode 100644
index 0000000000..439b7b5eef
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateProcessW/test2/parentprocess.c
@@ -0,0 +1,245 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: createprocessw/test2/parentprocess.c
+**
+** Purpose: Test the following features of CreateProcessW:
+** - Check to see if hProcess & hThread are set in
+** return PROCESS_INFORMATION structure
+** - Check to see if stdin, stdout, & stderr handles
+** are used when STARTF_USESTDHANDLES is specified
+** in STARUPINFO flags and bInheritHandles = TRUE
+** - Check to see that proper arguments are passed to
+** child process
+**
+** Dependencies: CreatePipe
+** strcpy, strlen, strncmp, memset
+** WaitForSingleObject
+** WriteFile, ReadFile
+** GetExitCodeProcess
+**
+
+**
+**=========================================================*/
+
+#define UNICODE
+#include <palsuite.h>
+#include "test2.h"
+
+
+
+int __cdecl main( int argc, char **argv )
+{
+
+ /*******************************************
+ * Declarations
+ *******************************************/
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+
+ HANDLE hTestStdInR = NULL;
+ HANDLE hTestStdInW = NULL;
+ HANDLE hTestStdOutR = NULL;
+ HANDLE hTestStdOutW = NULL;
+ HANDLE hTestStdErrR = NULL;
+ HANDLE hTestStdErrW = NULL;
+
+ BOOL bRetVal = FALSE;
+ DWORD dwBytesWritten = 0;
+ DWORD dwBytesRead = 0;
+ DWORD dwExitCode = 0;
+
+ SECURITY_ATTRIBUTES pipeAttributes;
+
+ char szStdOutBuf[BUF_LEN];
+ char szStdErrBuf[BUF_LEN];
+ WCHAR szFullPathNameW[_MAX_PATH];
+
+
+ /*******************************************
+ * Initialization
+ *******************************************/
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ /*Setup SECURITY_ATTRIBUTES structure for CreatePipe*/
+ pipeAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
+ pipeAttributes.lpSecurityDescriptor = NULL;
+ pipeAttributes.bInheritHandle = TRUE;
+
+
+ /*Create a StdIn pipe for child*/
+ bRetVal = CreatePipe(&hTestStdInR, /* read handle*/
+ &hTestStdInW, /* write handle */
+ &pipeAttributes, /* security attributes*/
+ 1024); /* pipe size*/
+
+ if (bRetVal == FALSE)
+ {
+ Fail("ERROR: %ld :Unable to create stdin pipe\n", GetLastError());
+ }
+
+
+ /*Create a StdOut pipe for child*/
+ bRetVal = CreatePipe(&hTestStdOutR, /* read handle*/
+ &hTestStdOutW, /* write handle */
+ &pipeAttributes, /* security attributes*/
+ 0); /* pipe size*/
+
+ if (bRetVal == FALSE)
+ {
+ Fail("ERROR: %ld :Unable to create stdout pipe\n", GetLastError());
+ }
+
+
+ /*Create a StdErr pipe for child*/
+ bRetVal = CreatePipe(&hTestStdErrR, /* read handle*/
+ &hTestStdErrW, /* write handle */
+ &pipeAttributes, /* security attributes*/
+ 0); /* pipe size*/
+
+ if (bRetVal == FALSE)
+ {
+ Fail("ERROR: %ld :Unable to create stderr pipe\n", GetLastError());
+ }
+
+ /* Zero the data structure space */
+ ZeroMemory ( &pi, sizeof(pi) );
+ ZeroMemory ( &si, sizeof(si) );
+
+ /* Set the process flags and standard io handles */
+ si.cb = sizeof(si);
+ si.dwFlags = STARTF_USESTDHANDLES;
+ si.hStdInput = hTestStdInR;
+ si.hStdOutput = hTestStdOutW;
+ si.hStdError = hTestStdErrW;
+
+ wcscpy(szFullPathNameW, szChildFileW);
+ wcscat(szFullPathNameW, szArgs);
+
+ /*******************************************
+ * Start Testing
+ *******************************************/
+
+ /* Launch the child */
+ if ( !CreateProcess (NULL, szFullPathNameW, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi ))
+ {
+ Fail("ERROR: CreateProcess call failed. GetLastError returned %d\n",
+ GetLastError() );
+ }
+
+ /* Check the returned process information for validity */
+ if (pi.hProcess == 0 || pi.hThread == 0)
+ {
+ Fail("ERROR: CreateProcess Error: Process Handle = %u, Thread Handle = %u\n",
+ pi.hProcess, pi.hThread);
+ }
+
+
+ /* Write the Constructed string to stdin pipe for the child process */
+ if (WriteFile(hTestStdInW, szTestString, strlen(szTestString), &dwBytesWritten, NULL) == FALSE
+ || WriteFile(hTestStdInW, "\n", strlen("\n"), &dwBytesWritten, NULL) == FALSE)
+ {
+ Fail("ERROR: %ld :unable to write to write pipe handle "
+ "hTestStdInW=0x%lx\n", GetLastError(), hTestStdInW);
+ }
+
+ /* Wait for the child to finish, Max 20 seconds */
+ dwExitCode = WaitForSingleObject(pi.hProcess, 20000);
+
+ /* If the child failed then whole thing fails */
+ if (dwExitCode != WAIT_OBJECT_0)
+ {
+ TerminateProcess(pi.hProcess, 0);
+ Fail("ERROR: The child failed to run properly.\n");
+ }
+
+ /* Check for problems in the child process */
+ if (GetExitCodeProcess(pi.hProcess, &dwExitCode) == FALSE)
+ {
+ Fail("ERROR: Call to GetExitCodeProcess failed.\n");
+ }
+ else if (dwExitCode == EXIT_ERR_CODE1)
+ {
+ Fail("ERROR: The Child process could not reead the string "
+ "written to the stdin pipe.\n");
+ }
+ else if (dwExitCode == EXIT_ERR_CODE2)
+ {
+ Fail("ERROR: The Child process could not write the string "
+ "the stdout pipe or stderr pipe.\n");
+ }
+ else if (dwExitCode == EXIT_ERR_CODE3)
+ {
+ Fail("ERROR: The Child received the wrong number of "
+ "command line arguments.\n");
+ }
+ else if (dwExitCode == EXIT_ERR_CODE4)
+ {
+ Fail("ERROR: The Child received the wrong "
+ "command line arguments.\n");
+ }
+ else if (dwExitCode != EXIT_OK_CODE)
+ {
+ Fail("ERROR: Unexpected exit code returned: %u. Child process "
+ "did not complete its part of the test.\n", dwExitCode);
+ }
+
+
+ /* The child ran ok, so check to see if we received the proper */
+ /* strings through the pipes. */
+
+ /* clear our buffers */
+ memset(szStdOutBuf, 0, BUF_LEN);
+ memset(szStdErrBuf, 0, BUF_LEN);
+
+ /* Read the data back from the child process stdout */
+ bRetVal = ReadFile(hTestStdOutR, /* handle to read pipe*/
+ szStdOutBuf, /* buffer to write to*/
+ BUF_LEN, /* number of bytes to read*/
+ &dwBytesRead, /* number of bytes read*/
+ NULL); /* overlapped buffer*/
+
+ /*Read the data back from the child process stderr */
+ bRetVal = ReadFile(hTestStdErrR, /* handle to read pipe*/
+ szStdErrBuf, /* buffer to write to*/
+ BUF_LEN, /* number of bytes to read*/
+ &dwBytesRead, /* number of bytes read*/
+ NULL); /* overlapped buffer*/
+
+
+ /* Confirm that we recieved the same string that we originally */
+ /* wrote to the child and was received on both stdout & stderr.*/
+ if (strncmp(szTestString, szStdOutBuf, strlen(szTestString)) != 0
+ || strncmp(szTestString, szStdErrBuf, strlen(szTestString)) != 0)
+ {
+ Fail("ERROR: The data read back from child does not match "
+ "what was written. STDOUT: %s STDERR: %s\n",
+ szStdOutBuf, szStdErrBuf);
+ }
+
+
+ /*******************************************
+ * Clean Up
+ *******************************************/
+
+ /* Close process and thread handle */
+ CloseHandle ( pi.hProcess );
+ CloseHandle ( pi.hThread );
+
+ CloseHandle(hTestStdInR);
+ CloseHandle(hTestStdInW);
+ CloseHandle(hTestStdOutR);
+ CloseHandle(hTestStdOutW);
+ CloseHandle(hTestStdErrR);
+ CloseHandle(hTestStdErrW);
+
+ PAL_Terminate();
+ return ( PASS );
+}
diff --git a/src/pal/tests/palsuite/threading/CreateProcessW/test2/test2.h b/src/pal/tests/palsuite/threading/CreateProcessW/test2/test2.h
new file mode 100644
index 0000000000..07d40b8942
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateProcessW/test2/test2.h
@@ -0,0 +1,31 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test2.h
+**
+**
+
+**
+**=========================================================*/
+
+
+const WCHAR szChildFileW[] = u"paltest_createprocessw_test2_child";
+const WCHAR szArgs[] = {' ',0x41,' ','B',' ','C','\0'};
+const WCHAR szArg1[] = {0x41,'\0'};
+const WCHAR szArg2[] = {'B','\0'};
+const WCHAR szArg3[] = {'C','\0'};
+
+const char *szTestString = "An uninteresting test string (it works though)";
+
+const DWORD EXIT_OK_CODE = 100;
+const DWORD EXIT_ERR_CODE1 = 101;
+const DWORD EXIT_ERR_CODE2 = 102;
+const DWORD EXIT_ERR_CODE3 = 103;
+const DWORD EXIT_ERR_CODE4 = 104;
+const DWORD EXIT_ERR_CODE5 = 105;
+
+#define BUF_LEN 128
+
diff --git a/src/pal/tests/palsuite/threading/CreateProcessW/test2/testinfo.dat b/src/pal/tests/palsuite/threading/CreateProcessW/test2/testinfo.dat
new file mode 100644
index 0000000000..d16ae593f2
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateProcessW/test2/testinfo.dat
@@ -0,0 +1,20 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = CreateProcessW
+Name = PROCESS_INFORMATION and HANDLE Inheritance
+TYPE = DEFAULT
+EXE1 = parentprocess
+EXE2 = childprocess
+Description
+= Test the following features of CreateProcessW:
+= - Check to see if hProcess & hThread are set in
+= return PROCESS_INFORMATION structure
+= - Check to see if stdin, stdout, & stderr handles
+= are used when STARTF_USESTDHANDLES is specified
+= in STARUPINFO flags and bInheritHandles = TRUE
+= - Check to see that proper arguments are passed to
+= child process
diff --git a/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/CMakeLists.txt
new file mode 100644
index 0000000000..1962ade358
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+
diff --git a/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/CMakeLists.txt
new file mode 100644
index 0000000000..f89e150a32
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ CreateSemaphore.c
+)
+
+add_executable(paltest_createsemaphorea_releasesemaphore_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createsemaphorea_releasesemaphore_test1 coreclrpal)
+
+target_link_libraries(paltest_createsemaphorea_releasesemaphore_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/CreateSemaphore.c b/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/CreateSemaphore.c
new file mode 100644
index 0000000000..342b15ec29
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/CreateSemaphore.c
@@ -0,0 +1,322 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: createsemaphorea_releasesemaphore/test1/createsemaphore.c
+**
+** Purpose: Test Semaphore operation using classic IPC problem:
+** "Producer-Consumer Problem".
+**
+** Dependencies: CreateThread
+** ReleaseSemaphore
+** WaitForSingleObject
+** Sleep
+** fflush
+**
+
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+#define PRODUCTION_TOTAL 26
+
+#define _BUF_SIZE 10
+
+DWORD dwThreadId; /* consumer thread identifier */
+
+HANDLE hThread; /* handle to consumer thread */
+
+HANDLE hSemaphoreM; /* handle to mutual exclusion semaphore */
+
+HANDLE hSemaphoreE; /* handle to semaphore that counts empty buffer slots */
+
+HANDLE hSemaphoreF; /* handle to semaphore that counts full buffer slots */
+
+typedef struct Buffer
+{
+ short readIndex;
+ short writeIndex;
+ CHAR message[_BUF_SIZE];
+
+} BufferStructure;
+
+CHAR producerItems[PRODUCTION_TOTAL + 1];
+
+CHAR consumerItems[PRODUCTION_TOTAL + 1];
+
+/*
+ * Read next message from the Buffer into provided pointer.
+ * Returns: 0 on failure, 1 on success.
+ */
+int
+readBuf(BufferStructure *Buffer, char *c)
+{
+ if( Buffer -> writeIndex == Buffer -> readIndex )
+ {
+ return 0;
+ }
+ *c = Buffer -> message[Buffer -> readIndex++];
+ Buffer -> readIndex %= _BUF_SIZE;
+ return 1;
+}
+
+/*
+ * Write message generated by the producer to Buffer.
+ * Returns: 0 on failure, 1 on success.
+ */
+int
+writeBuf(BufferStructure *Buffer, CHAR c)
+{
+ if( ( ((Buffer -> writeIndex) + 1) % _BUF_SIZE) ==
+ (Buffer -> readIndex) )
+ {
+ return 0;
+ }
+ Buffer -> message[Buffer -> writeIndex++] = c;
+ Buffer -> writeIndex %= _BUF_SIZE;
+ return 1;
+}
+
+/*
+ * Atomic decrement of semaphore value.
+ */
+VOID
+down(HANDLE hSemaphore)
+{
+ switch ( (WaitForSingleObject (
+ hSemaphore,
+ 10000))) /* Wait 10 seconds */
+ {
+ case WAIT_OBJECT_0: /*
+ * Semaphore was signaled. OK to access
+ * semaphore.
+ */
+ break;
+ case WAIT_ABANDONED: /*
+ * Object was mutex object whose owning
+ * thread has terminated. Shouldn't occur.
+ */
+ Fail("WaitForSingleObject call returned 'WAIT_ABANDONED'.\n"
+ "Failing Test.\n");
+ break;
+ case WAIT_FAILED: /* WaitForSingleObject function failed */
+ Fail("WaitForSingleObject call returned 'WAIT_FAILED'.\n"
+ "GetLastError returned %d\nFailing Test.\n",GetLastError());
+ break;
+ default:
+ Fail("WaitForSingleObject call returned an unexpected value.\n"
+ "Failing Test.\n");
+ break;
+ }
+
+}
+
+/*
+ * Atomic increment of semaphore value.
+ */
+VOID
+up(HANDLE hSemaphore)
+{
+ if (!ReleaseSemaphore (
+ hSemaphore,
+ 1,
+ NULL)
+ )
+ {
+ Fail("ReleaseSemaphore call failed. GetLastError returned %d\n",
+ GetLastError());
+ }
+}
+
+/*
+ * Sleep 500 milleseconds.
+ */
+VOID
+consumerSleep(VOID)
+{
+ Sleep(500);
+}
+
+/*
+ * Sleep between 10 milleseconds.
+ */
+VOID
+producerSleep(VOID)
+{
+ Sleep(10);
+}
+
+/*
+ * Produce a message and write the message to Buffer.
+ */
+VOID
+producer(BufferStructure *Buffer)
+{
+
+ int n = 0;
+ char c;
+
+ while (n < PRODUCTION_TOTAL)
+ {
+ c = 'A' + n ; /* Produce Item */
+
+ down(hSemaphoreE);
+ down(hSemaphoreM);
+
+ if (writeBuf(Buffer, c))
+ {
+ Trace("Producer produces %c.\n", c);
+ fflush(stdout);
+ producerItems[n++] = c;
+ }
+
+ up(hSemaphoreM);
+ up(hSemaphoreF);
+
+ producerSleep();
+ }
+
+ return;
+}
+
+/*
+ * Read and "Consume" the messages in Buffer.
+ */
+DWORD
+PALAPI
+consumer( LPVOID lpParam )
+{
+ int n = 0;
+ char c;
+
+ consumerSleep();
+
+ while (n < PRODUCTION_TOTAL)
+ {
+
+ down(hSemaphoreF);
+ down(hSemaphoreM);
+
+ if (readBuf((BufferStructure*)lpParam, &c))
+ {
+ Trace("\tConsumer consumes %c.\n", c);
+ fflush(stdout);
+ consumerItems[n++] = c;
+ }
+
+ up(hSemaphoreM);
+ up(hSemaphoreE);
+
+ consumerSleep();
+ }
+
+ return 0;
+}
+
+int __cdecl main (int argc, char **argv)
+{
+
+ BufferStructure Buffer, *pBuffer;
+
+ pBuffer = &Buffer;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ /*
+ * Create Semaphores
+ */
+ hSemaphoreM = CreateSemaphoreA (
+ NULL,
+ 1,
+ 1,
+ NULL);
+
+ if ( NULL == hSemaphoreM )
+ {
+ Fail ( "hSemaphoreM = CreateSemaphoreA () - returned NULL\n"
+ "Failing Test.\nGetLastError returned %d\n", GetLastError());
+ }
+
+
+ hSemaphoreE = CreateSemaphoreA (
+ NULL,
+ _BUF_SIZE ,
+ _BUF_SIZE ,
+ NULL);
+
+ if ( NULL == hSemaphoreE )
+ {
+ Fail ( "hSemaphoreE = CreateSemaphoreA () - returned NULL\n"
+ "Failing Test.\nGetLastError returned %d\n", GetLastError());
+ }
+
+ hSemaphoreF = CreateSemaphoreA (
+ NULL,
+ 0,
+ _BUF_SIZE ,
+ NULL);
+
+ if ( NULL == hSemaphoreF )
+ {
+ Fail ( "hSemaphoreF = CreateSemaphoreA () - returned NULL\n"
+ "Failing Test.\nGetLastError returned %d\n", GetLastError());
+ }
+
+
+ /*
+ * Initialize Buffer
+ */
+ pBuffer->writeIndex = pBuffer->readIndex = 0;
+
+ /*
+ * Create Consumer
+ */
+ hThread = CreateThread(
+ NULL,
+ 0,
+ consumer,
+ &Buffer,
+ 0,
+ &dwThreadId);
+
+ if ( NULL == hThread )
+ {
+ Fail ( "CreateThread() returned NULL. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+ /*
+ * Start producing
+ */
+ producer(pBuffer);
+
+ /*
+ * Wait for consumer to complete
+ */
+ WaitForSingleObject (hThread, INFINITE);
+
+ /*
+ * Compare items produced vs. items consumed
+ */
+ if ( 0 != strncmp (producerItems, consumerItems, PRODUCTION_TOTAL) )
+ {
+ Fail("The producerItems string %s\n and the consumerItems string "
+ "%s\ndo not match. This could be a problem with the strncmp()"
+ " function\n FailingTest\nGetLastError() returned %d\n",
+ producerItems, consumerItems, GetLastError());
+ }
+
+ Trace ("producerItems and consumerItems arrays match. All %d\nitems "
+ "were produced and consumed in order.\nTest passed.\n",
+ PRODUCTION_TOTAL);
+
+ PAL_Terminate();
+ return ( PASS );
+
+}
diff --git a/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/testinfo.dat b/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/testinfo.dat
new file mode 100644
index 0000000000..880746e43e
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/testinfo.dat
@@ -0,0 +1,18 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = CreateSemaphoreA / ReleaseSemaphore
+Name = Positive Test for CreateSemaphoreA and ReleaseSemaphore
+TYPE = DEFAULT
+EXE1 = createsemaphore
+Description
+= Implementation of Producer / Consumer IPC problem using CreateSemaphoreA
+= and ReleaseSemaphore functions. This test case exercises CreateSemaphoreA
+= , ReleaseSemaphore, CreateThread and WaitForSingleObject functions.
+= Since there is no way to currently create "pseudo" random events in the
+= pal, this example does not behave as classic bounded buffers would. This
+= test case is designed to starve the consumer and have the producer fill
+= the buffer.
diff --git a/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/CMakeLists.txt
new file mode 100644
index 0000000000..f3e01749b8
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ CreateSemaphore.c
+)
+
+add_executable(paltest_createsemaphorea_releasesemaphore_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createsemaphorea_releasesemaphore_test2 coreclrpal)
+
+target_link_libraries(paltest_createsemaphorea_releasesemaphore_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/CreateSemaphore.c b/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/CreateSemaphore.c
new file mode 100644
index 0000000000..bff5b51c33
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/CreateSemaphore.c
@@ -0,0 +1,313 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: CreateSemaphoreA_ReleaseSemaphore/test2/createsemaphore.c
+**
+** Purpose: Test Semaphore operation using classic IPC problem:
+** "Producer-Consumer Problem".
+**
+** Dependencies: CreateThread
+** ReleaseSemaphore
+** WaitForSingleObject
+** Sleep
+** fflush
+**
+
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+#define PRODUCTION_TOTAL 26
+
+#define _BUF_SIZE 10
+
+DWORD dwThreadId; /* consumer thread identifier */
+
+HANDLE hThread; /* handle to consumer thread */
+
+HANDLE hSemaphoreM; /* handle to mutual exclusion semaphore */
+
+HANDLE hSemaphoreE; /* handle to semaphore that counts empty buffer slots */
+
+HANDLE hSemaphoreF; /* handle to semaphore that counts full buffer slots */
+
+typedef struct Buffer
+{
+ short readIndex;
+ short writeIndex;
+ CHAR message[_BUF_SIZE];
+
+} BufferStructure;
+
+CHAR producerItems[PRODUCTION_TOTAL + 1];
+
+CHAR consumerItems[PRODUCTION_TOTAL + 1];
+
+/*
+ * Read next message from the Buffer into provided pointer.
+ * Returns: 0 on failure, 1 on success.
+ */
+int
+readBuf(BufferStructure *Buffer, char *c)
+{
+ if( Buffer -> writeIndex == Buffer -> readIndex )
+ {
+ return 0;
+ }
+ *c = Buffer -> message[Buffer -> readIndex++];
+ Buffer -> readIndex %= _BUF_SIZE;
+ return 1;
+}
+
+/*
+ * Write message generated by the producer to Buffer.
+ * Returns: 0 on failure, 1 on success.
+ */
+int
+writeBuf(BufferStructure *Buffer, CHAR c)
+{
+ if( ( ((Buffer -> writeIndex) + 1) % _BUF_SIZE) ==
+ (Buffer -> readIndex) )
+ {
+ return 0;
+ }
+ Buffer -> message[Buffer -> writeIndex++] = c;
+ Buffer -> writeIndex %= _BUF_SIZE;
+ return 1;
+}
+
+/*
+ * Atomic decrement of semaphore value.
+ */
+VOID
+down(HANDLE hSemaphore)
+{
+ switch ( (WaitForSingleObject (
+ hSemaphore,
+ 10000)))
+ {
+ case WAIT_OBJECT_0: /*
+ * Semaphore was signaled. OK to access semaphore.
+ */
+ break;
+ case WAIT_ABANDONED: /*
+ * Object was mutex object whose owning
+ * thread has terminated. Shouldn't occur.
+ */
+ Fail("WaitForSingleObject call returned 'WAIT_ABANDONED'.\n"
+ "Failing Test.\n");
+ break;
+ case WAIT_FAILED: /* WaitForSingleObject function failed */
+ Fail("WaitForSingleObject call returned 'WAIT_FAILED'.\n"
+ "GetLastError returned %d\nFailing Test.\n",GetLastError());
+ break;
+ default:
+ Fail("WaitForSingleObject call returned an unexpected value.\n"
+ "Failing Test.\n");
+ break;
+ }
+
+}
+
+/*
+ * Atomic increment of semaphore value.
+ */
+VOID
+up(HANDLE hSemaphore)
+{
+ if (!ReleaseSemaphore (
+ hSemaphore,
+ 1,
+ NULL)
+ )
+ {
+ Fail("ReleaseSemaphore call failed. GetLastError returned %d\n",
+ GetLastError());
+ }
+}
+
+/*
+ * Sleep 10 milleseconds.
+ */
+VOID
+consumerSleep(VOID)
+{
+ Sleep(10);
+}
+
+/*
+ * Sleep 500 milleseconds.
+ */
+VOID
+producerSleep(VOID)
+{
+ Sleep(500);
+}
+
+/*
+ * Produce a message and write the message to Buffer.
+ */
+VOID
+producer(BufferStructure *Buffer)
+{
+
+ int n = 0;
+ char c;
+
+ while (n < PRODUCTION_TOTAL)
+ {
+ c = 'A' + n ; /* Produce Item */
+
+ down(hSemaphoreE);
+ down(hSemaphoreM);
+
+ if (writeBuf(Buffer, c))
+ {
+ Trace("Producer produces %c.\n", c);
+ fflush(stdout);
+ producerItems[n++] = c;
+ }
+
+ up(hSemaphoreM);
+ up(hSemaphoreF);
+
+ producerSleep();
+ }
+ return;
+}
+
+/*
+ * Read and "Consume" the messages in Buffer.
+ */
+DWORD
+PALAPI
+consumer( LPVOID lpParam )
+{
+ int n = 0;
+ char c;
+
+ consumerSleep();
+
+ while (n < PRODUCTION_TOTAL)
+ {
+
+ down(hSemaphoreF);
+ down(hSemaphoreM);
+
+ if (readBuf((BufferStructure*)lpParam, &c))
+ {
+ Trace("\tConsumer consumes %c.\n", c);
+ fflush(stdout);
+ consumerItems[n++] = c;
+ }
+
+ up(hSemaphoreM);
+ up(hSemaphoreE);
+
+ consumerSleep();
+ }
+ return 0;
+}
+
+int __cdecl main (int argc, char **argv)
+{
+
+ BufferStructure Buffer, *pBuffer;
+
+ pBuffer = &Buffer;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return (FAIL);
+ }
+
+ /*
+ * Create Semaphores
+ */
+ hSemaphoreM = CreateSemaphoreA (
+ NULL,
+ 1,
+ 1,
+ NULL);
+
+ if ( NULL == hSemaphoreM )
+ {
+ Fail ( "hSemaphoreM = CreateSemaphoreA () - returned NULL\n"
+ "Failing Test.\n");
+ }
+
+ hSemaphoreE = CreateSemaphoreA (
+ NULL,
+ _BUF_SIZE ,
+ _BUF_SIZE ,
+ NULL);
+
+ if ( NULL == hSemaphoreE )
+ {
+ Fail ( "hSemaphoreE = CreateSemaphoreA () - returned NULL\n"
+ "Failing Test.\n");
+ }
+
+ hSemaphoreF = CreateSemaphoreA (
+ NULL,
+ 0,
+ _BUF_SIZE ,
+ NULL);
+
+ if ( NULL == hSemaphoreF )
+ {
+ Fail ( "hSemaphoreF = CreateSemaphoreA () - returned NULL\n"
+ "Failing Test.\n");
+ }
+
+ /*
+ * Initialize Buffer
+ */
+ pBuffer->writeIndex = pBuffer->readIndex = 0;
+
+ /*
+ * Create Consumer
+ */
+ hThread = CreateThread(
+ NULL,
+ 0,
+ consumer,
+ &Buffer,
+ 0,
+ &dwThreadId);
+
+ if ( NULL == hThread )
+ {
+ Fail ( "CreateThread() returned NULL. Failing test.\n");
+ }
+
+ /*
+ * Start producing
+ */
+ producer(pBuffer);
+
+ /*
+ * Wait for consumer to complete
+ */
+ WaitForSingleObject (hThread, INFINITE);
+
+ if ( 0 != strncmp (producerItems, consumerItems, PRODUCTION_TOTAL) )
+ {
+ Fail("The producerItems string %s\n and the consumerItems string "
+ "%s\ndo not match. This could be a problem with the strncmp()"
+ " function\n FailingTest\nGetLastError() returned %d\n",
+ producerItems, consumerItems, GetLastError());
+ }
+
+ Trace ("producerItems and consumerItems arrays match. All %d\nitems "
+ "were produced and consumed in order.\nTest passed.\n",
+ PRODUCTION_TOTAL);
+
+ PAL_Terminate();
+ return ( PASS );
+
+}
diff --git a/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/testinfo.dat b/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/testinfo.dat
new file mode 100644
index 0000000000..5a6c2e7909
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/testinfo.dat
@@ -0,0 +1,18 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = CreateSemaphoreA / ReleaseSemaphore
+Name = Positive Test for CreateSemaphoreA and ReleaseSemaphore
+TYPE = DEFAULT
+EXE1 = createsemaphore
+Description
+= Implementation of Producer / Consumer IPC problem using CreateSemaphoreA
+= and ReleaseSemaphore functions. This test case exercises CreateSemaphoreA
+= , ReleaseSemaphore, CreateThread and WaitForSingleObject functions.
+= Since there is no way to currently create "pseudo" random events in the
+= pal, this example does not behave as classic bounded buffers would. This
+= test case is designed to starve the producer and have the consumer fill
+= the buffer.
diff --git a/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/CMakeLists.txt
new file mode 100644
index 0000000000..0c604d6ced
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ createsemaphore.c
+)
+
+add_executable(paltest_createsemaphorea_releasesemaphore_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createsemaphorea_releasesemaphore_test3 coreclrpal)
+
+target_link_libraries(paltest_createsemaphorea_releasesemaphore_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/createsemaphore.c b/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/createsemaphore.c
new file mode 100644
index 0000000000..7c6db6b055
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/createsemaphore.c
@@ -0,0 +1,200 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: createsemaphorea_releasesemaphore/test3/createsemaphore.c
+**
+** Purpose: Test attributes of CreateSemaphoreA and ReleaseSemaphore.
+** Insure for CreateSemaphore that lInitialCount and lMaximumCount
+** constraints are respected. Validate that CreateSemaphore rejects
+** conditions where initial count and / or maximum count are negative
+** and conditions where the initial count is greater than the maximum
+** count. For ReleaseSemaphore validate that lpPreviousCount gets set
+** to the previous semaphore count and lpPreviousCount can be NULL.
+** Also establish ReleaseSemaphore fails when called in a semaphore
+** with count equal to lMaximumCount.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+struct testcase
+{
+ LPSECURITY_ATTRIBUTES lpSemaphoreAttributes;
+ LONG lInitialCount;
+ LONG lMaximumCount;
+ LPCTSTR lpName;
+ BOOL bNegativeTest;
+};
+
+struct testcase testCases[] =
+{
+ {NULL, -1, 1, NULL, TRUE},
+ {NULL, 1, -1, NULL, TRUE},
+ {NULL, -1, -1, NULL, TRUE},
+ {NULL, 2, 1, NULL, TRUE},
+ {NULL, 1, 2, NULL, FALSE},
+ {NULL, 0, 10, NULL, FALSE},
+ {NULL, INT_MAX - 1, INT_MAX, NULL, FALSE},
+ {NULL, INT_MAX, INT_MAX, NULL, FALSE}
+};
+
+HANDLE hSemaphore[sizeof(testCases)/sizeof(struct testcase)];
+
+BOOL cleanup(int index)
+{
+ int i;
+ BOOL bRet = TRUE;
+ for (i = 0; i < index; i++)
+ {
+ if (!CloseHandle(hSemaphore[i]))
+ {
+ bRet = FALSE;
+ Trace("PALSUITE ERROR: CloseHandle(%p) call failed for index %d\n",
+ hSemaphore[i], i);
+ }
+ }
+ return(bRet);
+}
+
+int __cdecl main (int argc, char **argv)
+{
+ int i;
+ int j;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return (FAIL);
+ }
+ /* create semaphores */
+ for (i = 0; i < sizeof(testCases)/sizeof(struct testcase); i++)
+ {
+ hSemaphore[i] = CreateSemaphoreA (testCases[i].lpSemaphoreAttributes,
+ testCases[i].lInitialCount,
+ testCases[i].lMaximumCount,
+ testCases[i].lpName);
+
+ if (NULL == hSemaphore[i])
+ {
+ if (!testCases[i].bNegativeTest)
+ {
+ Trace("PALSUITE ERROR: CreateSemaphoreA('%p' '%ld' '%ld' "
+ "'%p') returned NULL at index %d.\nGetLastError "
+ "returned %d.\n", testCases[i].lpSemaphoreAttributes,
+ testCases[i].lInitialCount, testCases[i].lMaximumCount,
+ testCases[i].lpName, i, GetLastError());
+ if (i > 0)
+ {
+ cleanup(i - 1);
+ }
+ Fail("");
+ }
+ else
+ {
+ continue;
+ }
+ }
+
+ /* increment semaphore count to lMaximumCount */
+ for (j = testCases[i].lInitialCount; (ULONG)j <= (ULONG)testCases[i].lMaximumCount;
+ j++)
+ {
+ if (testCases[i].lMaximumCount == j)
+ {
+ /* Call ReleaseSemaphore once more to ensure ReleaseSemaphore
+ fails */
+ if(ReleaseSemaphore(hSemaphore[i], 1, NULL))
+ {
+ Trace("PALSUITE ERROR: ReleaseSemaphore('%p' '%ld' '%p') "
+ "call returned %d\nwhen it should have returned "
+ "%d.\nThe semaphore's count was %d.\nGetLastError "
+ "returned %d.\n", hSemaphore[i], 1, NULL, TRUE,
+ FALSE, j, GetLastError());
+ cleanup(i);
+ Fail("");
+ }
+ }
+ else
+ {
+ int previous;
+ BOOL bRet = ReleaseSemaphore(hSemaphore[i], 1, &previous);
+ DWORD dwError = GetLastError();
+
+ if(!bRet)
+ {
+ Trace("PALSUITE ERROR: ReleaseSemaphore('%p' '%ld' '%p') "
+ "call returned %d\nwhen it should have returned "
+ "%d.\nThe semaphore count was %d and it's "
+ "lMaxCount was %d.\nGetLastError returned %d.\n",
+ hSemaphore[i], 1, &previous, bRet, TRUE, j,
+ testCases[i].lMaximumCount, dwError);
+ cleanup(i);
+ Fail("");
+ }
+ if (previous != j)
+ {
+ Trace("PALSUITE ERROR: ReleaseSemaphore('%p' '%ld' '%p') "
+ "call set %p to %d instead of %d.\n The semaphore "
+ "count was %d and GetLastError returned %d.\n",
+ hSemaphore[i], 1, &previous, &previous, previous,
+ j, j, dwError);
+ cleanup(i);
+ Fail("");
+ }
+ }
+ }
+
+ // Skip exhaustive decrement tests for too large an initial count
+ if(testCases[i].lInitialCount >= INT_MAX - 1)
+ {
+ continue;
+ }
+
+ /* decrement semaphore count to 0 */
+ for (j = testCases[i].lMaximumCount; j >= 0; j--)
+ {
+ DWORD dwRet = WaitForSingleObject(hSemaphore[i], 0);
+ DWORD dwError = GetLastError();
+
+ if (0 == j)
+ {
+ /* WaitForSingleObject should report that the
+ semaphore is nonsignaled */
+ if (WAIT_TIMEOUT != dwRet)
+ {
+ Trace("PALSUITE ERROR: WaitForSingleObject('%p' '%u') "
+ "call returned %d\nwhen it should have returned "
+ "%d.\nThe semaphore's count was %d.\nGetLastError "
+ "returned %d.\n", hSemaphore[i], 0, dwRet,
+ WAIT_TIMEOUT, j, dwError);
+ cleanup(i);
+ Fail("");
+ }
+ }
+ else
+ {
+ /* WaitForSingleObject should report that the
+ semaphore is signaled */
+ if (WAIT_OBJECT_0 != dwRet)
+ {
+ Trace("PALSUITE ERROR: WaitForSingleObject('%p' '%u') "
+ "call returned %d\nwhen it should have returned "
+ "%d.\nThe semaphore's count was %d.\nGetLastError "
+ "returned %d.\n", hSemaphore[i], 0, dwRet,
+ WAIT_OBJECT_0, j, dwError);
+ cleanup(i);
+ Fail("");
+ }
+ }
+ }
+ }
+ PAL_Terminate();
+ return (PASS);
+}
+
+
+
+
diff --git a/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/testinfo.dat b/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/testinfo.dat
new file mode 100644
index 0000000000..d8cd590923
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/testinfo.dat
@@ -0,0 +1,20 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = CreateSemaphoreA / ReleaseSemaphore
+Name = Positive Test for CreateSemaphoreA and ReleaseSemaphore
+TYPE = DEFAULT
+EXE1 = createsemaphore
+Description
+= Test attributes of CreateSemaphoreA and ReleaseSemaphore.
+= Insure for CreateSemaphore that lInitialCount and lMaximumCount
+= constraints are respected. Validate that CreateSemaphore rejects
+= conditions where, initial count and / or maximum count are negative
+= and conditions where the initial count is greater than the maximum
+= count. For ReleaseSemaphore validate that lpPreviousCount gets set
+= to the previous semaphore count and lpPreviousCount can be NULL.
+= Also establish ReleaseSemaphore fails when called in a semaphore
+= with count equal to lMaximumCount.
diff --git a/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/CMakeLists.txt
new file mode 100644
index 0000000000..1962ade358
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+
diff --git a/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/CMakeLists.txt
new file mode 100644
index 0000000000..b40f2695bc
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ CreateSemaphore.c
+)
+
+add_executable(paltest_createsemaphorew_releasesemaphore_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createsemaphorew_releasesemaphore_test1 coreclrpal)
+
+target_link_libraries(paltest_createsemaphorew_releasesemaphore_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/CreateSemaphore.c b/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/CreateSemaphore.c
new file mode 100644
index 0000000000..854d16d0ef
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/CreateSemaphore.c
@@ -0,0 +1,323 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: CreateSemaphoreW_ReleaseSemaphore/test1/CreateSemaphore.c
+**
+** Purpose: Test Semaphore operation using classic IPC problem:
+** "Producer-Consumer Problem".
+**
+** Dependencies: CreateThread
+** ReleaseSemaphore
+** WaitForSingleObject
+** Sleep
+** fflush
+**
+
+**
+**=========================================================*/
+
+#define UNICODE
+#include <palsuite.h>
+
+#define PRODUCTION_TOTAL 26
+
+#define _BUF_SIZE 10
+
+DWORD dwThreadId; /* consumer thread identifier */
+
+HANDLE hThread; /* handle to consumer thread */
+
+HANDLE hSemaphoreM; /* handle to mutual exclusion semaphore */
+
+HANDLE hSemaphoreE; /* handle to semaphore that counts empty buffer slots */
+
+HANDLE hSemaphoreF; /* handle to semaphore that counts full buffer slots */
+
+typedef struct Buffer
+{
+ short readIndex;
+ short writeIndex;
+ CHAR message[_BUF_SIZE];
+
+} BufferStructure;
+
+CHAR producerItems[PRODUCTION_TOTAL + 1];
+
+CHAR consumerItems[PRODUCTION_TOTAL + 1];
+
+/*
+ * Read next message from the Buffer into provided pointer.
+ * Returns: 0 on failure, 1 on success.
+ */
+int
+readBuf(BufferStructure *Buffer, char *c)
+{
+ if( Buffer -> writeIndex == Buffer -> readIndex )
+ {
+ return 0;
+ }
+ *c = Buffer -> message[Buffer -> readIndex++];
+ Buffer -> readIndex %= _BUF_SIZE;
+ return 1;
+}
+
+/*
+ * Write message generated by the producer to Buffer.
+ * Returns: 0 on failure, 1 on success.
+ */
+int
+writeBuf(BufferStructure *Buffer, CHAR c)
+{
+ if( ( ((Buffer -> writeIndex) + 1) % _BUF_SIZE) ==
+ (Buffer -> readIndex) )
+ {
+ return 0;
+ }
+ Buffer -> message[Buffer -> writeIndex++] = c;
+ Buffer -> writeIndex %= _BUF_SIZE;
+ return 1;
+}
+
+/*
+ * Atomic decrement of semaphore value.
+ */
+VOID
+down(HANDLE hSemaphore)
+{
+ switch ( (WaitForSingleObject (
+ hSemaphore,
+ 10000))) /* Wait 10 seconds */
+ {
+ case WAIT_OBJECT_0: /*
+ * Semaphore was signaled. OK to access
+ * semaphore.
+ */
+ break;
+ case WAIT_ABANDONED: /*
+ * Object was mutex object whose owning
+ * thread has terminated. Shouldn't occur.
+ */
+ Fail("WaitForSingleObject call returned 'WAIT_ABANDONED'.\n"
+ "Failing Test.\n");
+ break;
+ case WAIT_FAILED: /* WaitForSingleObject function failed */
+ Fail("WaitForSingleObject call returned 'WAIT_FAILED'.\n"
+ "GetLastError returned %d\nFailing Test.\n",GetLastError());
+ break;
+ default:
+ Fail("WaitForSingleObject call returned an unexpected value.\n"
+ "Failing Test.\n");
+ break;
+ }
+
+}
+
+/*
+ * Atomic increment of semaphore value.
+ */
+VOID
+up(HANDLE hSemaphore)
+{
+ if (!ReleaseSemaphore (
+ hSemaphore,
+ 1,
+ NULL)
+ )
+ {
+ Fail("ReleaseSemaphore call failed. GetLastError returned %d\n",
+ GetLastError());
+ }
+}
+
+/*
+ * Sleep 500 milleseconds.
+ */
+VOID
+consumerSleep(VOID)
+{
+ Sleep(500);
+}
+
+/*
+ * Sleep between 10 milleseconds.
+ */
+VOID
+producerSleep(VOID)
+{
+ Sleep(10);
+}
+
+/*
+ * Produce a message and write the message to Buffer.
+ */
+VOID
+producer(BufferStructure *Buffer)
+{
+
+ int n = 0;
+ char c;
+
+ while (n < PRODUCTION_TOTAL)
+ {
+ c = 'A' + n ; /* Produce Item */
+
+ down(hSemaphoreE);
+ down(hSemaphoreM);
+
+ if (writeBuf(Buffer, c))
+ {
+ Trace("Producer produces %c.\n", c);
+ fflush(stdout);
+ producerItems[n++] = c;
+ }
+
+ up(hSemaphoreM);
+ up(hSemaphoreF);
+
+ producerSleep();
+ }
+
+ return;
+}
+
+/*
+ * Read and "Consume" the messages in Buffer.
+ */
+DWORD
+PALAPI
+consumer( LPVOID lpParam )
+{
+ int n = 0;
+ char c;
+
+ consumerSleep();
+
+ while (n < PRODUCTION_TOTAL)
+ {
+
+ down(hSemaphoreF);
+ down(hSemaphoreM);
+
+ if (readBuf((BufferStructure*)lpParam, &c))
+ {
+ Trace("\tConsumer consumes %c.\n", c);
+ fflush(stdout);
+ consumerItems[n++] = c;
+ }
+
+ up(hSemaphoreM);
+ up(hSemaphoreE);
+
+ consumerSleep();
+ }
+
+ return 0;
+}
+
+int __cdecl main (int argc, char **argv)
+{
+
+ BufferStructure Buffer, *pBuffer;
+
+ pBuffer = &Buffer;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ /*
+ * Create Semaphores
+ */
+ hSemaphoreM = CreateSemaphoreW (
+ NULL,
+ 1,
+ 1,
+ NULL);
+
+ if ( NULL == hSemaphoreM )
+ {
+ Fail ( "hSemaphoreM = CreateSemaphoreW () - returned NULL\n"
+ "Failing Test.\nGetLastError returned %d\n", GetLastError());
+ }
+
+
+ hSemaphoreE = CreateSemaphoreW (
+ NULL,
+ _BUF_SIZE ,
+ _BUF_SIZE ,
+ NULL);
+
+ if ( NULL == hSemaphoreE )
+ {
+ Fail ( "hSemaphoreE = CreateSemaphoreW () - returned NULL\n"
+ "Failing Test.\nGetLastError returned %d\n", GetLastError());
+ }
+
+ hSemaphoreF = CreateSemaphoreW (
+ NULL,
+ 0,
+ _BUF_SIZE ,
+ NULL);
+
+ if ( NULL == hSemaphoreF )
+ {
+ Fail ( "hSemaphoreF = CreateSemaphoreW () - returned NULL\n"
+ "Failing Test.\nGetLastError returned %d\n", GetLastError());
+ }
+
+
+ /*
+ * Initialize Buffer
+ */
+ pBuffer->writeIndex = pBuffer->readIndex = 0;
+
+ /*
+ * Create Consumer
+ */
+ hThread = CreateThread(
+ NULL,
+ 0,
+ consumer,
+ &Buffer,
+ 0,
+ &dwThreadId);
+
+ if ( NULL == hThread )
+ {
+ Fail ( "CreateThread() returned NULL. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+ /*
+ * Start producing
+ */
+ producer(pBuffer);
+
+ /*
+ * Wait for consumer to complete
+ */
+ WaitForSingleObject (hThread, INFINITE);
+
+ /*
+ * Compare items produced vs. items consumed
+ */
+ if ( 0 != strncmp (producerItems, consumerItems, PRODUCTION_TOTAL) )
+ {
+ Fail("The producerItems string %s\n and the consumerItems string "
+ "%s\ndo not match. This could be a problem with the strncmp()"
+ " function\n FailingTest\nGetLastError() returned %d\n",
+ producerItems, consumerItems, GetLastError());
+ }
+
+ Trace ("producerItems and consumerItems arrays match. All %d\nitems "
+ "were produced and consumed in order.\nTest passed.\n",
+ PRODUCTION_TOTAL);
+
+ PAL_Terminate();
+ return ( PASS );
+
+}
diff --git a/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/testinfo.dat b/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/testinfo.dat
new file mode 100644
index 0000000000..9127589333
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/testinfo.dat
@@ -0,0 +1,18 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = CreateSemaphoreW / ReleaseSemaphore
+Name = Positive Test for CreateSemaphoreW and ReleaseSemaphore
+TYPE = DEFAULT
+EXE1 = createsemaphore
+Description
+= Implementation of Producer / Consumer IPC problem using CreateSemaphoreW
+= and ReleaseSemaphore functions. This test case exercises CreateSemaphoreW
+= , ReleaseSemaphore, CreateThread and WaitForSingleObject functions.
+= Since there is no way to currently create "pseudo" random events in the
+= pal, this example does not behave as classic bounded buffers would. This
+= test case is designed to starve the consumer and have the producer fill
+= the buffer.
diff --git a/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/CMakeLists.txt
new file mode 100644
index 0000000000..b14284d08f
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ CreateSemaphore.c
+)
+
+add_executable(paltest_createsemaphorew_releasesemaphore_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createsemaphorew_releasesemaphore_test2 coreclrpal)
+
+target_link_libraries(paltest_createsemaphorew_releasesemaphore_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/CreateSemaphore.c b/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/CreateSemaphore.c
new file mode 100644
index 0000000000..62532737ac
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/CreateSemaphore.c
@@ -0,0 +1,314 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: CreateSemaphoreW_ReleaseSemaphore/test1/CreateSemaphore.c
+**
+** Purpose: Test Semaphore operation using classic IPC problem:
+** "Producer-Consumer Problem".
+**
+** Dependencies: CreateThread
+** ReleaseSemaphore
+** WaitForSingleObject
+** Sleep
+** fflush
+**
+
+**
+**=========================================================*/
+
+#define UNICODE
+#include <palsuite.h>
+
+#define PRODUCTION_TOTAL 26
+
+#define _BUF_SIZE 10
+
+DWORD dwThreadId; /* consumer thread identifier */
+
+HANDLE hThread; /* handle to consumer thread */
+
+HANDLE hSemaphoreM; /* handle to mutual exclusion semaphore */
+
+HANDLE hSemaphoreE; /* handle to semaphore that counts empty buffer slots */
+
+HANDLE hSemaphoreF; /* handle to semaphore that counts full buffer slots */
+
+typedef struct Buffer
+{
+ short readIndex;
+ short writeIndex;
+ CHAR message[_BUF_SIZE];
+
+} BufferStructure;
+
+CHAR producerItems[PRODUCTION_TOTAL + 1];
+
+CHAR consumerItems[PRODUCTION_TOTAL + 1];
+
+/*
+ * Read next message from the Buffer into provided pointer.
+ * Returns: 0 on failure, 1 on success.
+ */
+int
+readBuf(BufferStructure *Buffer, char *c)
+{
+ if( Buffer -> writeIndex == Buffer -> readIndex )
+ {
+ return 0;
+ }
+ *c = Buffer -> message[Buffer -> readIndex++];
+ Buffer -> readIndex %= _BUF_SIZE;
+ return 1;
+}
+
+/*
+ * Write message generated by the producer to Buffer.
+ * Returns: 0 on failure, 1 on success.
+ */
+int
+writeBuf(BufferStructure *Buffer, CHAR c)
+{
+ if( ( ((Buffer -> writeIndex) + 1) % _BUF_SIZE) ==
+ (Buffer -> readIndex) )
+ {
+ return 0;
+ }
+ Buffer -> message[Buffer -> writeIndex++] = c;
+ Buffer -> writeIndex %= _BUF_SIZE;
+ return 1;
+}
+
+/*
+ * Atomic decrement of semaphore value.
+ */
+VOID
+down(HANDLE hSemaphore)
+{
+ switch ( (WaitForSingleObject (
+ hSemaphore,
+ 10000)))
+ {
+ case WAIT_OBJECT_0: /*
+ * Semaphore was signaled. OK to access semaphore.
+ */
+ break;
+ case WAIT_ABANDONED: /*
+ * Object was mutex object whose owning
+ * thread has terminated. Shouldn't occur.
+ */
+ Fail("WaitForSingleObject call returned 'WAIT_ABANDONED'.\n"
+ "Failing Test.\n");
+ break;
+ case WAIT_FAILED: /* WaitForSingleObject function failed */
+ Fail("WaitForSingleObject call returned 'WAIT_FAILED'.\n"
+ "GetLastError returned %d\nFailing Test.\n",GetLastError());
+ break;
+ default:
+ Fail("WaitForSingleObject call returned an unexpected value.\n"
+ "Failing Test.\n");
+ break;
+ }
+
+}
+
+/*
+ * Atomic increment of semaphore value.
+ */
+VOID
+up(HANDLE hSemaphore)
+{
+ if (!ReleaseSemaphore (
+ hSemaphore,
+ 1,
+ NULL)
+ )
+ {
+ Fail("ReleaseSemaphore call failed. GetLastError returned %d\n",
+ GetLastError());
+ }
+}
+
+/*
+ * Sleep 10 milleseconds.
+ */
+VOID
+consumerSleep(VOID)
+{
+ Sleep(10);
+}
+
+/*
+ * Sleep 500 milleseconds.
+ */
+VOID
+producerSleep(VOID)
+{
+ Sleep(500);
+}
+
+/*
+ * Produce a message and write the message to Buffer.
+ */
+VOID
+producer(BufferStructure *Buffer)
+{
+
+ int n = 0;
+ char c;
+
+ while (n < PRODUCTION_TOTAL)
+ {
+ c = 'A' + n ; /* Produce Item */
+
+ down(hSemaphoreE);
+ down(hSemaphoreM);
+
+ if (writeBuf(Buffer, c))
+ {
+ Trace("Producer produces %c.\n", c);
+ fflush(stdout);
+ producerItems[n++] = c;
+ }
+
+ up(hSemaphoreM);
+ up(hSemaphoreF);
+
+ producerSleep();
+ }
+ return;
+}
+
+/*
+ * Read and "Consume" the messages in Buffer.
+ */
+DWORD
+PALAPI
+consumer( LPVOID lpParam )
+{
+ int n = 0;
+ char c;
+
+ consumerSleep();
+
+ while (n < PRODUCTION_TOTAL)
+ {
+
+ down(hSemaphoreF);
+ down(hSemaphoreM);
+
+ if (readBuf((BufferStructure*)lpParam, &c))
+ {
+ Trace("\tConsumer consumes %c.\n", c);
+ fflush(stdout);
+ consumerItems[n++] = c;
+ }
+
+ up(hSemaphoreM);
+ up(hSemaphoreE);
+
+ consumerSleep();
+ }
+ return 0;
+}
+
+int __cdecl main (int argc, char **argv)
+{
+
+ BufferStructure Buffer, *pBuffer;
+
+ pBuffer = &Buffer;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return (FAIL);
+ }
+
+ /*
+ * Create Semaphores
+ */
+ hSemaphoreM = CreateSemaphoreW (
+ NULL,
+ 1,
+ 1,
+ NULL);
+
+ if ( NULL == hSemaphoreM )
+ {
+ Fail ( "hSemaphoreM = CreateSemaphoreW () - returned NULL\n"
+ "Failing Test.\n");
+ }
+
+ hSemaphoreE = CreateSemaphoreW (
+ NULL,
+ _BUF_SIZE ,
+ _BUF_SIZE ,
+ NULL);
+
+ if ( NULL == hSemaphoreE )
+ {
+ Fail ( "hSemaphoreE = CreateSemaphoreW () - returned NULL\n"
+ "Failing Test.\n");
+ }
+
+ hSemaphoreF = CreateSemaphoreW (
+ NULL,
+ 0,
+ _BUF_SIZE ,
+ NULL);
+
+ if ( NULL == hSemaphoreF )
+ {
+ Fail ( "hSemaphoreF = CreateSemaphoreW () - returned NULL\n"
+ "Failing Test.\n");
+ }
+
+ /*
+ * Initialize Buffer
+ */
+ pBuffer->writeIndex = pBuffer->readIndex = 0;
+
+ /*
+ * Create Consumer
+ */
+ hThread = CreateThread(
+ NULL,
+ 0,
+ consumer,
+ &Buffer,
+ 0,
+ &dwThreadId);
+
+ if ( NULL == hThread )
+ {
+ Fail ( "CreateThread() returned NULL. Failing test.\n");
+ }
+
+ /*
+ * Start producing
+ */
+ producer(pBuffer);
+
+ /*
+ * Wait for consumer to complete
+ */
+ WaitForSingleObject (hThread, INFINITE);
+
+ if ( 0 != strncmp (producerItems, consumerItems, PRODUCTION_TOTAL) )
+ {
+ Fail("The producerItems string %s\n and the consumerItems string "
+ "%s\ndo not match. This could be a problem with the strncmp()"
+ " function\n FailingTest\nGetLastError() returned %d\n",
+ producerItems, consumerItems, GetLastError());
+ }
+
+ Trace ("producerItems and consumerItems arrays match. All %d\nitems "
+ "were produced and consumed in order.\nTest passed.\n",
+ PRODUCTION_TOTAL);
+
+ PAL_Terminate();
+ return ( PASS );
+
+}
diff --git a/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/testinfo.dat b/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/testinfo.dat
new file mode 100644
index 0000000000..32b107fd9e
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/testinfo.dat
@@ -0,0 +1,18 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = CreateSemaphoreW / ReleaseSemaphore
+Name = Positive Test for CreateSemaphoreW and ReleaseSemaphore
+TYPE = DEFAULT
+EXE1 = createsemaphore
+Description
+= Implementation of Producer / Consumer IPC problem using CreateSemaphoreW
+= and ReleaseSemaphore functions. This test case exercises CreateSemaphoreW
+= , ReleaseSemaphore, CreateThread and WaitForSingleObject functions.
+= Since there is no way to currently create "pseudo" random events in the
+= pal, this example does not behave as classic bounded buffers would. This
+= test case is designed to starve the producer and have the consumer fill
+= the buffer.
diff --git a/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/CMakeLists.txt
new file mode 100644
index 0000000000..f7f0905761
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ createsemaphore.c
+)
+
+add_executable(paltest_createsemaphorew_releasesemaphore_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createsemaphorew_releasesemaphore_test3 coreclrpal)
+
+target_link_libraries(paltest_createsemaphorew_releasesemaphore_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/createsemaphore.c b/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/createsemaphore.c
new file mode 100644
index 0000000000..ea0a5e0846
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/createsemaphore.c
@@ -0,0 +1,201 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: createsemaphorew_releasesemaphore/test3/createsemaphore.c
+**
+** Purpose: Test attributes of CreateSemaphoreW and ReleaseSemaphore.
+** Insure for CreateSemaphore that lInitialCount and lMaximumCount
+** constraints are respected. Validate that CreateSemaphore rejects
+** conditions where initial count and / or maximum count are negative
+** and conditions where the initial count is greater than the maximum
+** count. For ReleaseSemaphore validate that lpPreviousCount gets set
+** to the previous semaphore count and lpPreviousCount can be NULL.
+** Also establish ReleaseSemaphore fails when called in a semaphore
+** with count equal to lMaximumCount.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+struct testcase
+{
+ LPSECURITY_ATTRIBUTES lpSemaphoreAttributes;
+ LONG lInitialCount;
+ LONG lMaximumCount;
+ LPCWSTR lpName;
+ BOOL bNegativeTest;
+};
+
+struct testcase testCases[] =
+{
+ {NULL, -1, 1, NULL, TRUE},
+ {NULL, 1, -1, NULL, TRUE},
+ {NULL, -1, -1, NULL, TRUE},
+ {NULL, 2, 1, NULL, TRUE},
+ {NULL, 1, 2, NULL, FALSE},
+ {NULL, 0, 10, NULL, FALSE},
+ {NULL, INT_MAX - 1, INT_MAX, NULL, FALSE},
+ {NULL, INT_MAX, INT_MAX, NULL, FALSE}
+};
+
+HANDLE hSemaphore[sizeof(testCases)/sizeof(struct testcase)];
+
+BOOL cleanup(int index)
+{
+ int i;
+ BOOL bRet = TRUE;
+ for (i = 0; i < index; i++)
+ {
+ if (!CloseHandle(hSemaphore[i]))
+ {
+ bRet = FALSE;
+ Trace("PALSUITE ERROR: CloseHandle(%p) call failed for index %d\n",
+ hSemaphore[i], i);
+ }
+ }
+ return(bRet);
+}
+
+int __cdecl main (int argc, char **argv)
+{
+ int i;
+ int j;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return (FAIL);
+ }
+ /* create semaphores */
+ for (i = 0; i < sizeof(testCases)/sizeof(struct testcase); i++)
+ {
+ hSemaphore[i] = CreateSemaphoreW (testCases[i].lpSemaphoreAttributes,
+ testCases[i].lInitialCount,
+ testCases[i].lMaximumCount,
+ testCases[i].lpName);
+
+ if (NULL == hSemaphore[i])
+ {
+ if (!testCases[i].bNegativeTest)
+ {
+ Trace("PALSUITE ERROR: CreateSemaphoreW('%p' '%ld' '%ld' "
+ "'%p') returned NULL at index %d.\nGetLastError "
+ "returned %d.\n", testCases[i].lpSemaphoreAttributes,
+ testCases[i].lInitialCount, testCases[i].lMaximumCount,
+ testCases[i].lpName, i, GetLastError());
+ if (i > 0)
+ {
+ cleanup(i - 1);
+ }
+ Fail("");
+ }
+ else
+ {
+ continue;
+ }
+ }
+
+ /* increment semaphore count to lMaximumCount */
+ for (j = testCases[i].lInitialCount; (ULONG)j <= (ULONG)testCases[i].lMaximumCount;
+ j++)
+ {
+ if (testCases[i].lMaximumCount == j)
+ {
+ /* Call ReleaseSemaphore once more to ensure ReleaseSemaphore
+ fails */
+ if(ReleaseSemaphore(hSemaphore[i], 1, NULL))
+ {
+ Trace("PALSUITE ERROR: ReleaseSemaphore('%p' '%ld' '%p') "
+ "call returned %d\nwhen it should have returned "
+ "%d.\nThe semaphore's count was %d.\nGetLastError "
+ "returned %d.\n", hSemaphore[i], 1, NULL, TRUE,
+ FALSE, j, GetLastError());
+ cleanup(i);
+ Fail("");
+ }
+ }
+ else
+ {
+ int previous;
+ BOOL bRet = ReleaseSemaphore(hSemaphore[i], 1, &previous);
+ DWORD dwError = GetLastError();
+
+ if(!bRet)
+ {
+ Trace("PALSUITE ERROR: ReleaseSemaphore('%p' '%ld' '%p') "
+ "call returned %d\nwhen it should have returned "
+ "%d.\nThe semaphore count was %d and it's "
+ "lMaxCount was %d.\nGetLastError returned %d.\n",
+ hSemaphore[i], 1, &previous, bRet, TRUE, j,
+ testCases[i].lMaximumCount, dwError);
+ cleanup(i);
+ Fail("");
+ }
+ if (previous != j)
+ {
+ Trace("PALSUITE ERROR: ReleaseSemaphore('%p' '%ld' '%p') "
+ "call set %p to %d instead of %d.\n The semaphore "
+ "count was %d and GetLastError returned %d.\n",
+ hSemaphore[i], 1, &previous, &previous, previous,
+ j, j, dwError);
+ cleanup(i);
+ Fail("");
+ }
+ }
+ }
+
+ // Skip exhaustive decrement tests for too large an initial count
+ if(testCases[i].lInitialCount >= INT_MAX - 1)
+ {
+ continue;
+ }
+
+ /* decrement semaphore count to 0 */
+ for (j = testCases[i].lMaximumCount; j >= 0; j--)
+ {
+ DWORD dwRet = WaitForSingleObject(hSemaphore[i], 0);
+ DWORD dwError = GetLastError();
+
+ if (0 == j)
+ {
+ /* WaitForSingleObject should report that the
+ semaphore is nonsignaled */
+ if (WAIT_TIMEOUT != dwRet)
+ {
+ Trace("PALSUITE ERROR: WaitForSingleObject('%p' '%u') "
+ "call returned %d\nwhen it should have returned "
+ "%d.\nThe semaphore's count was %d.\nGetLastError "
+ "returned %d.\n", hSemaphore[i], 0, dwRet,
+ WAIT_TIMEOUT, j, dwError);
+ cleanup(i);
+ Fail("");
+ }
+ }
+ else
+ {
+ /* WaitForSingleObject should report that the
+ semaphore is signaled */
+ if (WAIT_OBJECT_0 != dwRet)
+ {
+ Trace("PALSUITE ERROR: WaitForSingleObject('%p' '%u') "
+ "call returned %d\nwhen it should have returned "
+ "%d.\nThe semaphore's count was %d.\nGetLastError "
+ "returned %d.\n", hSemaphore[i], 0, dwRet,
+ WAIT_OBJECT_0, j, dwError);
+ cleanup(i);
+ Fail("");
+ }
+ }
+ }
+ }
+ PAL_Terminate();
+ return (PASS);
+}
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/testinfo.dat b/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/testinfo.dat
new file mode 100644
index 0000000000..beaac95f97
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/testinfo.dat
@@ -0,0 +1,20 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = CreateSemaphoreW / ReleaseSemaphore
+Name = Positive Test for CreateSemaphoreW and ReleaseSemaphore
+TYPE = DEFAULT
+EXE1 = createsemaphore
+Description
+= Test attributes of CreateSemaphoreW and ReleaseSemaphore.
+= Insure for CreateSemaphore that lInitialCount and lMaximumCount
+= constraints are respected. Validate that CreateSemaphore rejects
+= conditions where, initial count and / or maximum count are negative
+= and conditions where the initial count is greater than the maximum
+= count. For ReleaseSemaphore validate that lpPreviousCount gets set
+= to the previous semaphore count and lpPreviousCount can be NULL.
+= Also establish ReleaseSemaphore fails when called in a semaphore
+= with count equal to lMaximumCount.
diff --git a/src/pal/tests/palsuite/threading/CreateThread/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateThread/CMakeLists.txt
new file mode 100644
index 0000000000..1962ade358
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateThread/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+
diff --git a/src/pal/tests/palsuite/threading/CreateThread/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateThread/test1/CMakeLists.txt
new file mode 100644
index 0000000000..d3921c4409
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateThread/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_createthread_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createthread_test1 coreclrpal)
+
+target_link_libraries(paltest_createthread_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/CreateThread/test1/test1.c b/src/pal/tests/palsuite/threading/CreateThread/test1/test1.c
new file mode 100644
index 0000000000..2dd2f6acb6
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateThread/test1/test1.c
@@ -0,0 +1,119 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test1.c
+**
+** Purpose: Test for CreateThread. Call CreateThread and ensure
+** that it succeeds. Also check to ensure the paramater is passed
+** properly.
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+#ifndef PLATFORM_UNIX
+#define LLFORMAT "%I64u"
+#else
+#define LLFORMAT "%llu"
+#endif
+
+ULONGLONG dwCreateThreadTestParameter = 0;
+
+DWORD PALAPI CreateThreadTestThread( LPVOID lpParameter)
+{
+ DWORD dwRet = 0;
+
+ /* save parameter for test */
+ dwCreateThreadTestParameter = (ULONGLONG)lpParameter;
+
+ return dwRet;
+}
+
+BOOL CreateThreadTest()
+{
+ BOOL bRet = FALSE;
+ DWORD dwRet = 0;
+
+ LPSECURITY_ATTRIBUTES lpThreadAttributes = NULL;
+ DWORD dwStackSize = 0;
+ LPTHREAD_START_ROUTINE lpStartAddress = &CreateThreadTestThread;
+ LPVOID lpParameter = lpStartAddress;
+ DWORD dwCreationFlags = 0; /* run immediately */
+ DWORD dwThreadId = 0;
+
+ HANDLE hThread = 0;
+
+ dwCreateThreadTestParameter = 0;
+
+ /* Create a thread, passing the appropriate paramaters as declared
+ above.
+ */
+
+ hThread = CreateThread( lpThreadAttributes,
+ dwStackSize,
+ lpStartAddress,
+ lpParameter,
+ dwCreationFlags,
+ &dwThreadId );
+
+ /* Ensure that the HANDLE is not invalid! */
+ if (hThread != INVALID_HANDLE_VALUE)
+ {
+ dwRet = WaitForSingleObject(hThread,INFINITE);
+
+ if (dwRet != WAIT_OBJECT_0)
+ {
+ Trace("CreateThreadTest:WaitForSingleObject "
+ "failed (%x)\n",GetLastError());
+ }
+ else
+ {
+ /* Check to ensure that the parameter passed to the thread
+ function is the same in the function as what we passed.
+ */
+
+ if (dwCreateThreadTestParameter != (ULONGLONG)lpParameter)
+ {
+ Trace("CreateThreadTest:parameter error. The "
+ "parameter passed should have been " LLFORMAT " but when "
+ "passed to the Thread function it was " LLFORMAT " . GetLastError[%x]\n",
+ dwCreateThreadTestParameter,lpParameter, GetLastError());
+ }
+ else
+ {
+ bRet = TRUE;
+ }
+
+ }
+ CloseHandle(hThread);
+ }
+ else
+ {
+ Trace("CreateThreadTest:CreateThread failed (%x)\n",GetLastError());
+ }
+
+ return bRet;
+}
+
+
+int __cdecl main(int argc, char **argv)
+{
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ if(!CreateThreadTest())
+ {
+ Fail ("Test failed\n");
+ }
+
+ Trace("Test Passed\n");
+ PAL_Terminate();
+ return ( PASS );
+
+}
diff --git a/src/pal/tests/palsuite/threading/CreateThread/test1/testinfo.dat b/src/pal/tests/palsuite/threading/CreateThread/test1/testinfo.dat
new file mode 100644
index 0000000000..3ae70625c2
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateThread/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = CreateThread
+Name = Positive Test for CreateThread
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Test for CreateThread. Call CreateThread and ensure
+= that it succeeds. Also check to ensure the paramater is passed
+= properly.
diff --git a/src/pal/tests/palsuite/threading/CreateThread/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateThread/test2/CMakeLists.txt
new file mode 100644
index 0000000000..350cf66e9b
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateThread/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_createthread_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createthread_test2 coreclrpal)
+
+target_link_libraries(paltest_createthread_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/CreateThread/test2/test2.c b/src/pal/tests/palsuite/threading/CreateThread/test2/test2.c
new file mode 100644
index 0000000000..f64c32ea87
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateThread/test2/test2.c
@@ -0,0 +1,184 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*===========================================================
+**
+** Source: test2.c
+**
+** Purpose: Test that lpThreadId is assigned the correct
+** threadId value and that lpThreadId can be NULL.
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+#define NUM_TESTS 3
+
+HANDLE hThread[NUM_TESTS];
+DWORD dwThreadId[NUM_TESTS];
+volatile BOOL bResult[NUM_TESTS];
+volatile DWORD dwThreadId1[NUM_TESTS];
+
+DWORD PALAPI Thread( LPVOID lpParameter)
+{
+ dwThreadId1[(DWORD) lpParameter] = GetCurrentThreadId();
+ bResult[(DWORD) lpParameter] = TRUE;
+ return (DWORD) lpParameter;
+}
+
+struct testCase
+{
+ LPSECURITY_ATTRIBUTES lpThreadAttributes;
+ DWORD dwStackSize;
+ LPTHREAD_START_ROUTINE lpStartAddress;
+ DWORD dwCreationFlags;
+ LPVOID lpThreadId;
+};
+
+struct testCase testCases[]=
+{
+ {NULL, 0, &Thread, 0, NULL},
+ {NULL, 0, &Thread, CREATE_SUSPENDED, NULL},
+ {NULL, 0, &Thread, 0, (LPVOID) 1}
+};
+
+/*
+ * close handles
+ */
+BOOL cleanup(int index)
+{
+ int i;
+ BOOL bRet = TRUE;
+
+ for (i = 0; i < index; i++)
+ {
+ if (!CloseHandle(hThread[i]))
+ {
+ bRet = FALSE;
+ Trace("PALSUITE ERROR: CloseHandle(%p) call failed for index %d\n",
+ hThread[i], i);
+ }
+ }
+
+ return(bRet);
+}
+
+int __cdecl main(int argc, char **argv)
+{
+ SIZE_T i;
+ DWORD dwRetWFSO;
+ DWORD dwRetRT;
+ BOOL bRet = TRUE;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return (FAIL);
+ }
+
+ /* set results array to FALSE */
+ for (i = 0; i < NUM_TESTS; i++)
+ {
+ bResult[i]=FALSE;
+ dwThreadId[i]=0;
+ }
+
+ for (i = 0; i < NUM_TESTS; i++)
+ {
+ if (NULL != testCases[i].lpThreadId)
+ {
+ testCases[i].lpThreadId = &dwThreadId[i];
+ }
+ /* pass the index as the thread argument */
+ hThread[i] = CreateThread( testCases[i].lpThreadAttributes,
+ testCases[i].dwStackSize,
+ testCases[i].lpStartAddress,
+ (LPVOID) i,
+ testCases[i].dwCreationFlags,
+ testCases[i].lpThreadId);
+ if (hThread[i] == NULL)
+ {
+ Trace("PALSUITE ERROR: CreateThread('%p' '%d' '%p' '%p' '%d' "
+ "'%p') call failed.\nGetLastError returned '%u'.\n",
+ testCases[i].lpThreadAttributes, testCases[i].dwStackSize,
+ testCases[i].lpStartAddress, (LPVOID) i,
+ testCases[i].dwCreationFlags,
+ testCases[i].lpThreadId, GetLastError());
+ cleanup(i - 1);
+ Fail("");
+ }
+
+ /* Resume suspended threads */
+ if (testCases[i].dwCreationFlags == CREATE_SUSPENDED)
+ {
+ dwRetRT = ResumeThread (hThread[i]);
+ if (dwRetRT != 1)
+ {
+ Trace ("PALSUITE ERROR: ResumeThread(%p) "
+ "call returned %d it should have returned %d.\n"
+ "GetLastError returned %u.\n", hThread[i], dwRetRT,
+ 1, GetLastError());
+ cleanup(i);
+ Fail("");
+ }
+ }
+ }
+
+ /* cleanup */
+ for (i = 0; i < NUM_TESTS; i++)
+ {
+ dwRetWFSO = WaitForSingleObject(hThread[i], 10000);
+ if (dwRetWFSO != WAIT_OBJECT_0)
+ {
+ Trace ("PALSUITE ERROR: WaitForSingleObject('%p' '%d') "
+ "call returned %d instead of WAIT_OBJECT_0 ('%d').\n"
+ "GetLastError returned %u.\n", hThread[i], 10000,
+ dwRetWFSO, WAIT_OBJECT_0, GetLastError());
+ cleanup(i);
+ Fail("");
+ }
+ }
+ if(!cleanup(NUM_TESTS))
+ {
+ Fail("");
+ }
+
+ for (i = 0; i < NUM_TESTS; i++)
+ {
+ /*
+ * check to see that all threads were created and were passed
+ * the array index as an argument.
+ */
+ if (FALSE == bResult[i])
+ {
+ bRet = FALSE;
+ Trace("PALSUITE ERROR: result[%d]=%d. It should be %d\n", i,
+ FALSE, TRUE);
+ }
+ /*
+ * check to see that lpThreadId received the correct value.
+ */
+ if (0 != dwThreadId[i])
+ {
+ if (dwThreadId[i] != dwThreadId1[i])
+ {
+ bRet = FALSE;
+ Trace("PALSUITE ERROR: dwThreadId[%d]=%p and dwThreadId1[%d]"
+ "=%p\nThese values should be identical.\n", i,
+ dwThreadId[i], i, dwThreadId1[i]);
+ }
+ }
+ }
+ if (!bRet)
+ {
+ cleanup(NUM_TESTS);
+ Fail("");
+ }
+
+ PAL_Terminate();
+ return (PASS);
+}
+
+
+
diff --git a/src/pal/tests/palsuite/threading/CreateThread/test2/testinfo.dat b/src/pal/tests/palsuite/threading/CreateThread/test2/testinfo.dat
new file mode 100644
index 0000000000..0333beb360
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateThread/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = CreateThread
+Name = Positive Test for CreateThread
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Test that lpThreadId is assigned the correct threadId value and
+= that lpThreadId can be NULL.
diff --git a/src/pal/tests/palsuite/threading/CreateThread/test3/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateThread/test3/CMakeLists.txt
new file mode 100644
index 0000000000..923d7a72ab
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateThread/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_createthread_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_createthread_test3 coreclrpal)
+
+target_link_libraries(paltest_createthread_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/CreateThread/test3/test3.c b/src/pal/tests/palsuite/threading/CreateThread/test3/test3.c
new file mode 100644
index 0000000000..0c44d1fdd0
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateThread/test3/test3.c
@@ -0,0 +1,101 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*===========================================================
+**
+** Source: test3.c
+**
+** Purpose: Check to see that the handle CreateThread returns
+** can be closed while the thread is still running.
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+HANDLE hThread;
+HANDLE hEvent;
+
+DWORD PALAPI Thread( LPVOID lpParameter)
+{
+ DWORD dwRet;
+ dwRet = WaitForSingleObject(hEvent, INFINITE);
+ /* if this thread continues beyond here, fail */
+ Fail("");
+
+ return 0;
+}
+
+int __cdecl main(int argc, char **argv)
+{
+ DWORD dwThreadId;
+ DWORD dwRet;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return (FAIL);
+ }
+
+ hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ if (hEvent == NULL)
+ {
+ Fail("PALSUITE ERROR: CreateEvent call #0 failed. GetLastError "
+ "returned %u.\n", GetLastError());
+ }
+
+ /* pass the index as the thread argument */
+ hThread = CreateThread( NULL,
+ 0,
+ &Thread,
+ (LPVOID) 0,
+ 0,
+ &dwThreadId);
+ if (hThread == NULL)
+ {
+ Trace("PALSUITE ERROR: CreateThread('%p' '%d' '%p' '%p' '%d' '%p') "
+ "call failed.\nGetLastError returned '%u'.\n", NULL,
+ 0, &Thread, (LPVOID) 0, 0, &dwThreadId, GetLastError());
+ if (0 == CloseHandle(hEvent))
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during "
+ "clean up.\nGetLastError returned '%u'.\n", hEvent);
+ }
+ Fail("");
+ }
+
+ dwRet = WaitForSingleObject(hThread, 10000);
+ if (dwRet != WAIT_TIMEOUT)
+ {
+ Trace ("PALSUITE ERROR: WaitForSingleObject('%p' '%d') "
+ "call returned %d instead of WAIT_TIMEOUT ('%d').\n"
+ "GetLastError returned '%u'.\n", hThread, 10000,
+ dwRet, WAIT_TIMEOUT, GetLastError());
+ Fail("");
+ }
+
+ if (0 == CloseHandle(hThread))
+ {
+ Trace("PALSUITE ERROR: Unable to CloseHandle(%p) on a running thread."
+ "\nGetLastError returned '%u'.\n", hThread, GetLastError());
+ if (0 == CloseHandle(hEvent))
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during "
+ "cleanup.\nGetLastError returned '%u'.\n", hEvent,
+ GetLastError());
+ }
+ Fail("");
+ }
+ if (0 == CloseHandle(hEvent))
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during "
+ "cleanup.\nGetLastError returned '%u'.\n", hEvent,
+ GetLastError());
+ Fail("");
+ }
+
+ PAL_Terminate();
+ return (PASS);
+}
+
diff --git a/src/pal/tests/palsuite/threading/CreateThread/test3/testinfo.dat b/src/pal/tests/palsuite/threading/CreateThread/test3/testinfo.dat
new file mode 100644
index 0000000000..712c3a6652
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CreateThread/test3/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = CreateThread
+Name = Positive Test for CreateThread
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Check to see that the handle CreateThread returns can be closed while
+= the thread is still running.
+
diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/CMakeLists.txt b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/CMakeLists.txt
new file mode 100644
index 0000000000..b7c6e394b0
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/CMakeLists.txt
@@ -0,0 +1,11 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+add_subdirectory(test7)
+add_subdirectory(test8)
+
diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/CMakeLists.txt
new file mode 100644
index 0000000000..5ba04fd801
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ InitializeCriticalSection.c
+)
+
+add_executable(paltest_criticalsectionfunctions_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_criticalsectionfunctions_test1 coreclrpal)
+
+target_link_libraries(paltest_criticalsectionfunctions_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/InitializeCriticalSection.c b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/InitializeCriticalSection.c
new file mode 100644
index 0000000000..f294cea472
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/InitializeCriticalSection.c
@@ -0,0 +1,235 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: criticalsectionfunctions/test1/initializecriticalsection.c
+**
+** Purpose: Test Semaphore operation using classic IPC problem:
+** "Producer-Consumer Problem".
+**
+** Dependencies: CreateThread
+** InitializeCriticalSection
+** EnterCriticalSection
+** LeaveCriticalSection
+** DeleteCriticalSection
+** WaitForSingleObject
+** Sleep
+**
+
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+#define PRODUCTION_TOTAL 26
+
+#define _BUF_SIZE 10
+
+DWORD dwThreadId; /* consumer thread identifier */
+
+HANDLE hThread; /* handle to consumer thread */
+
+CRITICAL_SECTION CriticalSectionM; /* Critical Section Object (used as mutex) */
+
+typedef struct Buffer
+{
+ short readIndex;
+ short writeIndex;
+ CHAR message[_BUF_SIZE];
+
+} BufferStructure;
+
+CHAR producerItems[PRODUCTION_TOTAL + 1];
+
+CHAR consumerItems[PRODUCTION_TOTAL + 1];
+
+/*
+ * Read next message from the Buffer into provided pointer.
+ * Returns: 0 on failure, 1 on success.
+ */
+int
+readBuf(BufferStructure *Buffer, char *c)
+{
+ if( Buffer -> writeIndex == Buffer -> readIndex )
+ {
+ return 0;
+ }
+ *c = Buffer -> message[Buffer -> readIndex++];
+ Buffer -> readIndex %= _BUF_SIZE;
+ return 1;
+}
+
+/*
+ * Write message generated by the producer to Buffer.
+ * Returns: 0 on failure, 1 on success.
+ */
+int
+writeBuf(BufferStructure *Buffer, CHAR c)
+{
+ if( ( ((Buffer -> writeIndex) + 1) % _BUF_SIZE) ==
+ (Buffer -> readIndex) )
+ {
+ return 0;
+ }
+ Buffer -> message[Buffer -> writeIndex++] = c;
+ Buffer -> writeIndex %= _BUF_SIZE;
+ return 1;
+}
+
+/*
+ * Sleep 500 milleseconds.
+ */
+VOID
+consumerSleep(VOID)
+{
+ Sleep(500);
+}
+
+/*
+ * Sleep between 10 milleseconds.
+ */
+VOID
+producerSleep(VOID)
+{
+ Sleep(10);
+}
+
+/*
+ * Produce a message and write the message to Buffer.
+ */
+VOID
+producer(BufferStructure *Buffer)
+{
+
+ int n = 0;
+ char c;
+
+ while (n < PRODUCTION_TOTAL)
+ {
+ c = 'A' + n ; /* Produce Item */
+
+ EnterCriticalSection(&CriticalSectionM);
+
+ if (writeBuf(Buffer, c))
+ {
+ printf("Producer produces %c.\n", c);
+ producerItems[n++] = c;
+ }
+
+ LeaveCriticalSection(&CriticalSectionM);
+
+ producerSleep();
+ }
+
+ return;
+}
+
+/*
+ * Read and "Consume" the messages in Buffer.
+ */
+DWORD
+PALAPI
+consumer( LPVOID lpParam )
+{
+ int n = 0;
+ char c;
+
+ consumerSleep();
+
+ while (n < PRODUCTION_TOTAL)
+ {
+
+ EnterCriticalSection(&CriticalSectionM);
+
+ if (readBuf((BufferStructure*)lpParam, &c))
+ {
+ printf("\tConsumer consumes %c.\n", c);
+ consumerItems[n++] = c;
+ }
+
+ LeaveCriticalSection(&CriticalSectionM);
+
+ consumerSleep();
+ }
+
+ return 0;
+}
+
+int __cdecl main (int argc, char **argv)
+{
+
+ BufferStructure Buffer, *pBuffer;
+
+ pBuffer = &Buffer;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /*
+ * Create mutual exclusion mechanisms
+ */
+
+ InitializeCriticalSection ( &CriticalSectionM );
+
+ /*
+ * Initialize Buffer
+ */
+ pBuffer->writeIndex = pBuffer->readIndex = 0;
+
+
+
+ /*
+ * Create Consumer
+ */
+ hThread = CreateThread(
+ NULL,
+ 0,
+ consumer,
+ &Buffer,
+ 0,
+ &dwThreadId);
+
+ if ( NULL == hThread )
+ {
+ Fail ( "CreateThread() returned NULL. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+ /*
+ * Start producing
+ */
+ producer(pBuffer);
+
+ /*
+ * Wait for consumer to complete
+ */
+ WaitForSingleObject (hThread, INFINITE);
+
+ /*
+ * Compare items produced vs. items consumed
+ */
+ if ( 0 != strncmp (producerItems, consumerItems, PRODUCTION_TOTAL) )
+ {
+ Fail("The producerItems string %s\n and the consumerItems string "
+ "%s\ndo not match. This could be a problem with the strncmp()"
+ " function\n FailingTest\nGetLastError() returned %d\n",
+ producerItems, consumerItems, GetLastError());
+ }
+
+ /*
+ * Clean up Critical Section object
+ */
+ DeleteCriticalSection(&CriticalSectionM);
+
+ Trace("producerItems and consumerItems arrays match. All %d\nitems "
+ "were produced and consumed in order.\nTest passed.\n",
+ PRODUCTION_TOTAL);
+
+ PAL_Terminate();
+ return (PASS);
+
+}
diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/testinfo.dat b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/testinfo.dat
new file mode 100644
index 0000000000..494b899b90
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/testinfo.dat
@@ -0,0 +1,21 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = InitializeCriticalSection / EnterCriticalSection / LeaveCriticalSection / DeleteCriticalSection
+Name = Positive Test for InitializeCriticalSection, EnterCriticalSection, LeaveCriticalSection and DeleteCriticalSection
+TYPE = DEFAULT
+EXE1 = initializecriticalsection
+Description
+= Implementation of Producer / Consumer IPC problem using the
+= "CriticalSection" functions to provide a mutual exclusion mechanism.
+= This test case exercises InitializeCriticalSection, EnterCriticalSection,
+= LeaveCriticalSection, DeleteCriticalSection, and WaitForSingleObject
+= functions.
+= This case doesn't work with more than one producer and one consumer.
+= The producer thread and consumer thread each take turns blocking on
+= the CriticalSection object and do not have any other synchronization
+= mechanisms. This prevents adding producers or consumers as there are
+= no mechanisms to block them once the buffer is full.
diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/CMakeLists.txt
new file mode 100644
index 0000000000..d26658cf5d
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_criticalsectionfunctions_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_criticalsectionfunctions_test2 coreclrpal)
+
+target_link_libraries(paltest_criticalsectionfunctions_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/test2.c b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/test2.c
new file mode 100644
index 0000000000..47659a1c18
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/test2.c
@@ -0,0 +1,226 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: CriticalSectionFunctions/test2/test2.c
+**
+** Purpose: Test that we are able to nest critical section calls.
+** The initial thread makes a call to EnterCriticalSection once,
+** blocking on a CRITICAL_SECTION object and creates a new thread.
+** The newly created thread blocks on the same CRITICAL_SECTION object.
+** The first thread now makes a call to LeaveCriticalSection.
+** Test to see that the new thread doesn't get unblocked.
+**
+** Dependencies: CreateThread
+** InitializeCriticalSection
+** EnterCriticalSection
+** LeaveCriticalSection
+** DeleteCriticalSection
+** WaitForSingleObject
+**
+
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+CRITICAL_SECTION CriticalSection;
+
+volatile BOOL t0_tflag = FAIL; /* thread 0 timeout flag */
+volatile BOOL t1_aflag = FAIL; /* thread 1 access flag */
+volatile BOOL t1_cflag = FAIL; /* thread 1 critical section flag */
+volatile BOOL bTestResult = FAIL;
+
+DWORD PALAPI Thread(LPVOID lpParam)
+{
+ t1_aflag = PASS;
+ EnterCriticalSection(&CriticalSection);
+ t1_cflag = PASS;
+ LeaveCriticalSection(&CriticalSection);
+ return 0;
+}
+
+int __cdecl main (int argc, char **argv)
+{
+ HANDLE hThread;
+ DWORD dwThreadId;
+ DWORD dwRet;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return (bTestResult);
+ }
+
+ /*
+ * Create critical section object and enter it
+ */
+ InitializeCriticalSection ( &CriticalSection );
+ EnterCriticalSection(&CriticalSection);
+
+ /*
+ * Create a suspended thread
+ */
+ hThread = CreateThread(NULL,
+ 0,
+ &Thread,
+ (LPVOID) NULL,
+ CREATE_SUSPENDED,
+ &dwThreadId);
+
+ if (hThread == NULL)
+ {
+ Trace("PALSUITE ERROR: CreateThread call failed. GetLastError "
+ "returned %d.\n", GetLastError());
+ LeaveCriticalSection(&CriticalSection);
+ DeleteCriticalSection(&CriticalSection);
+ Fail("");
+ }
+
+ EnterCriticalSection(&CriticalSection);
+ /*
+ * Set priority of the thread to greater than that of the currently
+ * running thread so it is guaranteed to run.
+ */
+ dwRet = (DWORD) SetThreadPriority(hThread, THREAD_PRIORITY_ABOVE_NORMAL);
+
+ if (0 == dwRet)
+ {
+ Trace("PALSUITE ERROR: SetThreadPriority (%p, %d) call failed.\n"
+ "GetLastError returned %d.\n", hThread,
+ THREAD_PRIORITY_NORMAL, GetLastError());
+ LeaveCriticalSection(&CriticalSection);
+ CloseHandle(hThread);
+ DeleteCriticalSection(&CriticalSection);
+ Fail("");
+ }
+
+ dwRet = ResumeThread(hThread);
+
+ if (-1 == dwRet)
+ {
+ Trace("PALSUITE ERROR: ResumeThread(%p) call failed.\nGetLastError "
+ "returned %d.\n", hThread, GetLastError());
+ LeaveCriticalSection(&CriticalSection);
+ CloseHandle(hThread);
+ DeleteCriticalSection(&CriticalSection);
+ Fail("");
+ }
+ /*
+ * Sleep until we know the thread has been invoked. This sleep in
+ * combination with the higher priority of the other thread should
+ * guarantee both threads block on the critical section.
+ */
+ while (t1_aflag == FAIL)
+ {
+ Sleep(1);
+ }
+
+ LeaveCriticalSection(&CriticalSection);
+
+ switch ((WaitForSingleObject(
+ hThread,
+ 10000))) /* Wait 10 seconds */
+ {
+ case WAIT_OBJECT_0:
+ /* Object (thread) is signaled */
+ LeaveCriticalSection(&CriticalSection);
+ CloseHandle(hThread);
+ DeleteCriticalSection(&CriticalSection);
+ Fail("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have "
+ "returned\nWAIT_TIMEOUT ('%d'), instead it returned "
+ "WAIT_OBJECT_0 ('%d').\nA nested LeaveCriticalSection(%p) "
+ "call released both threads that were waiting on it!\n",
+ hThread, 10000, WAIT_TIMEOUT, WAIT_OBJECT_0, &CriticalSection);
+ break;
+ case WAIT_ABANDONED:
+ /*
+ * Object was mutex object whose owning
+ * thread has terminated. Shouldn't occur.
+ */
+ Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have "
+ "returned\nWAIT_TIMEOUT ('%d'), instead it returned "
+ "WAIT_ABANDONED ('%d').\nGetLastError returned '%d'\n",
+ hThread, 10000, WAIT_TIMEOUT, WAIT_ABANDONED, GetLastError());
+ LeaveCriticalSection(&CriticalSection);
+ CloseHandle(hThread);
+ DeleteCriticalSection(&CriticalSection);
+ Fail("");
+ break;
+ case WAIT_FAILED: /* WaitForSingleObject function failed */
+ Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have "
+ "returned\nWAIT_TIMEOUT ('%d'), instead it returned "
+ "WAIT_FAILED ('%d').\nGetLastError returned '%d'\n",
+ hThread, 10000, WAIT_TIMEOUT, WAIT_FAILED, GetLastError());
+ LeaveCriticalSection(&CriticalSection);
+ CloseHandle(hThread);
+ DeleteCriticalSection(&CriticalSection);
+ Fail("");
+ break;
+ case WAIT_TIMEOUT:
+ /*
+ * We expect this thread to timeout waiting for the
+ * critical section object to become available.
+ */
+ t0_tflag = PASS;
+ break;
+ }
+
+ LeaveCriticalSection(&CriticalSection);
+
+ if (WAIT_OBJECT_0 != WaitForSingleObject (hThread, 10000))
+ {
+ if (0 == CloseHandle(hThread))
+ {
+ Trace("PALSUITE ERROR: CloseHandle(%p) call failed.\n"
+ "WaitForSingleObject(%p,%d) should have returned "
+ "WAIT_OBJECT_0 ('%d').\nBoth calls failed. "
+ "Deleted CRITICAL_SECTION object which likely means\n"
+ "thread %p is now in an undefined state. GetLastError "
+ "returned '%d'.\n", hThread, hThread, 10000, WAIT_OBJECT_0,
+ hThread, GetLastError());
+ DeleteCriticalSection(&CriticalSection);
+ Fail("");
+ }
+ else
+ {
+ Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have "
+ "returned WAIT_OBJECT_0 ('%d').\n GetLastError returned "
+ "'%d'.\n", hThread, hThread, 10000, WAIT_OBJECT_0,
+ hThread, GetLastError());
+ DeleteCriticalSection(&CriticalSection);
+ Fail("");
+ }
+ }
+
+ if (0 == CloseHandle(hThread))
+ {
+ Trace("PALSUITE ERROR: CloseHandle(%p) call failed.\n"
+ "Deleted CRITICAL_SECTION object which likely means\n"
+ "thread %p is now in an undefined state. GetLastError "
+ "returned '%d'.\n", hThread, hThread, GetLastError());
+ DeleteCriticalSection(&CriticalSection);
+ Fail("");
+
+ }
+ DeleteCriticalSection(&CriticalSection);
+ /*
+ * Ensure both thread 0 experienced a wait timeout and thread 1
+ * accessed the critical section or fail the test, otherwise pass it.
+ */
+ if ((t0_tflag == FAIL) || (t1_cflag == FAIL))
+ {
+ Trace("PALSUITE ERROR: Thread 0 returned %d when %d was expected.\n"
+ "Thread 1 returned %d when %d was expected.\n", t0_tflag,
+ PASS, t1_cflag, PASS);
+ bTestResult=FAIL;
+ }
+ else
+ {
+ bTestResult=PASS;
+ }
+
+ PAL_TerminateEx(bTestResult);
+ return (bTestResult);
+}
diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/testinfo.dat b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/testinfo.dat
new file mode 100644
index 0000000000..06842124b9
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/testinfo.dat
@@ -0,0 +1,18 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = CriticalSectionFunctions
+Name = Positive test to ensure CRITICAL_SECTION objects can be nested
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Test that we are able to nest critical section calls.
+= The initial thread makes a call to EnterCriticalSection once,
+= blocking on a CRITICAL_SECTION object and creates a new thread.
+= The newly created thread blocks on the same CRITICAL_SECTION object.
+= The first thread now makes a call to LeaveCriticalSection.
+= Test to see that the new thread doesn't get unblocked.
+
diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/CMakeLists.txt b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/CMakeLists.txt
new file mode 100644
index 0000000000..8bd2a72878
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_criticalsectionfunctions_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_criticalsectionfunctions_test3 coreclrpal)
+
+target_link_libraries(paltest_criticalsectionfunctions_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/test3.c b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/test3.c
new file mode 100644
index 0000000000..d5911267b2
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/test3.c
@@ -0,0 +1,376 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: CriticalSectionFunctions/test3/test3.c
+**
+** Purpose: Create two threads to exercise TryEnterCriticalSection
+** and EnterCriticalSection. TryEnterCriticalSection acquires
+** and holds a CRITICAL_SECTION object. Another call to
+** TryEnterCriticalSection is made from a different thread, at
+** this time, to establish a call to TryEnterCriticalSection
+** will return immediatly and to establish
+** TryEnterCriticalSection returns the proper value when it
+** attempts to lock a CRITICAL_SECTION that is already owned
+** by another thread. The CRITICAL_SECTION object is then
+** released and held by a call to EnterCriticalSection. A new
+** thread is invoked and attempts to acquire the held
+** CRITICAL_SECTION with a call to TryEnterCriticalSection.
+** TryEnterCriticalSection returns immediatly and returns
+** with the value that states the CRITICAL_SECTION object is
+** held by another thread. This establishes
+** TryEnterCriticalSection behaves the same way with
+** CriticalSections locked by TryEnterCriticalSection and
+** EnterCriticalSection.
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+#define NUM_THREADS 2
+
+HANDLE hThread[NUM_THREADS];
+HANDLE hEvent[NUM_THREADS];
+CRITICAL_SECTION CriticalSection;
+BOOL bRet = FAIL;
+
+DWORD PALAPI Thread(LPVOID lpParam)
+{
+ DWORD dwRet;
+
+ if (0 == TryEnterCriticalSection(&CriticalSection))
+ {
+ dwRet = WaitForMultipleObjects(NUM_THREADS, hEvent, TRUE, 10000);
+ if ((WAIT_OBJECT_0 > dwRet) ||
+ ((WAIT_OBJECT_0 + NUM_THREADS - 1) < dwRet))
+ {
+#if 0
+ if (0 == CloseHandle(hThread[1]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) "
+ "during clean up.\nGetLastError returned '%d'.\n",
+ hThread[1], GetLastError());
+ }
+#endif
+ Trace("PALSUITE ERROR: WaitForMultipleObjects(%d, %p, %d, %d) call"
+ "returned an unexpected value, '%d'.\nGetLastError returned "
+ "%d.\n", NUM_THREADS, hEvent, TRUE, 10000, dwRet,
+ GetLastError());
+ }
+ else
+ {
+ bRet = PASS;
+ }
+ }
+ else
+ {
+ /* signal thread 0 */
+ if (0 == SetEvent(hEvent[0]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute SetEvent(%p) during "
+ "clean up.\nGetLastError returned '%d'.\n", hEvent[0],
+ GetLastError());
+ LeaveCriticalSection(&CriticalSection);
+ if (0 == CloseHandle(hThread[0]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) "
+ "during clean up\nGetLastError returned '%d'.\n",
+ hThread[0], GetLastError());
+ }
+ if (0 == CloseHandle(hEvent[0]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) "
+ "during clean up\nGetLastError returned '%d'.\n",
+ hEvent[0], GetLastError());
+ }
+ if (0 == CloseHandle(hEvent[1]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) "
+ "during clean up\nGetLastError returned '%d'.\n",
+ hEvent[1], GetLastError());
+ }
+ DeleteCriticalSection(&CriticalSection);
+ Fail("");
+ }
+
+ /* wait to be signaled */
+ dwRet = WaitForSingleObject(hEvent[1], 10000);
+ if (WAIT_OBJECT_0 != dwRet)
+ {
+ Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have "
+ "returned\nWAIT_OBJECT_0 ('%d'), instead it returned "
+ "('%d').\nGetLastError returned '%d'.\n",
+ hEvent[0], 10000, WAIT_OBJECT_0, dwRet, GetLastError());
+ if (0 == CloseHandle(hThread[0]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) "
+ "during clean up.\nGetLastError returned '%d'.\n",
+ hThread[0], GetLastError());
+ }
+ if (0 == CloseHandle(hEvent[0]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) "
+ "during clean up.\nGetLastError returned '%d'.\n",
+ hEvent[0], GetLastError());
+ }
+ if (0 == CloseHandle(hEvent[1]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) "
+ "during clean up.\nGetLastError returned '%d.'\n",
+ hEvent[1], GetLastError());
+ }
+ DeleteCriticalSection(&CriticalSection);
+ Fail("");
+ }
+ LeaveCriticalSection(&CriticalSection);
+ }
+ return FAIL;
+}
+
+int __cdecl main(int argc, char **argv)
+{
+ HANDLE hThread[NUM_THREADS];
+ DWORD dwThreadId[NUM_THREADS];
+ DWORD dwRet;
+
+ if ((PAL_Initialize(argc,argv)) != 0)
+ {
+ return(bRet);
+ }
+
+ /* thread 0 event */
+ hEvent[0] = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ if (hEvent[0] == NULL)
+ {
+ Fail("PALSUITE ERROR: CreateEvent call #0 failed. GetLastError "
+ "returned %d.\n", GetLastError());
+ }
+
+ /* thread 1 event */
+ hEvent[1] = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ if (hEvent[1] == NULL)
+ {
+ Trace("PALSUITE ERROR: CreateEvent call #1 failed. GetLastError "
+ "returned %d.\n", GetLastError());
+ if (0 == CloseHandle(hEvent[0]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during "
+ "clean up.\nGetLastError returned '%d'.\n", hEvent[0]);
+ }
+ Fail("");
+ }
+
+ InitializeCriticalSection ( &CriticalSection );
+
+ hThread[0] = CreateThread(NULL,
+ 0,
+ &Thread,
+ (LPVOID) NULL,
+ 0,
+ &dwThreadId[0]);
+
+ if (hThread[0] == NULL)
+ {
+ Trace("PALSUITE ERROR: CreateThread call #0 failed. GetLastError "
+ "returned %d.\n", GetLastError());
+ if (0 == CloseHandle(hEvent[0]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during "
+ "clean up.\nGetLastError returned '%d'.\n", hEvent[0],
+ GetLastError());
+ }
+ if (0 == CloseHandle(hEvent[1]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during "
+ "clean up.\nGetLastError returned '%d'.\n", hEvent[1],
+ GetLastError());
+ }
+ DeleteCriticalSection(&CriticalSection);
+ Fail("");
+ }
+
+
+ /* wait for thread 0 to be signaled */
+ dwRet = WaitForSingleObject(hEvent[0], 10000);
+ if (WAIT_OBJECT_0 != dwRet)
+ {
+ Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have "
+ "returned\nWAIT_OBJECT_0 ('%d'), instead it returned "
+ "('%d').\nGetLastError returned '%d'.\n", hEvent[0], 10000,
+ WAIT_OBJECT_0, dwRet, GetLastError());
+ if (0 == CloseHandle(hThread[0]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during "
+ "clean up.\nGetLastError returned '%d'.\n", hThread[0],
+ GetLastError());
+ }
+ if (0 == CloseHandle(hEvent[0]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during "
+ "clean up.\nGetLastError returned '%d'.\n", hEvent[0],
+ GetLastError());
+ }
+ if (0 == CloseHandle(hEvent[1]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during "
+ "clean up.\nGetLastError returned '%d'.\n", hEvent[1],
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ /*
+ * Attempting to enter CRITICAL_SECTION object owned by the
+ * created thread and locked with TryEnterCriticalSection
+ */
+ if (0 == TryEnterCriticalSection(&CriticalSection))
+ {
+ /* signal thread 1 */
+ if (0 == SetEvent(hEvent[1]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute SetEvent(%p) call.\n"
+ "GetLastError returned '%d'.\n", hEvent[1],
+ GetLastError());
+ goto done;
+ }
+ }
+ else
+ {
+ Trace("PALSUITE_ERROR: TryEnterCriticalSection was able to grab a"
+ " CRITICAL_SECTION object\nwhich was already owned.\n");
+ LeaveCriticalSection(&CriticalSection);
+ if (0 == CloseHandle(hThread[0]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during "
+ "clean up.\nGetLastError returned '%d'.\n", hThread[0],
+ GetLastError());
+ }
+ if (0 == CloseHandle(hEvent[0]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during "
+ "clean up.\nGetLastError returned '%d'.\n", hEvent[0],
+ GetLastError());
+ }
+ if (0 == CloseHandle(hEvent[1]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during "
+ "clean up.\nGetLastError returned '%d'.\n", hEvent[1],
+ GetLastError());
+ }
+ DeleteCriticalSection(&CriticalSection);
+ Fail("");
+ }
+ /*
+ * Enter the CRITICAL_SECTION and launch another thread to attempt
+ * to access the CRITICAL_SECTION with a call to TryEnterCriticalSection.
+ */
+ EnterCriticalSection(&CriticalSection);
+
+ hThread[1] = CreateThread(NULL,
+ 0,
+ &Thread,
+ (LPVOID) NULL,
+ 0,
+ &dwThreadId[1]);
+
+ if (hThread[1] == NULL)
+ {
+ Trace("PALSUITE ERROR: CreateThread call #1 failed. GetLastError "
+ "returned %d.\n", GetLastError());
+ LeaveCriticalSection(&CriticalSection);
+ if (0 == CloseHandle(hThread[0]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during "
+ "clean up.\nGetLastError returned '%d'.\n", hThread[0],
+ GetLastError());
+ }
+ if (0 == CloseHandle(hEvent[0]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during "
+ "clean up.\nGetLastError returned '%d'.\n", hEvent[0],
+ GetLastError());
+ }
+ if (0 == CloseHandle(hEvent[1]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during "
+ "clean up.\nGetLastError returned '%d'.\n", hEvent[1],
+ GetLastError());
+ }
+ DeleteCriticalSection(&CriticalSection);
+ Fail("");
+ }
+
+ dwRet = WaitForMultipleObjects(NUM_THREADS, hThread, TRUE, 10000);
+ if ((WAIT_OBJECT_0 > dwRet) ||
+ ((WAIT_OBJECT_0 + NUM_THREADS - 1) < dwRet))
+ {
+ Trace("PALSUITE ERROR: WaitForMultipleObjects(%d, %p, %d, %d) call "
+ "returned an unexpected value, '%d'.\nGetLastError returned "
+ "%d.\n", NUM_THREADS, hThread, TRUE, 10000, dwRet,
+ GetLastError());
+ LeaveCriticalSection(&CriticalSection);
+ if (0 == CloseHandle(hThread[0]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during "
+ "clean up.\nGetLastError returned '%d'.\n", hThread[0],
+ GetLastError());
+ }
+ if (0 == CloseHandle(hThread[1]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during "
+ "clean up.\nGetLastError returned '%d'.\n", hThread[1],
+ GetLastError());
+ }
+ if (0 == CloseHandle(hEvent[0]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during "
+ "clean up.\nGetLastError returned '%d'.\n", hEvent[0],
+ GetLastError());
+ }
+ if (0 == CloseHandle(hEvent[1]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during "
+ "clean up.\nGetLastError returned '%d'.\n", hEvent[1],
+ GetLastError());
+ }
+ DeleteCriticalSection(&CriticalSection);
+ Fail("");
+ }
+
+ LeaveCriticalSection(&CriticalSection);
+ if (0 == CloseHandle(hThread[1]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during "
+ "clean up.\nGetLastError returned '%d'.\n", hThread[1],
+ GetLastError());
+ }
+done:
+ if (0 == CloseHandle(hThread[0]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during "
+ "clean up.\nGetLastError returned '%d'.\n", hThread[0],
+ GetLastError());
+ }
+ if (0 == CloseHandle(hEvent[0]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during "
+ "clean up.\nGetLastError returned '%d'.\n", hEvent[0],
+ GetLastError());
+ }
+ if (0 == CloseHandle(hEvent[1]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during "
+ "clean up.\nGetLastError returned '%d'.\n", hEvent[1],
+ GetLastError());
+ }
+ DeleteCriticalSection(&CriticalSection);
+
+ PAL_TerminateEx(bRet);
+
+ return (bRet);
+}
+
diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/testinfo.dat b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/testinfo.dat
new file mode 100644
index 0000000000..818b4870a2
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/testinfo.dat
@@ -0,0 +1,29 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = CriticalSectionFunctions
+Name = Positive Test for TryEnterCriticalSection
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Create two threads to exercise TryEnterCriticalSection
+= and EnterCriticalSection. TryEnterCriticalSection acquires
+= and holds a CRITICAL_SECTION object. Another call to
+= TryEnterCriticalSection is made from a different thread, at
+= this time, to establish a call to TryEnterCriticalSection
+= will return immediatly and to establish
+= TryEnterCriticalSection returns the proper value when it
+= attempts to lock a CRITICAL_SECTION that is already owned
+= by another thread. The CRITICAL_SECTION object is then
+= released and held by a call to EnterCriticalSection. A new
+= thread is invoked and attempts to acquire the held
+= CRITICAL_SECTION with a call to TryEnterCriticalSection.
+= TryEnterCriticalSection returns immediatly and returns
+= with the value that states the CRITICAL_SECTION object is
+= held by another thread. This establishes
+= TryEnterCriticalSection behaves the same way with
+= CriticalSections locked by TryEnterCriticalSection and
+= EnterCriticalSection.
diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/CMakeLists.txt b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/CMakeLists.txt
new file mode 100644
index 0000000000..0626631640
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_criticalsectionfunctions_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_criticalsectionfunctions_test4 coreclrpal)
+
+target_link_libraries(paltest_criticalsectionfunctions_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/test4.c b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/test4.c
new file mode 100644
index 0000000000..8a245a4776
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/test4.c
@@ -0,0 +1,241 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: criticalsectionfunctions/test4/test4.c
+**
+** Purpose: Test to see if threads blocked on a CRITICAL_SECTION object will
+** be released in an orderly manner. This case looks at the following
+** scenario. If one thread owns a CRITICAL_SECTION object and two threads
+** block in EnterCriticalSection, trying to hold the already owned
+** CRITICAL_SECTION object, when the first thread releases the CRITICAL_SECTION
+** object, will one and only one of the waiters get unblocked?
+**
+** Dependencies: CreateThread
+** InitializeCriticalSection
+** EnterCriticalSection
+** LeaveCriticalSection
+** DeleteCriticalSection
+** Sleep
+** WaitForSingleObject
+**
+
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+#define NUM_BLOCKING_THREADS 2
+
+BOOL bTestResult;
+CRITICAL_SECTION CriticalSection;
+HANDLE hThread[NUM_BLOCKING_THREADS];
+HANDLE hEvent;
+DWORD dwThreadId[NUM_BLOCKING_THREADS];
+volatile int flags[NUM_BLOCKING_THREADS] = {0,0};
+
+DWORD PALAPI ThreadTest1(LPVOID lpParam)
+{
+
+ EnterCriticalSection ( &CriticalSection );
+
+ flags[0] = 1;
+
+ return 0;
+
+}
+
+DWORD PALAPI ThreadTest2(LPVOID lpParam)
+{
+
+ EnterCriticalSection ( &CriticalSection );
+
+ flags[1] = 1;
+
+ return 0;
+
+}
+
+int __cdecl main(int argc, char **argv)
+{
+
+ DWORD dwRet;
+ DWORD dwRet1;
+ bTestResult = FAIL;
+
+ if ((PAL_Initialize(argc,argv)) != 0)
+ {
+ return(bTestResult);
+ }
+
+ /*
+ * Create Critical Section Object
+ */
+ InitializeCriticalSection ( &CriticalSection );
+
+ EnterCriticalSection ( &CriticalSection );
+
+ hThread[0] = CreateThread(NULL,
+ 0,
+ &ThreadTest1,
+ (LPVOID) 0,
+ CREATE_SUSPENDED,
+ &dwThreadId[0]);
+ if (hThread[0] == NULL)
+ {
+ Trace("PALSUITE ERROR: CreateThread(%p, %d, %p, %p, %d, %p) call "
+ "failed.\nGetLastError returned %d.\n", NULL, 0, &ThreadTest1,
+ (LPVOID) 0, CREATE_SUSPENDED, &dwThreadId[0], GetLastError());
+ LeaveCriticalSection(&CriticalSection);
+ DeleteCriticalSection ( &CriticalSection );
+ Fail("");
+ }
+
+ hThread[1] = CreateThread(NULL,
+ 0,
+ &ThreadTest2,
+ (LPVOID) 0,
+ CREATE_SUSPENDED,
+ &dwThreadId[1]);
+ if (hThread[1] == NULL)
+ {
+ Trace("PALSUITE ERROR: CreateThread(%p, %d, %p, %p, %d, %p) call "
+ "failed.\nGetLastError returned %d.\n", NULL, 0, &ThreadTest2,
+ (LPVOID) 0, CREATE_SUSPENDED, &dwThreadId[1], GetLastError());
+ LeaveCriticalSection(&CriticalSection);
+
+ dwRet = ResumeThread(hThread[0]);
+ if (-1 == dwRet)
+ {
+ Trace("PALSUITE ERROR: ResumeThread(%p) call failed.\n"
+ "GetLastError returned '%d'.\n", hThread[0],
+ GetLastError());
+ }
+
+ dwRet = WaitForSingleObject(hThread[0], 10000);
+ if (WAIT_OBJECT_0 == dwRet)
+ {
+ Trace("PALSUITE ERROR: WaitForSingleObject(%p, %d) call "
+ "failed. '%d' was returned instead of the expected '%d'.\n"
+ "GetLastError returned '%d'.\n", hThread[0], 10000, dwRet,
+ WAIT_OBJECT_0, GetLastError());
+ }
+
+ if (0 == CloseHandle(hThread[0]))
+ {
+ Trace("PALSUITE NOTIFICATION: CloseHandle(%p) call failed.\n"
+ "GetLastError returned %d. Not failing tests.\n",
+ hThread[0], GetLastError());
+ }
+
+ DeleteCriticalSection(&CriticalSection);
+ Fail("");
+ }
+
+ /*
+ * Set other thread priorities to be higher than ours & Sleep to ensure
+ * we give up the processor.
+ */
+ dwRet = (DWORD) SetThreadPriority(hThread[0],
+ THREAD_PRIORITY_ABOVE_NORMAL);
+ if (0 == dwRet)
+ {
+ Trace("PALSUITE ERROR: SetThreadPriority(%p, %d) call failed.\n"
+ "GetLastError returned %d", hThread[0],
+ THREAD_PRIORITY_ABOVE_NORMAL, GetLastError());
+ }
+
+ dwRet = (DWORD) SetThreadPriority(hThread[1],
+ THREAD_PRIORITY_ABOVE_NORMAL);
+ if (0 == dwRet)
+ {
+ Trace("PALSUITE ERROR: SetThreadPriority(%p, %d) call failed.\n"
+ "GetLastError returned %d", hThread[1],
+ THREAD_PRIORITY_ABOVE_NORMAL, GetLastError());
+ }
+
+ dwRet = ResumeThread(hThread[0]);
+ if (-1 == dwRet)
+ {
+ Trace("PALSUITE ERROR: ResumeThread(%p, %d) call failed.\n"
+ "GetLastError returned %d", hThread[0],
+ GetLastError() );
+ }
+
+ dwRet = ResumeThread(hThread[1]);
+ if (-1 == dwRet)
+ {
+ Trace("PALSUITE ERROR: ResumeThread(%p, %d) call failed.\n"
+ "GetLastError returned %d", hThread[0],
+ GetLastError());
+ }
+
+ Sleep (0);
+
+ LeaveCriticalSection (&CriticalSection);
+
+ dwRet = WaitForSingleObject(hThread[0], 10000);
+ dwRet1 = WaitForSingleObject(hThread[1], 10000);
+
+ if ((WAIT_OBJECT_0 == dwRet) ||
+ (WAIT_OBJECT_0 == dwRet1))
+ {
+ if ((1 == flags[0] && 0 == flags[1]) ||
+ (0 == flags[0] && 1 == flags[1]))
+ {
+ bTestResult = PASS;
+ }
+ else
+ {
+ bTestResult = FAIL;
+ Trace ("PALSUITE ERROR: flags[%d] = {%d,%d}. These values are"
+ "inconsistent.\nCriticalSection test failed.\n",
+ NUM_BLOCKING_THREADS, flags[0], flags[1]);
+ }
+
+ /* Fail the test if both threads returned WAIT_OBJECT_0 */
+ if ((WAIT_OBJECT_0 == dwRet) && (WAIT_OBJECT_0 == dwRet1))
+ {
+ bTestResult = FAIL;
+ Trace ("PALSUITE ERROR: WaitForSingleObject(%p, %d) and "
+ "WaitForSingleObject(%p, %d)\nboth returned dwRet = '%d'\n"
+ "One should have returned WAIT_TIMEOUT ('%d').\n",
+ hThread[0], 10000, hThread[1], 10000, dwRet, WAIT_TIMEOUT);
+ }
+ }
+ else
+ {
+ bTestResult = FAIL;
+ Trace ("PALSUITE ERROR: WaitForSingleObject(%p, %d) and "
+ "WaitForSingleObject(%p, %d)\nReturned dwRet = '%d' and\n"
+ "dwRet1 = '%d' respectively.\n", hThread[0], 10000, hThread[1],
+ 10000, dwRet, dwRet1);
+ }
+
+ if (WAIT_OBJECT_0 == dwRet)
+ {
+ if (0 == CloseHandle(hThread[0]))
+ {
+ Trace("PALSUITE NOTIFICATION: CloseHandle(%p) call failed.\n"
+ "GetLastError returned %d. Not failing tests.\n",
+ hThread[0], GetLastError());
+ }
+ }
+ if (WAIT_OBJECT_0 == dwRet1)
+ {
+ if (0 == CloseHandle(hThread[1]))
+ {
+ Trace("PALSUITE NOTIFICATION: CloseHandle(%p) call failed.\n"
+ "GetLastError returned %d. Not failing tests.\n",
+ hThread[1], GetLastError());
+ }
+ }
+
+ /* Leaking the CS on purpose, since there is still a thread
+ waiting on it */
+
+ PAL_TerminateEx(bTestResult);
+ return (bTestResult);
+}
diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/testinfo.dat b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/testinfo.dat
new file mode 100644
index 0000000000..9c07c24113
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = LeaveCriticalSection
+Name = Positive test to ensure CRITICAL_SECTION objects are released properly
+TYPE = DEFAULT
+EXE1 = test4
+Description
+= Test to see if threads blocked on a CRITICAL_SECTION object will
+= be released in an orderly manner. This case looks at the following
+= scenario. If one thread owns a CRITICAL_SECTION object and two threads
+= block in EnterCriticalSection, trying to hold the already owned
+= CRITICAL_SECTION object, when the first thread releases the CRITICAL_SECTION
+= object, will one and only one of the waiters get unblocked?
diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/CMakeLists.txt b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/CMakeLists.txt
new file mode 100644
index 0000000000..37d709f121
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test5.c
+)
+
+add_executable(paltest_criticalsectionfunctions_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_criticalsectionfunctions_test5 coreclrpal)
+
+target_link_libraries(paltest_criticalsectionfunctions_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/test5.c b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/test5.c
new file mode 100644
index 0000000000..8dfa4f5f3d
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/test5.c
@@ -0,0 +1,187 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: CriticalSectionFunctions/test5/test5.c
+**
+** Purpose: Attempt to delete a critical section owned by another
+** thread.
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+/*
+ * Tokens 0 and 1 are events. Token 2 is the thread.
+ */
+#define NUM_TOKENS 3
+
+HANDLE hToken[NUM_TOKENS];
+CRITICAL_SECTION CriticalSection;
+
+BOOL CleanupHelper (HANDLE *hArray, DWORD dwIndex)
+{
+ BOOL bCHRet;
+
+ bCHRet = CloseHandle(hArray[dwIndex]);
+ if (!bCHRet)
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during "
+ "clean up.\nGetLastError returned '%u'.\n", hArray[dwIndex],
+ GetLastError());
+ }
+
+ return (bCHRet);
+}
+
+BOOL Cleanup(HANDLE *hArray, DWORD dwIndex)
+{
+ BOOL bCRet;
+ BOOL bCHRet = FALSE;
+
+ while (--dwIndex > 0)
+ {
+ bCHRet = CleanupHelper(&hArray[0], dwIndex);
+ }
+
+ bCRet = CloseHandle(hArray[0]);
+ if (!bCRet)
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during "
+ "clean up.\nGetLastError returned '%u'.\n", hArray[dwIndex],
+ GetLastError());
+ }
+
+ return (bCRet&&bCHRet);
+}
+
+DWORD PALAPI Thread(LPVOID lpParam)
+{
+ DWORD dwTRet;
+
+ EnterCriticalSection(&CriticalSection);
+
+ /* signal thread 0 */
+ if (0 == SetEvent(hToken[0]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute SetEvent(%p) during "
+ "clean up.\nGetLastError returned '%u'.\n", hToken[0],
+ GetLastError());
+ LeaveCriticalSection(&CriticalSection);
+ Cleanup (&hToken[0], NUM_TOKENS);
+ DeleteCriticalSection(&CriticalSection);
+ Fail("");
+ }
+
+ /* wait to be signaled */
+ dwTRet = WaitForSingleObject(hToken[1], 10000);
+ if (WAIT_OBJECT_0 != dwTRet)
+
+ {
+ Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have "
+ "returned\nWAIT_OBJECT_0 ('%d'), instead it returned "
+ "('%d').\nGetLastError returned '%u'.\n",
+ hToken[1], 10000, WAIT_OBJECT_0, dwTRet, GetLastError());
+ LeaveCriticalSection(&CriticalSection);
+ Cleanup (&hToken[0], NUM_TOKENS);
+ DeleteCriticalSection(&CriticalSection);
+ Fail("");
+ }
+
+ LeaveCriticalSection(&CriticalSection);
+ return 0;
+}
+
+int __cdecl main(int argc, char **argv)
+{
+ DWORD dwThreadId;
+ DWORD dwMRet;
+
+ if ((PAL_Initialize(argc,argv)) != 0)
+ {
+ return(FAIL);
+ }
+
+ /* thread 0 event */
+ hToken[0] = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (NULL == hToken[0])
+ {
+ Fail("PALSUITE ERROR: CreateEvent call #0 failed. GetLastError "
+ "returned %u.\n", GetLastError());
+ }
+
+ /* thread 1 event */
+ hToken[1] = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (NULL == hToken[1])
+ {
+ Trace("PALSUITE ERROR: CreateEvent call #1 failed. GetLastError "
+ "returned %u.\n", GetLastError());
+ Cleanup(&hToken[0], (NUM_TOKENS - 2));
+ Fail("");
+ }
+
+ InitializeCriticalSection(&CriticalSection);
+
+ hToken[2] = CreateThread(NULL,
+ 0,
+ &Thread,
+ (LPVOID) NULL,
+ 0,
+ &dwThreadId);
+ if (hToken[2] == NULL)
+ {
+ Trace("PALSUITE ERROR: CreateThread call #0 failed. GetLastError "
+ "returned %u.\n", GetLastError());
+ Cleanup(&hToken[0], (NUM_TOKENS - 1));
+ DeleteCriticalSection(&CriticalSection);
+ Fail("");
+ }
+
+ /* wait for thread 0 to be signaled */
+ dwMRet = WaitForSingleObject(hToken[0], 10000);
+ if (WAIT_OBJECT_0 != dwMRet)
+ {
+ Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have "
+ "returned\nWAIT_OBJECT_0 ('%d'), instead it returned "
+ "('%d').\nGetLastError returned '%u'.\n", hToken[0], 10000,
+ WAIT_OBJECT_0, dwMRet, GetLastError());
+ Cleanup(&hToken[0], NUM_TOKENS);
+ Fail("");
+ }
+
+ /*
+ * Attempt to do delete CriticalSection object owned by other thread
+ */
+ DeleteCriticalSection(&CriticalSection);
+
+ /* signal thread 1 */
+ if (0 == SetEvent(hToken[1]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute SetEvent(%p) call.\n"
+ "GetLastError returned '%u'.\n", hToken[1],
+ GetLastError());
+ Cleanup(&hToken[0], NUM_TOKENS);
+ Fail("");
+ }
+
+ dwMRet = WaitForSingleObject(hToken[2], 10000);
+ if (WAIT_OBJECT_0 != dwMRet)
+ {
+ Trace("PALSUITE ERROR: WaitForSingleObject(%p, %d) call "
+ "returned an unexpected value '%d'.\nGetLastError returned "
+ "%u.\n", hToken[2], 10000, dwMRet, GetLastError());
+ Cleanup(&hToken[0], NUM_TOKENS);
+ Fail("");
+ }
+
+ if (!Cleanup(&hToken[0], NUM_TOKENS))
+ {
+ Fail("");
+ }
+
+ PAL_Terminate();
+
+ return (PASS);
+}
diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/testinfo.dat b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/testinfo.dat
new file mode 100644
index 0000000000..aa1124925b
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = CriticalSectionFunctions
+Name = Positive test for DeleteCriticalSection
+TYPE = DEFAULT
+EXE1 = test5
+Description
+= Attempt to delete a critical section owned by another thread.
diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/CMakeLists.txt b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/CMakeLists.txt
new file mode 100644
index 0000000000..c580fdbd6b
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test6.c
+)
+
+add_executable(paltest_criticalsectionfunctions_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_criticalsectionfunctions_test6 coreclrpal)
+
+target_link_libraries(paltest_criticalsectionfunctions_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/test6.c b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/test6.c
new file mode 100644
index 0000000000..c27db86e5b
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/test6.c
@@ -0,0 +1,190 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: CriticalSectionFunctions/test6/test6.c
+**
+** Purpose: Attempt to leave a critical section which is owned by
+** another thread.
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+/*
+ * Tokens 0 and 1 are events. Token 2 is the thread.
+ */
+#define NUM_TOKENS 3
+
+HANDLE hToken[NUM_TOKENS];
+CRITICAL_SECTION CriticalSection;
+
+BOOL CleanupHelper (HANDLE *hArray, DWORD dwIndex)
+{
+ BOOL bCHRet;
+
+ bCHRet = CloseHandle(hArray[dwIndex]);
+ if (!bCHRet)
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during "
+ "clean up.\nGetLastError returned '%u'.\n", hArray[dwIndex],
+ GetLastError());
+ }
+
+ return (bCHRet);
+}
+
+BOOL Cleanup(HANDLE *hArray, DWORD dwIndex)
+{
+ BOOL bCRet;
+ BOOL bCHRet;
+
+ while (--dwIndex > 0)
+ {
+ bCHRet = CleanupHelper(&hArray[0], dwIndex);
+ }
+
+ bCRet = CloseHandle(hArray[0]);
+ if (!bCRet)
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during "
+ "clean up.\nGetLastError returned '%u'.\n", hArray[dwIndex],
+ GetLastError());
+ }
+
+ return (bCRet&&bCHRet);
+}
+
+DWORD PALAPI Thread(LPVOID lpParam)
+{
+ DWORD dwTRet;
+
+ EnterCriticalSection(&CriticalSection);
+
+ /* signal thread 0 */
+ if (0 == SetEvent(hToken[0]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute SetEvent(%p) during "
+ "clean up.\nGetLastError returned '%u'.\n", hToken[0],
+ GetLastError());
+ LeaveCriticalSection(&CriticalSection);
+ Cleanup (&hToken[0], NUM_TOKENS);
+ DeleteCriticalSection(&CriticalSection);
+ Fail("");
+ }
+
+ /* wait to be signaled */
+ dwTRet = WaitForSingleObject(hToken[1], 10000);
+ if (WAIT_OBJECT_0 != dwTRet)
+ {
+ Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have "
+ "returned\nWAIT_OBJECT_0 ('%d'), instead it returned "
+ "('%d').\nGetLastError returned '%u'.\n",
+ hToken[1], 10000, WAIT_OBJECT_0, dwTRet, GetLastError());
+ LeaveCriticalSection(&CriticalSection);
+ Cleanup (&hToken[0], NUM_TOKENS);
+ DeleteCriticalSection(&CriticalSection);
+ Fail("");
+ }
+
+ LeaveCriticalSection(&CriticalSection);
+
+ return 0;
+}
+
+int __cdecl main(int argc, char **argv)
+{
+ DWORD dwThreadId;
+ DWORD dwMRet;
+
+ if ((PAL_Initialize(argc,argv)) != 0)
+ {
+ return(FAIL);
+ }
+
+ /* thread 0 event */
+ hToken[0] = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ if (hToken[0] == NULL)
+ {
+ Fail("PALSUITE ERROR: CreateEvent call #0 failed. GetLastError "
+ "returned %u.\n", GetLastError());
+ }
+
+ /* thread 1 event */
+ hToken[1] = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ if (hToken[1] == NULL)
+ {
+ Trace("PALSUITE ERROR: CreateEvent call #1 failed. GetLastError "
+ "returned %u.\n", GetLastError());
+ Cleanup(&hToken[0], (NUM_TOKENS - 2));
+ Fail("");
+ }
+
+ InitializeCriticalSection(&CriticalSection);
+
+ hToken[2] = CreateThread(NULL,
+ 0,
+ &Thread,
+ (LPVOID) NULL,
+ 0,
+ &dwThreadId);
+
+ if (hToken[2] == NULL)
+ {
+ Trace("PALSUITE ERROR: CreateThread call #0 failed. GetLastError "
+ "returned %u.\n", GetLastError());
+ Cleanup(&hToken[0], (NUM_TOKENS - 1));
+ DeleteCriticalSection(&CriticalSection);
+ Fail("");
+ }
+
+ /* wait for thread 0 to be signaled */
+ dwMRet = WaitForSingleObject(hToken[0], 10000);
+ if (WAIT_OBJECT_0 != dwMRet)
+ {
+ Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have "
+ "returned\nWAIT_OBJECT_0 ('%d'), instead it returned "
+ "('%d').\nGetLastError returned '%u'.\n", hToken[0], 10000,
+ WAIT_OBJECT_0, dwMRet, GetLastError());
+ Cleanup(&hToken[0], NUM_TOKENS);
+ Fail("");
+ }
+
+ /*
+ * Attempt to leave critical section which is owned by the other thread.
+ */
+ LeaveCriticalSection(&CriticalSection);
+
+ /* signal thread 1 */
+ if (0 == SetEvent(hToken[1]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute SetEvent(%p) call.\n"
+ "GetLastError returned '%u'.\n", hToken[1],
+ GetLastError());
+ Cleanup(&hToken[0], NUM_TOKENS);
+ Fail("");
+ }
+
+ dwMRet = WaitForSingleObject(hToken[2], 10000);
+ if (WAIT_OBJECT_0 != dwMRet)
+ {
+ Trace("PALSUITE ERROR: WaitForSingleObject(%p, %d) call "
+ "returned an unexpected value '%d'.\nGetLastError returned "
+ "%u.\n", hToken[2], 10000, dwMRet, GetLastError());
+ Cleanup(&hToken[0], NUM_TOKENS);
+ Fail("");
+ }
+
+ if (!Cleanup(&hToken[0], NUM_TOKENS))
+ {
+ Fail("");
+ }
+
+ PAL_Terminate();
+
+ return(PASS);
+}
diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/testinfo.dat b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/testinfo.dat
new file mode 100644
index 0000000000..151e1ed4d0
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = CriticalSectionFunctions
+Name = Positive Test for LeaveCriticalSection
+TYPE = DEFAULT
+EXE1 = test6
+Description
+= Attempt to leave a critical section which is owned by another thread.
diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/CMakeLists.txt b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/CMakeLists.txt
new file mode 100644
index 0000000000..0a12bfe3ef
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test7.c
+)
+
+add_executable(paltest_criticalsectionfunctions_test7
+ ${SOURCES}
+)
+
+add_dependencies(paltest_criticalsectionfunctions_test7 coreclrpal)
+
+target_link_libraries(paltest_criticalsectionfunctions_test7
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/test7.c b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/test7.c
new file mode 100644
index 0000000000..1c030d3c03
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/test7.c
@@ -0,0 +1,188 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: CriticalSectionFunctions/test7/test7.c
+**
+** Purpose: Attempt to delete a critical section owned by the current
+** thread.
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+/*
+ * Tokens 0 and 1 are events. Token 2 is the thread.
+ */
+#define NUM_TOKENS 3
+
+HANDLE hToken[NUM_TOKENS];
+CRITICAL_SECTION CriticalSection;
+
+BOOL CleanupHelper (HANDLE *hArray, DWORD dwIndex)
+{
+ BOOL bCHRet;
+
+ bCHRet = CloseHandle(hArray[dwIndex]);
+ if (!bCHRet)
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during "
+ "clean up.\nGetLastError returned '%u'.\n", hArray[dwIndex],
+ GetLastError());
+ }
+
+ return (bCHRet);
+}
+
+BOOL Cleanup(HANDLE *hArray, DWORD dwIndex)
+{
+ BOOL bCRet;
+ BOOL bCHRet = 0;
+
+ while (--dwIndex > 0)
+ {
+ bCHRet = CleanupHelper(&hArray[0], dwIndex);
+ }
+
+ bCRet = CloseHandle(hArray[0]);
+ if (!bCRet)
+ {
+ Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during "
+ "clean up.\nGetLastError returned '%u'.\n", hArray[dwIndex],
+ GetLastError());
+ }
+
+ return (bCRet&&bCHRet);
+}
+
+DWORD PALAPI Thread(LPVOID lpParam)
+{
+ DWORD dwTRet;
+
+ EnterCriticalSection(&CriticalSection);
+
+ /* signal thread 0 */
+ if (0 == SetEvent(hToken[0]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute SetEvent(%p) during "
+ "clean up.\nGetLastError returned '%u'.\n", hToken[0],
+ GetLastError());
+ LeaveCriticalSection(&CriticalSection);
+ Cleanup (&hToken[0], NUM_TOKENS);
+ DeleteCriticalSection(&CriticalSection);
+ Fail("");
+ }
+
+ /* wait to be signaled */
+ dwTRet = WaitForSingleObject(hToken[1], 10000);
+ if (WAIT_OBJECT_0 != dwTRet)
+ {
+ Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have "
+ "returned\nWAIT_OBJECT_0 ('%d'), instead it returned "
+ "('%d').\nGetLastError returned '%u'.\n",
+ hToken[0], 10000, WAIT_OBJECT_0, dwTRet, GetLastError());
+ LeaveCriticalSection(&CriticalSection);
+ Cleanup (&hToken[0], NUM_TOKENS);
+ DeleteCriticalSection(&CriticalSection);
+ Fail("");
+ }
+
+ DeleteCriticalSection(&CriticalSection);
+
+ return 0;
+}
+
+int __cdecl main(int argc, char **argv)
+{
+ DWORD dwThreadId;
+ DWORD dwMRet;
+
+ if ((PAL_Initialize(argc,argv)) != 0)
+ {
+ return(FAIL);
+ }
+
+ /* thread 0 event */
+ hToken[0] = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ if (hToken[0] == NULL)
+ {
+ Fail("PALSUITE ERROR: CreateEvent call #0 failed. GetLastError "
+ "returned %u.\n", GetLastError());
+ }
+
+ /* thread 1 event */
+ hToken[1] = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ if (hToken[1] == NULL)
+ {
+ Trace("PALSUITE ERROR: CreateEvent call #1 failed. GetLastError "
+ "returned %u.\n", GetLastError());
+ Cleanup (&hToken[0], (NUM_TOKENS - 2));
+ Fail("");
+ }
+
+ InitializeCriticalSection(&CriticalSection);
+
+ hToken[2] = CreateThread(NULL,
+ 0,
+ &Thread,
+ (LPVOID) NULL,
+ 0,
+ &dwThreadId);
+
+ if (hToken[2] == NULL)
+ {
+ Trace("PALSUITE ERROR: CreateThread call #0 failed. GetLastError "
+ "returned %u.\n", GetLastError());
+ Cleanup (&hToken[0], (NUM_TOKENS - 1));
+ DeleteCriticalSection(&CriticalSection);
+ Fail("");
+ }
+
+ /* wait for thread 0 to be signaled */
+ dwMRet = WaitForSingleObject(hToken[0], 10000);
+ if (WAIT_OBJECT_0 != dwMRet)
+ {
+ Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have "
+ "returned\nWAIT_OBJECT_0 ('%d'), instead it returned "
+ "('%d').\nGetLastError returned '%u'.\n", hToken[0], 10000,
+ WAIT_OBJECT_0, dwMRet, GetLastError());
+ Cleanup (&hToken[0], NUM_TOKENS);
+ Fail("");
+ }
+
+ /* signal thread 1 */
+ if (0 == SetEvent(hToken[1]))
+ {
+ Trace("PALSUITE ERROR: Unable to execute SetEvent(%p) call.\n"
+ "GetLastError returned '%u'.\n", hToken[1],
+ GetLastError());
+ Cleanup (&hToken[0], NUM_TOKENS);
+ Fail("");
+ }
+
+ dwMRet = WaitForSingleObject(hToken[2], 10000);
+ if (WAIT_OBJECT_0 != dwMRet)
+ {
+ Trace("PALSUITE ERROR: WaitForSingleObject(%p, %d) call "
+ "returned an unexpected value '%d'.\nGetLastError returned "
+ "%u.\n", hToken[2], 10000, dwMRet, GetLastError());
+ Cleanup (&hToken[0], NUM_TOKENS);
+ Fail("");
+ }
+
+ if (!Cleanup(&hToken[0], NUM_TOKENS))
+ {
+ Fail("");
+ }
+
+ PAL_Terminate();
+
+ return (PASS);
+}
+
+
+
diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/testinfo.dat b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/testinfo.dat
new file mode 100644
index 0000000000..5cf5809622
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = CriticalSectionFunctions
+Name = Positive test for DeleteCriticalSection
+TYPE = DEFAULT
+EXE1 = test7
+Description
+= Attempt to delete a critical section owned by the current thread.
diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/CMakeLists.txt b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/CMakeLists.txt
new file mode 100644
index 0000000000..0d95a95410
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test8.c
+)
+
+add_executable(paltest_criticalsectionfunctions_test8
+ ${SOURCES}
+)
+
+add_dependencies(paltest_criticalsectionfunctions_test8 coreclrpal)
+
+target_link_libraries(paltest_criticalsectionfunctions_test8
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/test8.c b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/test8.c
new file mode 100644
index 0000000000..7f0c58cd26
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/test8.c
@@ -0,0 +1,217 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: CriticalSectionFunctions/test8/test8.c
+**
+** Pyrpose: Ensure critical section functionality is working by
+** having multiple threads racing on a CS under different
+** scenarios
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+#define MAX_THREAD_COUNT 128
+#define DEFAULT_THREAD_COUNT 10
+#define DEFAULT_LOOP_COUNT 1000
+
+#ifndef MIN
+#define MIN(a,b) (((a)<(b)) ? (a) : (b))
+#endif
+
+int g_iThreadCount = DEFAULT_THREAD_COUNT;
+int g_iLoopCount = DEFAULT_LOOP_COUNT;
+volatile LONG g_lCriticalCount = 0;
+HANDLE g_hEvStart = NULL;
+
+CRITICAL_SECTION g_cs;
+DWORD PALAPI Thread(LPVOID lpParam)
+{
+ int i, j, iLpCnt;
+ DWORD dwRet = 0;
+ DWORD dwTid = GetCurrentThreadId();
+ LONG lRet;
+ BOOL bSleepInside;
+ BOOL bSleepOutside;
+
+ Trace("[tid=%u] Thread starting\n", dwTid);
+
+ dwRet = WaitForSingleObject(g_hEvStart, INFINITE);
+ if (WAIT_OBJECT_0 != dwRet)
+ {
+ Fail("WaitForSingleObject returned unexpected %u [GetLastError()=%u]\n",
+ dwRet, GetLastError());
+ }
+
+ for (j=0;j<8;j++)
+ {
+ bSleepInside = 2 & j;
+ bSleepOutside = 4 & j;
+
+ iLpCnt = g_iLoopCount;
+ if (bSleepInside || bSleepOutside)
+ {
+ iLpCnt /= 10;
+ }
+
+ for (i=0;i<iLpCnt;i++)
+ {
+ EnterCriticalSection(&g_cs);
+ if (1 & i)
+ {
+ // Simple increment on odd iterations
+ lRet = (g_lCriticalCount += 1);
+ }
+ else
+ {
+ // Interlocked increment on even iterations
+ lRet = InterlockedIncrement(&g_lCriticalCount);
+ }
+
+ if (1 != lRet || 1 != g_lCriticalCount)
+ {
+ Fail("Detected %d threads in area protected by critical section "
+ "[expected: 1 thread]\n", g_lCriticalCount);
+ }
+ if (bSleepInside)
+ {
+ Sleep(rand()%10);
+ }
+ if (1 != g_lCriticalCount)
+ {
+ Fail("Detected %d threads inside area protected by critical section "
+ "[expected: 1 thread]\n", (int)g_lCriticalCount);
+ }
+
+ if (1 & i)
+ {
+ // Simple decrement on odd iterations
+ lRet = (g_lCriticalCount -= 1);
+ }
+ else
+ {
+ // Interlocked decrement on even iterations
+ lRet = InterlockedDecrement(&g_lCriticalCount);
+ }
+ LeaveCriticalSection(&g_cs);
+
+ if (bSleepOutside)
+ {
+ Sleep(rand()%10);
+ }
+ }
+ }
+
+ Trace("[tid=%u] Thread done\n", dwTid);
+
+ return 0;
+}
+
+int __cdecl main(int argc, char **argv)
+{
+ DWORD dwThreadId;
+ DWORD dwRet;
+ HANDLE hThreads[MAX_THREAD_COUNT] = { 0 };
+ int iThreadCount = 0;
+ int i, iVal;
+
+ if ((PAL_Initialize(argc,argv)) != 0)
+ {
+ return(FAIL);
+ }
+
+ srand(time(NULL));
+
+ for (i=1; i<argc; i++)
+ {
+ if ('-' == *argv[i])
+ {
+ switch(*(argv[i]+1))
+ {
+ case 'n':
+ if (i < argc-1)
+ {
+ i += 1;
+ iVal = atoi(argv[i]);
+ if (0 < iVal)
+ {
+ g_iLoopCount = iVal;
+ }
+ }
+ break;
+ case 't':
+ if (i < argc-1)
+ {
+ i += 1;
+ iVal = atoi(argv[i]);
+ if (0 < iVal && MAX_THREAD_COUNT >= iVal)
+ {
+ g_iThreadCount = iVal;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ Trace ("Iterations:\t%d\n", g_iLoopCount);
+ Trace ("Threads:\t%d\n", g_iThreadCount);
+
+ g_hEvStart = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ if (g_hEvStart == NULL)
+ {
+ Fail("CreateEvent call failed. GetLastError "
+ "returned %u.\n", GetLastError());
+ }
+
+ InitializeCriticalSection(&g_cs);
+
+ for (i=0;i<g_iThreadCount;i++)
+ {
+ hThreads[iThreadCount] = CreateThread(NULL,
+ 0,
+ &Thread,
+ (LPVOID) NULL,
+ 0,
+ &dwThreadId);
+ if (NULL != hThreads[iThreadCount])
+ {
+ iThreadCount++;
+ }
+ }
+
+ Sleep(100);
+
+ Trace("Created %d client threads\n", g_iThreadCount);
+
+ if (2 > iThreadCount)
+ {
+ Fail("Failed to create minimum number if threads, i.e. 2\n");
+ }
+
+ if (!SetEvent(g_hEvStart))
+ {
+ Fail("SetEvent failed [GetLastError()=%u]\n", GetLastError());
+ }
+
+ for (i=0; i<iThreadCount; i+=64)
+ {
+ dwRet = WaitForMultipleObjects(MIN(iThreadCount-i,64),
+ hThreads+i,
+ TRUE,
+ INFINITE);
+ if (WAIT_OBJECT_0 != dwRet)
+ {
+ Fail("Wait for all threads failed\n");
+ }
+ }
+
+ PAL_Terminate();
+ return (PASS);
+}
diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/thistest.dat b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/thistest.dat
new file mode 100644
index 0000000000..1057eca5c5
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/thistest.dat
@@ -0,0 +1,2 @@
+
+PAL,threading,palsuite\threading\criticalsectionfunctions\test8,Test8forCriticalSectionFunctionalities=test8.c,
diff --git a/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test1/test1.c b/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test1/test1.c
new file mode 100644
index 0000000000..b64fd0c7d2
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test1/test1.c
@@ -0,0 +1,145 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests that DisableThreadLibraryCalls actually stops thread
+** attach/detach notifications to a library. Also tests how it
+** handles an invalid module handle.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+/* SHLEXT is defined only for Unix variants */
+
+#if defined(SHLEXT)
+#define LibName "testlib"SHLEXT
+#define GETCALLCOUNT "GetCallCount"
+#else
+#define LibName "testlib"
+#define GETCALLCOUNT "_GetCallCount@0"
+#endif
+
+DWORD __stdcall ThreadFunc(LPVOID lpParam);
+int RunTest(int DisableThreadCalls);
+
+int __cdecl main(int argc, char **argv)
+{
+ int ret;
+
+ if ((PAL_Initialize(argc,argv)) != 0)
+ {
+ return (FAIL);
+ }
+
+
+ /*
+ * Although MSDN says that DisableThreadLibraryCalls will fail if passed
+ * an invalid handle, it actually returns success!
+ */
+ ret = DisableThreadLibraryCalls(NULL);
+ if (!ret)
+ {
+ Fail("DisableThreadLibraryCalls failed on an invalid module "
+ "handle (it actually should pass)!\n");
+ }
+
+
+ /*
+ * Test once without calling DisableThreadLibraryCalls and make sure we
+ * get expected results.
+ */
+ ret = RunTest(0);
+ if (ret != 2)
+ {
+ Fail("Expected to get 2 thread library calls, got %d!\n", ret);
+ }
+
+
+ /*
+ * Test again, this time calling DisableThreadLibraryCalls.
+ */
+ ret = RunTest(1);
+ if (ret != 0)
+ {
+ Fail("Expected to get 0 thread library calls, got %d!\n", ret);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+/*
+ * Thread entry point. Doesn't do anything.
+ */
+DWORD __stdcall ThreadFunc(LPVOID lpParam)
+{
+ return 0;
+}
+
+
+int RunTest(int DisableThreadCalls)
+{
+ HMODULE LibMod;
+ HANDLE hThread;
+ DWORD threadID;
+ DWORD WaitRet;
+ int (*GetCallCount)();
+ int count;
+
+ LibMod = LoadLibrary(LibName);
+ if (LibMod == NULL)
+ {
+ Fail("Unable to load test library!\nGetLastError returned %d\n",
+ GetLastError());
+ }
+
+ GetCallCount = (int(*)())GetProcAddress(LibMod, GETCALLCOUNT);
+ if (GetCallCount == NULL)
+ {
+ Fail("Unable to get function GetCallCount from library!\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+ if (DisableThreadCalls)
+ {
+ if (!DisableThreadLibraryCalls(LibMod))
+ {
+ Fail("DisabledThreadLibraryCalls failed!\n"
+ "GetLastError returned %d!\n", GetLastError());
+ }
+ }
+
+ hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) ThreadFunc,
+ NULL, 0, &threadID);
+
+ if (hThread == NULL)
+ {
+ Fail("Unable to create a thread!\n");
+ }
+
+ WaitRet = WaitForSingleObject(hThread, INFINITE);
+ if (WaitRet == WAIT_FAILED)
+ {
+ Fail("Unable to wait on thread!\nGetLastError returned %d\n",
+ GetLastError());
+ }
+
+ count = GetCallCount();
+
+ CloseHandle(hThread);
+
+ if (!FreeLibrary(LibMod))
+ {
+ Fail("Failed freeing library!\nGetLastError returned %d\n",
+ GetLastError());
+ }
+
+ return count;
+}
diff --git a/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test1/testinfo.dat b/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test1/testinfo.dat
new file mode 100644
index 0000000000..6d32f3591a
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Threading
+Function = DisableThreadLibraryCalls
+Name = Positive Test #1 for DisableThreadLibraryCalls
+TYPE = DEFAULT
+EXE1 = test1
+LIB1 = testlib
+Description
+=Tests that DisableThreadLibraryCalls actually stops thread
+=attach/detach notifications to a library. Also tests how it
+=handles an invalid module handle.
diff --git a/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test1/testlib.c b/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test1/testlib.c
new file mode 100644
index 0000000000..53b66d1357
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test1/testlib.c
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: testlib.c
+**
+** Purpose: Simple library that counts thread attach/detach notifications
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+static int Count;
+
+BOOL __stdcall DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+
+ if (fdwReason == DLL_PROCESS_ATTACH)
+ {
+ Count = 0;
+ }
+ else if (fdwReason == DLL_THREAD_ATTACH ||
+ fdwReason == DLL_THREAD_DETACH)
+ {
+ Count++;
+ }
+
+ return TRUE;
+}
+
+#ifdef WIN32
+BOOL __stdcall _DllMainCRTStartup(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ return DllMain(hinstDLL, fdwReason, lpvReserved);
+}
+#endif
+
+#ifdef WIN32
+__declspec(dllexport)
+#endif
+int __stdcall GetCallCount()
+{
+ return Count;
+}
diff --git a/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/dllmain1.c b/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/dllmain1.c
new file mode 100644
index 0000000000..5010a27665
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/dllmain1.c
@@ -0,0 +1,66 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: dllmain1.c
+**
+** Purpose: Test to ensure DllMain() is called with THREAD_ATTACH
+** when a thread in the application is started.
+**
+** Dependencies: none
+**
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+/* count of the number of times DllMain() was called with THREAD_DETACH */
+static int g_attachCount = 0;
+
+
+/* standard DllMain() */
+BOOL PALAPI DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID lpvReserved)
+{
+ BOOL bResult = TRUE;
+
+ switch( reason )
+ {
+ case DLL_PROCESS_ATTACH:
+ {
+ break;
+ }
+
+ case DLL_PROCESS_DETACH:
+ {
+ break;
+ }
+
+ case DLL_THREAD_ATTACH:
+ /* increment g_attachCount */
+ g_attachCount++;
+ break;
+
+ case DLL_THREAD_DETACH:
+ break;
+ }
+ return bResult;
+}
+
+
+#ifdef WIN32
+BOOL __stdcall _DllMainCRTStartup(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ return DllMain(hinstDLL, fdwReason, lpvReserved);
+}
+#endif
+
+/* function to return the current attach count */
+#ifdef WIN32
+__declspec(dllexport)
+#endif
+int PALAPI GetAttachCount( void )
+{
+ return g_attachCount;
+}
diff --git a/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/dllmain2.c b/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/dllmain2.c
new file mode 100644
index 0000000000..4e3f8862a4
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/dllmain2.c
@@ -0,0 +1,66 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: dllmain2.c
+**
+** Purpose: Test to ensure DllMain() is called with THREAD_ATTACH
+** when a thread in the application is started.
+**
+** Dependencies: none
+**
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+/* count of the number of times DllMain() was called with THREAD_DETACH */
+static int g_attachCount = 0;
+
+
+/* standard DllMain() */
+BOOL PALAPI DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID lpvReserved)
+{
+ BOOL bResult = TRUE;
+
+ switch( reason )
+ {
+ case DLL_PROCESS_ATTACH:
+ {
+ break;
+ }
+
+ case DLL_PROCESS_DETACH:
+ {
+ break;
+ }
+
+ case DLL_THREAD_ATTACH:
+ /* increment g_attachCount */
+ g_attachCount++;
+ break;
+
+ case DLL_THREAD_DETACH:
+ break;
+ }
+ return bResult;
+}
+
+
+#ifdef WIN32
+BOOL __stdcall _DllMainCRTStartup(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ return DllMain(hinstDLL, fdwReason, lpvReserved);
+}
+#endif
+
+/* function to return the current attach count */
+#ifdef WIN32
+__declspec(dllexport)
+#endif
+int PALAPI GetAttachCount( void )
+{
+ return g_attachCount;
+}
diff --git a/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/test2.c b/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/test2.c
new file mode 100644
index 0000000000..5fb694ea14
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/test2.c
@@ -0,0 +1,237 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test2.c
+**
+** Purpose: Test to ensure DisableThreadLibraryCalls() called for one
+** library will not disrupt THREAD_ATTACH notifications etc. by
+** other loaded modules.
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** CreateThread
+** ResumeThread
+** LoadLibrary
+** FreeLibrary
+** GetProcAddress
+** WaitForSingleObject
+** GetLastError
+**
+**
+**===========================================================================*/
+#include <palsuite.h>
+
+/* SHLEXT is defined only for Unix variants */
+
+#if defined(SHLEXT)
+#define rgchLibraryFile1 "dllmain1"SHLEXT
+#define rgchLibraryFile2 "dllmain2"SHLEXT
+#define szFunction "GetAttachCount"
+#else
+#define rgchLibraryFile1 "dllmain1"
+#define rgchLibraryFile2 "dllmain2"
+#define szFunction "_GetAttachCount@0"
+#endif
+
+/* define our test function type */
+typedef int ( PALAPI *LPTESTFUNC )( void );
+
+
+
+/**
+ * ThreadFunc
+ *
+ * Dummy thread function for causing DLL thread notifications.
+ */
+DWORD PALAPI ThreadFunc( LPVOID param )
+{
+ /* simulate some brief "work" */
+ int i;
+ for( i=0; i<100000; i++ )
+ {
+ }
+
+ return 0;
+}
+
+
+/* main program entry point */
+int __cdecl main( int argc, char **argv )
+
+{
+ /* local variables */
+
+ HANDLE hLib1 = NULL;
+ HANDLE hLib2 = NULL;
+ LPTESTFUNC pFunc1;
+ LPTESTFUNC pFunc2;
+ int attachCount1a = 0;
+ int attachCount1b = 0;
+ int attachCount2a = 0;
+ int attachCount2b = 0;
+
+ HANDLE hThread = NULL;
+ DWORD IDThread;
+ DWORD dwRet;
+
+ BOOL bResult = FAIL;
+
+ /* initialize the PAL */
+ if( PAL_Initialize(argc, argv) != 0 )
+ {
+ return( FAIL );
+ }
+
+ /* Load the first test library */
+ hLib1 = LoadLibrary( rgchLibraryFile1 );
+ if(hLib1 == NULL)
+ {
+ Fail( "ERROR:%lu:LoadLibrary() call failed for %s\n",
+ GetLastError(),
+ rgchLibraryFile1 );
+ }
+
+ /* Load the second test library */
+ hLib2 = LoadLibrary( rgchLibraryFile2 );
+ if(hLib2 == NULL)
+ {
+ Trace( "ERROR:%lu:LoadLibrary() call failed for %s\n",
+ GetLastError(),
+ rgchLibraryFile2 );
+ if( ! FreeLibrary( hLib1 ) )
+ {
+ Trace( "ERROR:%lu:FreeLibrary() call failed\n", GetLastError() );
+ }
+ Fail( "test failed\n" );
+ }
+
+
+ /* Get the addresses of our test functions in the dlls */
+ pFunc1 = (LPTESTFUNC)GetProcAddress( hLib1, szFunction );
+ if( pFunc1 == NULL )
+ {
+ Trace( "ERROR:%lu%:Unable to find \"%s\" in library \"%s\"\n",
+ GetLastError(),
+ szFunction,
+ rgchLibraryFile1 );
+ goto cleanup;
+ }
+
+ pFunc2 = (LPTESTFUNC)GetProcAddress( hLib2, szFunction );
+ if( pFunc1 == NULL )
+ {
+ Trace( "ERROR:%lu%:Unable to find \"%s\" in library \"%s\"\n",
+ GetLastError(),
+ szFunction,
+ rgchLibraryFile2 );
+ goto cleanup;
+ }
+
+ /* disable thread library calls for the first library */
+ if( ! DisableThreadLibraryCalls( (HMODULE)hLib1 ) )
+ {
+ Trace( "ERROR:%lu:DisableThreadLibraryCalls() call failed\n",
+ GetLastError() );
+ goto cleanup;
+ }
+
+ /* Execute the test function to get the attach count */
+ attachCount1a = pFunc1();
+ attachCount2a = pFunc2();
+
+ /* run another dummy thread to cause notification of the libraries */
+ hThread = CreateThread( NULL, /* no security attributes */
+ 0, /* use default stack size */
+ (LPTHREAD_START_ROUTINE) ThreadFunc, /* thread function */
+ (LPVOID) NULL, /* pass thread index as */
+ /* function argument */
+ CREATE_SUSPENDED, /* create suspended */
+ &IDThread ); /* returns thread id */
+
+ /* Check the return value for success. */
+ if( hThread == NULL )
+ {
+ /* error creating thread */
+ Trace( "ERROR:%lu:CreateThread() call failed\n",
+ GetLastError() );
+ goto cleanup;
+ }
+
+ /* Resume the suspended thread */
+ if( ResumeThread( hThread ) == -1 )
+ {
+ Trace( "ERROR:%lu:ResumeThread() call failed\n", GetLastError() );
+ goto cleanup;
+ }
+
+
+ /* wait for the thread to complete */
+ dwRet = WaitForSingleObject( hThread, INFINITE );
+ if( dwRet != WAIT_OBJECT_0 )
+ {
+ Trace( "ERROR: WaitForSingleObject returned %lu, "
+ "expected WAIT_OBJECT_0\n",
+ dwRet );
+ goto cleanup;
+ }
+
+
+ /* Execute the test function to get the new detach count */
+ attachCount1b = pFunc1();
+ attachCount2b = pFunc2();
+
+ /* validate the result */
+ if( attachCount1b != attachCount1a )
+ {
+ Trace( "FAIL: unexpected DLL attach count %d, expected %d\n",
+ attachCount1b,
+ attachCount1a );
+ goto cleanup;
+ }
+
+ /* validate the result */
+ if( attachCount2b != (attachCount2a + 1) )
+ {
+ Trace( "FAIL: unexpected DLL attach count %d, expected %d\n",
+ attachCount2b,
+ (attachCount2a + 1) );
+ goto cleanup;
+ }
+
+ bResult = PASS;
+
+cleanup:
+ /* Unload the test libraries */
+ if( !FreeLibrary( hLib1 ) )
+ {
+ Trace( "ERROR:%u:FreeLibrary() failed on library \"%s\"\n",
+ GetLastError(),
+ rgchLibraryFile1 );
+ bResult = FAIL;
+ }
+
+ if( !FreeLibrary( hLib2 ) )
+ {
+ Trace( "ERROR:%u:FreeLibrary() failed on library \"%s\"\n",
+ GetLastError(),
+ rgchLibraryFile2 );
+ bResult = FAIL;
+ }
+
+ /* check for failure */
+ if( bResult == FAIL )
+ {
+ Fail( "test failed\n" );
+ }
+
+ /* terminate the PAL */
+ PAL_Terminate();
+
+ /* return success */
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/testinfo.dat b/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/testinfo.dat
new file mode 100644
index 0000000000..6d28595628
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/testinfo.dat
@@ -0,0 +1,18 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = DisableThreadLibraryCalls
+Name = Test for DisableThreadLibraryCalls
+TYPE = DEFAULT
+EXE1 = test2
+LIB1 = dllmain1
+LIB2 = dllmain2
+Description
+= Test to ensure proper operation of the DisableThreadLibraryCalls()
+= API. This tests to make sure the DisableThreadLibraryCalls() called
+= for one DLL loaded by a process takes effect *only* for that DLL
+= and not for any others, by checking the THREAD_ATTACH notifications
+= in each.
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/CMakeLists.txt b/src/pal/tests/palsuite/threading/DuplicateHandle/CMakeLists.txt
new file mode 100644
index 0000000000..b908c1246b
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/CMakeLists.txt
@@ -0,0 +1,15 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test10)
+add_subdirectory(test11)
+add_subdirectory(test12)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+add_subdirectory(test7)
+add_subdirectory(test8)
+add_subdirectory(test9)
+
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/DuplicateHandle/test1/CMakeLists.txt
new file mode 100644
index 0000000000..04588b75fe
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_duplicatehandle_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_duplicatehandle_test1 coreclrpal)
+
+target_link_libraries(paltest_duplicatehandle_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test1/test1.c b/src/pal/tests/palsuite/threading/DuplicateHandle/test1/test1.c
new file mode 100644
index 0000000000..e080e98ae8
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test1/test1.c
@@ -0,0 +1,152 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c (DuplicateHandle)
+**
+** Purpose: Tests the PAL implementation of the DuplicateHandle function.
+** This test will create two handles to file, one to write and
+** one to read what was written. Test on a closed handle and a
+** NULL handle, both should fail.
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ HANDLE hFile;
+ HANDLE hDupFile;
+ char buf[256];
+ char teststr[] = "A uNiQuE tEsT sTrInG";
+ char lpFileName[] = "testfile.txt";
+ DWORD dwBytesWritten;
+ DWORD dwBytesRead;
+ BOOL bRetVal;
+
+ /*Initalize the PAL*/
+ if ((PAL_Initialize(argc,argv)) != 0)
+ {
+ return (FAIL);
+ }
+
+ /*Create a file handle with CreateFile*/
+ hFile = CreateFile(lpFileName,
+ GENERIC_WRITE|GENERIC_READ,
+ FILE_SHARE_WRITE|FILE_SHARE_READ,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: %u :unable to create file \"%s\".\n",
+ GetLastError(),
+ lpFileName);
+ }
+
+ /*Write test string to the file.*/
+ bRetVal = WriteFile(hFile, // handle to file
+ teststr, // data buffer
+ strlen(teststr), // number of bytes to write
+ &dwBytesWritten, // number of bytes written
+ NULL); // overlapped buffer
+
+ if (bRetVal == FALSE)
+ {
+ Trace("ERROR: %u : unable to write to file handle "
+ "hFile=0x%lx\n",
+ GetLastError(),
+ hFile);
+ CloseHandle(hFile);
+ Fail("");
+ }
+
+ /*Create a duplicate handle with DuplicateHandle.*/
+ if (!(DuplicateHandle(
+ GetCurrentProcess(),
+ hFile,
+ GetCurrentProcess(),
+ &hDupFile,
+ GENERIC_READ|GENERIC_WRITE,
+ FALSE,
+ DUPLICATE_SAME_ACCESS)))
+ {
+ Trace("ERROR: %u : Fail to create the duplicate handle"
+ " to hFile=0x%lx\n",
+ GetLastError(),
+ hFile);
+ CloseHandle(hFile);
+ Fail("");
+ }
+
+ memset(buf, 0, 256);
+
+ /*Read from the Duplicated handle.*/
+ bRetVal = ReadFile(hDupFile,
+ buf,
+ 256,
+ &dwBytesRead,
+ NULL);
+ if (bRetVal == FALSE)
+ {
+ Trace("ERROR: %u :unable to read from file handle "
+ "hFile=0x%lx\n",
+ GetLastError(),
+ hFile);
+ CloseHandle(hFile);
+ CloseHandle(hDupFile);
+ Fail("");
+ }
+
+ /*Compare what was written to what was read.*/
+ if (memcmp(teststr, buf, dwBytesRead) != 0)
+ {
+ Trace("ERROR: expected %s, got %s\n", teststr, buf);
+ CloseHandle(hFile);
+ CloseHandle(hDupFile);
+ Fail("");
+ }
+
+ /*Close the handles*/
+ CloseHandle(hFile);
+ CloseHandle(hDupFile);
+
+ /*Failure test: Create DuplicateHandle to a closed handle*/
+ if ((DuplicateHandle(
+ GetCurrentProcess(),
+ hFile,
+ GetCurrentProcess(),
+ &hDupFile,
+ GENERIC_READ|GENERIC_WRITE,
+ FALSE,
+ DUPLICATE_SAME_ACCESS)))
+ {
+ Fail("ERROR: %u :Created a duplicate handle to"
+ " a closed handle hFile=0x%lx\n",
+ GetLastError(),
+ hFile);
+ }
+
+ /*Failure test: Create DuplicateHandle to a NULL handle*/
+ hFile = NULL;
+ if ((DuplicateHandle(
+ GetCurrentProcess(),
+ hFile,
+ GetCurrentProcess(),
+ &hDupFile,
+ GENERIC_READ|GENERIC_WRITE,
+ FALSE,
+ DUPLICATE_SAME_ACCESS)))
+ {
+ Fail("ERROR: %u :Created a duplicate handle to "
+ " a NULL handle hFile=0x%lx\n",
+ GetLastError(),
+ hFile);
+ }
+
+ PAL_Terminate();
+ return (PASS);
+}
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test1/testinfo.dat b/src/pal/tests/palsuite/threading/DuplicateHandle/test1/testinfo.dat
new file mode 100644
index 0000000000..e22b0bea6a
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Threading
+Function = DuplicateHandle
+Name = Positive Test for DuplicateHandle
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests the PAL implementation of the DuplicateHandle function.
+= This test will create two handles to file, one to write and
+= one to read what was written. Test on a closed handle and a
+= NULL handle, both should fail.
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test10/CMakeLists.txt b/src/pal/tests/palsuite/threading/DuplicateHandle/test10/CMakeLists.txt
new file mode 100644
index 0000000000..ba16252cb4
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test10/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test10.c
+)
+
+add_executable(paltest_duplicatehandle_test10
+ ${SOURCES}
+)
+
+add_dependencies(paltest_duplicatehandle_test10 coreclrpal)
+
+target_link_libraries(paltest_duplicatehandle_test10
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test10/test10.c b/src/pal/tests/palsuite/threading/DuplicateHandle/test10/test10.c
new file mode 100644
index 0000000000..108d748de6
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test10/test10.c
@@ -0,0 +1,239 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test10.c (DuplicateHandle)
+**
+** Purpose: Tests the PAL implementation of the DuplicateHandle function.
+** This tests the operation of a duplicated Semaphore handle
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+enum wait_results
+{
+ WR_WAITING,
+ WR_GOT_MUTEX,
+ WR_TIMED_OUT,
+ WR_RELEASED
+};
+
+
+volatile int t1_result=WR_WAITING;
+volatile int t2_result=WR_WAITING;
+
+
+DWORD PALAPI ThreadTest1(LPVOID lpParam)
+{
+ DWORD dwWait;
+
+ dwWait = WaitForSingleObject((HANDLE)lpParam, 0);
+ if (dwWait == WAIT_OBJECT_0)
+ {
+ /* tell the main thread we got the mutex */
+ t1_result=WR_GOT_MUTEX;
+
+ /* wait for main thread to tell us to release the mutex */
+ while(WR_GOT_MUTEX == t1_result)
+ Sleep(1);
+ ReleaseSemaphore((HANDLE)lpParam, 1, NULL);
+
+ /* tell the main thread we released the mutex */
+ t1_result = WR_RELEASED;
+ }
+ else
+ {
+ t1_result = WR_TIMED_OUT;
+ }
+ return 0;
+}
+
+DWORD PALAPI ThreadTest2(LPVOID lpParam)
+{
+ DWORD dwWait;
+
+ dwWait = WaitForSingleObject((HANDLE)lpParam, 0 );
+ if (dwWait == WAIT_OBJECT_0)
+ {
+ ReleaseSemaphore((HANDLE)lpParam, 1, NULL);
+ t2_result = WR_GOT_MUTEX;
+ }
+ else
+ {
+ t2_result = WR_TIMED_OUT;
+ }
+
+ return 0;
+}
+
+
+int __cdecl main(int argc, char **argv)
+{
+
+ HANDLE hDupSemaphore;
+ HANDLE hSemaphore;
+ HANDLE hThread;
+ HANDLE hThread2;
+ BOOL bDupHandle=FALSE;
+ DWORD dwThreadId = 0;
+
+ if ((PAL_Initialize(argc,argv)) != 0)
+ {
+ return(FAIL);
+ }
+
+ hSemaphore = CreateSemaphoreW( NULL,
+ 1,
+ 1,
+ NULL);
+ if (hSemaphore == NULL)
+ {
+ Fail("PALSUITE ERROR:%u: Unable to create mutex\n",
+ GetLastError());
+ }
+
+ /*Create Duplicate of the Semaphore above*/
+ bDupHandle = DuplicateHandle(GetCurrentProcess(),
+ hSemaphore,
+ GetCurrentProcess(),
+ &hDupSemaphore,
+ GENERIC_READ|GENERIC_WRITE,
+ FALSE,
+ DUPLICATE_SAME_ACCESS);
+ if (!bDupHandle)
+ {
+ Trace("PALSUITE ERROR:%u: Created the duplicate handle to "
+ "closed event handle hSemaphore=0x%lx\n",
+ GetLastError(),
+ hSemaphore);
+ CloseHandle(hSemaphore);
+ Fail("");
+ }
+
+ /*Create a thread to test the Semaphore*/
+ hThread = CreateThread(NULL,
+ 0,
+ &ThreadTest1,
+ hSemaphore,
+ 0,
+ &dwThreadId);
+ if (hThread == NULL)
+ {
+ Trace("PALSUITE ERROR:%u: unable to create thread\n",
+ GetLastError());
+ CloseHandle(hSemaphore);
+ CloseHandle(hDupSemaphore);
+ Fail("");
+ }
+
+ /* wait until thread has taken the mutex */
+ while (WR_WAITING == t1_result)
+ Sleep(1);
+
+ if(WR_TIMED_OUT == t1_result)
+ {
+ Trace("PALSUITE ERROR: %u: thread couldn't acquire the semaphore\n",
+ GetLastError());
+ CloseHandle(hSemaphore);
+ CloseHandle(hDupSemaphore);
+ CloseHandle(hThread);
+ Fail("");
+ }
+
+ /*Create a second thread to use the Semaphore's duplicate handle*/
+ /*This thread should block since the Semaphore is owned by another
+ thread*/
+ hThread2 = CreateThread(NULL,
+ 0,
+ &ThreadTest2,
+ hDupSemaphore,
+ 0,
+ &dwThreadId);
+
+ if (hThread2 == NULL)
+ {
+ Trace("PALSUITE ERROR:%u: unable to create thread\n",
+ GetLastError());
+ CloseHandle(hSemaphore);
+ CloseHandle(hDupSemaphore);
+ CloseHandle(hThread);
+ Fail("");
+ }
+
+ /* wait until thread has tried to take the mutex */
+ while (WR_WAITING == t2_result)
+ Sleep(1);
+
+ if (WR_TIMED_OUT != t2_result )
+ {
+ Trace("PALSUITE ERROR:%u: Able to take mutex %#x while its "
+ "duplicate %#x is held\n", GetLastError(), hDupSemaphore,
+ hSemaphore);
+ CloseHandle(hSemaphore);
+ CloseHandle(hDupSemaphore);
+ CloseHandle(hThread);
+ CloseHandle(hThread2);
+ Fail("");
+ }
+
+ /* reset second thread status */
+ t2_result = WR_WAITING;
+
+ /* tell thread 1 to release the mutex */
+ t1_result = WR_WAITING;
+
+ /* wait for thread 1 to release the mutex */
+ while (WR_WAITING == t1_result)
+ Sleep(1);
+
+ CloseHandle(hThread2);
+
+ /*Re-Create the second thread to reuse the duplicated Semaphore*/
+ /*Since the Semaphore has since been released, the thread should
+ put WR_GOT_MUTEX into t2_result */
+ hThread2 = CreateThread(NULL,
+ 0,
+ &ThreadTest2,
+ hDupSemaphore,
+ 0,
+ &dwThreadId);
+
+ if (hThread2 == NULL)
+ {
+ Trace("PALSUITE ERROR:%u: unable to create thread\n",
+ GetLastError());
+ CloseHandle(hSemaphore);
+ CloseHandle(hDupSemaphore);
+ CloseHandle(hThread);
+ Fail("");
+ }
+
+ /* wait until thread has taken the semaphore */
+ while (WR_WAITING == t2_result)
+ Sleep(1);
+
+ if (WR_GOT_MUTEX != t2_result )
+ {
+ Trace("PALSUITE ERROR:%u: Unable to take semaphore %#x after its"
+ " duplicate %#x was released\n", GetLastError(), hDupSemaphore,
+ hSemaphore);
+ CloseHandle(hSemaphore);
+ CloseHandle(hDupSemaphore);
+ CloseHandle(hThread);
+ CloseHandle(hThread2);
+ Fail("");
+ }
+
+ /*Cleanup.*/
+ CloseHandle(hSemaphore);
+ CloseHandle(hDupSemaphore);
+ CloseHandle(hThread);
+ CloseHandle(hThread2);
+
+ PAL_Terminate();
+ return (PASS);
+}
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test10/testinfo.dat b/src/pal/tests/palsuite/threading/DuplicateHandle/test10/testinfo.dat
new file mode 100644
index 0000000000..674c71c2b3
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test10/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Threading
+Function = DuplicateHandle
+Name = Test for DuplicateHandle (CreateSemaphore)
+TYPE = DEFAULT
+EXE1 = test10
+Description
+= Tests the PAL implementation of the DuplicateHandle function.
+= This test duplication of a Semaphore handle. The test will
+= create a Semaphore and duplicate a handle to it.
+= Then two subthreads will be used to verify that they can selectively
+= block each other with different handles that refer to the
+= same Semaphore
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test11/CMakeLists.txt b/src/pal/tests/palsuite/threading/DuplicateHandle/test11/CMakeLists.txt
new file mode 100644
index 0000000000..68ce7b23fb
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test11/CMakeLists.txt
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(TESTSOURCES
+ test11.c
+)
+
+add_executable(paltest_duplicatehandle_test11
+ ${TESTSOURCES}
+)
+
+add_dependencies(paltest_duplicatehandle_test11 coreclrpal)
+
+target_link_libraries(paltest_duplicatehandle_test11
+ pthread
+ m
+ coreclrpal
+)
+
+
+set(HELPERSOURCES
+ childprocess.c
+)
+
+add_executable(paltest_duplicatehandle_test11_child
+ ${HELPERSOURCES}
+)
+
+add_dependencies(paltest_duplicatehandle_test11_child coreclrpal)
+
+target_link_libraries(paltest_duplicatehandle_test11_child
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test11/childprocess.c b/src/pal/tests/palsuite/threading/DuplicateHandle/test11/childprocess.c
new file mode 100644
index 0000000000..d5b310e46c
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test11/childprocess.c
@@ -0,0 +1,74 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: childprocess.c
+**
+** Purpose: Test to ensure DuplicateHandle works properly.
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** CreateMutexW
+** WaitForSingleObject
+** CloseHandle
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+#include "myexitcode.h"
+
+
+int __cdecl main( int argc, char **argv )
+{
+ HANDLE hMutex;
+ WCHAR wszMutexName[] = { 'T','E','S','T','1','1','\0' };
+ DWORD dwRet;
+ int i;
+
+ /* initialize the PAL */
+ if( PAL_Initialize(argc, argv) != 0 )
+ {
+ return( FAIL );
+ }
+
+ /* open a mutex to synchronize with the parent process */
+ hMutex = CreateMutexW( NULL, FALSE, wszMutexName );
+ if( hMutex == NULL )
+ {
+ Fail( "ERROR:%lu:CreateMutex() call failed\r\n", GetLastError() );
+ }
+
+ /* acquire the mutex lock */
+ dwRet = WaitForSingleObject( hMutex, 10000 );
+ if( dwRet != WAIT_OBJECT_0 )
+ {
+ Trace( "ERROR:WaitForSingleObject() returned %lu, "
+ "expected WAIT_OBJECT_0",
+ dwRet );
+ if( ! CloseHandle( hMutex ) )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ }
+ Fail( "test failed\n" );
+ }
+
+
+ /* simulate some activity */
+ for( i=0; i<50000; i++ )
+ ;
+
+ /* close our mutex handle */
+ if( ! CloseHandle( hMutex ) )
+ {
+ Fail( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ }
+
+ /* terminate the PAL */
+ PAL_Terminate();
+
+ /* return the predefined exit code */
+ return TEST_EXIT_CODE;
+}
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test11/myexitcode.h b/src/pal/tests/palsuite/threading/DuplicateHandle/test11/myexitcode.h
new file mode 100644
index 0000000000..84801cbb54
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test11/myexitcode.h
@@ -0,0 +1,13 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: duplicatehandle/test11/myexitcode.h
+**
+** Purpose: Define an exit code constant.
+**
+**
+**=========================================================*/
+#define TEST_EXIT_CODE 31
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test11/test11.c b/src/pal/tests/palsuite/threading/DuplicateHandle/test11/test11.c
new file mode 100644
index 0000000000..b05244c4b8
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test11/test11.c
@@ -0,0 +1,364 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test11.c
+**
+** Purpose:
+**
+** Test to ensure proper operation of the DuplicateHandle API.
+** The test launches a trivial child process, then opens
+** a handle to it using OpenProcess. It then duplicates that
+** handle and uses it to wait for the child process to terminate,
+** and then checks the exit code of the child process in order to
+** verify that it was in fact a handle to the correct
+** process. The test tries to duplicate the handle again after
+** the process has been closed, to verify that failure ensues.
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** ZeroMemory
+** GetCurrentDirectoryW
+** CreateProcessW
+** WaitForSingleObject
+** CreateMutexW
+** ReleaseMutex
+** CloseHandle
+** GetLastError
+** strlen
+** strncpy
+**
+**
+**===========================================================================*/
+#include <palsuite.h>
+#include "myexitcode.h"
+
+
+static const char* rgchPathDelim = "\\";
+
+
+int
+mkAbsoluteFilename( LPSTR dirName,
+ DWORD dwDirLength,
+ LPCSTR fileName,
+ DWORD dwFileLength,
+ LPSTR absPathName )
+{
+ DWORD sizeDN, sizeFN, sizeAPN;
+
+ sizeDN = strlen( dirName );
+ sizeFN = strlen( fileName );
+ sizeAPN = (sizeDN + 1 + sizeFN + 1);
+
+ /* ensure ((dirName + DELIM + fileName + \0) =< _MAX_PATH ) */
+ if( sizeAPN > _MAX_PATH )
+ {
+ return ( 0 );
+ }
+
+ strncpy( absPathName, dirName, dwDirLength +1 );
+ strncpy( absPathName, rgchPathDelim, 2 );
+ strncpy( absPathName, fileName, dwFileLength +1 );
+
+ return (sizeAPN);
+
+}
+
+
+int __cdecl main( int argc, char **argv )
+
+{
+ const char* rgchChildFile = "childprocess";
+
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+
+ DWORD dwError;
+ DWORD dwExitCode;
+ DWORD dwFileLength;
+ DWORD dwDirLength;
+ DWORD dwSize;
+ DWORD dwRet;
+
+ HANDLE hMutex;
+ HANDLE hChildProcess;
+ HANDLE hDupChildProcess;
+
+ char rgchDirName[_MAX_DIR];
+ char absPathBuf[_MAX_PATH];
+ char* rgchAbsPathName;
+
+ BOOL ret = FAIL;
+ BOOL bChildDone = FALSE;
+ WCHAR wszMutexName[] = { 'T','E','S','T','1','1','\0' };
+
+ /* initialize the PAL */
+ if( PAL_Initialize(argc, argv) != 0 )
+ {
+ return( FAIL );
+ }
+
+ /* create a mutex to synchronize with the child process */
+ hMutex = CreateMutexW( NULL, TRUE, wszMutexName );
+ if( hMutex == NULL )
+ {
+ Fail( "ERROR:%lu:CreateMutex() call failed\r\n", GetLastError() );
+ }
+
+ /* zero our process and startup info structures */
+ ZeroMemory( &si, sizeof(si) );
+ si.cb = sizeof( si );
+ ZeroMemory( &pi, sizeof(pi) );
+
+ /* build the absolute path to the child process */
+ rgchAbsPathName = &absPathBuf[0];
+ dwFileLength = strlen( rgchChildFile );
+
+ dwDirLength = GetCurrentDirectory( _MAX_PATH, rgchDirName );
+ if( dwDirLength == 0 )
+ {
+ dwError = GetLastError();
+ if( ReleaseMutex( hMutex ) == 0 )
+ {
+ Trace( "ERROR:%lu:ReleaseMutex() call failed\n", GetLastError() );
+ }
+ if( CloseHandle( hMutex ) == 0 )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ }
+ Fail( "GetCurrentDirectory call failed with error code %d\n",
+ dwError );
+ }
+
+ dwSize = mkAbsoluteFilename( rgchDirName,
+ dwDirLength,
+ rgchChildFile,
+ dwFileLength,
+ rgchAbsPathName );
+ if( dwSize == 0 )
+ {
+ if( ReleaseMutex( hMutex ) == 0 )
+ {
+ Trace( "ERROR:%lu:ReleaseMutex() call failed\n", GetLastError() );
+ }
+ if( CloseHandle( hMutex ) == 0 )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ }
+ Fail( "Palsuite Code: mkAbsoluteFilename() call failed. Could ",
+ "not build absolute path name to file\n. Exiting.\n" );
+ }
+
+ /* launch the child process */
+ if( !CreateProcess( NULL, /* module name to execute */
+ rgchAbsPathName, /* command line */
+ NULL, /* process handle not */
+ /* inheritable */
+ NULL, /* thread handle not */
+ /*inheritable */
+ FALSE, /* handle inheritance */
+ CREATE_NEW_CONSOLE, /* dwCreationFlags */
+ NULL, /* use parent's environment */
+ NULL, /* use parent's starting */
+ /* directory */
+ &si, /* startup info struct */
+ &pi ) /* process info struct */
+ )
+ {
+ dwError = GetLastError();
+ if( ReleaseMutex( hMutex ) == 0 )
+ {
+ Trace( "ERROR:%lu:ReleaseMutex() call failed\n", GetLastError() );
+ }
+ if( CloseHandle( hMutex ) == 0 )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ }
+ Fail( "CreateProcess call failed with error code %d\n",
+ dwError );
+ }
+
+ /* open another handle to the child process */
+ hChildProcess = OpenProcess( PROCESS_ALL_ACCESS, /* access */
+ FALSE, /* inheritable */
+ pi.dwProcessId /* process id */
+ );
+ if( hChildProcess == NULL )
+ {
+ dwError = GetLastError();
+ if( ReleaseMutex( hMutex ) == 0 )
+ {
+ Trace( "ERROR:%lu:ReleaseMutex() call failed\n", GetLastError() );
+ }
+ Trace( "ERROR:%lu:OpenProcess call failed\n", dwError );
+ goto cleanup3;
+ }
+
+ /* duplicate the child process handle */
+ if( ! DuplicateHandle( GetCurrentProcess(),
+ hChildProcess,
+ GetCurrentProcess(),
+ &hDupChildProcess,
+ GENERIC_READ|GENERIC_WRITE,
+ FALSE,
+ DUPLICATE_SAME_ACCESS) )
+ {
+ Trace( "ERROR:%lu:DuplicateHandle() call failed\n", GetLastError() );
+ if( ReleaseMutex( hMutex ) == 0 )
+ {
+ Trace( "ERROR:%lu:ReleaseMutex() call failed\n", GetLastError() );
+ }
+ goto cleanup2;
+ }
+
+ /* release the mutex so the child can proceed */
+ if( ReleaseMutex( hMutex ) == 0 )
+ {
+ Trace( "ERROR:%lu:ReleaseMutex() call failed\n", GetLastError() );
+ goto cleanup1;
+ }
+
+ /* wait for the child process to complete, using the new handle */
+ dwRet = WaitForSingleObject( hDupChildProcess, 10000 );
+ if( dwRet != WAIT_OBJECT_0 )
+ {
+ Trace( "ERROR:WaitForSingleObject call returned %lu, "
+ "expected WAIT_OBJECT_0",
+ dwRet );
+ goto cleanup1;
+ }
+
+ /* remember that we waited until the child was finished */
+ bChildDone = TRUE;
+
+ /* check the exit code from the process -- this is a bit of an */
+ /* extra verification that we opened the correct process handle */
+ if( ! GetExitCodeProcess( hDupChildProcess, &dwExitCode ) )
+ {
+ Trace( "ERROR:%lu:GetExitCodeProcess call failed\n", GetLastError() );
+ goto cleanup1;
+ }
+
+ /* verification */
+ if( (dwExitCode & 0xFF) != (TEST_EXIT_CODE & 0xFF) )
+ {
+ Trace( "GetExitCodeProcess returned an incorrect exit code %d, "
+ "expected value is %d\n",
+ (dwExitCode & 0xFF),
+ (TEST_EXIT_CODE & 0xFF));
+ goto cleanup1;
+ }
+
+ /* close the duplicate handle */
+ if( ! CloseHandle( hDupChildProcess ) )
+ {
+ Trace( "ERROR:%lu:CloseHandle call failed\n", GetLastError() );
+ goto cleanup2;
+ }
+
+ /* close the child process handle */
+ if( ! CloseHandle ( hChildProcess ) )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ goto cleanup3;
+ }
+
+ /* try to call duplicate handle on the closed child process handle */
+ if( DuplicateHandle( GetCurrentProcess(),
+ hChildProcess,
+ GetCurrentProcess(),
+ &hDupChildProcess,
+ GENERIC_READ|GENERIC_WRITE,
+ FALSE,
+ DUPLICATE_SAME_ACCESS) )
+ {
+ Trace( "ERROR:%lu:DuplicateHandle call succeeded on "
+ "a closed process handle, expected ERROR_INVALID_HANDLE\n" );
+ if( ! CloseHandle( hDupChildProcess ) )
+ {
+ Trace( "ERROR:%lu:CloseHandle call failed\n", GetLastError() );
+ }
+ goto cleanup3;
+ }
+
+ /* verify that the last error was ERROR_INVALID_HANDLE */
+ dwRet = GetLastError();
+ if( dwRet != ERROR_INVALID_HANDLE )
+ {
+ Trace( "ERROR:DuplicateHandle returned %lu, "
+ "expected ERROR_INVALID_HANDLE\n",
+ dwRet );
+ goto cleanup3;
+ }
+
+
+ /* success if we get here */
+ ret = PASS;
+
+ /* skip the cleanup stuff that's already done */
+ goto cleanup3;
+
+
+cleanup1:
+ /* close our duplicate handle */
+ if( ! CloseHandle( hDupChildProcess ) )
+ {
+ Trace( "ERROR:%lu:CloseHandle call failed\n", GetLastError() );
+ ret = FAIL;
+ }
+
+cleanup2:
+ /* wait on the child process to complete if necessary */
+ if( ! bChildDone )
+ {
+ dwRet = WaitForSingleObject( hChildProcess, 10000 );
+ if( dwRet != WAIT_OBJECT_0 )
+ {
+ Trace( "ERROR:WaitForSingleObject call returned %lu, "
+ "expected WAIT_OBJECT_0",
+ dwRet );
+ ret = FAIL;
+ }
+ }
+
+ /* close our child process handle */
+ if( CloseHandle ( hChildProcess ) == 0 )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ ret = FAIL;
+ }
+
+cleanup3:
+ /* close all our other handles */
+ if( CloseHandle ( pi.hProcess ) == 0 )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ ret = FAIL;
+ }
+ if( CloseHandle ( pi.hThread ) == 0 )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ ret = FAIL;
+ }
+ if( CloseHandle( hMutex ) == 0 )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ ret = FAIL;
+ }
+
+ if( ret == FAIL )
+ {
+ Fail( "test failed\n" );
+ }
+
+
+
+ /* terminate the PAL */
+ PAL_Terminate();
+
+ /* return success */
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test11/testinfo.dat b/src/pal/tests/palsuite/threading/DuplicateHandle/test11/testinfo.dat
new file mode 100644
index 0000000000..1937877880
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test11/testinfo.dat
@@ -0,0 +1,19 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = DuplicateHandle
+Name = Test for DuplicateHandle
+TYPE = DEFAULT
+EXE1 = test11
+EXE2 = childprocess
+Description
+= Test to ensure proper operation of the DuplicateHandle API.
+= The test launches a trivial child process, then opens
+= a handle to it using OpenProcess. It then duplicates that
+= handle and uses it to wait for the child process to terminate,
+= and then checks the exit code of the child process in order to
+= verify that it was in fact a handle to the correct= process. The test tries to duplicate the handle again after
+= the process has been closed, to verify that failure ensues.
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test12/CMakeLists.txt b/src/pal/tests/palsuite/threading/DuplicateHandle/test12/CMakeLists.txt
new file mode 100644
index 0000000000..961a9c64e6
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test12/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test12.c
+)
+
+add_executable(paltest_duplicatehandle_test12
+ ${SOURCES}
+)
+
+add_dependencies(paltest_duplicatehandle_test12 coreclrpal)
+
+target_link_libraries(paltest_duplicatehandle_test12
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test12/test12.c b/src/pal/tests/palsuite/threading/DuplicateHandle/test12/test12.c
new file mode 100644
index 0000000000..519194bc3a
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test12/test12.c
@@ -0,0 +1,129 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test12.c (DuplicateHandle)
+**
+** Purpose: Tests the PAL implementation of the DuplicateHandle function.
+** This test will create handle to file (to write) and close it,
+** then call duplicate handle to read what was written.
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ HANDLE hFile;
+ HANDLE hDupFile;
+ char buf[256];
+ char teststr[] = "A uNiQuE tEsT sTrInG";
+ char lpFileName[] = "testfile.txt";
+ DWORD dwBytesWritten;
+ DWORD dwBytesRead;
+ BOOL bRetVal;
+
+ /*Initalize the PAL*/
+ if ((PAL_Initialize(argc,argv)) != 0)
+ {
+ return (FAIL);
+ }
+
+ /*Create a file handle with CreateFile*/
+ hFile = CreateFile(lpFileName,
+ GENERIC_WRITE|GENERIC_READ,
+ FILE_SHARE_WRITE|FILE_SHARE_READ,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ Fail("ERROR: %u :unable to create file \"%s\".\n",
+ GetLastError(),
+ lpFileName);
+ }
+
+ /*Write test string to the file.*/
+ bRetVal = WriteFile(hFile, // handle to file
+ teststr, // data buffer
+ strlen(teststr), // number of bytes to write
+ &dwBytesWritten, // number of bytes written
+ NULL); // overlapped buffer
+
+ if (bRetVal == FALSE)
+ {
+ Trace("ERROR: %u : unable to write to file handle "
+ "hFile=0x%lx\n",
+ GetLastError(),
+ hFile);
+ CloseHandle(hFile);
+ Fail("");
+ }
+
+ /*Create a duplicate handle with DuplicateHandle.*/
+ if (!(DuplicateHandle(
+ GetCurrentProcess(),
+ hFile,
+ GetCurrentProcess(),
+ &hDupFile,
+ GENERIC_READ|GENERIC_WRITE,
+ FALSE,
+ DUPLICATE_SAME_ACCESS)))
+ {
+ Trace("ERROR: %u : Fail to create the duplicate handle"
+ " to hFile=0x%lx\n",
+ GetLastError(),
+ hFile);
+ CloseHandle(hFile);
+ Fail("");
+ }
+
+ if( !CloseHandle(hFile) )
+ {
+ Fail("Duplicate Handle:Unable to close original file: Error[%u]\n", GetLastError());
+ }
+
+ memset(buf, 0, 256);
+
+ /*Read from the Duplicated handle.*/
+ bRetVal = ReadFile(hDupFile,
+ buf,
+ 256,
+ &dwBytesRead,
+ NULL);
+ if (bRetVal == FALSE)
+ {
+ Trace("ERROR: %u :unable to read from file handle "
+ "hFile=0x%lx\n",
+ GetLastError(),
+ hDupFile);
+ CloseHandle(hDupFile);
+ Fail("");
+ }
+
+ /*Compare what was written to what was read.*/
+ if (memcmp(teststr, buf, dwBytesRead) != 0)
+ {
+ Trace("ERROR: expected %s, got %s\n", teststr, buf);
+ CloseHandle(hDupFile);
+ Fail("");
+ }
+
+ /*Close the handles*/
+ CloseHandle(hDupFile);
+
+ bRetVal = DeleteFileA(lpFileName);
+ if (bRetVal != TRUE)
+ {
+ Trace("Error:%u: DuplicateHandle, DeleteFileA: Couldn't delete DeleteFileA's"
+ " %s\n", GetLastError(), lpFileName);
+ Fail("");
+ }
+
+
+ PAL_Terminate();
+ return (PASS);
+}
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test12/testinfo.dat b/src/pal/tests/palsuite/threading/DuplicateHandle/test12/testinfo.dat
new file mode 100644
index 0000000000..3d73362eb3
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test12/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Threading
+Function = DuplicateHandle
+Name = Positive Test for DuplicateHandle
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests the PAL implementation of the DuplicateHandle function.
+= This test will create handle to file (to write),
+= then call duplicate handle, and close the original handle
+= and then use duplicated handle to read what was written.
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/DuplicateHandle/test2/CMakeLists.txt
new file mode 100644
index 0000000000..06529a6204
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_duplicatehandle_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_duplicatehandle_test2 coreclrpal)
+
+target_link_libraries(paltest_duplicatehandle_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test2/test2.c b/src/pal/tests/palsuite/threading/DuplicateHandle/test2/test2.c
new file mode 100644
index 0000000000..d1411e62d9
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test2/test2.c
@@ -0,0 +1,96 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test2.c (DuplicateHandle)
+**
+** Purpose: Tests the PAL implementation of the DuplicateHandle function.
+** This will test duplication of an CreateEvent handle. Test an
+** event in a signaled state to wait, and then set the duplicate
+** to nonsignaled state and perform the wait again. The wait on
+** the event should fail. Test the duplication of closed and NULL
+** events, these should fail.
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ HANDLE hEvent;
+ HANDLE hDupEvent;
+
+ /*Initalize the PAL.*/
+ if ((PAL_Initialize(argc,argv)) != 0)
+ {
+ return (FAIL);
+ }
+
+ /*Create an Event, and set it in the signaled state.*/
+ hEvent = CreateEvent(0, TRUE, TRUE, 0);
+ if (hEvent == NULL)
+ {
+ Fail("ERROR: %u :unable to create event\n",
+ GetLastError());
+ }
+
+ /*Create a duplicate Event handle.*/
+ if (!(DuplicateHandle(GetCurrentProcess(),
+ hEvent,GetCurrentProcess(),
+ &hDupEvent,
+ GENERIC_READ|GENERIC_WRITE,
+ FALSE, DUPLICATE_SAME_ACCESS)))
+ {
+ Trace("ERROR: %u :Fail to create the duplicate handle"
+ " to hEvent=0x%lx\n",
+ GetLastError(),
+ hEvent);
+ CloseHandle(hEvent);
+ Fail("");
+ }
+
+ /*Perform wait on Event that is in signaled state.*/
+ if ((WaitForSingleObject(hEvent, 1000)) != WAIT_OBJECT_0)
+ {
+ Trace("ERROR: %u :WaitForSignalObject on Event=0x%lx set to "
+ " signaled state failed",
+ GetLastError(),
+ hEvent);
+ CloseHandle(hEvent);
+ CloseHandle(hDupEvent);
+ Fail("");
+ }
+
+ /*Set the Duplicate Event handle to nonsignaled state.*/
+ if ((ResetEvent(hDupEvent)) == 0)
+ {
+ Trace("ERROR: %u :unable to reset dup event\n",
+ GetLastError());
+ CloseHandle(hEvent);
+ CloseHandle(hDupEvent);
+ Fail("");
+ }
+
+ /*Perform wait on Event that is in signaled state.*/
+ if ((WaitForSingleObject(hEvent, 1000)) == WAIT_OBJECT_0)
+ {
+ Trace("ERROR: %u: WaitForSignalObject succeeded on Event=0x%lx "
+ " when Duplicate Event=0x%lx set to nonsignaled state"
+ " succeeded\n",
+ GetLastError(),
+ hEvent,
+ hDupEvent);
+ CloseHandle(hEvent);
+ CloseHandle(hDupEvent);
+ Fail("");
+ }
+
+ /*Close handles to events.*/
+ CloseHandle(hEvent);
+ CloseHandle(hDupEvent);
+
+ PAL_Terminate();
+ return (PASS);
+}
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test2/testinfo.dat b/src/pal/tests/palsuite/threading/DuplicateHandle/test2/testinfo.dat
new file mode 100644
index 0000000000..273440804e
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test2/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Threading
+Function = DuplicateHandle
+Name = Test for DuplicateHandle
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Tests the PAL implementation of the DuplicateHandle function.
+= This will test duplication of an CreateEvent handle. Test an
+= event in a signaled state to wait, and then set the duplicate
+= to nonsignaled state and perform the wait again. The wait on
+= the event should fail. Test the duplication of closed and NULL
+= events, these should fail.
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test3/CMakeLists.txt b/src/pal/tests/palsuite/threading/DuplicateHandle/test3/CMakeLists.txt
new file mode 100644
index 0000000000..7f961c2213
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_duplicatehandle_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_duplicatehandle_test3 coreclrpal)
+
+target_link_libraries(paltest_duplicatehandle_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test3/test3.c b/src/pal/tests/palsuite/threading/DuplicateHandle/test3/test3.c
new file mode 100644
index 0000000000..fc91b5ec22
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test3/test3.c
@@ -0,0 +1,123 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test3.c (DuplicateHandle)
+**
+** Purpose: Tests the PAL implementation of the DuplicateHandle function.
+** This will test duplication of an OpenEvent handle. Test an
+** event in a signaled state to wait, and then set the duplicate
+** to nonsignaled state and perform the wait again. The wait on
+** the event should fail. Test the duplication of closed and NULL
+** events, these should fail.
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ HANDLE hCreateEvent;
+ HANDLE hOpenEvent;
+ HANDLE hDupEvent;
+ WCHAR lpEventName[]={'E','v','e','n','t','\0'};
+
+ /*Initialize the PAL.*/
+ if ((PAL_Initialize(argc,argv)) != 0)
+ {
+ return (FAIL);
+ }
+
+ /*Create an Event, and set it in the signaled state.*/
+ hCreateEvent = CreateEventW(0,
+ TRUE,
+ TRUE,
+ lpEventName);
+ if (hCreateEvent == NULL)
+ {
+ Fail("ERROR: %u :unable to create event %s\n",
+ GetLastError(),
+ lpEventName);
+ }
+
+ /*Open another handle to hCreateHandle with OpenEvent*/
+ hOpenEvent = OpenEventW(EVENT_ALL_ACCESS,
+ TRUE,
+ lpEventName);
+ if (hOpenEvent == NULL)
+ {
+ Trace("ERROR: %u :unable to create handle with OpenEvent to %s\n",
+ GetLastError(),
+ lpEventName);
+ CloseHandle(hCreateEvent);
+ Fail("");
+ }
+
+ /*Create a duplicate Event handle*/
+ if (!(DuplicateHandle(GetCurrentProcess(),
+ hOpenEvent,
+ GetCurrentProcess(),
+ &hDupEvent,
+ GENERIC_READ|GENERIC_WRITE,
+ FALSE,
+ DUPLICATE_SAME_ACCESS)))
+ {
+ Trace("ERROR: %u :Fail to create the duplicate handle"
+ " to hCreateEvent=0x%lx\n",
+ GetLastError(),
+ hCreateEvent);
+ CloseHandle(hCreateEvent);
+ CloseHandle(hOpenEvent);
+ Fail("");
+ }
+
+ /*Perform wait on Event that is in signaled state*/
+ if ((WaitForSingleObject(hOpenEvent, 1000)) != WAIT_OBJECT_0)
+ {
+ Trace("ERROR: %u :WaitForSignalObject on hOpenEvent=0x%lx set to "
+ " signaled state failed\n",
+ GetLastError(),
+ hOpenEvent);
+ CloseHandle(hCreateEvent);
+ CloseHandle(hOpenEvent);
+ CloseHandle(hDupEvent);
+ Fail("");
+ }
+
+ /*Set the Duplicate Event handle to nonsignaled state*/
+ if ((ResetEvent(hDupEvent)) == 0)
+ {
+ Trace("ERROR: %u: unable to reset hDupEvent=0x%lx\n",
+ GetLastError(),
+ hDupEvent);
+ CloseHandle(hCreateEvent);
+ CloseHandle(hOpenEvent);
+ CloseHandle(hDupEvent);
+ Fail("");
+ }
+
+ /*Perform wait on Event that is in signaled state*/
+ if ((WaitForSingleObject(hOpenEvent, 1000)) == WAIT_OBJECT_0)
+ {
+ Trace("ERROR: %u :WaitForSignalObject succeeded on hOpenEvent=0x%lx "
+ " when Duplicate hDupEvent=0x%lx set to nonsignaled state"
+ " succeeded\n",
+ GetLastError(),
+ hOpenEvent,
+ hDupEvent);
+ CloseHandle(hCreateEvent);
+ CloseHandle(hOpenEvent);
+ CloseHandle(hDupEvent);
+ Fail("");
+ }
+
+ /*Close handles the events*/
+ CloseHandle(hCreateEvent);
+ CloseHandle(hOpenEvent);
+ CloseHandle(hDupEvent);
+
+ PAL_Terminate();
+ return (PASS);
+}
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test3/testinfo.dat b/src/pal/tests/palsuite/threading/DuplicateHandle/test3/testinfo.dat
new file mode 100644
index 0000000000..a10adb9a8e
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test3/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Threading
+Function = DuplicateHandle
+Name = Test for DuplicateHandle
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Tests the PAL implementation of the DuplicateHandle function.
+= This will test duplication of an OpenEvent handle. Test an
+= event in a signaled state to wait, and then set the duplicate
+= to nonsignaled state and perform the wait again. The wait on
+= the event should fail. Test the duplication of closed and NULL
+= events, these should fail.
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test4/CMakeLists.txt b/src/pal/tests/palsuite/threading/DuplicateHandle/test4/CMakeLists.txt
new file mode 100644
index 0000000000..c3040d09ec
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_duplicatehandle_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_duplicatehandle_test4 coreclrpal)
+
+target_link_libraries(paltest_duplicatehandle_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test4/test4.c b/src/pal/tests/palsuite/threading/DuplicateHandle/test4/test4.c
new file mode 100644
index 0000000000..14a72db461
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test4/test4.c
@@ -0,0 +1,239 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test4.c (DuplicateHandle)
+**
+** Purpose: Tests the PAL implementation of the DuplicateHandle function.
+** This test duplication of a Mutex handle. The test will comprise
+** of creating a Mutex and its duplicate and create a thread that
+** will get ownership. Another thread will be create that will
+** attempt to get ownership of the duplicate Mutex, this will
+** fail, since the Mutex is owned by another thread. The Mutex
+** will be released and then the thread will attempt to get
+** ownership of the duplicate Mutex, this will succeed.
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+enum wait_results
+{
+ WR_WAITING,
+ WR_GOT_MUTEX,
+ WR_TIMED_OUT,
+ WR_RELEASED
+};
+
+
+volatile int t1_result=WR_WAITING;
+volatile int t2_result=WR_WAITING;
+
+
+DWORD PALAPI ThreadTest1(LPVOID lpParam)
+{
+ DWORD dwWait;
+
+ dwWait = WaitForSingleObject((HANDLE)lpParam, 0);
+ if (dwWait == WAIT_OBJECT_0)
+ {
+ /* tell the main thread we got the mutex */
+ t1_result=WR_GOT_MUTEX;
+
+ /* wait for main thread to tell us to release the mutex */
+ while(WR_GOT_MUTEX == t1_result)
+ Sleep(1);
+ ReleaseMutex((HANDLE)lpParam);
+
+ /* tell the main thread we released the mutex */
+ t1_result = WR_RELEASED;
+ }
+ else
+ {
+ t1_result = WR_TIMED_OUT;
+ }
+ return 0;
+}
+
+DWORD PALAPI ThreadTest2(LPVOID lpParam)
+{
+ DWORD dwWait;
+
+ dwWait = WaitForSingleObject((HANDLE)lpParam, 0 );
+ if (dwWait == WAIT_OBJECT_0)
+ {
+ ReleaseMutex((HANDLE)lpParam);
+ t2_result = WR_GOT_MUTEX;
+ }
+ else
+ {
+ t2_result = WR_TIMED_OUT;
+ }
+
+ return 0;
+}
+
+
+int __cdecl main(int argc, char **argv)
+{
+
+ HANDLE hDupMutex;
+ HANDLE hMutex;
+ HANDLE hThread;
+ HANDLE hThread2;
+ BOOL bDupHandle=FALSE;
+ DWORD dwThreadId = 0;
+
+ if ((PAL_Initialize(argc,argv)) != 0)
+ {
+ return(FAIL);
+ }
+
+ /*Create Mutex without ownership*/
+ hMutex = CreateMutexW(NULL, // no security attributes
+ FALSE, // initially not owned
+ NULL); // name of mutex
+ if (hMutex == NULL)
+ {
+ Fail("ERROR:%u: Unable to create mutex\n",
+ GetLastError());
+ }
+
+ /*Create Duplicate of the Mutex above*/
+ bDupHandle = DuplicateHandle(GetCurrentProcess(),
+ hMutex,
+ GetCurrentProcess(),
+ &hDupMutex,
+ GENERIC_READ|GENERIC_WRITE,
+ FALSE,
+ DUPLICATE_SAME_ACCESS);
+ if (!bDupHandle)
+ {
+ Trace("ERROR:%u: Created the duplicate handle to "
+ "closed event handle hMutex=0x%lx\n",
+ GetLastError(),
+ hMutex);
+ CloseHandle(hMutex);
+ Fail("");
+ }
+
+ /*Create a thread to test the Mutex*/
+ hThread = CreateThread(NULL,
+ 0,
+ &ThreadTest1,
+ hMutex,
+ 0,
+ &dwThreadId);
+ if (hThread == NULL)
+ {
+ Trace("ERROR:%u: unable to create thread\n",
+ GetLastError());
+ CloseHandle(hMutex);
+ CloseHandle(hDupMutex);
+ Fail("");
+ }
+
+ /* wait until thread has taken the mutex */
+ while (WR_WAITING == t1_result)
+ Sleep(1);
+
+ if(WR_TIMED_OUT == t1_result)
+ {
+ Trace("ERROR: %u: thread 1 couldn't acquire the mutex\n");
+ CloseHandle(hMutex);
+ CloseHandle(hDupMutex);
+ CloseHandle(hThread);
+ Fail("");
+ }
+
+ /*Create a second thread to use the duplicate Mutex*/
+ /*This should fail since the Mutex is owned hThread*/
+ hThread2 = CreateThread(NULL,
+ 0,
+ &ThreadTest2,
+ hDupMutex,
+ 0,
+ &dwThreadId);
+
+ if (hThread2 == NULL)
+ {
+ Trace("ERROR:%u: unable to create thread\n",
+ GetLastError());
+ CloseHandle(hMutex);
+ CloseHandle(hDupMutex);
+ CloseHandle(hThread);
+ Fail("");
+ }
+
+ /* wait until thread has tried to take the mutex */
+ while (WR_WAITING == t2_result)
+ Sleep(1);
+
+ if (WR_TIMED_OUT != t2_result )
+ {
+ Trace("ERROR:%u: Able to take mutex %#x while its duplicate %#x is "
+ "held\n", hDupMutex, hMutex);
+ CloseHandle(hMutex);
+ CloseHandle(hDupMutex);
+ CloseHandle(hThread);
+ CloseHandle(hThread2);
+ Fail("");
+ }
+
+ /* reset second thread status */
+ t2_result = WR_WAITING;
+
+ /* tell thread 1 to release the mutex */
+ t1_result = WR_WAITING;
+
+ /* wait for thread 1 to release the mutex */
+ while (WR_WAITING == t1_result)
+ Sleep(1);
+
+ CloseHandle(hThread2);
+
+ /*Re-Create the second thread to reuse the duplicated Mutex*/
+ /*This test should pass, the Mutex has since been released*/
+ hThread2 = CreateThread(NULL,
+ 0,
+ &ThreadTest2,
+ hDupMutex,
+ 0,
+ &dwThreadId);
+
+ if (hThread2 == NULL)
+ {
+ Trace("ERROR:%u: unable to create thread\n",
+ GetLastError());
+ CloseHandle(hMutex);
+ CloseHandle(hDupMutex);
+ CloseHandle(hThread);
+ Fail("");
+ }
+
+ /* wait until thread has taken the mutex */
+ while (WR_WAITING == t2_result)
+ Sleep(1);
+
+ if (WR_GOT_MUTEX != t2_result )
+ {
+ Trace("ERROR:%u: Unable to take mutex %#x after its duplicate %#x was "
+ "released\n", hDupMutex, hMutex);
+ CloseHandle(hMutex);
+ CloseHandle(hDupMutex);
+ CloseHandle(hThread);
+ CloseHandle(hThread2);
+ Fail("");
+ }
+
+ /*Cleanup.*/
+ CloseHandle(hMutex);
+ CloseHandle(hDupMutex);
+ CloseHandle(hThread);
+ CloseHandle(hThread2);
+
+ PAL_Terminate();
+ return (PASS);
+}
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test4/testinfo.dat b/src/pal/tests/palsuite/threading/DuplicateHandle/test4/testinfo.dat
new file mode 100644
index 0000000000..64842f8713
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test4/testinfo.dat
@@ -0,0 +1,19 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Threading
+Function = DuplicateHandle
+Name = Test for DuplicateHandle (CreateMutex)
+TYPE = DEFAULT
+EXE1 = test4
+Description
+= Tests the PAL implementation of the DuplicateHandle function.
+= This test duplication of a Mutex handle. The test will comprise
+= of creating a Mutex and its duplicate and create a thread that will
+= get ownership. Another thread will be create that will attempt to
+= get ownership of the duplicate Mutex, this will fail, since the
+= Mutex is owned by another thread. The Mutex will be released and
+= then the thread will attempt to get ownership of the duplicate
+= Mutex, this will succeed.
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test5/CMakeLists.txt b/src/pal/tests/palsuite/threading/DuplicateHandle/test5/CMakeLists.txt
new file mode 100644
index 0000000000..bc468a4a75
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test5.c
+)
+
+add_executable(paltest_duplicatehandle_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_duplicatehandle_test5 coreclrpal)
+
+target_link_libraries(paltest_duplicatehandle_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test5/test5.c b/src/pal/tests/palsuite/threading/DuplicateHandle/test5/test5.c
new file mode 100644
index 0000000000..a588928f00
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test5/test5.c
@@ -0,0 +1,145 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test5.c (DuplicateHandle)
+**
+** Purpose: Tests the PAL implementation of the DuplicateHandle function,
+** with CreatePipe. This test will create a pipe and write to it,
+** the duplicate the read handle and read what was written.
+**
+** Depends: WriteFile
+** ReadFile
+** memcmp
+** CloseHandle
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+const char* cTestString = "one fish, two fish, red fish, blue fish.";
+
+int __cdecl main(int argc, char **argv)
+{
+ HANDLE hReadPipe = NULL;
+ HANDLE hWritePipe = NULL;
+ HANDLE hDupPipe = NULL;
+ BOOL bRetVal = FALSE;
+ DWORD dwBytesWritten;
+ DWORD dwBytesRead;
+ char buffer[256];
+
+ SECURITY_ATTRIBUTES lpPipeAttributes;
+
+ /*Initialize the PAL*/
+ if ((PAL_Initialize(argc, argv)) != 0)
+ {
+ return (FAIL);
+ }
+
+ /*Setup SECURITY_ATTRIBUTES structure for CreatePipe*/
+ lpPipeAttributes.nLength = sizeof(lpPipeAttributes);
+ lpPipeAttributes.lpSecurityDescriptor = NULL;
+ lpPipeAttributes.bInheritHandle = TRUE;
+
+ /*Create a Pipe*/
+ bRetVal = CreatePipe(&hReadPipe, /* read handle*/
+ &hWritePipe, /* write handle */
+ &lpPipeAttributes,/* security attributes*/
+ 0); /* pipe size*/
+ if (bRetVal == FALSE)
+ {
+ Fail("ERROR:%u:Unable to create pipe\n", GetLastError());
+ }
+
+ /*Write to the write pipe handle*/
+ bRetVal = WriteFile(hWritePipe, /* handle to write pipe*/
+ cTestString, /* buffer to write*/
+ strlen(cTestString),/* number of bytes to write*/
+ &dwBytesWritten, /* number of bytes written*/
+ NULL); /* overlapped buffer*/
+ if (bRetVal == FALSE)
+ {
+ Trace("ERROR:%u:unable to write to write pipe handle "
+ "hWritePipe=0x%lx\n", GetLastError(), hWritePipe);
+ CloseHandle(hReadPipe);
+ CloseHandle(hWritePipe);
+ Fail("");
+ }
+
+ /*Duplicate the pipe handle*/
+ if (!(DuplicateHandle(GetCurrentProcess(), /* source handle process*/
+ hReadPipe, /* handle to duplicate*/
+ GetCurrentProcess(), /* target process handle*/
+ &hDupPipe, /* duplicate handle*/
+ GENERIC_READ|GENERIC_WRITE,/* requested access*/
+ FALSE, /* handle inheritance*/
+ DUPLICATE_SAME_ACCESS))) /* optional actions*/
+ {
+ Trace("ERROR:%u:Fail to create the duplicate handle"
+ " to hReadPipe=0x%lx",
+ GetLastError(),
+ hReadPipe);
+ CloseHandle(hReadPipe);
+ CloseHandle(hWritePipe);
+ Fail("");
+ }
+
+ /*Read from the duplicated handle, 256 bytes, more bytes
+ than actually written. This will allow us to use the
+ value that ReadFile returns for comparision.*/
+ bRetVal = ReadFile(hDupPipe, /* handle to read pipe*/
+ buffer, /* buffer to write to*/
+ 256, /* number of bytes to read*/
+ &dwBytesRead, /* number of bytes read*/
+ NULL); /* overlapped buffer*/
+ if (bRetVal == FALSE)
+ {
+ Trace("ERROR:%u:unable read from the duplicated pipe "
+ "hDupPipe=0x%lx\n",
+ GetLastError(),
+ hDupPipe);
+ CloseHandle(hReadPipe);
+ CloseHandle(hWritePipe);
+ CloseHandle(hDupPipe);
+ Fail("");
+ }
+
+ /*Compare what was read with what was written.*/
+ if ((memcmp(cTestString, buffer, dwBytesRead)) != 0)
+ {
+ Trace("ERROR:%u: read \"%s\" expected \"%s\" \n",
+ GetLastError(),
+ buffer,
+ cTestString);
+ CloseHandle(hReadPipe);
+ CloseHandle(hWritePipe);
+ CloseHandle(hDupPipe);
+ Fail("");
+ }
+
+ /*Compare values returned from WriteFile and ReadFile.*/
+ if (dwBytesWritten != dwBytesRead)
+ {
+ Trace("ERROR:%u: WriteFile wrote \"%s\", but ReadFile read \"%s\","
+ " these should be the same\n",
+ GetLastError(),
+ buffer,
+ cTestString);
+ CloseHandle(hReadPipe);
+ CloseHandle(hWritePipe);
+ CloseHandle(hDupPipe);
+ Fail("");
+ }
+
+ /*Cleanup.*/
+ CloseHandle(hWritePipe);
+ CloseHandle(hReadPipe);
+ CloseHandle(hDupPipe);
+
+ PAL_Terminate();
+ return (PASS);
+}
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test5/testinfo.dat b/src/pal/tests/palsuite/threading/DuplicateHandle/test5/testinfo.dat
new file mode 100644
index 0000000000..97e42a9787
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test5/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Threading
+Function = DuplicateHandle
+Name = Test for DuplicateHandle (CreatePipe)
+TYPE = DEFAULT
+EXE1 = test5
+Description
+= Tests the PAL implementation of the DuplicateHandle function,
+= with CreatePipe. This test will create a pipe and write to it,
+= then duplicate the read handle and read what was written.
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test6/CMakeLists.txt b/src/pal/tests/palsuite/threading/DuplicateHandle/test6/CMakeLists.txt
new file mode 100644
index 0000000000..20f7822b1e
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test6.c
+)
+
+add_executable(paltest_duplicatehandle_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_duplicatehandle_test6 coreclrpal)
+
+target_link_libraries(paltest_duplicatehandle_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test6/test6.c b/src/pal/tests/palsuite/threading/DuplicateHandle/test6/test6.c
new file mode 100644
index 0000000000..026f315a44
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test6/test6.c
@@ -0,0 +1,146 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test6.c (DuplicateHandle)
+**
+** Purpose: Tests the PAL implementation of the DuplicateHandle function,
+** with CreatePipe. This test will create a pipe, then duplicate
+** the write handle, write to the handle, and use the read to
+** verify.
+**
+** Depends: WriteFile
+** ReadFile
+** memcmp
+** CloseHandle
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+const char* cTestString = "one fish, two fish, red fish, blue fish.";
+
+int __cdecl main(int argc, char **argv)
+{
+ HANDLE hReadPipe = NULL;
+ HANDLE hWritePipe = NULL;
+ HANDLE hDupPipe = NULL;
+ BOOL bRetVal = FALSE;
+ DWORD dwBytesWritten;
+ DWORD dwBytesRead;
+ char buffer[256];
+
+ SECURITY_ATTRIBUTES lpPipeAttributes;
+
+ /*Initialize the PAL*/
+ if ((PAL_Initialize(argc, argv)) != 0)
+ {
+ return (FAIL);
+ }
+
+ /*Setup SECURITY_ATTRIBUTES structure for CreatePipe*/
+ lpPipeAttributes.nLength = sizeof(lpPipeAttributes);
+ lpPipeAttributes.lpSecurityDescriptor = NULL;
+ lpPipeAttributes.bInheritHandle = TRUE;
+
+ /*Create a Pipe*/
+ bRetVal = CreatePipe(&hReadPipe, /* read handle*/
+ &hWritePipe, /* write handle */
+ &lpPipeAttributes,/* security attributes*/
+ 0); /* pipe size*/
+ if (bRetVal == FALSE)
+ {
+ Fail("ERROR: %ld :Unable to create pipe\n", GetLastError());
+ }
+
+ /*Duplicate the pipe handle*/
+ if (!(DuplicateHandle(GetCurrentProcess(), /* source handle process*/
+ hWritePipe, /* handle to duplicate*/
+ GetCurrentProcess(), /* target process handle*/
+ &hDupPipe, /* duplicate handle*/
+ GENERIC_READ|GENERIC_WRITE,/* requested access*/
+ FALSE, /* handle inheritance*/
+ DUPLICATE_SAME_ACCESS))) /* optional actions*/
+ {
+ Trace("ERROR: %ld :Fail to create the duplicate handle"
+ " to hWritePipe=0x%lx",
+ GetLastError(),
+ hWritePipe);
+ CloseHandle(hReadPipe);
+ CloseHandle(hWritePipe);
+ Fail("");
+ }
+
+ /*Write to the duplicate write pipe handle*/
+ bRetVal = WriteFile(hDupPipe, /* handle to write pipe*/
+ cTestString, /* buffer to write*/
+ strlen(cTestString),/* number of bytes to write*/
+ &dwBytesWritten, /* number of bytes written*/
+ NULL); /* overlapped buffer*/
+ if (bRetVal == FALSE)
+ {
+ Trace("ERROR: %ld :unable to write to duplicate write pipe handle "
+ "hDupPipe=0x%lx\n",
+ GetLastError(),
+ hDupPipe);
+ CloseHandle(hReadPipe);
+ CloseHandle(hWritePipe);
+ CloseHandle(hDupPipe);
+ Fail("");
+ }
+
+ /*Read from the read handle, 256 bytes, more bytes
+ then actually written. This will give allow us to use
+ the value that ReadFile returns for comparision.*/
+ bRetVal = ReadFile(hReadPipe, /* handle to read pipe*/
+ buffer, /* buffer to write to*/
+ 256, /* number of bytes to read*/
+ &dwBytesRead, /* number of bytes read*/
+ NULL); /* overlapped buffer*/
+ if (bRetVal == FALSE)
+ {
+ Trace("ERROR: %ld : unable read hReadPipe=0x%lx\n",
+ GetLastError(), hReadPipe);
+ CloseHandle(hReadPipe);
+ CloseHandle(hWritePipe);
+ CloseHandle(hDupPipe);
+ Fail("");
+ }
+
+ /*Compare what was read with what was written.*/
+ if ((memcmp(cTestString, buffer, dwBytesRead)) != 0)
+ {
+ Trace("ERROR: read \"%s\" expected \"%s\" \n",
+ buffer,
+ cTestString);
+ CloseHandle(hReadPipe);
+ CloseHandle(hWritePipe);
+ CloseHandle(hDupPipe);
+ Fail("");
+ }
+
+ /*Compare values returned from WriteFile and ReadFile.*/
+ if (dwBytesWritten != dwBytesRead)
+ {
+ Trace("ERROR: WriteFile wrote \"%s\", but ReadFile read \"%s\","
+ " these should be the same\n",
+ buffer,
+ cTestString);
+ CloseHandle(hReadPipe);
+ CloseHandle(hWritePipe);
+ CloseHandle(hDupPipe);
+ Fail("");
+ }
+
+ /*Cleanup.*/
+ CloseHandle(hReadPipe);
+ CloseHandle(hWritePipe);
+ CloseHandle(hDupPipe);
+
+
+ PAL_Terminate();
+ return (PASS);
+}
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test6/testinfo.dat b/src/pal/tests/palsuite/threading/DuplicateHandle/test6/testinfo.dat
new file mode 100644
index 0000000000..6c49d64f89
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test6/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Threading
+Function = DuplicateHandle
+Name = Test for DuplicateHandle (CreatePipe)
+TYPE = DEFAULT
+EXE1 = test6
+Description
+= Tests the PAL implementation of the DuplicateHandle function,
+= with CreatePipe. This test will create a pipe, then duplicate
+= the write handle, write to the handle, and use the read to
+= verify.
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test7/CMakeLists.txt b/src/pal/tests/palsuite/threading/DuplicateHandle/test7/CMakeLists.txt
new file mode 100644
index 0000000000..df3fdf9ae0
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test7/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test7.c
+)
+
+add_executable(paltest_duplicatehandle_test7
+ ${SOURCES}
+)
+
+add_dependencies(paltest_duplicatehandle_test7 coreclrpal)
+
+target_link_libraries(paltest_duplicatehandle_test7
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test7/test7.c b/src/pal/tests/palsuite/threading/DuplicateHandle/test7/test7.c
new file mode 100644
index 0000000000..0477291922
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test7/test7.c
@@ -0,0 +1,149 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test7.c (DuplicateHandle)
+**
+** Purpose: Tests the PAL implementation of the DuplicateHandle function,
+** with a handle from CreateThread. The test will create a thread
+** handle and its duplicate. Then get the priorities of the threads,
+** set the priority of one and the change should be seen in the
+** other.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+DWORD PALAPI CreateTestThread(LPVOID lpParam);
+
+int __cdecl main(int argc, char* argv[])
+{
+ HANDLE hThread;
+ HANDLE hDupThread;
+ DWORD dwThreadId = 0;
+ LPTHREAD_START_ROUTINE lpStartAddress = &CreateTestThread;
+
+ int threadPriority;
+ int duplicatePriority;
+ int finalPriority;
+
+ /* Initialize the PAL.*/
+ if ((PAL_Initialize(argc, argv)) != 0)
+ {
+ return (FAIL);
+ }
+
+ /* Create a thread.*/
+ hThread = CreateThread(NULL, /* SD*/
+ (DWORD)0, /* initial stack size*/
+ lpStartAddress, /* thread function*/
+ NULL, /* thread argument*/
+ (DWORD)0, /* creation option*/
+ &dwThreadId); /* thread identifier*/
+ if (hThread == NULL)
+ {
+ Fail("ERROR:%u: Unable to create thread.\n",
+ GetLastError());
+ }
+
+ /* Duplicate the thread handle.*/
+ if (!(DuplicateHandle(GetCurrentProcess(), /* source handle process*/
+ hThread, /* handle to duplicate*/
+ GetCurrentProcess(), /* target process handle*/
+ &hDupThread, /* duplicate handle*/
+ (DWORD)0, /* requested access*/
+ FALSE, /* handle inheritance*/
+ DUPLICATE_SAME_ACCESS))) /* optional actions*/
+ {
+ Trace("ERROR: %ld :Fail to create the duplicate handle"
+ " to hThread=0x%lx",
+ GetLastError(),
+ hThread);
+ CloseHandle(hThread);
+ Fail("");
+ }
+
+ /* Get the priority of the thread.*/
+ threadPriority = GetThreadPriority(hThread);
+ if(threadPriority != 0)
+ {
+ Trace("ERROR: Thread priority of hThread=0x%lx should be "
+ "set to normal THREAD_PRIORITY_NORMAL=%d\n",
+ hThread,
+ THREAD_PRIORITY_NORMAL);
+ CloseHandle(hThread);
+ CloseHandle(hDupThread);
+ Fail("");
+ }
+
+ /* Get the priority of the duplicated handle, and compare it to
+ * the priority of the original thread. Should be the same.*/
+ duplicatePriority = GetThreadPriority(hThread);
+ if(duplicatePriority != threadPriority)
+ {
+ Trace("ERROR: Expected priority of hThread=0x%lx and hDupThread=0x%lx"
+ " to be the same. Priorities:hThread=\"%d\":hDupThread=\"%d\"\n",
+ hThread,
+ hDupThread,
+ threadPriority,
+ duplicatePriority);
+ CloseHandle(hThread);
+ CloseHandle(hDupThread);
+ Fail("");
+ }
+
+ /* Set the priority of the duplicate thread.*/
+ if(!SetThreadPriority (hDupThread,THREAD_PRIORITY_HIGHEST))
+ {
+ Trace("ERROR:%u: SetThreadPriority failed on hThread=0x%lx\n",
+ GetLastError(),
+ hDupThread);
+ CloseHandle(hThread);
+ CloseHandle(hDupThread);
+ Fail("");
+ }
+
+ /* Get the priority of the origianl thread, and
+ * compare it to what the duplicate was set to.*/
+ finalPriority = GetThreadPriority(hThread);
+ if (finalPriority != THREAD_PRIORITY_HIGHEST)
+ {
+ Trace("ERROR: Expected priority of hThread=0x%lw and "
+ "hDupThread=0x%lw to be set the same. Priorities:"
+ "hThread=\"%d\":hDupThread=\"%d\".\n",
+ hThread,
+ hDupThread,
+ threadPriority,
+ duplicatePriority);
+ CloseHandle(hThread);
+ CloseHandle(hDupThread);
+ Fail("");
+ }
+
+ /* Wait on the original thread.*/
+ if((WaitForSingleObject(hThread, 100)) != WAIT_OBJECT_0)
+ {
+ Trace("ERROR:%u: hThread=0x%lx is in a non-signalled "
+ "mode, yet created signalled.\n",
+ GetLastError(),
+ hThread);
+ CloseHandle(hThread);
+ CloseHandle(hDupThread);
+ Fail("");
+ }
+
+ /* Clean-up thread and Terminate the PAL.*/
+ CloseHandle(hThread);
+ CloseHandle(hDupThread);
+ PAL_Terminate();
+ return PASS;
+}
+
+/*Thread testing function, only return '0'*/
+DWORD PALAPI CreateTestThread(LPVOID lpParam)
+{
+ return (DWORD)0;
+}
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test7/testinfo.dat b/src/pal/tests/palsuite/threading/DuplicateHandle/test7/testinfo.dat
new file mode 100644
index 0000000000..b8092d6152
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test7/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Threading
+Function = DuplicateHandle
+Name = Test for DuplicateHandle (CreateThread)
+TYPE = DEFAULT
+EXE1 = test7
+Description
+= Tests the PAL implementation of the DuplicateHandle function,
+= with a handle from CreateThread. The test will create a thread
+= handle and its duplicate. Then get the priorities of the threads,
+= set the priority of one and the change should be seen in the
+= other.
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test8/CMakeLists.txt b/src/pal/tests/palsuite/threading/DuplicateHandle/test8/CMakeLists.txt
new file mode 100644
index 0000000000..15ec23d272
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test8/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test8.c
+)
+
+add_executable(paltest_duplicatehandle_test8
+ ${SOURCES}
+)
+
+add_dependencies(paltest_duplicatehandle_test8 coreclrpal)
+
+target_link_libraries(paltest_duplicatehandle_test8
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test8/test8.c b/src/pal/tests/palsuite/threading/DuplicateHandle/test8/test8.c
new file mode 100644
index 0000000000..6748c5dffd
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test8/test8.c
@@ -0,0 +1,164 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test8.c (DuplicateHandle)
+**
+** Purpose: Tests the PAL implementation of the DuplicateHandle function,
+** with a handle from GetCurrentThread. The test will create a thread
+** handle, get the current thread and its duplicate. Then get the
+** priorities of the threads, set the priority of one and the change
+** should be seen in the other.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+DWORD PALAPI CreateTestThread(LPVOID lpParam);
+
+int __cdecl main(int argc, char* argv[])
+{
+ HANDLE hThread;
+ HANDLE hCurrentThread;
+ HANDLE hDupThread;
+ DWORD dwThreadId = 0;
+ LPTHREAD_START_ROUTINE lpStartAddress = &CreateTestThread;
+
+ int threadPriority;
+ int duplicatePriority;
+ int finalPriority;
+
+ /* Initialize the PAL.*/
+ if ((PAL_Initialize(argc, argv)) != 0)
+ {
+ return (FAIL);
+ }
+
+#if !HAVE_SCHED_OTHER_ASSIGNABLE
+ /* Defining thread priority for SCHED_OTHER is implementation defined.
+ Some platforms like NetBSD cannot reassign it as they are dynamic.
+ */
+ printf("paltest_duplicatehandle_test8 has been disabled on this platform\n");
+#else
+
+ /* Create a thread.*/
+ hThread = CreateThread(NULL, /* SD*/
+ (DWORD)0, /* initial stack size*/
+ lpStartAddress, /* thread function*/
+ NULL, /* thread argument*/
+ (DWORD)0, /* creation option*/
+ &dwThreadId); /* thread identifier*/
+ if (hThread == NULL)
+ {
+ Fail("ERROR:%u: Unable to create thread.\n",
+ GetLastError());
+ }
+
+ /*Get a psuedo handle to the current thread.*/
+ hCurrentThread = GetCurrentThread();
+
+ /* Duplicate the psuedo thread handle.*/
+ if (!(DuplicateHandle(GetCurrentProcess(), /* source handle process*/
+ hCurrentThread, /* handle to duplicate*/
+ GetCurrentProcess(), /* target process handle*/
+ &hDupThread, /* duplicate handle*/
+ (DWORD)0, /* requested access*/
+ FALSE, /* handle inheritance*/
+ DUPLICATE_SAME_ACCESS))) /* optional actions*/
+ {
+ Trace("ERROR: %ld :Fail to create the duplicate handle"
+ " to hThread=0x%lx",
+ GetLastError(),
+ hThread);
+ CloseHandle(hThread);
+ Fail("");
+ }
+
+ /* Get the priority of the thread.*/
+ threadPriority = GetThreadPriority(hCurrentThread);
+ if(threadPriority != 0)
+ {
+ Trace("ERROR: Thread priority of hCurrentThread=0x%lx should be "
+ "set to normal THREAD_PRIORITY_NORMAL=%d\n",
+ hCurrentThread,
+ THREAD_PRIORITY_NORMAL);
+ CloseHandle(hThread);
+ CloseHandle(hDupThread);
+ Fail("");
+ }
+
+ /* Get the priority of the duplicated handle, and compare it to
+ * the priority of the original thread. Should be the same.*/
+ duplicatePriority = GetThreadPriority(hCurrentThread);
+ if(duplicatePriority != threadPriority)
+ {
+ Trace("ERROR: Expected priority of hCurrentThread=0x%lx and "
+ "hDupThread=0x%lx to be the same. Priorities:hThread="
+ "\"%d\":hDupThread=\"%d\"\n",
+ hCurrentThread,
+ hDupThread,
+ threadPriority,
+ duplicatePriority);
+ CloseHandle(hThread);
+ CloseHandle(hDupThread);
+ Fail("");
+ }
+
+ /* Set the priority of the original thread.*/
+ if(!SetThreadPriority (hCurrentThread,THREAD_PRIORITY_HIGHEST))
+ {
+ Trace("ERROR:%u: SetThreadPriority failed on hCurrentThread=0x%lx\n",
+ GetLastError(),
+ hCurrentThread);
+ CloseHandle(hThread);
+ CloseHandle(hDupThread);
+ Fail("");
+ }
+
+ /* Get the priority of the duplicate thread, and
+ * compare it to what the original was set to.*/
+ finalPriority = GetThreadPriority(hDupThread);
+ if (finalPriority != THREAD_PRIORITY_HIGHEST)
+ {
+ Trace("ERROR: Expected priority of hCurrentThread=0x%lw and "
+ "hDupThread=0x%lw to be set the same. Priorities:"
+ "hCurrentThread=\"%d\":hDupThread=\"%d\".\n",
+ hCurrentThread,
+ hDupThread,
+ threadPriority,
+ duplicatePriority);
+ CloseHandle(hThread);
+ CloseHandle(hDupThread);
+ Fail("");
+ }
+
+ /* Wait on the original thread.*/
+ if((WaitForSingleObject(hThread, 100)) != WAIT_OBJECT_0)
+ {
+ Trace("ERROR:%u: hCurrentThread=0x%lx is in a non-signalled "
+ "mode, yet created signalled.\n",
+ GetLastError(),
+ hThread);
+ CloseHandle(hThread);
+ CloseHandle(hDupThread);
+ Fail("");
+ }
+
+ /* Clean-up thread and Terminate the PAL.*/
+ CloseHandle(hThread);
+ CloseHandle(hDupThread);
+
+#endif
+
+ PAL_Terminate();
+ return PASS;
+}
+
+/*Thread testing function, only return '0'*/
+DWORD PALAPI CreateTestThread(LPVOID lpParam)
+{
+ return (DWORD)0;
+}
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test8/testinfo.dat b/src/pal/tests/palsuite/threading/DuplicateHandle/test8/testinfo.dat
new file mode 100644
index 0000000000..ae1353af18
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test8/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Threading
+Function = DuplicateHandle
+Name = Test for DuplicateHandle (GetCurrentThread)
+TYPE = DEFAULT
+EXE1 = test8
+Description
+=Tests the PAL implementation of the DuplicateHandle function,
+=with a handle from GetCurrentThread. The test will create a thread
+=handle, get the current thread and its duplicate. Then get the
+=priorities of the threads, set the priority of one and the change
+=should be seen in the other.
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test9/CMakeLists.txt b/src/pal/tests/palsuite/threading/DuplicateHandle/test9/CMakeLists.txt
new file mode 100644
index 0000000000..e4442e327c
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test9/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test9.c
+)
+
+add_executable(paltest_duplicatehandle_test9
+ ${SOURCES}
+)
+
+add_dependencies(paltest_duplicatehandle_test9 coreclrpal)
+
+target_link_libraries(paltest_duplicatehandle_test9
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test9/test9.c b/src/pal/tests/palsuite/threading/DuplicateHandle/test9/test9.c
new file mode 100644
index 0000000000..f15871c57d
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test9/test9.c
@@ -0,0 +1,127 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test9.c (DuplicateHandle)
+**
+** Purpose: Tests the PAL implementation of the DuplicateHandle function,
+** with a handle from GetCurrentProcess. The test will create a
+** process, duplicate it, then using ReadProcessMemory will
+** read from the memory location of the CreateProcess process
+** memory and the DuplicateHandle process memory. If the
+** duplication is correct the memory will be the same for both.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char* argv[])
+{
+ HANDLE hProcess;
+ HANDLE hDupProcess;
+ char lpBuffer[64];
+ char lpDupBuffer[64];
+ SIZE_T lpNumberOfBytesRead;
+ SIZE_T lpDupNumberOfBytesRead;
+ char lpTestBuffer[] = "abcdefghijklmnopqrstuvwxyz";
+
+ /* Initalize the PAL.
+ */
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Initalize the buffers.
+ */
+ ZeroMemory( &lpBuffer, sizeof(lpBuffer) );
+ ZeroMemory( &lpDupBuffer, sizeof(lpDupBuffer) );
+
+ /* Get current proces, this will be duplicated.
+ */
+ hProcess = GetCurrentProcess();
+ if(hProcess == NULL)
+ {
+ Fail("ERROR: Unable to get the current process\n");
+ }
+
+ /* Duplicate the current process handle.
+ */
+ if (!(DuplicateHandle(GetCurrentProcess(), /* source handle process*/
+ hProcess, /* handle to duplicate*/
+ GetCurrentProcess(), /* target process handle*/
+ &hDupProcess, /* duplicate handle*/
+ (DWORD)0, /* requested access*/
+ FALSE, /* handle inheritance*/
+ DUPLICATE_SAME_ACCESS))) /* optional actions*/
+ {
+ Trace("ERROR:%u: Failed to create the duplicate handle"
+ " to hProcess=0x%lx",
+ GetLastError(),
+ hProcess);
+ CloseHandle(hProcess);
+ Fail("");
+ }
+
+ /* Get memory read of the current process.
+ */
+ if ((ReadProcessMemory(hDupProcess, &lpTestBuffer,
+ lpDupBuffer, sizeof(lpDupBuffer), &lpDupNumberOfBytesRead)) == 0)
+ {
+ Trace("ERROR:%u: Unable to read the process memory of "
+ "hDupProcess=0x%lx.\n",
+ GetLastError(),
+ hDupProcess);
+ CloseHandle(hProcess);
+ CloseHandle(hDupProcess);
+ Fail("");
+ }
+
+ /* Get read memory of the created process.
+ */
+ if ((ReadProcessMemory(hProcess, &lpTestBuffer,
+ lpBuffer, sizeof(lpBuffer), &lpNumberOfBytesRead)) == 0)
+ {
+ Trace("ERROR:%u: Unable to read the process memory of "
+ "hProcess=0x%lx.\n",
+ GetLastError(),
+ hProcess);
+ CloseHandle(hProcess);
+ CloseHandle(hDupProcess);
+ Fail("");
+ }
+
+ /* Compare the number of bytes that were read by each
+ * ReadProcessMemory.*/
+ if (lpDupNumberOfBytesRead != lpNumberOfBytesRead)
+ {
+ Trace("ERROR: ReadProcessMemory read different numbers of bytes "
+ "from duplicate process handles.\n");
+ CloseHandle(hProcess);
+ CloseHandle(hDupProcess);
+ Fail("");
+ }
+
+ /* Compare the two buffers to make sure they are equal.
+ */
+ if ((strcmp(lpBuffer, lpDupBuffer)) != 0)
+ {
+ Trace("ERROR: ReadProcessMemory read different numbers of bytes "
+ "from duplicate process handles. hProcess read \"%s\" and "
+ "hDupProcess read \"%s\"\n",
+ lpBuffer,
+ lpDupBuffer);
+ CloseHandle(hProcess);
+ CloseHandle(hDupProcess);
+ Fail("");
+ }
+
+ /* Clean-up thread and Terminate the PAL.*/
+ CloseHandle(hProcess);
+ CloseHandle(hDupProcess);
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test9/testinfo.dat b/src/pal/tests/palsuite/threading/DuplicateHandle/test9/testinfo.dat
new file mode 100644
index 0000000000..c7122908fd
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test9/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Threading
+Function = DuplicateHandle
+Name = Test for DuplicateHandle (GetCurrentProcess)
+TYPE = DEFAULT
+EXE1 = test9
+Description
+= Tests the PAL implementation of the DuplicateHandle function,
+= with a handle from GetCurrentProcess. The test will create a
+= process, duplicate it, then using ReadProcessMemory will
+= read from the memory location of the CreateProcess process
+= memory and the DuplicateHandle process memory. If the
+= duplication is correct the memory will be the same for both.
diff --git a/src/pal/tests/palsuite/threading/ExitProcess/CMakeLists.txt b/src/pal/tests/palsuite/threading/ExitProcess/CMakeLists.txt
new file mode 100644
index 0000000000..1962ade358
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ExitProcess/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+
diff --git a/src/pal/tests/palsuite/threading/ExitProcess/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/ExitProcess/test1/CMakeLists.txt
new file mode 100644
index 0000000000..decddb8512
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ExitProcess/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ ExitProcess.c
+)
+
+add_executable(paltest_exitprocess_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_exitprocess_test1 coreclrpal)
+
+target_link_libraries(paltest_exitprocess_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/ExitProcess/test1/ExitProcess.c b/src/pal/tests/palsuite/threading/ExitProcess/test1/ExitProcess.c
new file mode 100644
index 0000000000..2b089a0b83
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ExitProcess/test1/ExitProcess.c
@@ -0,0 +1,32 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: exitprocess/test1/exitprocess.c
+**
+** Purpose: Test to ensure ExitProcess returns the argument given
+** to it.
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main( int argc, char **argv )
+
+{
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ ExitProcess(PASS);
+
+ Fail ("ExitProcess(0) failed to exit.\n Test Failed.\n");
+
+ return ( FAIL);
+
+}
diff --git a/src/pal/tests/palsuite/threading/ExitProcess/test1/testinfo.dat b/src/pal/tests/palsuite/threading/ExitProcess/test1/testinfo.dat
new file mode 100644
index 0000000000..d8b85abad6
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ExitProcess/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = ExitProcess
+Name = Positive Test for ExitProcess
+TYPE = DEFAULT
+EXE1 = exitprocess
+Description
+= Test the ExitProcess function. The test runs the ExitProcess function
+= with the TEST_RETURN enumeration value PASS
diff --git a/src/pal/tests/palsuite/threading/ExitProcess/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/ExitProcess/test2/CMakeLists.txt
new file mode 100644
index 0000000000..881c7d0eee
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ExitProcess/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_exitprocess_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_exitprocess_test2 coreclrpal)
+
+target_link_libraries(paltest_exitprocess_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/ExitProcess/test2/test2.c b/src/pal/tests/palsuite/threading/ExitProcess/test2/test2.c
new file mode 100644
index 0000000000..8023ad7bab
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ExitProcess/test2/test2.c
@@ -0,0 +1,30 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test2.c
+**
+** Purpose: Positive test for ExitProcess.
+**
+** Dependencies: none
+**
+
+**
+**===========================================================================*/
+#include <palsuite.h>
+
+
+
+int __cdecl main( int argc, char **argv )
+
+{
+ /* call ExitProcess() -- should work without PAL_Initialize() */
+ ExitProcess(PASS);
+
+
+ /* return failure if we reach here -- note no attempt at */
+ /* meaningful output because we never called PAL_Initialize(). */
+ return FAIL;
+}
diff --git a/src/pal/tests/palsuite/threading/ExitProcess/test2/testinfo.dat b/src/pal/tests/palsuite/threading/ExitProcess/test2/testinfo.dat
new file mode 100644
index 0000000000..0aa07eb15a
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ExitProcess/test2/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = ExitProcess
+Name = Positive test for ExitProcess
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Test to ensure proper operation of the ExitProcess()
+= API by ensuring it works before PAL_Initialize() is
+= called.
diff --git a/src/pal/tests/palsuite/threading/ExitProcess/test3/CMakeLists.txt b/src/pal/tests/palsuite/threading/ExitProcess/test3/CMakeLists.txt
new file mode 100644
index 0000000000..638408e986
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ExitProcess/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_exitprocess_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_exitprocess_test3 coreclrpal)
+
+target_link_libraries(paltest_exitprocess_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/ExitProcess/test3/test3.c b/src/pal/tests/palsuite/threading/ExitProcess/test3/test3.c
new file mode 100644
index 0000000000..aea485e5e3
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ExitProcess/test3/test3.c
@@ -0,0 +1,40 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test3.c
+**
+** Purpose: Positive test for ExitProcess.
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+**
+
+**
+**===========================================================================*/
+#include <palsuite.h>
+
+
+
+int __cdecl main( int argc, char **argv )
+
+{
+ /* initialize the PAL */
+ if( PAL_Initialize(argc, argv) != 0 )
+ {
+ return( FAIL );
+ }
+
+ /* terminate the PAL */
+ PAL_Terminate();
+
+ /* call ExitProcess() -- should work after PAL_Terminate() */
+ ExitProcess( PASS );
+
+
+ /* return failure if we reach here -- note no attempt at */
+ /* meaningful output because we've called PAL_Terminte(). */
+ return FAIL;
+}
diff --git a/src/pal/tests/palsuite/threading/ExitProcess/test3/testinfo.dat b/src/pal/tests/palsuite/threading/ExitProcess/test3/testinfo.dat
new file mode 100644
index 0000000000..c857d885cc
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ExitProcess/test3/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = ExitProcess
+Name = Positive test for ExitProcess
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Test to ensure proper operation of the ExitProcess()
+= API by ensuring it works after PAL_Terminate() is
+= called.
diff --git a/src/pal/tests/palsuite/threading/ExitThread/CMakeLists.txt b/src/pal/tests/palsuite/threading/ExitThread/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ExitThread/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/threading/ExitThread/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/ExitThread/test1/CMakeLists.txt
new file mode 100644
index 0000000000..15e0c1b62d
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ExitThread/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_exitthread_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_exitthread_test1 coreclrpal)
+
+target_link_libraries(paltest_exitthread_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/ExitThread/test1/test1.c b/src/pal/tests/palsuite/threading/ExitThread/test1/test1.c
new file mode 100644
index 0000000000..2963745bef
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ExitThread/test1/test1.c
@@ -0,0 +1,114 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test1.c
+**
+** Purpose: Test for ExitThread. Create a thread and then call
+** exit thread within the threading function. Ensure that it exits
+** immediatly.
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+DWORD dwExitThreadTestParameter = 0;
+
+DWORD PALAPI ExitThreadTestThread( LPVOID lpParameter)
+{
+ DWORD dwRet = 0;
+
+ /* Save parameter for test */
+ dwExitThreadTestParameter = (DWORD)lpParameter;
+
+ /* Call the ExitThread function */
+ ExitThread(dwRet);
+
+ /* If we didn't exit, get caught in this loop. But, the
+ program will exit.
+ */
+ while (!dwRet)
+ {
+ Fail("ERROR: Entered an infinite loop because ExitThread "
+ "failed to exit from the thread. Forcing exit from "
+ "the test now.");
+ }
+
+ return dwRet;
+}
+
+BOOL ExitThreadTest()
+{
+ BOOL bRet = FALSE;
+ DWORD dwRet = 0;
+
+ LPSECURITY_ATTRIBUTES lpThreadAttributes = NULL;
+ DWORD dwStackSize = 0;
+ LPTHREAD_START_ROUTINE lpStartAddress = &ExitThreadTestThread;
+ LPVOID lpParameter = lpStartAddress;
+ DWORD dwCreationFlags = 0; //run immediately
+ DWORD dwThreadId = 0;
+
+ HANDLE hThread = 0;
+
+ dwExitThreadTestParameter = 0;
+
+ /* Create a Thread. We'll need this to test that we're able
+ to exit the thread.
+ */
+ hThread = CreateThread( lpThreadAttributes,
+ dwStackSize, lpStartAddress, lpParameter,
+ dwCreationFlags, &dwThreadId );
+
+ if (hThread != INVALID_HANDLE_VALUE)
+ {
+ dwRet = WaitForSingleObject(hThread,INFINITE);
+
+ if (dwRet != WAIT_OBJECT_0)
+ {
+ Trace("ExitThreadTest:WaitForSingleObject failed "
+ "(%x)\n",GetLastError());
+ }
+ else
+ {
+ /* Check to ensure that the parameter set in the Thread
+ function is correct.
+ */
+ if (dwExitThreadTestParameter != (DWORD)lpParameter)
+ {
+ Trace("ERROR: The paramater passed should have been "
+ "%d but turned up as %d.",
+ dwExitThreadTestParameter, lpParameter);
+ }
+ else
+ {
+ bRet = TRUE;
+ }
+ }
+ }
+ else
+ {
+ Trace("ExitThreadTest:CreateThread failed (%x)\n",GetLastError());
+ }
+
+ return bRet;
+}
+
+int __cdecl main(int argc, char **argv)
+{
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ if(!ExitThreadTest())
+ {
+ Fail ("Test failed\n");
+ }
+
+ PAL_Terminate();
+ return ( PASS );
+}
diff --git a/src/pal/tests/palsuite/threading/ExitThread/test1/testinfo.dat b/src/pal/tests/palsuite/threading/ExitThread/test1/testinfo.dat
new file mode 100644
index 0000000000..a526f8e127
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ExitThread/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = ExitThread
+Name = Positive Test for ExitThread
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Test for ExitThread. Create a thread and then call
+= exit thread within the threading function. Ensure that it exits
+= immediatly.
diff --git a/src/pal/tests/palsuite/threading/ExitThread/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/ExitThread/test2/CMakeLists.txt
new file mode 100644
index 0000000000..aa05382feb
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ExitThread/test2/CMakeLists.txt
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(TESTSOURCES
+ test2.c
+)
+
+add_executable(paltest_exitthread_test2
+ ${TESTSOURCES}
+)
+
+add_dependencies(paltest_exitthread_test2 coreclrpal)
+
+target_link_libraries(paltest_exitthread_test2
+ pthread
+ m
+ coreclrpal
+)
+
+
+set(HELPERSOURCES
+ childprocess.c
+)
+
+add_executable(paltest_exitthread_test2_child
+ ${HELPERSOURCES}
+)
+
+add_dependencies(paltest_exitthread_test2_child coreclrpal)
+
+target_link_libraries(paltest_exitthread_test2_child
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/ExitThread/test2/childprocess.c b/src/pal/tests/palsuite/threading/ExitThread/test2/childprocess.c
new file mode 100644
index 0000000000..7fbe208f91
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ExitThread/test2/childprocess.c
@@ -0,0 +1,41 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: childprocess.c
+**
+** Purpose: Test to ensure ExitThread returns the right
+** value when shutting down the last thread of a process.
+** All this program does is call ExitThread() with a predefined
+** value.
+**
+** Dependencies: none
+**
+
+**
+**=========================================================*/
+
+#include <palsuite.h>
+#include "myexitcode.h"
+
+int __cdecl main( int argc, char **argv )
+{
+ /* initialize the PAL */
+ if( PAL_Initialize(argc, argv) != 0 )
+ {
+ return( FAIL );
+ }
+
+ /* exit the current thread with a magic test value -- it should */
+ /* terminate the process and return that test value from this */
+ /* program. */
+ ExitThread( TEST_EXIT_CODE );
+
+ /* technically we should never get here */
+ PAL_Terminate();
+
+ /* return failure */
+ return FAIL;
+}
diff --git a/src/pal/tests/palsuite/threading/ExitThread/test2/myexitcode.h b/src/pal/tests/palsuite/threading/ExitThread/test2/myexitcode.h
new file mode 100644
index 0000000000..566becb9a0
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ExitThread/test2/myexitcode.h
@@ -0,0 +1,14 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: myexitcode.h
+**
+** Purpose: Define an exit code.
+**
+**
+**==========================================================================*/
+
+#define TEST_EXIT_CODE 316
diff --git a/src/pal/tests/palsuite/threading/ExitThread/test2/test2.c b/src/pal/tests/palsuite/threading/ExitThread/test2/test2.c
new file mode 100644
index 0000000000..c31af8a079
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ExitThread/test2/test2.c
@@ -0,0 +1,168 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test2.c
+**
+** Purpose: Test to ensure ExitThread() called from the last thread of
+** a process shuts down that process and returns the proper
+** exit code as specified in the ExitThread() call.
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** ZeroMemory
+** GetCurrentDirectoryW
+** CreateProcessW
+** WaitForSingleObject
+** GetLastError
+** strlen
+** strncpy
+**
+
+**
+**===========================================================================*/
+#include <palsuite.h>
+#include "myexitcode.h"
+
+
+static const char* rgchPathDelim = "\\";
+
+
+int
+mkAbsoluteFilename( LPSTR dirName,
+ DWORD dwDirLength,
+ LPCSTR fileName,
+ DWORD dwFileLength,
+ LPSTR absPathName )
+{
+ DWORD sizeDN, sizeFN, sizeAPN;
+
+ sizeDN = strlen( dirName );
+ sizeFN = strlen( fileName );
+ sizeAPN = (sizeDN + 1 + sizeFN + 1);
+
+ /* ensure ((dirName + DELIM + fileName + \0) =< _MAX_PATH ) */
+ if( sizeAPN > _MAX_PATH )
+ {
+ return ( 0 );
+ }
+
+ strncpy( absPathName, dirName, dwDirLength +1 );
+ strncpy( absPathName, rgchPathDelim, 2 );
+ strncpy( absPathName, fileName, dwFileLength +1 );
+
+ return (sizeAPN);
+
+}
+
+
+int __cdecl main( int argc, char **argv )
+
+{
+ const char* rgchChildFile = "childprocess";
+
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+
+ DWORD dwError;
+ DWORD dwExitCode;
+ DWORD dwFileLength;
+ DWORD dwDirLength;
+ DWORD dwSize;
+ DWORD dwExpected = TEST_EXIT_CODE;
+
+ char rgchDirName[_MAX_DIR];
+ char absPathBuf[_MAX_PATH];
+ char* rgchAbsPathName;
+
+ /* initialize the PAL */
+ if( PAL_Initialize(argc, argv) != 0 )
+ {
+ return( FAIL );
+ }
+
+ /* zero our process and startup info structures */
+ ZeroMemory( &si, sizeof(si) );
+ si.cb = sizeof( si );
+ ZeroMemory( &pi, sizeof(pi) );
+
+ /* build the absolute path to the child process */
+ rgchAbsPathName = &absPathBuf[0];
+ dwFileLength = strlen( rgchChildFile );
+
+ dwDirLength = GetCurrentDirectory( _MAX_PATH, rgchDirName );
+ if( dwDirLength == 0 )
+ {
+ dwError = GetLastError();
+ Fail( "GetCurrentDirectory call failed with error code %d\n",
+ dwError );
+ }
+
+ dwSize = mkAbsoluteFilename( rgchDirName,
+ dwDirLength,
+ rgchChildFile,
+ dwFileLength,
+ rgchAbsPathName );
+ if( dwSize == 0 )
+ {
+ Fail( "Palsuite Code: mkAbsoluteFilename() call failed. Could ",
+ "not build absolute path name to file\n. Exiting.\n" );
+ }
+
+ /* launch the child process */
+ if( !CreateProcess( NULL, /* module name to execute */
+ rgchAbsPathName, /* command line */
+ NULL, /* process handle not */
+ /* inheritable */
+ NULL, /* thread handle not */
+ /* inheritable */
+ FALSE, /* handle inheritance */
+ CREATE_NEW_CONSOLE, /* dwCreationFlags */
+ NULL, /* use parent's environment */
+ NULL, /* use parent's starting */
+ /* directory */
+ &si, /* startup info struct */
+ &pi ) /* process info struct */
+ )
+ {
+ dwError = GetLastError();
+ Fail( "CreateProcess call failed with error code %d\n",
+ dwError );
+ }
+
+ /* wait for the child process to complete */
+ WaitForSingleObject ( pi.hProcess, INFINITE );
+
+ /* check the exit code from the process */
+ if( ! GetExitCodeProcess( pi.hProcess, &dwExitCode ) )
+ {
+ dwError = GetLastError();
+ CloseHandle ( pi.hProcess );
+ CloseHandle ( pi.hThread );
+ Fail( "GetExitCodeProcess call failed with error code %d\n",
+ dwError );
+ }
+
+ /* close process and thread handle */
+ CloseHandle ( pi.hProcess );
+ CloseHandle ( pi.hThread );
+
+ /* check for the expected exit code */
+ /* exit code for some systems is as small as a char, so that's all */
+ /* we'll compare for checking success */
+ if( LOBYTE(LOWORD(dwExitCode)) != LOBYTE(LOWORD(dwExpected)) )
+ {
+ Fail( "GetExitCodeProcess returned an incorrect exit code %d, "
+ "expected value is %d\n",
+ LOWORD(dwExitCode), dwExpected );
+ }
+
+ /* terminate the PAL */
+ PAL_Terminate();
+
+ /* return success */
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/threading/ExitThread/test2/testinfo.dat b/src/pal/tests/palsuite/threading/ExitThread/test2/testinfo.dat
new file mode 100644
index 0000000000..4b5bdc2ac6
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ExitThread/test2/testinfo.dat
@@ -0,0 +1,19 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = ExitThread
+Name = Test for ExitThread
+TYPE = DEFAULT
+EXE1 = test2
+EXE2 = childprocess
+Description
+= Test to ensure proper operation of the ExitThread
+= API. This test launches a simple child process that exits
+= by calling ExitThread() with a known value, and checks
+= that the correct value is returned to the parent process.
+= This verifies that when the last thread of a process exits
+= via ExitThread, the process exits with the proper return
+= code.
diff --git a/src/pal/tests/palsuite/threading/ExitThread/test3/dllmain.c b/src/pal/tests/palsuite/threading/ExitThread/test3/dllmain.c
new file mode 100644
index 0000000000..923650d1d3
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ExitThread/test3/dllmain.c
@@ -0,0 +1,65 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: dllmain.c
+**
+** Purpose: Test to ensure DllMain() is called with THREAD_DETACH
+** when a thread in the application calls ExitThread().
+**
+** Dependencies: none
+**
+
+**
+**===========================================================================*/
+
+#include <palsuite.h>
+
+/* count of the number of times DllMain() was called with THREAD_DETACH */
+static int g_detachCount = 0;
+
+
+/* standard DllMain() */
+BOOL PALAPI DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID lpvReserved)
+{
+ switch( reason )
+ {
+ case DLL_PROCESS_ATTACH:
+ {
+ break;
+ }
+
+ case DLL_PROCESS_DETACH:
+ {
+ break;
+ }
+
+ case DLL_THREAD_ATTACH:
+ break;
+
+ case DLL_THREAD_DETACH:
+ /* increment g_detachCount */
+ g_detachCount++;
+ break;
+ }
+ return TRUE;
+}
+
+#ifdef WIN32
+BOOL __stdcall _DllMainCRTStartup(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ return DllMain(hinstDLL, fdwReason, lpvReserved);
+}
+#endif
+
+
+/* function to return the current detach count */
+#ifdef WIN32
+__declspec(dllexport)
+#endif
+int PALAPI GetDetachCount( void )
+{
+ return g_detachCount;
+}
diff --git a/src/pal/tests/palsuite/threading/ExitThread/test3/test3.c b/src/pal/tests/palsuite/threading/ExitThread/test3/test3.c
new file mode 100644
index 0000000000..8a71c7cc99
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ExitThread/test3/test3.c
@@ -0,0 +1,162 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test3.c
+**
+** Purpose: Test to ensure ExitThread() results in any loaded dynamic
+** libraries having their entry point called with a THREAD_DETACH
+** notification.
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** GetCurrentDirectoryW
+** CreateThread
+** ResumeThread
+** LoadLibrary
+** FreeLibrary
+** GetProcAddress
+** WaitForSingleObject
+** GetLastError
+** strlen
+** strncpy
+**
+
+**
+**===========================================================================*/
+#include <palsuite.h>
+
+/* SHLEXT is defined only for Unix variants */
+
+#if defined(SHLEXT)
+#define rgchLibraryFile "dllmain"SHLEXT
+#define szFunction "GetDetachCount"
+#else
+#define rgchLibraryFile "dllmain"
+#define szFunction "_GetDetachCount@0"
+#endif
+
+/* define our test function type */
+typedef int ( PALAPI *LPTESTFUNC )( void );
+
+
+/**
+ * ThreadFunc
+ *
+ * Dummy thread function for causing DLL thread notifications.
+ */
+DWORD PALAPI ThreadFunc( LPVOID param )
+{
+ /* simulate some brief "work" */
+ int i;
+ for( i=0; i<100000; i++ )
+ ;
+
+ ExitThread( 0 );
+ return (0);
+}
+
+
+/* main program entry point */
+int __cdecl main( int argc, char **argv )
+
+{
+ /* local variables */
+
+ HANDLE hLib = NULL;
+ LPTESTFUNC pFunc;
+ int detachCount1 = 0;
+ int detachCount2 = 0;
+
+ HANDLE hThread = NULL;
+ DWORD IDThread;
+
+ /* initialize the PAL */
+ if( PAL_Initialize(argc, argv) != 0 )
+ {
+ return( FAIL );
+ }
+
+ /* Load the test library */
+ hLib = LoadLibrary( rgchLibraryFile );
+ if(hLib == NULL)
+ {
+ Fail("ERROR: Unable to load library %s\n", rgchLibraryFile );
+ }
+
+
+ /* Get the address of our test function in the dll */
+ pFunc = (LPTESTFUNC)GetProcAddress( hLib, szFunction );
+ if( pFunc == NULL )
+ {
+ Trace( "ERROR:%lu%:Unable to load function \"%s\" library \"%s\"\n",
+ GetLastError(),
+ szFunction,
+ rgchLibraryFile );
+ if( ! FreeLibrary( hLib ) ) {
+ Trace( "FreeLibrary() failed with error code %lu\n",
+ GetLastError() );
+ }
+ Fail( "Exiting\n" );
+ }
+
+ /* Execute the test function to get the detach count */
+ detachCount1 = pFunc();
+
+ /* run another dummy thread to cause notification of the library */
+ hThread = CreateThread( NULL, /* no security attributes */
+ 0, /* use default stack size */
+ (LPTHREAD_START_ROUTINE) ThreadFunc, /* thread function */
+ (LPVOID) NULL, /* pass thread index as */
+ /* function argument */
+ CREATE_SUSPENDED, /* create suspended */
+ &IDThread ); /* returns thread id */
+
+ /* Check the return value for success. */
+ if( hThread == NULL )
+ {
+ /* error creating thread */
+ Trace( "Unexpected CreateThread error %d\n",
+ GetLastError() );
+ if( ! FreeLibrary( hLib ) ) {
+ Trace( "FreeLibrary() failed with error code %lu\n",
+ GetLastError() );
+ }
+ Fail( "Exiting\n" );
+ }
+
+ /* Resume the suspended thread */
+ ResumeThread( hThread );
+
+ /* wait for the thread to complete */
+ WaitForSingleObject( hThread, INFINITE );
+
+ /* Execute the test function to get the new detach count */
+ detachCount2 = pFunc();
+
+ /* Unload the test library */
+ if( !FreeLibrary( hLib ) )
+ {
+ Fail( "ERROR:%u: Unable to free library \"%s\"\n",
+ GetLastError(),
+ rgchLibraryFile );
+ }
+
+ /* validate the result */
+ if( detachCount2 != (detachCount1 + 1) )
+ {
+ Fail( "FAIL: unexpected DLL detach count %d, expected %d\n",
+ detachCount2,
+ (detachCount1 + 1) );
+ }
+
+
+ /* terminate the PAL */
+ PAL_Terminate();
+
+ /* return success */
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/threading/ExitThread/test3/testinfo.dat b/src/pal/tests/palsuite/threading/ExitThread/test3/testinfo.dat
new file mode 100644
index 0000000000..1c9e8c7567
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ExitThread/test3/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = ExitThread
+Name = Test for ExitThread
+TYPE = DEFAULT
+EXE1 = test3
+LIB1 = dllmain
+Description
+= Test to ensure proper operation of the ExitThread
+= API. This tests to make sure ExitThread() results
+= in any loaded dynamic libraries having their entry
+= point called with a THREAD_DETACH notification.
diff --git a/src/pal/tests/palsuite/threading/GetCurrentProcess/CMakeLists.txt b/src/pal/tests/palsuite/threading/GetCurrentProcess/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/GetCurrentProcess/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/threading/GetCurrentProcess/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/GetCurrentProcess/test1/CMakeLists.txt
new file mode 100644
index 0000000000..44105348be
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/GetCurrentProcess/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ process.c
+)
+
+add_executable(paltest_getcurrentprocess_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getcurrentprocess_test1 coreclrpal)
+
+target_link_libraries(paltest_getcurrentprocess_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/GetCurrentProcess/test1/process.c b/src/pal/tests/palsuite/threading/GetCurrentProcess/test1/process.c
new file mode 100644
index 0000000000..17d9af6282
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/GetCurrentProcess/test1/process.c
@@ -0,0 +1,40 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: GetCurrentProcess/test1/process.c
+**
+** Purpose: Test for to see if the process GetCurrentProcess
+** returns a handle to the current process or not.
+**
+** Dependencies: TerminateProcess
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+INT __cdecl main( int argc, char **argv )
+{
+
+ HANDLE hProcess;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ hProcess = GetCurrentProcess();
+ Trace ("Testing the handle returned by GetCurrentProcess\n");
+ if ( 0 == ( TerminateProcess ( hProcess, PASS ) ) )
+ {
+ Fail ("Testing GetCurrentProcess, the TerminateProcess function "
+ "failed.\n");
+ }
+
+ PAL_Terminate();
+ return ( PASS );
+
+}
diff --git a/src/pal/tests/palsuite/threading/GetCurrentProcess/test1/testinfo.dat b/src/pal/tests/palsuite/threading/GetCurrentProcess/test1/testinfo.dat
new file mode 100644
index 0000000000..8eb2759fb9
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/GetCurrentProcess/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = GetCurrentProcess
+Name = Positive Test for GetCurrentProcess
+TYPE = DEFAULT
+EXE1 = process
+Description
+= Test to see if the function GetCurrentProcess returns a handle to the
+= current process or not.
diff --git a/src/pal/tests/palsuite/threading/GetCurrentProcessId/CMakeLists.txt b/src/pal/tests/palsuite/threading/GetCurrentProcessId/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/GetCurrentProcessId/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/CMakeLists.txt
new file mode 100644
index 0000000000..e5c31e6af2
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ processId.c
+)
+
+add_executable(paltest_getcurrentprocessid_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getcurrentprocessid_test1 coreclrpal)
+
+target_link_libraries(paltest_getcurrentprocessid_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/processId.c b/src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/processId.c
new file mode 100644
index 0000000000..cc689b3f8b
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/processId.c
@@ -0,0 +1,41 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: getcurrentprocessid/test1/processid.c
+**
+** Purpose: Test to ensure GetCurrentProcessId returns the current
+** process id number. This test compares the result of
+** GetCurrentProcessId to getpid.
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+INT __cdecl main( int argc, char **argv )
+{
+
+ DWORD dwProcessId;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ dwProcessId = GetCurrentProcessId();
+
+ if ( 0 >= dwProcessId )
+ {
+ Fail ("%s has dwProcessId has id value %d\n", argv[0],
+ dwProcessId );
+ }
+ Trace ("%s has dwProcessId %d\nPassing test as dwProcessId is > 0\n"
+ , argv[0], dwProcessId);
+
+ PAL_Terminate();
+ return ( PASS );
+
+}
diff --git a/src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/testinfo.dat b/src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/testinfo.dat
new file mode 100644
index 0000000000..db615c0bf9
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = GetCurrentProcessId
+Name = Positive Test for GetCurrentProcessId
+TYPE = DEFAULT
+EXE1 = processid
+Description
+= Test to ensure GetCurrentProcessId returns the current process id number.
+= This test compares the result of GetCurrentProcessId to getpid.
diff --git a/src/pal/tests/palsuite/threading/GetCurrentThread/CMakeLists.txt b/src/pal/tests/palsuite/threading/GetCurrentThread/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/GetCurrentThread/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/threading/GetCurrentThread/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/GetCurrentThread/test1/CMakeLists.txt
new file mode 100644
index 0000000000..84cbccbca0
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/GetCurrentThread/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ thread.c
+)
+
+add_executable(paltest_getcurrentthread_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getcurrentthread_test1 coreclrpal)
+
+target_link_libraries(paltest_getcurrentthread_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/GetCurrentThread/test1/testinfo.dat b/src/pal/tests/palsuite/threading/GetCurrentThread/test1/testinfo.dat
new file mode 100644
index 0000000000..29c9767ed0
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/GetCurrentThread/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = GetCurrentThread
+Name = Positive Test for GetCurrentThread
+TYPE = DEFAULT
+EXE1 = thread
+Description
+= Test to ensure GetCurrentThread returns a handle to the current thread.
diff --git a/src/pal/tests/palsuite/threading/GetCurrentThread/test1/thread.c b/src/pal/tests/palsuite/threading/GetCurrentThread/test1/thread.c
new file mode 100644
index 0000000000..b2bb97fd67
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/GetCurrentThread/test1/thread.c
@@ -0,0 +1,93 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: GetCurrentThread/test1/thread.c
+**
+** Purpose: Test to ensure GetCurrentThread returns a handle to
+** the current thread.
+**
+** Dependencies: GetThreadPriority
+** SetThreadPriority
+** Fail
+** Trace
+**
+
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main( int argc, char **argv )
+{
+
+ HANDLE hThread;
+ int nPriority;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+#if !HAVE_SCHED_OTHER_ASSIGNABLE
+ /* Defining thread priority for SCHED_OTHER is implementation defined.
+ Some platforms like NetBSD cannot reassign it as they are dynamic.
+ */
+ printf("paltest_getcurrentthread_test1 has been disabled on this platform\n");
+#else
+ hThread = GetCurrentThread();
+
+ nPriority = GetThreadPriority(hThread);
+
+ if ( THREAD_PRIORITY_NORMAL != nPriority )
+ {
+ if ( THREAD_PRIORITY_ERROR_RETURN == nPriority )
+ {
+ Fail ("GetThreadPriority function call failed for %s\n"
+ "GetLastError returned %d\n", argv[0], GetLastError());
+ }
+ else
+ {
+ Fail ("GetThreadPriority function call failed for %s\n"
+ "The priority returned was %d\n", argv[0], nPriority);
+ }
+ }
+ else
+ {
+ nPriority = 0;
+
+ if (0 == SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST))
+ {
+ Fail ("Unable to set thread priority. Either handle doesn't"
+ " point to current thread \nor SetThreadPriority "
+ "function failed. Failing test.\n");
+ }
+
+ nPriority = GetThreadPriority(hThread);
+
+ if ( THREAD_PRIORITY_ERROR_RETURN == nPriority )
+ {
+ Fail ("GetThreadPriority function call failed for %s\n"
+ "GetLastError returned %d\n", argv[0], GetLastError());
+ }
+ else if ( THREAD_PRIORITY_HIGHEST == nPriority )
+ {
+ Trace ("GetCurrentThread returns handle to the current "
+ "thread.\n");
+ exit ( PASS );
+ }
+ else
+ {
+ Fail ("Unable to set thread priority. Either handle doesn't"
+ " point to current thread \nor SetThreadPriority "
+ "function failed. Failing test.\n");
+ }
+ }
+#endif
+
+ PAL_Terminate();
+ return ( PASS );
+
+}
diff --git a/src/pal/tests/palsuite/threading/GetCurrentThread/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/GetCurrentThread/test2/CMakeLists.txt
new file mode 100644
index 0000000000..3fc3c3e7c6
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/GetCurrentThread/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_getcurrentthread_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getcurrentthread_test2 coreclrpal)
+
+target_link_libraries(paltest_getcurrentthread_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/GetCurrentThread/test2/test2.c b/src/pal/tests/palsuite/threading/GetCurrentThread/test2/test2.c
new file mode 100644
index 0000000000..beeb5ec241
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/GetCurrentThread/test2/test2.c
@@ -0,0 +1,144 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test2.c
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** CreateThread
+** SetThreadPriority
+** GetThreadPriority
+** ResumeThread
+** WaitForSingleObject
+** GetLastError
+**
+** Purpose:
+**
+** Test to ensure proper operation of the GetCurrentThread()
+** API. The test launches a thread in suspended mode, and sets
+** its priority to a non-default value using the handle returned
+** by CreateThread(). The new thread calls GetCurrentThred() to
+** retrieve a handle to itself, and calls GetThreadPriority()
+** to verify that its priority matches what it was set to on
+** the main execution thread.
+**
+
+**
+**===========================================================================*/
+#include <palsuite.h>
+
+
+/* we store the return code from the child thread here because */
+/* we're missing the GetExitCodeThread() API */
+
+static int g_priority = 0;
+
+/**
+ * ThreadFunc
+ *
+ * Thread function that calls GetCurrentThread() to get a pseudo-handle
+ * to itself, then checks its priority and exits with that value.
+ */
+DWORD PALAPI ThreadFunc( LPVOID param )
+{
+ int priority;
+ HANDLE hThread;
+
+ /* call GetCurrentThread() to get a pseudo-handle to */
+ /* the current thread */
+ hThread = GetCurrentThread();
+ if( hThread == NULL )
+ {
+ Fail( "GetCurrentThread() call failed\n" );
+ }
+
+
+ /* get the current thread priority */
+ priority = GetThreadPriority( hThread );
+ if( priority == THREAD_PRIORITY_ERROR_RETURN )
+ {
+ /* GetThreadPriority call failed */
+ Fail( "ERROR:%lu:GetThreadPriority() call failed\n", GetLastError() );
+ }
+
+ /* store this globally because we don't have GetExitCodeThread() */
+ g_priority = priority;
+ return (DWORD)priority;
+}
+
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+INT __cdecl main( INT argc, CHAR **argv )
+{
+ HANDLE hThread = NULL;
+ DWORD IDThread;
+ DWORD dwRet;
+
+ SIZE_T i = 0;
+
+ /* PAL initialization */
+ if( (PAL_Initialize(argc, argv)) != 0 )
+ {
+ return( FAIL );
+ }
+
+#if !HAVE_SCHED_OTHER_ASSIGNABLE
+ /* Defining thread priority for SCHED_OTHER is implementation defined.
+ Some platforms like NetBSD cannot reassign it as they are dynamic.
+ */
+ printf("paltest_getcurrentthread_test2 has been disabled on this platform\n");
+#else
+ /* Create multiple threads. */
+ hThread = CreateThread( NULL, /* no security attributes */
+ 0, /* use default stack size */
+ (LPTHREAD_START_ROUTINE) ThreadFunc, /* thread function */
+ (LPVOID) i, /* pass thread index as */
+ /* function argument */
+ CREATE_SUSPENDED, /* create suspended */
+ &IDThread ); /* returns thread identifier */
+
+ /* Check the return value for success. */
+ if( hThread == NULL )
+ {
+ /* ERROR */
+ Fail( "ERROR:%lu:CreateThread failed\n", GetLastError() );
+ }
+
+ /* set the thread priority of the new thread to the highest value */
+ if( ! SetThreadPriority( hThread, THREAD_PRIORITY_TIME_CRITICAL) )
+ {
+ Fail( "ERROR:%lu:SetThreadPriority() call failed\n", GetLastError() );
+ }
+
+ /* let the child thread run now */
+ ResumeThread( hThread );
+
+
+ /* wait for the thread to finish */
+ dwRet = WaitForSingleObject( hThread, INFINITE );
+ if( dwRet == WAIT_FAILED )
+ {
+ /* ERROR */
+ Fail( "ERROR:%lu:WaitForSingleObject call failed\n", GetLastError() );
+ }
+
+ /* validate the thread's exit code */
+ if( g_priority != THREAD_PRIORITY_TIME_CRITICAL )
+ {
+ /* ERROR */
+ Fail( "FAIL:Unexpected thread priority %d returned, expected %d\n",
+ g_priority, THREAD_PRIORITY_TIME_CRITICAL );
+ }
+#endif
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/threading/GetCurrentThread/test2/testinfo.dat b/src/pal/tests/palsuite/threading/GetCurrentThread/test2/testinfo.dat
new file mode 100644
index 0000000000..96a6d403bb
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/GetCurrentThread/test2/testinfo.dat
@@ -0,0 +1,18 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = GetCurrentThread
+Name = Test for GetCurrentThread
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Test to ensure proper operation of the GetCurrentThread()
+= API. The test launches a thread in suspended mode, and sets
+= its priority to a non-default value using the handle returned
+= by CreateThread(). The new thread calls GetCurrentThred() to
+= retrieve a handle to itself, and calls GetThreadPriority()
+= to verify that its priority matches what it was set to on
+= the main execution thread.
diff --git a/src/pal/tests/palsuite/threading/GetCurrentThreadId/CMakeLists.txt b/src/pal/tests/palsuite/threading/GetCurrentThreadId/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/GetCurrentThreadId/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/CMakeLists.txt
new file mode 100644
index 0000000000..490bff8f5f
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ threadId.c
+)
+
+add_executable(paltest_getcurrentthreadid_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getcurrentthreadid_test1 coreclrpal)
+
+target_link_libraries(paltest_getcurrentthreadid_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/testinfo.dat b/src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/testinfo.dat
new file mode 100644
index 0000000000..4d1e056b71
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = GetCurrentThreadId
+Name = Positive Test for GetCurrentThreadId
+TYPE = DEFAULT
+EXE1 = threadid
+Description
+= Test to ensure GetCurrentThreadId returns the threadId of the current
+= thread.
diff --git a/src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/threadId.c b/src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/threadId.c
new file mode 100644
index 0000000000..acbb1ff373
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/threadId.c
@@ -0,0 +1,82 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: getcurrentthreadid/test1/threadid.c
+**
+** Purpose: Test to ensure GetCurrentThreadId returns the threadId of the
+** current thread.
+**
+** Dependencies: CloseHandle
+** WaitForSingleObject
+** CreateThread
+**
+
+**
+**=========================================================*/
+
+
+#include <palsuite.h>
+
+DWORD dwThreadIdTF;
+
+DWORD PALAPI ThreadFunction ( LPVOID lpParam )
+{
+ Trace ("thread code executed\n");
+ dwThreadIdTF = GetCurrentThreadId();
+ return 0;
+}
+
+int __cdecl main( int argc, char **argv )
+{
+ extern DWORD dwThreadIdTF;
+ DWORD dwThreadIdCT;
+ HANDLE hThread;
+ DWORD dwThreadParam = 1;
+ DWORD dwThreadWait;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ hThread = CreateThread(
+ NULL,
+ 0,
+ ThreadFunction,
+ &dwThreadParam,
+ 0,
+ &dwThreadIdCT);
+
+ if ( NULL == hThread )
+ {
+ Fail ( "CreateThread() call failed - returned NULL");
+ }
+ else
+ {
+ dwThreadWait = WaitForSingleObject( hThread, INFINITE );
+
+ Trace ("dwThreadWait returned %d\n", dwThreadWait );
+
+ if ( dwThreadIdCT == dwThreadIdTF )
+ {
+ Trace ( "ThreadId numbers match - GetCurrentThreadId"
+ " works. dwThreadIdCT == dwThreadIdTF == %d\n",
+ dwThreadIdTF );
+ PAL_Terminate();
+ return ( PASS );
+ }
+ else
+ {
+ Fail ( "ThreadId numbers don't match - "
+ "GetCurrentThreadId fails dwThreadIdCT = %d "
+ "and dwThreadIdTF = %d\n", dwThreadIdCT, dwThreadIdTF);
+ }
+ }
+
+ PAL_TerminateEx(FAIL);
+ return (FAIL);
+
+}
diff --git a/src/pal/tests/palsuite/threading/GetExitCodeProcess/CMakeLists.txt b/src/pal/tests/palsuite/threading/GetExitCodeProcess/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/GetExitCodeProcess/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/CMakeLists.txt
new file mode 100644
index 0000000000..adddd97e6d
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/CMakeLists.txt
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(TESTSOURCES
+ test1.c
+)
+
+add_executable(paltest_getexitcodeprocess_test1
+ ${TESTSOURCES}
+)
+
+add_dependencies(paltest_getexitcodeprocess_test1 coreclrpal)
+
+target_link_libraries(paltest_getexitcodeprocess_test1
+ pthread
+ m
+ coreclrpal
+)
+
+
+set(HELPERSOURCES
+ childProcess.c
+)
+
+add_executable(paltest_getexitcodeprocess_test1_child
+ ${HELPERSOURCES}
+)
+
+add_dependencies(paltest_getexitcodeprocess_test1_child coreclrpal)
+
+target_link_libraries(paltest_getexitcodeprocess_test1_child
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/childProcess.c b/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/childProcess.c
new file mode 100644
index 0000000000..fe1b38fb31
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/childProcess.c
@@ -0,0 +1,31 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: childprocess.c
+**
+** Purpose: Test to ensure GetExitCodeProcess returns the right
+** value. All this program does is return a predefined value.
+**
+** Dependencies: none
+**
+
+**
+**=========================================================*/
+
+#include <pal.h>
+#include "myexitcode.h"
+
+int __cdecl main( int argc, char **argv )
+{
+ int i;
+
+ // simulate some activity
+ for( i=0; i<10000; i++ )
+ ;
+
+ // return the predefined exit code
+ return TEST_EXIT_CODE;
+}
diff --git a/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/myexitcode.h b/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/myexitcode.h
new file mode 100644
index 0000000000..60a140d1f3
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/myexitcode.h
@@ -0,0 +1,14 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: myexitcode.h
+**
+** Purpose: Define an exit code.
+**
+**
+**==========================================================================*/
+
+#define TEST_EXIT_CODE 104
diff --git a/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/test1.c b/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/test1.c
new file mode 100644
index 0000000000..0f98cf8f57
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/test1.c
@@ -0,0 +1,163 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test to ensure GetExitCodeProcess works properly.
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** ZeroMemory
+** GetCurrentDirectoryW
+** CreateProcessW
+** WaitForSingleObject
+** GetLastError
+** strlen
+** strncpy
+**
+
+**
+**===========================================================================*/
+#include <palsuite.h>
+#include "myexitcode.h"
+
+
+static const char* rgchPathDelim = "\\";
+
+
+int
+mkAbsoluteFilename( LPSTR dirName,
+ DWORD dwDirLength,
+ LPCSTR fileName,
+ DWORD dwFileLength,
+ LPSTR absPathName )
+{
+ DWORD sizeDN, sizeFN, sizeAPN;
+
+ sizeDN = strlen( dirName );
+ sizeFN = strlen( fileName );
+ sizeAPN = (sizeDN + 1 + sizeFN + 1);
+
+ /* ensure ((dirName + DELIM + fileName + \0) =< _MAX_PATH ) */
+ if( sizeAPN > _MAX_PATH )
+ {
+ return ( 0 );
+ }
+
+ strncpy( absPathName, dirName, dwDirLength +1 );
+ strncpy( absPathName, rgchPathDelim, 2 );
+ strncpy( absPathName, fileName, dwFileLength +1 );
+
+ return (sizeAPN);
+
+}
+
+
+int __cdecl main( int argc, char **argv )
+
+{
+ const char* rgchChildFile = "childprocess";
+
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+
+ DWORD dwError;
+ DWORD dwExitCode;
+ DWORD dwFileLength;
+ DWORD dwDirLength;
+ DWORD dwSize;
+
+ char rgchDirName[_MAX_DIR];
+ char absPathBuf[_MAX_PATH];
+ char* rgchAbsPathName;
+
+ /* initialize the PAL */
+ if( PAL_Initialize(argc, argv) != 0 )
+ {
+ return( FAIL );
+ }
+
+ /* zero our process and startup info structures */
+ ZeroMemory( &si, sizeof(si) );
+ si.cb = sizeof( si );
+ ZeroMemory( &pi, sizeof(pi) );
+
+ /* build the absolute path to the child process */
+ rgchAbsPathName = &absPathBuf[0];
+ dwFileLength = strlen( rgchChildFile );
+
+ dwDirLength = GetCurrentDirectory( _MAX_PATH, rgchDirName );
+ if( dwDirLength == 0 )
+ {
+ dwError = GetLastError();
+ Fail( "GetCurrentDirectory call failed with error code %d\n",
+ dwError );
+ }
+
+ dwSize = mkAbsoluteFilename( rgchDirName,
+ dwDirLength,
+ rgchChildFile,
+ dwFileLength,
+ rgchAbsPathName );
+ if( dwSize == 0 )
+ {
+ Fail( "Palsuite Code: mkAbsoluteFilename() call failed. Could ",
+ "not build absolute path name to file\n. Exiting.\n" );
+ }
+
+ /* launch the child process */
+ if( !CreateProcess( NULL, /* module name to execute */
+ rgchAbsPathName, /* command line */
+ NULL, /* process handle not */
+ /* inheritable */
+ NULL, /* thread handle not */
+ /* inheritable */
+ FALSE, /* handle inheritance */
+ CREATE_NEW_CONSOLE, /* dwCreationFlags */
+ NULL, /* use parent's environment */
+ NULL, /* use parent's starting */
+ /* directory */
+ &si, /* startup info struct */
+ &pi ) /* process info struct */
+ )
+ {
+ dwError = GetLastError();
+ Fail( "CreateProcess call failed with error code %d\n",
+ dwError );
+ }
+
+ /* wait for the child process to complete */
+ WaitForSingleObject ( pi.hProcess, INFINITE );
+
+ /* check the exit code from the process */
+ if( ! GetExitCodeProcess( pi.hProcess, &dwExitCode ) )
+ {
+ dwError = GetLastError();
+ CloseHandle ( pi.hProcess );
+ CloseHandle ( pi.hThread );
+ Fail( "GetExitCodeProcess call failed with error code %d\n",
+ dwError );
+ }
+
+ /* close process and thread handle */
+ CloseHandle ( pi.hProcess );
+ CloseHandle ( pi.hThread );
+
+ /* check for the expected exit code */
+ if( dwExitCode != TEST_EXIT_CODE )
+ {
+ Fail( "GetExitCodeProcess returned an incorrect exit code %d, "
+ "expected value is %d\n",
+ dwExitCode, TEST_EXIT_CODE );
+ }
+
+ /* terminate the PAL */
+ PAL_Terminate();
+
+ /* return success */
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/testinfo.dat b/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/testinfo.dat
new file mode 100644
index 0000000000..d06719f0b0
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = GetExitCodeProcess
+Name = Test for GetExitCodeProcess
+TYPE = DEFAULT
+EXE1 = test1
+EXE2 = childprocess
+Description
+= Test to ensure proper operation of the GetExitCodeProcess
+= API. This test launches a simple child process that exits
+= with a known value, and checks that the correct value is
+= returned by the function.
diff --git a/src/pal/tests/palsuite/threading/GetProcessTimes/CMakeLists.txt b/src/pal/tests/palsuite/threading/GetProcessTimes/CMakeLists.txt
new file mode 100644
index 0000000000..f4796dc1d3
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/GetProcessTimes/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/threading/GetProcessTimes/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/GetProcessTimes/test2/CMakeLists.txt
new file mode 100644
index 0000000000..0ef7260204
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/GetProcessTimes/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_getprocesstimes_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getprocesstimes_test2 coreclrpal)
+
+target_link_libraries(paltest_getprocesstimes_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/GetProcessTimes/test2/test2.c b/src/pal/tests/palsuite/threading/GetProcessTimes/test2/test2.c
new file mode 100644
index 0000000000..687facc584
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/GetProcessTimes/test2/test2.c
@@ -0,0 +1,122 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test2.c
+**
+** Purpose: Test to ensure GetProcessTimes works properly.
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** ZeroMemory
+** CompareFileTime
+** GetLastError
+**
+
+**
+**===========================================================================*/
+#include <palsuite.h>
+
+
+int __cdecl main( int argc, char **argv )
+
+{
+ int i, j, k;
+ int *total;
+
+ HANDLE hProcess;
+ FILETIME createTime;
+ FILETIME exitTime;
+ FILETIME kernelTime1;
+ FILETIME userTime1;
+ FILETIME kernelTime2;
+ FILETIME userTime2;
+
+ DWORD dwError;
+
+ /* initialize the PAL */
+ if( PAL_Initialize(argc, argv) != 0 )
+ {
+ return( FAIL );
+ }
+
+ /* get our own process handle */
+ hProcess = GetCurrentProcess();
+ if( hProcess == NULL )
+ {
+ Fail( "GetCurrentProcess() returned a NULL handle.\n" );
+ }
+
+ /* zero our time structures */
+ ZeroMemory( &createTime, sizeof(createTime) );
+ ZeroMemory( &exitTime, sizeof(exitTime) );
+ ZeroMemory( &kernelTime1, sizeof(kernelTime1) );
+ ZeroMemory( &userTime1, sizeof(userTime1) );
+ ZeroMemory( &kernelTime2, sizeof(kernelTime2) );
+ ZeroMemory( &userTime2, sizeof(userTime2) );
+
+ /* check the process times for the child process */
+ if( ! GetProcessTimes( hProcess,
+ &createTime,
+ &exitTime,
+ &kernelTime1,
+ &userTime1 ) )
+ {
+ dwError = GetLastError();
+ Fail( "GetProcessTimes() call failed with error code %d\n",
+ dwError );
+ }
+
+
+ /* simulate some activity */
+ for( i=0; i<1000; i++ )
+ {
+ for( j=0; j<1000; j++ )
+ {
+ /* do kernel work to increase system usage counters */
+ total = malloc(1024 * 1024);
+
+ *total = j * i;
+ for( k=0; k<1000; k++ )
+ {
+ *total += k + i;
+ }
+
+ free(total);
+ }
+ }
+
+ /* check the process times for the child process */
+ if( ! GetProcessTimes( hProcess,
+ &createTime,
+ &exitTime,
+ &kernelTime2,
+ &userTime2 ) )
+ {
+ dwError = GetLastError();
+ Fail( "GetProcessTimes() call failed with error code %d\n",
+ dwError );
+ }
+
+
+ /* very simple logical checking of the results */
+ if( CompareFileTime( &kernelTime1, &kernelTime2 ) > 0 )
+ {
+ Fail( "Unexpected kernel time value reported.\n" );
+ }
+
+ if( CompareFileTime( &userTime1, &userTime2 ) > 0 )
+ {
+ Fail( "Unexpected user time value reported.\n" );
+ }
+
+
+ /* terminate the PAL */
+ PAL_Terminate();
+
+ /* return success */
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/threading/GetProcessTimes/test2/testinfo.dat b/src/pal/tests/palsuite/threading/GetProcessTimes/test2/testinfo.dat
new file mode 100644
index 0000000000..d0d3b75f06
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/GetProcessTimes/test2/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = GetProcessTimes
+Name = Test for GetProcessTimes
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Test to ensure proper operation of the GetProcessTimes()
+= API. This test simply checks the kernel/user times for the
+= the current process, which is the only thing supported
+= for this function under the PAL.
diff --git a/src/pal/tests/palsuite/threading/GetThreadTimes/CMakeLists.txt b/src/pal/tests/palsuite/threading/GetThreadTimes/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/GetThreadTimes/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/threading/GetThreadTimes/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/GetThreadTimes/test1/CMakeLists.txt
new file mode 100644
index 0000000000..d7e2eb2a88
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/GetThreadTimes/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_getthreadtimes_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_getthreadtimes_test1 coreclrpal)
+
+target_link_libraries(paltest_getthreadtimes_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/GetThreadTimes/test1/test1.c b/src/pal/tests/palsuite/threading/GetThreadTimes/test1/test1.c
new file mode 100644
index 0000000000..6b62c05ec7
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/GetThreadTimes/test1/test1.c
@@ -0,0 +1,102 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source:
+**
+** Source : test1.c
+**
+** Purpose: Test for GetThreadTimes() function
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[]) {
+ int ret = FAIL;
+
+ //Test is failing unreliably, so for now we always return pass.
+ if (TRUE){
+ ret = PASS;
+ goto EXIT;
+ }
+
+ FILETIME kernelTime1, userTime1, kernelTime2, userTime2;
+ /* Delta = .01 sec */
+ LONG64 Actual, Expected, Delta = 850000000;
+ Actual = 0;
+ Expected = 0;
+ const ULONG64 MSEC_TO_NSEC = 1000000;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ HANDLE cThread = GetCurrentThread();
+
+ int i;
+ /* Take 2000 tiny measurements */
+ for (i = 0; i < 2000; i++){
+ ULONG64 Time1, Time2;
+
+ Sleep(1);
+
+ /* Grab a FirstCount, then loop for a bit to make the clock increase */
+ if (!GetThreadTimes(cThread, NULL, NULL, &kernelTime1, &userTime1))
+ {
+ Fail("ERROR: GetThreadTimes returned failure.\n");
+ }
+ LONG64 x, Init;
+ /* Init is in milliseconds, so we will convert later */
+ Init = (ULONG64)GetTickCount();
+ /* Spin for < 1 Quantum so we don't get interrupted */
+ x = Init + 3;
+ volatile int counter;
+ do {
+ for (counter = 0; counter < 100000; counter++)
+ {
+ // spin to consume CPU time
+ }
+
+ } while (x > GetTickCount());
+ Expected += (GetTickCount() - Init) * MSEC_TO_NSEC;
+ /* Get a second count */
+ if (!GetThreadTimes(cThread, NULL, NULL, &kernelTime2, &userTime2))
+ {
+ Fail("ERROR: GetThreadTimes returned failure.\n");
+ }
+
+ Time1 = ((ULONG64)kernelTime1.dwHighDateTime << 32);
+ Time1 += (ULONG64)kernelTime1.dwLowDateTime;
+ Time1 += ((ULONG64)userTime1.dwHighDateTime << 32);
+ Time1 += (ULONG64)userTime1.dwLowDateTime;
+
+ Time2 = ((ULONG64)kernelTime2.dwHighDateTime << 32);
+ Time2 += (ULONG64)kernelTime2.dwLowDateTime;
+ Time2 += ((ULONG64)userTime2.dwHighDateTime << 32);
+ Time2 += (ULONG64)userTime2.dwLowDateTime;
+
+ Actual += (Time2 - Time1) * 100;
+ }
+
+ if(labs(Expected - Actual) > Delta)
+ {
+ Fail("ERROR: The measured time (%llu millisecs) was not within Delta %llu "
+ "of the expected time (%llu millisecs).\n",
+ (Actual / MSEC_TO_NSEC), (Delta / MSEC_TO_NSEC), (Expected / MSEC_TO_NSEC));
+ }
+ //printf("%llu, %llu\n", Expected, Actual);
+ PAL_Terminate();
+ ret = PASS;
+
+EXIT:
+ return ret;
+}
diff --git a/src/pal/tests/palsuite/threading/NamedMutex/CMakeLists.txt b/src/pal/tests/palsuite/threading/NamedMutex/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/NamedMutex/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/threading/NamedMutex/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/NamedMutex/test1/CMakeLists.txt
new file mode 100644
index 0000000000..315144e1e8
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/NamedMutex/test1/CMakeLists.txt
@@ -0,0 +1,20 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ namedmutex.cpp
+ nopal.cpp
+)
+
+add_executable(paltest_namedmutex_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_namedmutex_test1 coreclrpal)
+
+target_link_libraries(paltest_namedmutex_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/NamedMutex/test1/namedmutex.cpp b/src/pal/tests/palsuite/threading/NamedMutex/test1/namedmutex.cpp
new file mode 100644
index 0000000000..3726214701
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/NamedMutex/test1/namedmutex.cpp
@@ -0,0 +1,1058 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// These test cases test named mutexes, including positive
+// and negative cases, cross - thread and cross - process, mutual
+// exclusion, abandon detection, etc.
+
+#include <palsuite.h>
+
+#ifndef _countof
+#define _countof(a) (sizeof(a) / sizeof(a[0]))
+#endif // !_countof
+
+const char *const SessionPrefix = "Local\\";
+const char *const GlobalPrefix = "Global\\";
+
+const char *const NamePrefix = "paltest_namedmutex_test1_";
+const char *const TempNamePrefix = "paltest_namedmutex_test1_temp_";
+const char *const InvalidNamePrefix0 = "paltest\\namedmutex_";
+const char *const InvalidNamePrefix1 = "paltest/namedmutex_";
+const char *const ParentEventNamePrefix0 = "paltest_namedmutex_test1_pe0_";
+const char *const ParentEventNamePrefix1 = "paltest_namedmutex_test1_pe1_";
+const char *const ChildEventNamePrefix0 = "paltest_namedmutex_test1_ce0_";
+const char *const ChildEventNamePrefix1 = "paltest_namedmutex_test1_ce1_";
+const char *const ChildRunningEventNamePrefix = "paltest_namedmutex_test1_cr_";
+
+const char *const GlobalShmFilePathPrefix = "/tmp/.dotnet/shm/global/";
+
+#define MaxPathSize (200)
+const DWORD PollLoopSleepMilliseconds = 100;
+const DWORD FailTimeoutMilliseconds = 30000;
+DWORD g_expectedTimeoutMilliseconds = 500;
+
+bool g_isParent = true;
+bool g_isStress = false;
+char g_processPath[4096], g_processCommandLinePath[4096];
+DWORD g_parentPid = static_cast<DWORD>(-1);
+
+extern char *(*test_strcpy)(char *dest, const char *src);
+extern int (*test_strcmp)(const char *s1, const char *s2);
+extern size_t (*test_strlen)(const char *s);
+extern int (*test_sprintf)(char *str, const char *format, ...);
+extern int (*test_sscanf)(const char *str, const char *format, ...);
+extern int(*test_close)(int fd);
+extern int (*test_unlink)(const char *pathname);
+extern unsigned int test_getpid();
+extern int test_kill(unsigned int pid);
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Test helpers
+
+extern bool TestFileExists(const char *path);
+extern bool WriteHeaderInfo(const char *path, char sharedMemoryType, char version, int *fdRef);
+
+#define TestAssert(expression) \
+ do \
+ { \
+ if (!(expression)) \
+ { \
+ if (!g_isParent) \
+ { \
+ Trace("Child process: "); \
+ } \
+ Trace("'paltest_namedmutex_test1' failed at line %u. Expression: " #expression "\n", __LINE__); \
+ fflush(stdout); \
+ return false; \
+ } \
+ } while(false)
+
+char *BuildName(const char *testName, char *buffer, const char *prefix0, const char *prefix1 = nullptr)
+{
+ size_t nameLength = 0;
+ const char *prefixes[] = {prefix0, prefix1};
+ for (int i = 0; i < 2; ++i)
+ {
+ const char *prefix = prefixes[i];
+ if (prefix == nullptr)
+ {
+ break;
+ }
+ test_strcpy(&buffer[nameLength], prefix);
+ nameLength += test_strlen(prefix);
+ }
+
+ if (g_isStress)
+ {
+ // Append the test name so that tests can run in parallel
+ nameLength += test_sprintf(&buffer[nameLength], "%s", testName);
+ buffer[nameLength++] = '_';
+ }
+
+ nameLength += test_sprintf(&buffer[nameLength], "%u", g_parentPid);
+ return buffer;
+}
+
+char *BuildGlobalShmFilePath(const char *testName, char *buffer, const char *namePrefix)
+{
+ size_t pathLength = 0;
+ test_strcpy(&buffer[pathLength], GlobalShmFilePathPrefix);
+ pathLength += test_strlen(GlobalShmFilePathPrefix);
+ test_strcpy(&buffer[pathLength], namePrefix);
+ pathLength += test_strlen(namePrefix);
+
+ if (g_isStress)
+ {
+ // Append the test name so that tests can run in parallel
+ pathLength += test_sprintf(&buffer[pathLength], "%s", testName);
+ buffer[pathLength++] = '_';
+ }
+
+ pathLength += test_sprintf(&buffer[pathLength], "%u", g_parentPid);
+ return buffer;
+}
+
+class AutoCloseMutexHandle
+{
+private:
+ HANDLE m_handle;
+
+public:
+ AutoCloseMutexHandle(HANDLE handle = nullptr) : m_handle(handle)
+ {
+ }
+
+ ~AutoCloseMutexHandle()
+ {
+ Close();
+ }
+
+public:
+ HANDLE GetHandle() const
+ {
+ return m_handle;
+ }
+
+ bool Release()
+ {
+ return !!ReleaseMutex(m_handle);
+ }
+
+ void Close()
+ {
+ if (m_handle != nullptr)
+ {
+ CloseHandle(m_handle);
+ m_handle = nullptr;
+ }
+ }
+
+ void Abandon()
+ {
+ // Don't close the handle
+ m_handle = nullptr;
+ }
+
+ AutoCloseMutexHandle &operator =(HANDLE handle)
+ {
+ Close();
+ m_handle = handle;
+ return *this;
+ }
+
+ operator HANDLE() const
+ {
+ return m_handle;
+ }
+
+private:
+ AutoCloseMutexHandle(const AutoCloseMutexHandle &other);
+ AutoCloseMutexHandle(AutoCloseMutexHandle &&other);
+ AutoCloseMutexHandle &operator =(const AutoCloseMutexHandle &other);
+};
+
+void TestCreateMutex(AutoCloseMutexHandle &m, const char *name, bool initiallyOwned = false)
+{
+ m.Close();
+ m = CreateMutexA(nullptr, initiallyOwned, name);
+}
+
+HANDLE TestOpenMutex(const char *name)
+{
+ return OpenMutexA(SYNCHRONIZE, false, name);
+}
+
+bool StartProcess(const char *funcName)
+{
+ // Command line format: <processPath> <parentPid> <testFunctionName> [stress]
+
+ size_t processCommandLinePathLength = 0;
+ g_processCommandLinePath[processCommandLinePathLength++] = '\"';
+ test_strcpy(&g_processCommandLinePath[processCommandLinePathLength], g_processPath);
+ processCommandLinePathLength += test_strlen(g_processPath);
+ g_processCommandLinePath[processCommandLinePathLength++] = '\"';
+ g_processCommandLinePath[processCommandLinePathLength++] = ' ';
+ processCommandLinePathLength += test_sprintf(&g_processCommandLinePath[processCommandLinePathLength], "%u", g_parentPid);
+ g_processCommandLinePath[processCommandLinePathLength++] = ' ';
+ test_strcpy(&g_processCommandLinePath[processCommandLinePathLength], funcName);
+ processCommandLinePathLength += test_strlen(funcName);
+
+ if (g_isStress)
+ {
+ test_strcpy(&g_processCommandLinePath[processCommandLinePathLength], " stress");
+ processCommandLinePathLength += _countof("stress") - 1;
+ }
+
+ STARTUPINFO si;
+ memset(&si, 0, sizeof(si));
+ si.cb = sizeof(si);
+ PROCESS_INFORMATION pi;
+ memset(&pi, 0, sizeof(pi));
+ if (!CreateProcessA(nullptr, g_processCommandLinePath, nullptr, nullptr, false, 0, nullptr, nullptr, &si, &pi))
+ {
+ return false;
+ }
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ return true;
+}
+
+bool StartThread(LPTHREAD_START_ROUTINE func, void *arg = nullptr, HANDLE *threadHandleRef = nullptr)
+{
+ DWORD threadId;
+ HANDLE handle = CreateThread(nullptr, 0, func, arg, 0, &threadId);
+ if (handle != nullptr)
+ {
+ if (threadHandleRef == nullptr)
+ {
+ CloseHandle(handle);
+ }
+ else
+ {
+ *threadHandleRef = handle;
+ }
+ return true;
+ }
+ return false;
+}
+
+bool WaitForMutexToBeCreated(const char *testName, AutoCloseMutexHandle &m, const char *eventNamePrefix)
+{
+ char eventName[MaxPathSize];
+ BuildName(testName, eventName, GlobalPrefix, eventNamePrefix);
+ DWORD startTime = GetTickCount();
+ while (true)
+ {
+ m = TestOpenMutex(eventName);
+ if (m != nullptr)
+ {
+ return true;
+ }
+ if (GetTickCount() - startTime >= FailTimeoutMilliseconds)
+ {
+ return false;
+ }
+ Sleep(PollLoopSleepMilliseconds);
+ }
+}
+
+// The following functions are used for parent/child tests, where the child runs in a separate thread or process. The tests are
+// organized such that one the parent or child is ever running code, and they yield control and wait for the other. Since the
+// named mutex is the only type of cross-process sync object available, they are used as events to synchronize. The parent and
+// child have a pair of event mutexes each, which they own initially. To release the other waiting thread/process, the
+// thread/process releases one of its mutexes, which the other thread/process would be waiting on. To wait, the thread/process
+// waits on one of the other thread/process' mutexes. All the while, they ping-pong between the two mutexes. YieldToChild() and
+// YieldToParent() below control the releasing, waiting, and ping-ponging, to help create a deterministic path through the
+// parent and child tests while both are running concurrently.
+
+bool AcquireChildRunningEvent(const char *testName, AutoCloseMutexHandle &childRunningEvent)
+{
+ char name[MaxPathSize];
+ TestCreateMutex(childRunningEvent, BuildName(testName, name, GlobalPrefix, ChildRunningEventNamePrefix));
+ TestAssert(WaitForSingleObject(childRunningEvent, FailTimeoutMilliseconds) == WAIT_OBJECT_0);
+ return true;
+}
+
+bool InitializeParent(const char *testName, AutoCloseMutexHandle parentEvents[2], AutoCloseMutexHandle childEvents[2])
+{
+ // Create parent events
+ char name[MaxPathSize];
+ for (int i = 0; i < 2; ++i)
+ {
+ TestCreateMutex(
+ parentEvents[i],
+ BuildName(testName, name, GlobalPrefix, i == 0 ? ParentEventNamePrefix0 : ParentEventNamePrefix1),
+ true);
+ TestAssert(parentEvents[i] != nullptr);
+ TestAssert(GetLastError() != ERROR_ALREADY_EXISTS);
+ }
+
+ // Wait for the child to create and acquire locks on its events so that the parent can wait on them
+ TestAssert(WaitForMutexToBeCreated(testName, childEvents[0], ChildEventNamePrefix0));
+ TestAssert(WaitForMutexToBeCreated(testName, childEvents[1], ChildEventNamePrefix1));
+ return true;
+}
+
+bool UninitializeParent(const char *testName, AutoCloseMutexHandle parentEvents[2], bool releaseParentEvents = true)
+{
+ if (releaseParentEvents)
+ {
+ TestAssert(parentEvents[0].Release());
+ TestAssert(parentEvents[1].Release());
+ }
+
+ // Wait for the child to finish its test. Child tests will release and close 'childEvents' before releasing
+ // 'childRunningEvent', so after this wait, the parent process can freely start another child that will deterministically
+ // recreate the 'childEvents', which the next parent test will wait on, upon its initialization.
+ AutoCloseMutexHandle childRunningEvent;
+ TestAssert(AcquireChildRunningEvent(testName, childRunningEvent));
+ TestAssert(childRunningEvent.Release());
+ return true;
+}
+
+bool InitializeChild(
+ const char *testName,
+ AutoCloseMutexHandle &childRunningEvent,
+ AutoCloseMutexHandle parentEvents[2],
+ AutoCloseMutexHandle childEvents[2])
+{
+ TestAssert(AcquireChildRunningEvent(testName, childRunningEvent));
+
+ // Create child events
+ char name[MaxPathSize];
+ for (int i = 0; i < 2; ++i)
+ {
+ TestCreateMutex(
+ childEvents[i],
+ BuildName(testName, name, GlobalPrefix, i == 0 ? ChildEventNamePrefix0 : ChildEventNamePrefix1),
+ true);
+ TestAssert(childEvents[i] != nullptr);
+ TestAssert(GetLastError() != ERROR_ALREADY_EXISTS);
+ }
+
+ // Wait for the parent to create and acquire locks on its events so that the child can wait on them
+ TestAssert(WaitForMutexToBeCreated(testName, parentEvents[0], ParentEventNamePrefix0));
+ TestAssert(WaitForMutexToBeCreated(testName, parentEvents[1], ParentEventNamePrefix1));
+
+ // Parent/child tests start with the parent, so after initialization, wait for the parent to tell the child test to start
+ TestAssert(WaitForSingleObject(parentEvents[0], FailTimeoutMilliseconds) == WAIT_OBJECT_0);
+ TestAssert(parentEvents[0].Release());
+ return true;
+}
+
+bool UninitializeChild(
+ AutoCloseMutexHandle &childRunningEvent,
+ AutoCloseMutexHandle parentEvents[2],
+ AutoCloseMutexHandle childEvents[2])
+{
+ // Release and close 'parentEvents' and 'childEvents' before releasing 'childRunningEvent' to avoid races, see
+ // UnitializeParent() for more info
+ TestAssert(childEvents[0].Release());
+ TestAssert(childEvents[1].Release());
+ childEvents[0].Close();
+ childEvents[1].Close();
+ parentEvents[0].Close();
+ parentEvents[1].Close();
+ TestAssert(childRunningEvent.Release());
+ return true;
+}
+
+bool YieldToChild(AutoCloseMutexHandle parentEvents[2], AutoCloseMutexHandle childEvents[2], int &ei)
+{
+ TestAssert(parentEvents[ei].Release());
+ TestAssert(WaitForSingleObject(childEvents[ei], FailTimeoutMilliseconds) == WAIT_OBJECT_0);
+ TestAssert(childEvents[ei].Release());
+ TestAssert(WaitForSingleObject(parentEvents[ei], 0) == WAIT_OBJECT_0);
+ ei = 1 - ei;
+ return true;
+}
+
+bool YieldToParent(AutoCloseMutexHandle parentEvents[2], AutoCloseMutexHandle childEvents[2], int &ei)
+{
+ TestAssert(childEvents[ei].Release());
+ ei = 1 - ei;
+ TestAssert(WaitForSingleObject(parentEvents[ei], FailTimeoutMilliseconds) == WAIT_OBJECT_0);
+ TestAssert(parentEvents[ei].Release());
+ TestAssert(WaitForSingleObject(childEvents[1 - ei], 0) == WAIT_OBJECT_0);
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Tests
+
+bool NameTests()
+{
+ const char *testName = "NameTests";
+
+ AutoCloseMutexHandle m;
+ char name[MaxPathSize];
+
+ // Empty name
+ TestCreateMutex(m, "");
+ TestAssert(m != nullptr);
+
+ // Normal name
+ TestCreateMutex(m, BuildName(testName, name, NamePrefix));
+ TestAssert(m != nullptr);
+ TestAssert(AutoCloseMutexHandle(TestOpenMutex(BuildName(testName, name, NamePrefix))) != nullptr);
+ TestCreateMutex(m, BuildName(testName, name, SessionPrefix, NamePrefix));
+ TestAssert(m != nullptr);
+ TestAssert(AutoCloseMutexHandle(TestOpenMutex(BuildName(testName, name, SessionPrefix, NamePrefix))) != nullptr);
+ TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix));
+ TestAssert(m != nullptr);
+ TestAssert(AutoCloseMutexHandle(TestOpenMutex(BuildName(testName, name, GlobalPrefix, NamePrefix))) != nullptr);
+
+ // Name too long. The maximum allowed length depends on the file system, so we're not checking for that.
+ {
+ char name[257];
+ memset(name, 'a', _countof(name) - 1);
+ name[_countof(name) - 1] = '\0';
+ TestCreateMutex(m, name);
+ TestAssert(m == nullptr);
+ TestAssert(GetLastError() == ERROR_FILENAME_EXCED_RANGE);
+ TestAssert(AutoCloseMutexHandle(TestOpenMutex(name)) == nullptr);
+ TestAssert(GetLastError() == ERROR_FILENAME_EXCED_RANGE);
+ }
+
+ // Invalid characters in name
+ TestCreateMutex(m, BuildName(testName, name, InvalidNamePrefix0));
+ TestAssert(m == nullptr);
+ TestAssert(GetLastError() == ERROR_INVALID_NAME);
+ TestAssert(AutoCloseMutexHandle(TestOpenMutex(BuildName(testName, name, InvalidNamePrefix0))) == nullptr);
+ TestAssert(GetLastError() == ERROR_INVALID_NAME);
+ TestCreateMutex(m, BuildName(testName, name, InvalidNamePrefix1));
+ TestAssert(m == nullptr);
+ TestAssert(GetLastError() == ERROR_INVALID_NAME);
+ TestAssert(AutoCloseMutexHandle(TestOpenMutex(BuildName(testName, name, InvalidNamePrefix1))) == nullptr);
+ TestAssert(GetLastError() == ERROR_INVALID_NAME);
+ TestCreateMutex(m, BuildName(testName, name, SessionPrefix, InvalidNamePrefix0));
+ TestAssert(m == nullptr);
+ TestAssert(GetLastError() == ERROR_INVALID_NAME);
+ TestAssert(AutoCloseMutexHandle(TestOpenMutex(BuildName(testName, name, SessionPrefix, InvalidNamePrefix0))) == nullptr);
+ TestAssert(GetLastError() == ERROR_INVALID_NAME);
+ TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, InvalidNamePrefix1));
+ TestAssert(m == nullptr);
+ TestAssert(GetLastError() == ERROR_INVALID_NAME);
+ TestAssert(AutoCloseMutexHandle(TestOpenMutex(BuildName(testName, name, GlobalPrefix, InvalidNamePrefix1))) == nullptr);
+ TestAssert(GetLastError() == ERROR_INVALID_NAME);
+
+ // Creating a second reference to the same named mutex yields an error indicating that it was opened, not created
+ {
+ TestCreateMutex(m, BuildName(testName, name, NamePrefix));
+ TestAssert(m != nullptr);
+ AutoCloseMutexHandle m2;
+ TestCreateMutex(m2, BuildName(testName, name, NamePrefix));
+ TestAssert(m2 != nullptr);
+ TestAssert(GetLastError() == ERROR_ALREADY_EXISTS);
+ }
+
+ return true;
+}
+
+bool HeaderMismatchTests()
+{
+ const char *testName = "HeaderMismatchTests";
+
+ AutoCloseMutexHandle m, m2;
+ char name[MaxPathSize];
+ int fd;
+
+ // Create and hold onto a mutex during this test to create the shared memory directory
+ TestCreateMutex(m2, BuildName(testName, name, GlobalPrefix, TempNamePrefix));
+ TestAssert(m2 != nullptr);
+
+ // Unknown shared memory type
+ TestAssert(WriteHeaderInfo(BuildGlobalShmFilePath(testName, name, NamePrefix), -1, 1, &fd));
+ TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix));
+ TestAssert(m == nullptr);
+ TestAssert(GetLastError() == ERROR_INVALID_HANDLE);
+ TestAssert(test_close(fd) == 0);
+ TestAssert(test_unlink(BuildGlobalShmFilePath(testName, name, NamePrefix)) == 0);
+
+ // Mismatched version
+ TestAssert(WriteHeaderInfo(BuildGlobalShmFilePath(testName, name, NamePrefix), 0, -1, &fd));
+ TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix));
+ TestAssert(m == nullptr);
+ TestAssert(GetLastError() == ERROR_INVALID_HANDLE);
+ TestAssert(test_close(fd) == 0);
+ TestAssert(test_unlink(BuildGlobalShmFilePath(testName, name, NamePrefix)) == 0);
+
+ return true;
+}
+
+bool MutualExclusionTests_Parent()
+{
+ const char *testName = "MutualExclusionTests";
+
+ AutoCloseMutexHandle parentEvents[2], childEvents[2];
+ TestAssert(InitializeParent(testName, parentEvents, childEvents));
+ int ei = 0;
+ char name[MaxPathSize];
+ AutoCloseMutexHandle m;
+
+ TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix));
+ TestAssert(m != nullptr);
+
+ // Recursive locking with various timeouts
+ TestAssert(WaitForSingleObject(m, 0) == WAIT_OBJECT_0);
+ TestAssert(WaitForSingleObject(m, FailTimeoutMilliseconds) == WAIT_OBJECT_0);
+ TestAssert(WaitForSingleObject(m, static_cast<DWORD>(-1)) == WAIT_OBJECT_0);
+ TestAssert(m.Release());
+ TestAssert(m.Release());
+ TestAssert(m.Release());
+ TestAssert(!m.Release()); // try to release the lock while nobody owns it, and verify recursive lock counting
+ TestAssert(GetLastError() == ERROR_NOT_OWNER);
+
+ TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child takes the lock
+
+ TestAssert(WaitForSingleObject(m, 0) == WAIT_TIMEOUT); // try to lock the mutex without waiting
+ TestAssert(WaitForSingleObject(m, g_expectedTimeoutMilliseconds) == WAIT_TIMEOUT); // try to lock the mutex with a timeout
+ TestAssert(!m.Release()); // try to release the lock while another thread owns it
+ TestAssert(GetLastError() == ERROR_NOT_OWNER);
+
+ TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child releases the lock
+
+ TestAssert(WaitForSingleObject(m, static_cast<DWORD>(-1)) == WAIT_OBJECT_0); // lock the mutex with no timeout and release
+ TestAssert(m.Release());
+
+ UninitializeParent(testName, parentEvents);
+ return true;
+}
+
+DWORD MutualExclusionTests_Child(void *arg = nullptr)
+{
+ const char *testName = "MutualExclusionTests";
+
+ AutoCloseMutexHandle childRunningEvent, parentEvents[2], childEvents[2];
+ TestAssert(InitializeChild(testName, childRunningEvent, parentEvents, childEvents));
+ int ei = 0;
+
+ {
+ char name[MaxPathSize];
+ AutoCloseMutexHandle m;
+
+ TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix));
+ TestAssert(m != nullptr);
+ TestAssert(WaitForSingleObject(m, 0) == WAIT_OBJECT_0); // lock the mutex
+ YieldToParent(parentEvents, childEvents, ei); // parent attempts to lock/release, and fails
+ TestAssert(m.Release()); // release the lock
+ }
+
+ UninitializeChild(childRunningEvent, parentEvents, childEvents);
+ return 0;
+}
+
+bool MutualExclusionTests()
+{
+ const char *testName = "MutualExclusionTests";
+
+ {
+ AutoCloseMutexHandle m;
+ char name[MaxPathSize];
+
+ // Releasing a lock that is not owned by any thread fails
+ TestCreateMutex(m, BuildName(testName, name, NamePrefix));
+ TestAssert(m != nullptr);
+ TestAssert(!m.Release());
+ TestAssert(GetLastError() == ERROR_NOT_OWNER);
+
+ // Acquire a lock during upon creation, and release
+ TestCreateMutex(m, BuildName(testName, name, NamePrefix), true);
+ TestAssert(m != nullptr);
+ TestAssert(m.Release());
+
+ // Multi-waits including a named mutex are not supported
+ AutoCloseMutexHandle m2;
+ TestCreateMutex(m2, nullptr);
+ TestAssert(m2 != nullptr);
+ HANDLE waitHandles[] = {m2.GetHandle(), m.GetHandle()};
+ TestAssert(
+ WaitForMultipleObjects(
+ _countof(waitHandles),
+ waitHandles,
+ false /* waitAll */,
+ FailTimeoutMilliseconds) ==
+ WAIT_FAILED);
+ TestAssert(GetLastError() == ERROR_NOT_SUPPORTED);
+ TestAssert(
+ WaitForMultipleObjects(
+ _countof(waitHandles),
+ waitHandles,
+ true /* waitAll */,
+ FailTimeoutMilliseconds) ==
+ WAIT_FAILED);
+ TestAssert(GetLastError() == ERROR_NOT_SUPPORTED);
+ }
+
+ // When another thread or process owns the lock, this process should not be able to acquire a lock, and the converse
+ TestAssert(StartThread(MutualExclusionTests_Child));
+ TestAssert(MutualExclusionTests_Parent());
+ TestAssert(StartProcess("MutualExclusionTests_Child"));
+ TestAssert(MutualExclusionTests_Parent());
+
+ return true;
+}
+
+bool LifetimeTests_Parent()
+{
+ const char *testName = "LifetimeTests";
+
+ AutoCloseMutexHandle parentEvents[2], childEvents[2];
+ TestAssert(InitializeParent(testName, parentEvents, childEvents));
+ int ei = 0;
+ char name[MaxPathSize];
+ AutoCloseMutexHandle m;
+
+ TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); // create first reference to mutex
+ TestAssert(m != nullptr);
+ TestAssert(TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix)));
+ TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child creates second reference to mutex using CreateMutex
+ m.Close(); // close first reference
+ TestAssert(TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix)));
+ TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child closes second reference
+ TestAssert(!TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix)));
+
+ TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); // create first reference to mutex
+ TestAssert(m != nullptr);
+ TestAssert(TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix)));
+ TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child creates second reference to mutex using OpenMutex
+ m.Close(); // close first reference
+ TestAssert(TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix)));
+ TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child closes second reference
+ TestAssert(!TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix)));
+
+ UninitializeParent(testName, parentEvents);
+ return true;
+}
+
+DWORD LifetimeTests_Child(void *arg = nullptr)
+{
+ const char *testName = "LifetimeTests";
+
+ AutoCloseMutexHandle childRunningEvent, parentEvents[2], childEvents[2];
+ TestAssert(InitializeChild(testName, childRunningEvent, parentEvents, childEvents));
+ int ei = 0;
+
+ {
+ char name[MaxPathSize];
+ AutoCloseMutexHandle m;
+
+ // ... parent creates first reference to mutex
+ TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); // create second reference to mutex using CreateMutex
+ TestAssert(m != nullptr);
+ TestAssert(YieldToParent(parentEvents, childEvents, ei)); // parent closes first reference
+ m.Close(); // close second reference
+
+ TestAssert(YieldToParent(parentEvents, childEvents, ei)); // parent verifies, and creates first reference to mutex again
+ m = TestOpenMutex(BuildName(testName, name, GlobalPrefix, NamePrefix)); // create second reference to mutex using OpenMutex
+ TestAssert(m != nullptr);
+ TestAssert(YieldToParent(parentEvents, childEvents, ei)); // parent closes first reference
+ m.Close(); // close second reference
+
+ TestAssert(YieldToParent(parentEvents, childEvents, ei)); // parent verifies
+ }
+
+ UninitializeChild(childRunningEvent, parentEvents, childEvents);
+ return 0;
+}
+
+bool LifetimeTests()
+{
+ const char *testName = "LifetimeTests";
+
+ {
+ AutoCloseMutexHandle m;
+ char name[MaxPathSize];
+
+ // Shm file should be created and deleted
+ TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix));
+ TestAssert(m != nullptr);
+ TestAssert(TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix)));
+ m.Close();
+ TestAssert(!TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix)));
+ }
+
+ // Shm file should not be deleted until last reference is released
+ TestAssert(StartThread(LifetimeTests_Child));
+ TestAssert(LifetimeTests_Parent());
+ TestAssert(StartProcess("LifetimeTests_Child"));
+ TestAssert(LifetimeTests_Parent());
+
+ return true;
+}
+
+DWORD AbandonTests_Child_TryLock(void *arg = nullptr);
+
+bool AbandonTests_Parent()
+{
+ const char *testName = "AbandonTests";
+
+ char name[MaxPathSize];
+ AutoCloseMutexHandle m;
+ {
+ AutoCloseMutexHandle parentEvents[2], childEvents[2];
+ TestAssert(InitializeParent(testName, parentEvents, childEvents));
+ int ei = 0;
+
+ TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix));
+ TestAssert(m != nullptr);
+ TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child locks mutex
+ TestAssert(parentEvents[0].Release());
+ TestAssert(parentEvents[1].Release()); // child sleeps for short duration and abandons the mutex
+ TestAssert(WaitForSingleObject(m, FailTimeoutMilliseconds) == WAIT_ABANDONED_0); // attempt to lock and see abandoned mutex
+
+ UninitializeParent(testName, parentEvents, false /* releaseParentEvents */); // parent events are released above
+ }
+
+ // Verify that the mutex lock is owned by this thread, by starting a new thread and trying to lock it
+ StartThread(AbandonTests_Child_TryLock);
+ {
+ AutoCloseMutexHandle parentEvents[2], childEvents[2];
+ TestAssert(InitializeParent(testName, parentEvents, childEvents));
+ int ei = 0;
+
+ TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child tries to lock mutex
+
+ UninitializeParent(testName, parentEvents);
+ }
+
+ // Verify that the mutex lock is owned by this thread, by starting a new process and trying to lock it
+ StartProcess("AbandonTests_Child_TryLock");
+ AutoCloseMutexHandle parentEvents[2], childEvents[2];
+ TestAssert(InitializeParent(testName, parentEvents, childEvents));
+ int ei = 0;
+
+ TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child tries to lock mutex
+
+ // Continue verification
+ TestAssert(m.Release());
+ TestAssert(WaitForSingleObject(m, FailTimeoutMilliseconds) == WAIT_OBJECT_0); // lock again to see it's not abandoned anymore
+ TestAssert(m.Release());
+
+ UninitializeParent(testName, parentEvents, false /* releaseParentEvents */); // parent events are released above
+
+ // Since the child abandons the mutex, and a child process may not release the file lock on the shared memory file before
+ // indicating completion to the parent, make sure to delete the shared memory file by repeatedly opening/closing the mutex
+ // until the parent process becomes the last process to reference the mutex and closing it deletes the file.
+ DWORD startTime = GetTickCount();
+ while (true)
+ {
+ m.Close();
+ if (!TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix)))
+ {
+ break;
+ }
+
+ TestAssert(GetTickCount() - startTime < FailTimeoutMilliseconds);
+ m = TestOpenMutex(BuildName(testName, name, GlobalPrefix, NamePrefix));
+ }
+
+ return true;
+}
+
+DWORD AbandonTests_Child_GracefulExit_Close(void *arg = nullptr)
+{
+ const char *testName = "AbandonTests";
+
+ AutoCloseMutexHandle childRunningEvent, parentEvents[2], childEvents[2];
+ TestAssert(InitializeChild(testName, childRunningEvent, parentEvents, childEvents));
+ int ei = 0;
+
+ {
+ char name[MaxPathSize];
+ AutoCloseMutexHandle m;
+
+ // ... parent waits for child to lock mutex
+ TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix));
+ TestAssert(m != nullptr);
+ TestAssert(WaitForSingleObject(m, 0) == WAIT_OBJECT_0);
+ TestAssert(YieldToParent(parentEvents, childEvents, ei)); // parent waits on mutex
+ Sleep(g_expectedTimeoutMilliseconds); // wait for parent to wait on mutex
+ m.Close(); // close mutex without releasing lock
+ }
+
+ UninitializeChild(childRunningEvent, parentEvents, childEvents);
+ return 0;
+}
+
+DWORD AbandonTests_Child_GracefulExit_NoClose(void *arg = nullptr)
+{
+ const char *testName = "AbandonTests";
+
+ // This test needs to run in a separate process because it does not close the mutex handle. Running it in a separate thread
+ // causes the mutex object to retain a reference until the process terminates.
+ TestAssert(test_getpid() != g_parentPid);
+
+ AutoCloseMutexHandle childRunningEvent, parentEvents[2], childEvents[2];
+ TestAssert(InitializeChild(testName, childRunningEvent, parentEvents, childEvents));
+ int ei = 0;
+
+ {
+ char name[MaxPathSize];
+ AutoCloseMutexHandle m;
+
+ // ... parent waits for child to lock mutex
+ TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix));
+ TestAssert(m != nullptr);
+ TestAssert(WaitForSingleObject(m, 0) == WAIT_OBJECT_0);
+ TestAssert(YieldToParent(parentEvents, childEvents, ei)); // parent waits on mutex
+ Sleep(g_expectedTimeoutMilliseconds); // wait for parent to wait on mutex
+ m.Abandon(); // don't close the mutex
+ }
+
+ UninitializeChild(childRunningEvent, parentEvents, childEvents);
+ return 0;
+}
+
+DWORD AbandonTests_Child_AbruptExit(void *arg = nullptr)
+{
+ const char *testName = "AbandonTests";
+
+ DWORD currentPid = test_getpid();
+ TestAssert(currentPid != g_parentPid); // this test needs to run in a separate process
+
+ {
+ AutoCloseMutexHandle childRunningEvent, parentEvents[2], childEvents[2];
+ TestAssert(InitializeChild(testName, childRunningEvent, parentEvents, childEvents));
+ int ei = 0;
+
+ {
+ char name[MaxPathSize];
+ AutoCloseMutexHandle m;
+
+ // ... parent waits for child to lock mutex
+ TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix));
+ TestAssert(m != nullptr);
+ TestAssert(WaitForSingleObject(m, 0) == WAIT_OBJECT_0);
+ TestAssert(YieldToParent(parentEvents, childEvents, ei)); // parent waits on mutex
+ Sleep(g_expectedTimeoutMilliseconds); // wait for parent to wait on mutex
+ m.Abandon(); // don't close the mutex
+ }
+
+ UninitializeChild(childRunningEvent, parentEvents, childEvents);
+ }
+
+ TestAssert(test_kill(currentPid) == 0); // abandon the mutex abruptly
+ return 0;
+}
+
+DWORD AbandonTests_Child_TryLock(void *arg)
+{
+ const char *testName = "AbandonTests";
+
+ AutoCloseMutexHandle childRunningEvent, parentEvents[2], childEvents[2];
+ TestAssert(InitializeChild(testName, childRunningEvent, parentEvents, childEvents));
+ int ei = 0;
+
+ {
+ char name[MaxPathSize];
+ AutoCloseMutexHandle m;
+
+ // ... parent waits for child to lock mutex
+ TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix));
+ TestAssert(m != nullptr);
+ TestAssert(WaitForSingleObject(m, 0) == WAIT_TIMEOUT); // try to lock the mutex while the parent holds the lock
+ TestAssert(WaitForSingleObject(m, g_expectedTimeoutMilliseconds) == WAIT_TIMEOUT);
+ }
+
+ UninitializeChild(childRunningEvent, parentEvents, childEvents);
+ return 0;
+}
+
+bool AbandonTests()
+{
+ const char *testName = "AbandonTests";
+
+ // Abandon by graceful exit where the lock owner closes the mutex before releasing it, unblocks a waiter
+ TestAssert(StartThread(AbandonTests_Child_GracefulExit_Close));
+ TestAssert(AbandonTests_Parent());
+ TestAssert(StartProcess("AbandonTests_Child_GracefulExit_Close"));
+ TestAssert(AbandonTests_Parent());
+
+ // Abandon by graceful exit without closing the mutex unblocks a waiter
+ TestAssert(StartProcess("AbandonTests_Child_GracefulExit_NoClose"));
+ TestAssert(AbandonTests_Parent());
+
+ // Abandon by abrupt exit unblocks a waiter
+ TestAssert(StartProcess("AbandonTests_Child_AbruptExit"));
+ TestAssert(AbandonTests_Parent());
+
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Test harness
+
+bool (*const (TestList[]))() =
+{
+ NameTests,
+ HeaderMismatchTests,
+ MutualExclusionTests,
+ LifetimeTests,
+ AbandonTests
+};
+
+bool RunTests()
+{
+ bool allPassed = true;
+ for (SIZE_T i = 0; i < _countof(TestList); ++i)
+ {
+ if (!TestList[i]())
+ {
+ allPassed = false;
+ }
+ }
+ return allPassed;
+}
+
+DWORD g_stressDurationMilliseconds = 0;
+LONG g_stressTestCounts[_countof(TestList)] = {0};
+LONG g_stressResult = true;
+
+DWORD StressTest(void *arg)
+{
+ // Run the specified test continuously for the stress duration
+ SIZE_T testIndex = reinterpret_cast<SIZE_T>(arg);
+ DWORD startTime = GetTickCount();
+ do
+ {
+ ++g_stressTestCounts[testIndex];
+ if (!TestList[testIndex]())
+ {
+ InterlockedExchange(&g_stressResult, false);
+ break;
+ }
+ } while (
+ InterlockedCompareExchange(&g_stressResult, false, false) == true &&
+ GetTickCount() - startTime < g_stressDurationMilliseconds);
+ return 0;
+}
+
+bool StressTests(DWORD durationMinutes)
+{
+ g_isStress = true;
+ g_expectedTimeoutMilliseconds = 1;
+ g_stressDurationMilliseconds = durationMinutes * (60 * 1000);
+
+ // Start a thread for each test
+ HANDLE threadHandles[_countof(TestList)];
+ for (SIZE_T i = 0; i < _countof(threadHandles); ++i)
+ {
+ TestAssert(StartThread(StressTest, reinterpret_cast<void *>(i), &threadHandles[i]));
+ }
+
+ while (true)
+ {
+ DWORD waitResult =
+ WaitForMultipleObjects(_countof(threadHandles), threadHandles, true /* bWaitAll */, 10 * 1000 /* dwMilliseconds */);
+ TestAssert(waitResult == WAIT_OBJECT_0 || waitResult == WAIT_TIMEOUT);
+ if (waitResult == WAIT_OBJECT_0)
+ {
+ break;
+ }
+
+ Trace("'paltest_namedmutex_test1' stress test counts: ");
+ for (SIZE_T i = 0; i < _countof(g_stressTestCounts); ++i)
+ {
+ if (i != 0)
+ {
+ Trace(", ");
+ }
+ Trace("%u", g_stressTestCounts[i]);
+ }
+ Trace("\n");
+ fflush(stdout);
+ }
+
+ for (SIZE_T i = 0; i < _countof(threadHandles); ++i)
+ {
+ CloseHandle(threadHandles[i]);
+ }
+ return static_cast<bool>(g_stressResult);
+}
+
+int __cdecl main(int argc, char **argv)
+{
+ if (argc < 1 || argc > 4)
+ {
+ return FAIL;
+ }
+
+ if (PAL_Initialize(argc, argv) != 0)
+ {
+ return FAIL;
+ }
+
+ test_strcpy(g_processPath, argv[0]);
+
+ if (argc == 1)
+ {
+ // Unit test arguments: <processPath>
+
+ g_parentPid = test_getpid();
+ int result = RunTests() ? PASS : FAIL;
+ ExitProcess(result);
+ return result;
+ }
+
+ if (test_strcmp(argv[1], "stress") == 0)
+ {
+ // Stress test arguments: <processPath> stress [durationMinutes]
+
+ DWORD durationMinutes = 1;
+ if (argc >= 3 && test_sscanf(argv[2], "%u", &durationMinutes) != 1)
+ {
+ ExitProcess(FAIL);
+ return FAIL;
+ }
+
+ g_parentPid = test_getpid();
+ int result = StressTests(durationMinutes) ? PASS : FAIL;
+ ExitProcess(result);
+ return result;
+ }
+
+ // Child test process arguments: <processPath> <parentPid> <testFunctionName> [stress]
+
+ g_isParent = false;
+
+ // Get parent process' ID from argument
+ if (test_sscanf(argv[1], "%u", &g_parentPid) != 1)
+ {
+ ExitProcess(FAIL);
+ return FAIL;
+ }
+
+ if (argc >= 4 && test_strcmp(argv[3], "stress") == 0)
+ {
+ g_isStress = true;
+ }
+
+ if (test_strcmp(argv[2], "MutualExclusionTests_Child") == 0)
+ {
+ MutualExclusionTests_Child();
+ }
+ else if (test_strcmp(argv[2], "LifetimeTests_Child") == 0)
+ {
+ LifetimeTests_Child();
+ }
+ else if (test_strcmp(argv[2], "AbandonTests_Child_GracefulExit_Close") == 0)
+ {
+ AbandonTests_Child_GracefulExit_Close();
+ }
+ else if (test_strcmp(argv[2], "AbandonTests_Child_GracefulExit_NoClose") == 0)
+ {
+ AbandonTests_Child_GracefulExit_NoClose();
+ }
+ else if (test_strcmp(argv[2], "AbandonTests_Child_AbruptExit") == 0)
+ {
+ AbandonTests_Child_AbruptExit();
+ }
+ else if (test_strcmp(argv[2], "AbandonTests_Child_TryLock") == 0)
+ {
+ AbandonTests_Child_TryLock();
+ }
+ ExitProcess(PASS);
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp b/src/pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp
new file mode 100644
index 0000000000..46a5d87341
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp
@@ -0,0 +1,65 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// Contains wrappers for functions whose required headers conflict with the PAL
+
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#define _countof(a) (sizeof(a) / sizeof(a[0]))
+
+#define PAGE_SIZE (4096)
+
+auto test_strcpy = strcpy;
+auto test_strcmp = strcmp;
+auto test_strlen = strlen;
+auto test_sprintf = sprintf;
+auto test_sscanf = sscanf;
+auto test_close = close;
+auto test_unlink = unlink;
+
+unsigned int test_getpid()
+{
+ return getpid();
+}
+
+int test_kill(unsigned int pid)
+{
+ return kill(pid, SIGKILL);
+}
+
+bool TestFileExists(const char *path)
+{
+ int fd = open(path, O_RDWR);
+ if (fd == -1)
+ return false;
+ close(fd);
+ return true;
+}
+
+bool WriteHeaderInfo(const char *path, char sharedMemoryType, char version, int *fdRef)
+{
+ int fd = open(path, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
+ if (fd == -1)
+ return false;
+ *fdRef = fd;
+ if (ftruncate(fd, PAGE_SIZE) != 0)
+ return false;
+ if (lseek(fd, 0, SEEK_SET) != 0)
+ return false;
+
+ // See SharedMemorySharedDataHeader for format
+ char buffer[] = {sharedMemoryType, version};
+ if (write(fd, buffer, _countof(buffer)) != _countof(buffer))
+ return false;
+
+ return flock(fd, LOCK_SH | LOCK_NB) == 0;
+}
diff --git a/src/pal/tests/palsuite/threading/NamedMutex/test1/testinfo.dat b/src/pal/tests/palsuite/threading/NamedMutex/test1/testinfo.dat
new file mode 100644
index 0000000000..e3090093ea
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/NamedMutex/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = Named mutex
+Name = Tests for named mutexes
+TYPE = DEFAULT
+EXE1 = namedmutex
+Description
+= These test cases test named mutexes, including positive
+= and negative cases, cross-thread and cross-process, mutual
+= exclusion, abandon detection, etc.
diff --git a/src/pal/tests/palsuite/threading/OpenEventW/CMakeLists.txt b/src/pal/tests/palsuite/threading/OpenEventW/CMakeLists.txt
new file mode 100644
index 0000000000..8083faf655
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/OpenEventW/CMakeLists.txt
@@ -0,0 +1,8 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+
diff --git a/src/pal/tests/palsuite/threading/OpenEventW/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/OpenEventW/test1/CMakeLists.txt
new file mode 100644
index 0000000000..2bb61e3044
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/OpenEventW/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_openeventw_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_openeventw_test1 coreclrpal)
+
+target_link_libraries(paltest_openeventw_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/OpenEventW/test1/test1.c b/src/pal/tests/palsuite/threading/OpenEventW/test1/test1.c
new file mode 100644
index 0000000000..9dcb3a4a68
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/OpenEventW/test1/test1.c
@@ -0,0 +1,134 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test for OpenEventW. This test creates an event,
+** opens a handle to the same event, then waits on both handles
+** in both a signalled and non-signalled state to verify they're.
+** pointing to the same event object.
+**
+**
+**==========================================================================*/
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ BOOL bRet = FAIL;
+ DWORD dwRet;
+ HANDLE hEvent;
+ HANDLE hOpenEvent;
+ WCHAR theName[] = {'E','v','e','n','t','\0'};
+ LPCWSTR lpName = theName;
+
+ /* PAL initialization */
+ if( (PAL_Initialize(argc, argv)) != 0 )
+ {
+ return( FAIL );
+ }
+
+ /* Create an event (with a 0 intial state!) and ensure that the
+ HANDLE is valid
+ */
+ hEvent = CreateEventW( NULL, TRUE, FALSE, lpName );
+ if( hEvent == NULL )
+ {
+ Fail( "ERROR:%lu:CreateEvent call failed\n", GetLastError() );
+ }
+
+
+ /* Call OpenEventW to get another HANDLE on
+ this event. Ensure the HANDLE is valid.
+ */
+ hOpenEvent = OpenEventW( EVENT_ALL_ACCESS, TRUE, lpName );
+ if( hOpenEvent == NULL )
+ {
+ Trace( "ERROR:%lu:OpenEventW call failed\n", GetLastError() );
+ goto cleanup2;
+ }
+
+ /* wait on the original event to verify that it's not signalled */
+ dwRet = WaitForSingleObject( hEvent, 0 );
+ if( dwRet != WAIT_TIMEOUT )
+ {
+ Trace( "ERROR:WaitForSingleObject returned %lu, "
+ "expected WAIT_TIMEOUT\n",
+ dwRet );
+ goto cleanup;
+ }
+
+ /* wait on the opened event to verify that it's not signalled either */
+ dwRet = WaitForSingleObject( hOpenEvent, 0 );
+ if( dwRet != WAIT_TIMEOUT )
+ {
+ Trace( "ERROR:WaitForSingleObject returned %lu, "
+ "expected WAIT_TIMEOUT\n",
+ dwRet );
+ goto cleanup;
+ }
+
+
+ /* Set this opened HANDLE */
+ if( ! SetEvent( hOpenEvent ) )
+ {
+ Trace( "ERROR:%lu:SetEvent call failed\n", GetLastError() );
+ goto cleanup;
+ }
+
+ /* wait on the original event to verify that it's signalled */
+ dwRet = WaitForSingleObject( hEvent, 0 );
+ if( dwRet != WAIT_OBJECT_0 )
+ {
+ Trace( "ERROR:WaitForSingleObject returned %lu, "
+ "expected WAIT_OBJECT_0\n",
+ dwRet );
+ goto cleanup;
+ }
+
+ /* wait on the opened event to verify that it's signalled too */
+ dwRet = WaitForSingleObject( hOpenEvent, 0 );
+ if( dwRet != WAIT_OBJECT_0 )
+ {
+ Trace( "ERROR:WaitForSingleObject returned %lu, "
+ "expected WAIT_OBJECT_0\n",
+ dwRet );
+ goto cleanup;
+ }
+
+ /* success if we get here */
+ bRet = PASS;
+
+cleanup:
+ /* close the opened handle */
+ if( ! CloseHandle( hOpenEvent ) )
+ {
+ Trace( "ERROR:%lu:CloseHandle call failed\n", GetLastError() );
+ bRet = FAIL;
+ }
+
+cleanup2:
+ /* close the original event handle */
+ if( ! CloseHandle( hEvent ) )
+ {
+ Trace( "ERROR:%lu:CloseHandle call failed\n", GetLastError() );
+ bRet = FAIL;
+ }
+
+ /* check for failure */
+ if( bRet == FAIL )
+ {
+ Fail( "test failed\n" );
+ }
+
+
+ /* terminate the PAL */
+ PAL_Terminate();
+
+ /* return success */
+ return ( PASS );
+
+}
+
diff --git a/src/pal/tests/palsuite/threading/OpenEventW/test1/testinfo.dat b/src/pal/tests/palsuite/threading/OpenEventW/test1/testinfo.dat
new file mode 100644
index 0000000000..cc9be71042
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/OpenEventW/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = OpenEventW
+Name = Positive Test for OpenEventW
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Purpose: Test for OpenEventW. This test creates an event,
+= opens a handle to the same event, then waits on both handles
+= in both a signalled and non-signalled state to verify they're
+= pointing to the same event object.
diff --git a/src/pal/tests/palsuite/threading/OpenEventW/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/OpenEventW/test2/CMakeLists.txt
new file mode 100644
index 0000000000..48fa1f2c4b
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/OpenEventW/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_openeventw_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_openeventw_test2 coreclrpal)
+
+target_link_libraries(paltest_openeventw_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/OpenEventW/test2/test2.c b/src/pal/tests/palsuite/threading/OpenEventW/test2/test2.c
new file mode 100644
index 0000000000..9cbf872b95
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/OpenEventW/test2/test2.c
@@ -0,0 +1,194 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test2.c
+**
+** Purpose: Positive test for OpenEventW.
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** CreateEvent
+** CloseHandle
+** WaitForSingleObject
+**
+** Purpose:
+**
+** Test to ensure proper operation of the OpenEventW()
+** API by creating a new named event and verifying that
+** it can be used interchangeably by setting the event
+** with the original handle and waiting on it with the
+** new one, then resetting it with the new one and waiting
+** on it with the original one.
+**
+**
+**===========================================================================*/
+#include <palsuite.h>
+
+
+
+int __cdecl main( int argc, char **argv )
+
+{
+ /* local variables */
+ BOOL ret = FAIL;
+ DWORD dwRet = 0;
+ HANDLE hEvent = NULL;
+ HANDLE hTestEvent = NULL;
+ LPSECURITY_ATTRIBUTES lpEventAttributes = NULL;
+ BOOL bManualReset = TRUE;
+ BOOL bInitialState = FALSE;
+ WCHAR wcName[] = {'W','o','o','B','a','b','y','\0'};
+ LPWSTR lpName = wcName;
+
+
+ /* PAL initialization */
+ if( (PAL_Initialize(argc, argv)) != 0 )
+ {
+ return( FAIL );
+ }
+
+
+ /* create an event which we can use with SetEvent */
+ hEvent = CreateEventW( lpEventAttributes,
+ bManualReset,
+ bInitialState,
+ lpName );
+
+ if( hEvent == NULL )
+ {
+ /* ERROR */
+ Fail( "ERROR:%lu:CreateEvent() call failed\n", GetLastError() );
+ }
+
+ /* open a new handle to our event */
+ hTestEvent = OpenEventW(EVENT_ALL_ACCESS, /* we want all rights */
+ FALSE, /* no inherit */
+ lpName );
+
+ if( hTestEvent == NULL )
+ {
+ /* ERROR */
+ Trace( "ERROR:%lu:OpenEventW() call failed\n", GetLastError() );
+ goto cleanup;
+ }
+
+ /* verify that the event isn't signalled yet by waiting on both */
+ /* handles to the event object */
+ dwRet = WaitForSingleObject( hEvent, 0 );
+ if( dwRet != WAIT_TIMEOUT )
+ {
+ /* ERROR */
+ Trace( "ERROR:WaitForSingleObject() call returned %lu, "
+ "expected WAIT_TIMEOUT\n",
+ dwRet );
+ goto cleanup;
+ }
+
+ dwRet = WaitForSingleObject( hTestEvent, 0 );
+ if( dwRet != WAIT_TIMEOUT )
+ {
+ /* ERROR */
+ Trace( "ERROR:WaitForSingleObject() call returned %lu, "
+ "expected WAIT_TIMEOUT\n",
+ dwRet );
+ goto cleanup;
+ }
+
+
+ /* set the event using the original handle */
+ if( ! SetEvent( hEvent ) )
+ {
+ /* ERROR */
+ Trace( "ERROR:%lu:SetEvent() call failed\n", GetLastError() );
+ goto cleanup;
+ }
+
+ /* verify that the event is signalled by waiting on both handles */
+ dwRet = WaitForSingleObject( hEvent, 0 );
+ if( dwRet != WAIT_OBJECT_0 )
+ {
+ /* ERROR */
+ Trace( "ERROR:WaitForSingleObject() call returned %lu, "
+ "expected WAIT_OBJECT_0\n",
+ dwRet );
+ goto cleanup;
+ }
+
+ dwRet = WaitForSingleObject( hTestEvent, 0 );
+ if( dwRet != WAIT_OBJECT_0 )
+ {
+ /* ERROR */
+ Trace( "ERROR:WaitForSingleObject() call returned %lu, "
+ "expected WAIT_OBJECT_0\n",
+ dwRet );
+ goto cleanup;
+ }
+
+ /* reset the event using the new handle */
+ if( ! ResetEvent( hTestEvent ) )
+ {
+ /* ERROR */
+ Trace( "ERROR:%lu:ResetEvent() call failed\n", GetLastError() );
+ goto cleanup;
+ }
+
+ /* verify that the event isn't signalled by waiting on both handles */
+ dwRet = WaitForSingleObject( hEvent, 0 );
+ if( dwRet != WAIT_TIMEOUT )
+ {
+ /* ERROR */
+ Trace( "ERROR:WaitForSingleObject() call returned %lu, "
+ "expected WAIT_TIMEOUT\n",
+ dwRet );
+ goto cleanup;
+ }
+
+ dwRet = WaitForSingleObject( hTestEvent, 0 );
+ if( dwRet != WAIT_TIMEOUT )
+ {
+ /* ERROR */
+ Trace( "ERROR:WaitForSingleObject() call returned %lu, "
+ "expected WAIT_TIMEOUT\n",
+ dwRet );
+ goto cleanup;
+ }
+
+
+ /* test was successful */
+ ret = PASS;
+
+
+cleanup:
+ /* close the new event handle */
+ if( hTestEvent != NULL )
+ {
+ if( ! CloseHandle( hTestEvent ) )
+ {
+ ret = FAIL;
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ }
+ }
+
+ /* close the original event handle */
+ if( ! CloseHandle( hEvent ) )
+ {
+ ret = FAIL;
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ }
+
+ /* failure message */
+ if( ret != PASS )
+ {
+ Fail( "Test failed\n" );
+ }
+
+
+ /* PAL termination */
+ PAL_Terminate();
+
+ /* return success or failure */
+ return ret;
+}
diff --git a/src/pal/tests/palsuite/threading/OpenEventW/test2/testinfo.dat b/src/pal/tests/palsuite/threading/OpenEventW/test2/testinfo.dat
new file mode 100644
index 0000000000..ad3f22eea0
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/OpenEventW/test2/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = OpenEventW
+Name = Positive test for OpenEventW
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Test to ensure proper operation of the OpenEventW()
+= API by creating a new named event and verifying that
+= it can be used interchangeably by setting the event
+= with the original handle and waiting on it with the
+= new one, then resetting it with the new one and waiting
+= on it with the original one.
diff --git a/src/pal/tests/palsuite/threading/OpenEventW/test3/CMakeLists.txt b/src/pal/tests/palsuite/threading/OpenEventW/test3/CMakeLists.txt
new file mode 100644
index 0000000000..433a3a255c
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/OpenEventW/test3/CMakeLists.txt
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(TESTSOURCES
+ test3.c
+)
+
+add_executable(paltest_openeventw_test3
+ ${TESTSOURCES}
+)
+
+add_dependencies(paltest_openeventw_test3 coreclrpal)
+
+target_link_libraries(paltest_openeventw_test3
+ pthread
+ m
+ coreclrpal
+)
+
+
+set(HELPERSOURCES
+ childprocess.c
+)
+
+add_executable(paltest_openeventw_test3_child
+ ${HELPERSOURCES}
+)
+
+add_dependencies(paltest_openeventw_test3_child coreclrpal)
+
+target_link_libraries(paltest_openeventw_test3_child
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/OpenEventW/test3/childprocess.c b/src/pal/tests/palsuite/threading/OpenEventW/test3/childprocess.c
new file mode 100644
index 0000000000..b5149e006f
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/OpenEventW/test3/childprocess.c
@@ -0,0 +1,81 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: childprocess.c
+**
+** Purpose: Test to ensure that OpenEventW() works when
+** opening an event created by another process. The test
+** program launches this program as a child, which creates
+** a named, initially-unset event. The child waits up to
+** 10 seconds for the parent process to open that event
+** and set it, and returns PASS if the event was set or FAIL
+** otherwise. The parent process checks the return value
+** from the child to verify that the opened event was
+** properly used across processes.
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** CreateEventW
+** WaitForSingleObject
+** CloseHandle
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main( int argc, char **argv )
+{
+ /* local variables */
+ HANDLE hEvent = NULL;
+ WCHAR wcName[] = {'P','A','L','R','o','c','k','s','\0'};
+ LPWSTR lpName = wcName;
+
+ int result = PASS;
+
+ /* initialize the PAL */
+ if( PAL_Initialize(argc, argv) != 0 )
+ {
+ return( FAIL );
+ }
+
+
+ /* open a handle to the event created in the child process */
+ hEvent = OpenEventW( EVENT_ALL_ACCESS, /* we want all rights */
+ FALSE, /* no inherit */
+ lpName );
+
+ if( hEvent == NULL )
+ {
+ /* ERROR */
+ Trace( "ERROR:%lu:OpenEventW() call failed\n", GetLastError() );
+ result = FAIL;
+ goto parentwait;
+ }
+
+ /* set the event -- should take effect in the child process */
+ if( ! SetEvent( hEvent ) )
+ {
+ /* ERROR */
+ Trace( "ERROR:%lu:SetEvent() call failed\n", GetLastError() );
+ result = FAIL;
+ }
+
+parentwait:
+ /* close the event handle */
+ if( ! CloseHandle( hEvent ) )
+ {
+ /* ERROR */
+ Fail( "ERROR:%lu:CloseHandle() call failed in child\n",
+ GetLastError());
+ }
+
+ /* terminate the PAL */
+ PAL_TerminateEx(result);
+
+ /* return success or failure */
+ return result;
+}
diff --git a/src/pal/tests/palsuite/threading/OpenEventW/test3/test3.c b/src/pal/tests/palsuite/threading/OpenEventW/test3/test3.c
new file mode 100644
index 0000000000..10a678a107
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/OpenEventW/test3/test3.c
@@ -0,0 +1,187 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test3.c
+**
+** Purpose: Test to ensure that OpenEventW() works when
+** opening an event created by another process. This test
+** program launches a child process which creates a
+** named, initially-unset event. The child waits up to
+** 10 seconds for the parent process to open that event
+** and set it, and returns PASS if the event was set or FAIL
+** otherwise. The parent process checks the return value
+** from the child to verify that the opened event was
+** properly used across processes.
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** ZeroMemory
+** GetCurrentDirectoryW
+** CreateProcessW
+** WaitForSingleObject
+** GetExitCodeProcess
+** GetLastError
+** strlen
+** strncpy
+**
+**
+**===========================================================================*/
+#include <palsuite.h>
+
+#define TIMEOUT 60000
+
+int __cdecl main( int argc, char **argv )
+{
+ BOOL ret = FAIL;
+ LPSECURITY_ATTRIBUTES lpEventAttributes = NULL;
+
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+
+ DWORD dwExitCode;
+
+ DWORD dwRet = 0;
+ HANDLE hEvent = NULL;
+ WCHAR wcName[] = {'P','A','L','R','o','c','k','s','\0'};
+ LPWSTR lpName = wcName;
+ char lpCommandLine[MAX_PATH] = "";
+
+ /* initialize the PAL */
+ if( PAL_Initialize(argc, argv) != 0 )
+ {
+ return( FAIL );
+ }
+
+ /* zero our process and startup info structures */
+ ZeroMemory( &si, sizeof(si) );
+ si.cb = sizeof( si );
+ ZeroMemory( &pi, sizeof(pi) );
+
+ /* create an event which we can use with SetEvent */
+ hEvent = CreateEventW( lpEventAttributes,
+ TRUE, /* manual reset */
+ FALSE, /* unsignalled */
+ lpName );
+
+ if( hEvent == NULL )
+ {
+ /* ERROR */
+ Fail( "ERROR:%lu:CreateEventW() call failed in child\n",
+ GetLastError());
+ }
+
+ ZeroMemory( lpCommandLine, MAX_PATH );
+ if ( _snprintf( lpCommandLine, MAX_PATH-1, "childprocess ") < 0 )
+ {
+ Fail ("Error: Insufficient lpCommandline for\n");
+ }
+
+ /* launch the child process */
+ if( !CreateProcess( NULL, /* module name to execute */
+ lpCommandLine, /* command line */
+ NULL, /* process handle not */
+ /* inheritable */
+ NULL, /* thread handle not */
+ /* inheritable */
+ FALSE, /* handle inheritance */
+ CREATE_NEW_CONSOLE, /* dwCreationFlags */
+ NULL, /* use parent's environment */
+ NULL, /* use parent's starting */
+ /* directory */
+ &si, /* startup info struct */
+ &pi ) /* process info struct */
+ )
+ {
+ Fail( "ERROR:%lu:CreateProcess call failed\n",
+ GetLastError() );
+ }
+
+ /* verify that the event is signalled by the child process */
+ dwRet = WaitForSingleObject( hEvent, TIMEOUT );
+ if( dwRet != WAIT_OBJECT_0 )
+ {
+ ret = FAIL;
+ /* ERROR */
+ Trace( "ERROR:WaitForSingleObject() call returned %lu, "
+ "expected WAIT_TIMEOUT\n",
+ "expected WAIT_OBJECT_0\n",
+ dwRet );
+
+ goto cleanup;
+
+ if( !CloseHandle( hEvent ) )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed in child\n",
+ GetLastError());
+ }
+ goto cleanup;
+ }
+
+ /* wait for the child process to complete */
+ dwRet = WaitForSingleObject ( pi.hProcess, TIMEOUT );
+ if( dwRet != WAIT_OBJECT_0 )
+ {
+ ret = FAIL;
+ Trace( "ERROR:WaitForSingleObject() returned %lu, "
+ "expected %lu\n",
+ dwRet,
+ WAIT_OBJECT_0 );
+ goto cleanup;
+ }
+
+ /* check the exit code from the process */
+ if( ! GetExitCodeProcess( pi.hProcess, &dwExitCode ) )
+ {
+ ret = FAIL;
+ Trace( "ERROR:%lu:GetExitCodeProcess call failed\n",
+ GetLastError() );
+ goto cleanup;
+ }
+
+ /* check for success */
+ ret = (dwExitCode == PASS) ? PASS : FAIL;
+
+cleanup:
+ if( hEvent != NULL )
+ {
+ if( ! CloseHandle ( hEvent ) )
+ {
+ Trace( "ERROR:%lu:CloseHandle call failed on event handle\n",
+ GetLastError() );
+ ret = FAIL;
+ }
+ }
+
+
+ /* close process and thread handle */
+ if( ! CloseHandle ( pi.hProcess ) )
+ {
+ Trace( "ERROR:%lu:CloseHandle call failed on process handle\n",
+ GetLastError() );
+ ret = FAIL;
+ }
+
+ if( ! CloseHandle ( pi.hThread ) )
+ {
+ Trace( "ERROR:%lu:CloseHandle call failed on thread handle\n",
+ GetLastError() );
+ ret = FAIL;
+ }
+
+ /* output a convenient error message and exit if we failed */
+ if( ret == FAIL )
+ {
+ Fail( "test failed\n" );
+ }
+
+
+ /* terminate the PAL */
+ PAL_Terminate();
+
+ /* return success */
+ return ret;
+}
diff --git a/src/pal/tests/palsuite/threading/OpenEventW/test3/testinfo.dat b/src/pal/tests/palsuite/threading/OpenEventW/test3/testinfo.dat
new file mode 100644
index 0000000000..96b2c06644
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/OpenEventW/test3/testinfo.dat
@@ -0,0 +1,21 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = OpenEventW
+Name = Test for OpenEventW
+TYPE = DEFAULT
+EXE1 = test3
+EXE2 = childprocess
+Description
+= Purpose: Test to ensure that OpenEventW() works when
+= opening an event created by another process. This test
+= program launches a child process which creates a
+= named, initially-unset event. The child waits up to
+= 10 seconds for the parent process to open that event
+= and set it, and returns PASS if the event was set or FAIL
+= otherwise. The parent process checks the return value
+= from the child to verify that the opened event was
+= properly used across processes.
diff --git a/src/pal/tests/palsuite/threading/OpenEventW/test4/CMakeLists.txt b/src/pal/tests/palsuite/threading/OpenEventW/test4/CMakeLists.txt
new file mode 100644
index 0000000000..ff17fea23b
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/OpenEventW/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_openeventw_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_openeventw_test4 coreclrpal)
+
+target_link_libraries(paltest_openeventw_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/OpenEventW/test4/test4.c b/src/pal/tests/palsuite/threading/OpenEventW/test4/test4.c
new file mode 100644
index 0000000000..ae657a0511
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/OpenEventW/test4/test4.c
@@ -0,0 +1,112 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test4.c
+**
+** Purpose: Positive test for OpenEventW.
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** CreateEvent
+** CloseHandle
+** WaitForSingleObject
+**
+** Purpose:
+**
+** Test to ensure proper operation of the OpenEventW()
+** API by trying to open an event with a name that is
+** already taken by a non-event object.
+**
+**
+**===========================================================================*/
+#include <palsuite.h>
+
+
+
+int __cdecl main( int argc, char **argv )
+
+{
+ /* local variables */
+ BOOL bRet = PASS;
+ DWORD dwLastError = 0;
+ HANDLE hMutex = NULL;
+ HANDLE hTestEvent = NULL;
+ LPSECURITY_ATTRIBUTES lpSecurityAttributes = NULL;
+ BOOL bInitialState = TRUE;
+ WCHAR wcName[] = {'I','m','A','M','u','t','e','x','\0'};
+ LPWSTR lpName = wcName;
+
+
+ /* PAL initialization */
+ if( (PAL_Initialize(argc, argv)) != 0 )
+ {
+ return( FAIL );
+ }
+
+ /* create a mutex object */
+ hMutex = CreateMutexW( lpSecurityAttributes,
+ bInitialState,
+ lpName );
+
+ if( hMutex == NULL )
+ {
+ /* ERROR */
+ Fail( "ERROR:%lu:CreateMutexW() call failed\n", GetLastError() );
+ }
+
+ /* open a new handle to our event */
+ hTestEvent = OpenEventW(EVENT_ALL_ACCESS, /* we want all rights */
+ FALSE, /* no inherit */
+ lpName );
+
+ if( hTestEvent != NULL )
+ {
+ /* ERROR */
+ Trace( "ERROR:OpenEventW() call succeeded against a named "
+ "mutex, should have returned NULL\n" );
+ if( ! CloseHandle( hTestEvent ) )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed \n", GetLastError() );
+ }
+ bRet = FAIL;
+ }
+ else
+ {
+ dwLastError = GetLastError();
+ if( dwLastError != ERROR_INVALID_HANDLE )
+ {
+ /* ERROR */
+ Trace( "ERROR:OpenEventW() call failed against a named "
+ "mutex, but returned an unexpected result: %lu\n",
+ dwLastError );
+ bRet = FAIL;
+ }
+ }
+
+
+ /* close the mutex handle */
+ if( ! CloseHandle( hMutex ) )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed \n", GetLastError() );
+ bRet = FAIL;
+ }
+
+
+ /* fail here if we weren't successful */
+ if( bRet == FAIL )
+ {
+ Fail( "" );
+ }
+
+
+ /* PAL termination */
+ PAL_Terminate();
+
+ /* return success or failure */
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/threading/OpenEventW/test4/testinfo.dat b/src/pal/tests/palsuite/threading/OpenEventW/test4/testinfo.dat
new file mode 100644
index 0000000000..1b3f2d83c6
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/OpenEventW/test4/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = OpenEventW
+Name = Negative test for OpenEventW
+TYPE = DEFAULT
+EXE1 = test4
+Description
+= Test to ensure proper operation of the OpenEventW()
+= API by trying to open an event with a name that is
+= already taken by a non-event object.
diff --git a/src/pal/tests/palsuite/threading/OpenEventW/test5/CMakeLists.txt b/src/pal/tests/palsuite/threading/OpenEventW/test5/CMakeLists.txt
new file mode 100644
index 0000000000..b78d7fbfc0
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/OpenEventW/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test5.c
+)
+
+add_executable(paltest_openeventw_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_openeventw_test5 coreclrpal)
+
+target_link_libraries(paltest_openeventw_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/OpenEventW/test5/test5.c b/src/pal/tests/palsuite/threading/OpenEventW/test5/test5.c
new file mode 100644
index 0000000000..43b585765c
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/OpenEventW/test5/test5.c
@@ -0,0 +1,197 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test5.c
+**
+** Purpose: Positive test for OpenEventW.
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** CreateEvent
+** CloseHandle
+** WaitForSingleObject
+**
+** Purpose:
+**
+** Test to ensure proper operation of the OpenEventW()
+** API by creating a new named event with CreateEventA()
+** and verifying that it can be opened with OpenEventW().
+** It should be possible to use the event handles
+** interchangeably, we test by setting the event with the
+** original handle and waiting on it with the new one,
+** then resetting it with the new one and waiting
+** on it with the original one.
+**
+**
+**===========================================================================*/
+#include <palsuite.h>
+
+
+
+int __cdecl main( int argc, char **argv )
+
+{
+ /* local variables */
+ BOOL ret = FAIL;
+ DWORD dwRet = 0;
+ HANDLE hEvent = NULL;
+ HANDLE hTestEvent = NULL;
+ LPSECURITY_ATTRIBUTES lpEventAttributes = NULL;
+ BOOL bManualReset = TRUE;
+ BOOL bInitialState = FALSE;
+ LPSTR lpNameA = "ShakeIt";
+ WCHAR wcName[] = {'S','h','a','k','e','I','t','\0'};
+ LPWSTR lpNameW = wcName;
+
+
+ /* PAL initialization */
+ if( (PAL_Initialize(argc, argv)) != 0 )
+ {
+ return( FAIL );
+ }
+
+
+ /* create an event which we can use with SetEvent */
+ hEvent = CreateEventA( lpEventAttributes,
+ bManualReset,
+ bInitialState,
+ lpNameA );
+
+ if( hEvent == NULL )
+ {
+ /* ERROR */
+ Fail( "ERROR:%lu:CreateEvent() call failed\n", GetLastError() );
+ }
+
+ /* open a new handle to our event */
+ hTestEvent = OpenEventW(EVENT_ALL_ACCESS, /* we want all rights */
+ FALSE, /* no inherit */
+ lpNameW );
+
+ if( hTestEvent == NULL )
+ {
+ /* ERROR */
+ Trace( "ERROR:%lu:OpenEventW() call failed\n", GetLastError() );
+ goto cleanup;
+ }
+
+ /* verify that the event isn't signalled yet by waiting on both */
+ /* handles to the event object */
+ dwRet = WaitForSingleObject( hEvent, 0 );
+ if( dwRet != WAIT_TIMEOUT )
+ {
+ /* ERROR */
+ Trace( "ERROR:WaitForSingleObject() call returned %lu, "
+ "expected WAIT_TIMEOUT\n",
+ dwRet );
+ goto cleanup;
+ }
+
+ dwRet = WaitForSingleObject( hTestEvent, 0 );
+ if( dwRet != WAIT_TIMEOUT )
+ {
+ /* ERROR */
+ Trace( "ERROR:WaitForSingleObject() call returned %lu, "
+ "expected WAIT_TIMEOUT\n",
+ dwRet );
+ goto cleanup;
+ }
+
+
+ /* set the event using the original handle */
+ if( ! SetEvent( hEvent ) )
+ {
+ /* ERROR */
+ Trace( "ERROR:%lu:SetEvent() call failed\n", GetLastError() );
+ goto cleanup;
+ }
+
+ /* verify that the event is signalled by waiting on both handles */
+ dwRet = WaitForSingleObject( hEvent, 0 );
+ if( dwRet != WAIT_OBJECT_0 )
+ {
+ /* ERROR */
+ Trace( "ERROR:WaitForSingleObject() call returned %lu, "
+ "expected WAIT_OBJECT_0\n",
+ dwRet );
+ goto cleanup;
+ }
+
+ dwRet = WaitForSingleObject( hTestEvent, 0 );
+ if( dwRet != WAIT_OBJECT_0 )
+ {
+ /* ERROR */
+ Trace( "ERROR:WaitForSingleObject() call returned %lu, "
+ "expected WAIT_OBJECT_0\n",
+ dwRet );
+ goto cleanup;
+ }
+
+ /* reset the event using the new handle */
+ if( ! ResetEvent( hTestEvent ) )
+ {
+ /* ERROR */
+ Trace( "ERROR:%lu:ResetEvent() call failed\n", GetLastError() );
+ goto cleanup;
+ }
+
+ /* verify that the event isn't signalled by waiting on both handles */
+ dwRet = WaitForSingleObject( hEvent, 0 );
+ if( dwRet != WAIT_TIMEOUT )
+ {
+ /* ERROR */
+ Trace( "ERROR:WaitForSingleObject() call returned %lu, "
+ "expected WAIT_TIMEOUT\n",
+ dwRet );
+ goto cleanup;
+ }
+
+ dwRet = WaitForSingleObject( hTestEvent, 0 );
+ if( dwRet != WAIT_TIMEOUT )
+ {
+ /* ERROR */
+ Trace( "ERROR:WaitForSingleObject() call returned %lu, "
+ "expected WAIT_TIMEOUT\n",
+ dwRet );
+ goto cleanup;
+ }
+
+
+ /* test was successful */
+ ret = PASS;
+
+
+cleanup:
+ /* close the new event handle */
+ if( hTestEvent != NULL )
+ {
+ if( ! CloseHandle( hTestEvent ) )
+ {
+ ret = FAIL;
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ }
+ }
+
+ /* close the original event handle */
+ if( ! CloseHandle( hEvent ) )
+ {
+ ret = FAIL;
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ }
+
+ /* failure message */
+ if( ret != PASS )
+ {
+ Fail( "Test failed\n" );
+ }
+
+
+ /* PAL termination */
+ PAL_Terminate();
+
+ /* return success or failure */
+ return ret;
+}
diff --git a/src/pal/tests/palsuite/threading/OpenEventW/test5/testinfo.dat b/src/pal/tests/palsuite/threading/OpenEventW/test5/testinfo.dat
new file mode 100644
index 0000000000..f5af943a7c
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/OpenEventW/test5/testinfo.dat
@@ -0,0 +1,19 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = OpenEventW
+Name = Positive test for OpenEventW
+TYPE = DEFAULT
+EXE1 = test5
+Description
+= Test to ensure proper operation of the OpenEventW()
+= API by creating a new named event with CreateEventA()
+= and verifying that it can be opened with OpenEventW().
+= It should be possible to use the event handles
+= interchangeably, we test by setting the event with the
+= original handle and waiting on it with the new one,
+= then resetting it with the new one and waiting
+= on it with the original one.
diff --git a/src/pal/tests/palsuite/threading/OpenProcess/CMakeLists.txt b/src/pal/tests/palsuite/threading/OpenProcess/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/OpenProcess/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/threading/OpenProcess/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/OpenProcess/test1/CMakeLists.txt
new file mode 100644
index 0000000000..26d30547a9
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/OpenProcess/test1/CMakeLists.txt
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(TESTSOURCES
+ test1.c
+)
+
+add_executable(paltest_openprocess_test1
+ ${TESTSOURCES}
+)
+
+add_dependencies(paltest_openprocess_test1 coreclrpal)
+
+target_link_libraries(paltest_openprocess_test1
+ pthread
+ m
+ coreclrpal
+)
+
+
+set(HELPERSOURCES
+ childProcess.c
+)
+
+add_executable(paltest_openprocess_test1_child
+ ${HELPERSOURCES}
+)
+
+add_dependencies(paltest_openprocess_test1_child coreclrpal)
+
+target_link_libraries(paltest_openprocess_test1_child
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/OpenProcess/test1/childProcess.c b/src/pal/tests/palsuite/threading/OpenProcess/test1/childProcess.c
new file mode 100644
index 0000000000..9ef07433fd
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/OpenProcess/test1/childProcess.c
@@ -0,0 +1,75 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: childprocess.c
+**
+** Purpose: Test to ensure OpenProcess works properly.
+** All this program does is return a predefined value.
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** CreateMutexW
+** WaitForSingleObject
+** CloseHandle
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+#include "myexitcode.h"
+
+
+int __cdecl main( int argc, char **argv )
+{
+ HANDLE hMutex;
+ WCHAR wszMutexName[] = { 'T','E','S','T','1','\0' };
+ DWORD dwRet;
+ int i;
+
+ /* initialize the PAL */
+ if( PAL_Initialize(argc, argv) != 0 )
+ {
+ return( FAIL );
+ }
+
+ /* open a mutex to synchronize with the parent process */
+ hMutex = CreateMutexW( NULL, FALSE, wszMutexName );
+ if( hMutex == NULL )
+ {
+ Fail( "ERROR:%lu:CreateMutex() call failed\r\n", GetLastError() );
+ }
+
+ /* acquire the mutex lock */
+ dwRet = WaitForSingleObject( hMutex, 10000 );
+ if( dwRet != WAIT_OBJECT_0 )
+ {
+ Trace( "ERROR:WaitForSingleObject() returned %lu, "
+ "expected WAIT_OBJECT_0",
+ dwRet );
+ if( ! CloseHandle( hMutex ) )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ }
+ Fail( "test failed\n" );
+ }
+
+
+ /* simulate some activity */
+ for( i=0; i<50000; i++ )
+ ;
+
+ /* close our mutex handle */
+ if( ! CloseHandle( hMutex ) )
+ {
+ Fail( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ }
+
+ /* terminate the PAL */
+ PAL_Terminate();
+
+ /* return the predefined exit code */
+ return TEST_EXIT_CODE;
+}
diff --git a/src/pal/tests/palsuite/threading/OpenProcess/test1/myexitcode.h b/src/pal/tests/palsuite/threading/OpenProcess/test1/myexitcode.h
new file mode 100644
index 0000000000..66b8f43a97
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/OpenProcess/test1/myexitcode.h
@@ -0,0 +1,14 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: myexitcode.h
+**
+** Purpose: Define an exit code.
+**
+**
+**==========================================================================*/
+
+#define TEST_EXIT_CODE 317
diff --git a/src/pal/tests/palsuite/threading/OpenProcess/test1/test1.c b/src/pal/tests/palsuite/threading/OpenProcess/test1/test1.c
new file mode 100644
index 0000000000..d0f9019646
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/OpenProcess/test1/test1.c
@@ -0,0 +1,282 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test to ensure OpenProcess works properly.
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** ZeroMemory
+** GetCurrentDirectoryW
+** CreateProcessW
+** WaitForSingleObject
+** CreateMutexW
+** ReleaseMutex
+** CloseHandle
+** GetLastError
+** strlen
+** strncpy
+**
+**
+**===========================================================================*/
+#include <palsuite.h>
+#include "myexitcode.h"
+
+
+static const char* rgchPathDelim = "\\";
+
+
+int
+mkAbsoluteFilename( LPSTR dirName,
+ DWORD dwDirLength,
+ LPCSTR fileName,
+ DWORD dwFileLength,
+ LPSTR absPathName )
+{
+ DWORD sizeDN, sizeFN, sizeAPN;
+
+ sizeDN = strlen( dirName );
+ sizeFN = strlen( fileName );
+ sizeAPN = (sizeDN + 1 + sizeFN + 1);
+
+ /* ensure ((dirName + DELIM + fileName + \0) =< _MAX_PATH ) */
+ if( sizeAPN > _MAX_PATH )
+ {
+ return ( 0 );
+ }
+
+ strncpy( absPathName, dirName, dwDirLength +1 );
+ strncpy( absPathName, rgchPathDelim, 2 );
+ strncpy( absPathName, fileName, dwFileLength +1 );
+
+ return (sizeAPN);
+
+}
+
+
+int __cdecl main( int argc, char **argv )
+
+{
+ const char* rgchChildFile = "childprocess";
+
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+
+ DWORD dwError;
+ DWORD dwExitCode;
+ DWORD dwFileLength;
+ DWORD dwDirLength;
+ DWORD dwSize;
+ DWORD dwRet;
+
+ HANDLE hMutex;
+ HANDLE hChildProcess;
+
+ char rgchDirName[_MAX_DIR];
+ char absPathBuf[_MAX_PATH];
+ char* rgchAbsPathName;
+
+ BOOL ret = FAIL;
+ BOOL bChildDone = FALSE;
+ WCHAR wszMutexName[] = { 'T','E','S','T','1','\0' };
+
+ /* initialize the PAL */
+ if( PAL_Initialize(argc, argv) != 0 )
+ {
+ return( FAIL );
+ }
+
+ /* create a mutex to synchronize with the child process */
+ hMutex = CreateMutexW( NULL, TRUE, wszMutexName );
+ if( hMutex == NULL )
+ {
+ Fail( "ERROR:%lu:CreateMutex() call failed\r\n", GetLastError() );
+ }
+
+ /* zero our process and startup info structures */
+ ZeroMemory( &si, sizeof(si) );
+ si.cb = sizeof( si );
+ ZeroMemory( &pi, sizeof(pi) );
+
+ /* build the absolute path to the child process */
+ rgchAbsPathName = &absPathBuf[0];
+ dwFileLength = strlen( rgchChildFile );
+
+ dwDirLength = GetCurrentDirectory( _MAX_PATH, rgchDirName );
+ if( dwDirLength == 0 )
+ {
+ dwError = GetLastError();
+ if( ReleaseMutex( hMutex ) == 0 )
+ {
+ Trace( "ERROR:%lu:ReleaseMutex() call failed\n", GetLastError() );
+ }
+ if( CloseHandle( hMutex ) == 0 )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ }
+ Fail( "GetCurrentDirectory call failed with error code %d\n",
+ dwError );
+ }
+
+ dwSize = mkAbsoluteFilename( rgchDirName,
+ dwDirLength,
+ rgchChildFile,
+ dwFileLength,
+ rgchAbsPathName );
+ if( dwSize == 0 )
+ {
+ if( ReleaseMutex( hMutex ) == 0 )
+ {
+ Trace( "ERROR:%lu:ReleaseMutex() call failed\n", GetLastError() );
+ }
+ if( CloseHandle( hMutex ) == 0 )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ }
+ Fail( "Palsuite Code: mkAbsoluteFilename() call failed. Could ",
+ "not build absolute path name to file\n. Exiting.\n" );
+ }
+
+ /* launch the child process */
+ if( !CreateProcess( NULL, /* module name to execute */
+ rgchAbsPathName, /* command line */
+ NULL, /* process handle not */
+ /* inheritable */
+ NULL, /* thread handle not */
+ /*inheritable */
+ FALSE, /* handle inheritance */
+ CREATE_NEW_CONSOLE, /* dwCreationFlags */
+ NULL, /* use parent's environment */
+ NULL, /* use parent's starting */
+ /* directory */
+ &si, /* startup info struct */
+ &pi ) /* process info struct */
+ )
+ {
+ dwError = GetLastError();
+ if( ReleaseMutex( hMutex ) == 0 )
+ {
+ Trace( "ERROR:%lu:ReleaseMutex() call failed\n", GetLastError() );
+ }
+ if( CloseHandle( hMutex ) == 0 )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ }
+ Fail( "CreateProcess call failed with error code %d\n",
+ dwError );
+ }
+
+ /* open another handle to the child process */
+ hChildProcess = OpenProcess( PROCESS_ALL_ACCESS, /* access */
+ FALSE, /* inheritable */
+ pi.dwProcessId /* process id */
+ );
+ if( hChildProcess == NULL )
+ {
+ dwError = GetLastError();
+ if( ReleaseMutex( hMutex ) == 0 )
+ {
+ Trace( "ERROR:%lu:ReleaseMutex() call failed\n", GetLastError() );
+ }
+ Trace( "ERROR:%lu:OpenProcess call failed\n", dwError );
+ goto cleanup2;
+ }
+
+ /* release the mutex so the child can proceed */
+ if( ReleaseMutex( hMutex ) == 0 )
+ {
+ Trace( "ERROR:%lu:ReleaseMutex() call failed\n", GetLastError() );
+ goto cleanup;
+ }
+
+ /* wait for the child process to complete, using the new handle */
+ dwRet = WaitForSingleObject( hChildProcess, 10000 );
+ if( dwRet != WAIT_OBJECT_0 )
+ {
+ Trace( "ERROR:WaitForSingleObject call returned %lu, "
+ "expected WAIT_OBJECT_0",
+ dwRet );
+ goto cleanup;
+ }
+
+ /* remember that we waited until the child was finished */
+ bChildDone = TRUE;
+
+ /* check the exit code from the process -- this is a bit of an */
+ /* extra verification that we opened the correct process handle */
+ if( ! GetExitCodeProcess( hChildProcess, &dwExitCode ) )
+ {
+ Trace( "ERROR:%lu:GetExitCodeProcess call failed\n", GetLastError() );
+ goto cleanup;
+ }
+
+ /* verification */
+ if( (dwExitCode & 0xFF) != (TEST_EXIT_CODE & 0xFF) )
+ {
+ Trace( "GetExitCodeProcess returned an incorrect exit code %d, "
+ "expected value is %d\n",
+ (dwExitCode & 0xFF),
+ (TEST_EXIT_CODE & 0xFF));
+ goto cleanup;
+ }
+
+ /* success if we get here */
+ ret = PASS;
+
+
+cleanup:
+ /* wait on the child process to complete if necessary */
+ if( ! bChildDone )
+ {
+ dwRet = WaitForSingleObject( hChildProcess, 10000 );
+ if( dwRet != WAIT_OBJECT_0 )
+ {
+ Trace( "ERROR:WaitForSingleObject call returned %lu, "
+ "expected WAIT_OBJECT_0",
+ dwRet );
+ ret = FAIL;
+ }
+ }
+
+ /* close all our handles */
+ if( CloseHandle ( hChildProcess ) == 0 )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ ret = FAIL;
+ }
+
+cleanup2:
+ if( CloseHandle ( pi.hProcess ) == 0 )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ ret = FAIL;
+ }
+ if( CloseHandle ( pi.hThread ) == 0 )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ ret = FAIL;
+ }
+ if( CloseHandle( hMutex ) == 0 )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ ret = FAIL;
+ }
+
+ if( ret == FAIL )
+ {
+ Fail( "test failed\n" );
+ }
+
+
+
+ /* terminate the PAL */
+ PAL_Terminate();
+
+ /* return success */
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/threading/OpenProcess/test1/testinfo.dat b/src/pal/tests/palsuite/threading/OpenProcess/test1/testinfo.dat
new file mode 100644
index 0000000000..dd6b2c0ffe
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/OpenProcess/test1/testinfo.dat
@@ -0,0 +1,19 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = OpenProcess
+Name = Test for OpenProcess
+TYPE = DEFAULT
+EXE1 = test1
+EXE2 = childprocess
+Description
+= Test to ensure proper operation of the OpenProcess API.
+= The test launches a trivial child process, then opens
+= a handle to it using OpenProcess. It uses that handle
+= to wait for the child process to terminate, and then
+= checks the exit code of the child process in order to
+= verify that it was in fact a handle to the correct
+= process.
diff --git a/src/pal/tests/palsuite/threading/QueryThreadCycleTime/CMakeLists.txt b/src/pal/tests/palsuite/threading/QueryThreadCycleTime/CMakeLists.txt
new file mode 100644
index 0000000000..5e1ef7f28b
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/QueryThreadCycleTime/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
diff --git a/src/pal/tests/palsuite/threading/QueryThreadCycleTime/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/QueryThreadCycleTime/test1/CMakeLists.txt
new file mode 100644
index 0000000000..ad3eec1a45
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/QueryThreadCycleTime/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_querythreadcycletime_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_querythreadcycletime_test1 coreclrpal)
+
+target_link_libraries(paltest_querythreadcycletime_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/QueryThreadCycleTime/test1/test1.c b/src/pal/tests/palsuite/threading/QueryThreadCycleTime/test1/test1.c
new file mode 100644
index 0000000000..54f0116bd0
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/QueryThreadCycleTime/test1/test1.c
@@ -0,0 +1,98 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source:
+**
+** Source : test1.c
+**
+** Purpose: Test for QueryThreadCycleTime() function
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char *argv[]) {
+ int ret = FAIL;
+
+ //Test is failing unreliably, so for now we always return pass.
+ if (TRUE){
+ ret = PASS;
+ goto EXIT;
+ }
+
+ LONG64 Actual, Expected, Delta = 850000000;
+ Actual = 0;
+ Expected = 0;
+ const LONG64 MSEC_TO_NSEC = 1000000;
+
+ /*
+ * Initialize the PAL and return FAILURE if this fails
+ */
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ HANDLE cThread = GetCurrentThread();
+
+ int i;
+ /* Take 2000 tiny measurements */
+ for (i = 0; i < 2000; i++){
+ ULONG64 FirstCount, SecondCount;
+ LONG64 Init;
+
+ Sleep(1);
+
+ /* Grab a FirstCount, then loop for a bit to make the clock increase */
+ if (!QueryThreadCycleTime(cThread, (PULONG64)&FirstCount))
+ {
+ Fail("ERROR: QueryThreadCycleTime returned failure.\n");
+ }
+
+ LONG64 x;
+ /* Init is in milliseconds, so we will convert later */
+ Init = (LONG64)GetTickCount();
+ x = Init + 3;
+ volatile int counter;
+ do {
+ for (counter = 0; counter < 100000; counter++)
+ {
+ // spin to consume CPU time
+ }
+
+ } while (x > GetTickCount());
+ Expected += (GetTickCount() - Init) * MSEC_TO_NSEC;
+ /* Get a second count */
+ if (!QueryThreadCycleTime(cThread, (PULONG64)&SecondCount))
+ {
+ Fail("ERROR: QueryThreadCycleTime returned failure.\n");
+ }
+
+ LONG64 trial = (LONG64)SecondCount - (LONG64)FirstCount;
+ if (trial < 0){
+ printf("Negative value %llu measured", trial);
+ }
+ Actual += (trial);
+
+ }
+
+
+
+ if(labs(Expected - Actual) > Delta)
+ {
+ Fail("ERROR: The measured time (%llu millisecs) was not within Delta %llu "
+ "of the expected time (%llu millisecs).\n",
+ (Actual / MSEC_TO_NSEC), (Delta / MSEC_TO_NSEC), (Expected / MSEC_TO_NSEC));
+ }
+ //printf("%llu, %llu\n", Expected, Actual);
+ PAL_Terminate();
+ ret = PASS;
+
+EXIT:
+ return ret;
+}
diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/CMakeLists.txt b/src/pal/tests/palsuite/threading/QueueUserAPC/CMakeLists.txt
new file mode 100644
index 0000000000..19ee487a6a
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/QueueUserAPC/CMakeLists.txt
@@ -0,0 +1,10 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+add_subdirectory(test7)
+
diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/QueueUserAPC/test1/CMakeLists.txt
new file mode 100644
index 0000000000..54a4d03719
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/QueueUserAPC/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_queueuserapc_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_queueuserapc_test1 coreclrpal)
+
+target_link_libraries(paltest_queueuserapc_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test1/test1.c b/src/pal/tests/palsuite/threading/QueueUserAPC/test1/test1.c
new file mode 100644
index 0000000000..3637897ba7
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/QueueUserAPC/test1/test1.c
@@ -0,0 +1,313 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests that APCs sent to a thread in an alertable state via
+** QueueUserAPC are executed in FIFO order. Also tests that the APC
+** function is executed within the context of the correct thread and
+** that the dwData parameter gets sent correctly.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+const int ChildThreadSleepTime = 2000;
+const int InterruptTime = 1000;
+
+VOID PALAPI APCFuncA(ULONG_PTR dwParam);
+VOID PALAPI APCFuncB(ULONG_PTR dwParam);
+VOID PALAPI APCFuncC(ULONG_PTR dwParam);
+VOID PALAPI APCFuncD(ULONG_PTR dwParam);
+DWORD PALAPI SleeperProc(LPVOID lpParameter);
+
+const char *ExpectedResults = "A0B0C0D0A1B1C1D1A2B2C2D2A3B3C3D3";
+char ResultBuffer[256];
+char *ResultPtr;
+DWORD ChildThread;
+
+/* synchronization events */
+static HANDLE hSyncEvent1 = NULL;
+static HANDLE hSyncEvent2 = NULL;
+
+/* thread result because we have no GetExitCodeThread() API */
+BOOL bThreadResult = FAIL;
+
+int __cdecl main (int argc, char **argv)
+{
+ HANDLE hThread = NULL;
+ int ret;
+ int i,j;
+ BOOL bResult = FAIL;
+
+ PAPCFUNC APCFuncs[] =
+ {
+ APCFuncA,
+ APCFuncB,
+ APCFuncC,
+ APCFuncD,
+ };
+
+ /* initialize the PAL */
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ ResultPtr = ResultBuffer;
+
+ /* create a pair of synchronization events to coordinate our threads */
+ hSyncEvent1 = CreateEvent( NULL, FALSE, FALSE, NULL );
+ if( hSyncEvent1 == NULL )
+ {
+ Trace( "ERROR:%lu:CreateEvent() call failed\n", GetLastError() );
+ goto cleanup;
+ }
+
+ hSyncEvent2 = CreateEvent( NULL, FALSE, FALSE, NULL );
+ if( hSyncEvent2 == NULL )
+ {
+ Trace( "ERROR:%lu:CreateEvent() call failed\n", GetLastError() );
+ goto cleanup;
+ }
+
+ /* create a child thread which will call SleepEx */
+ hThread = CreateThread( NULL,
+ 0,
+ (LPTHREAD_START_ROUTINE)SleeperProc,
+ 0,
+ 0,
+ &ChildThread);
+
+ if( hThread == NULL )
+ {
+ Trace( "ERROR:%lu:CreateThread() call failed\n",
+ GetLastError());
+ goto cleanup;
+ }
+
+
+ /* wait on our synchronization event to ensure the thread is running */
+ ret = WaitForSingleObject( hSyncEvent1, 20000 );
+ if( ret != WAIT_OBJECT_0 )
+ {
+ Trace( "ERROR:WaitForSingleObject() returned %lu, "
+ "expected WAIT_OBJECT_0\n",
+ ret );
+ goto cleanup;
+ }
+
+
+ /* queue our user APC functions on the thread */
+ for (i=0; i<4; i++)
+ {
+ for (j=0; j<sizeof(APCFuncs)/sizeof(APCFuncs[0]); j++)
+ {
+ ret = QueueUserAPC(APCFuncs[j], hThread, '0' + i);
+ if (ret == 0)
+ {
+ Trace( "ERROR:%lu:QueueUserAPC() call failed\n",
+ GetLastError());
+ goto cleanup;
+ }
+ }
+ }
+
+ /* signal the child thread to continue */
+ if( ! SetEvent( hSyncEvent2 ) )
+ {
+ Trace( "ERROR:%lu:SetEvent() call failed\n", GetLastError() );
+ goto cleanup;
+ }
+
+
+ /* wait on our synchronization event to ensure the other thread is done */
+ ret = WaitForSingleObject( hSyncEvent1, 20000 );
+ if( ret != WAIT_OBJECT_0 )
+ {
+ Trace( "ERROR:WaitForSingleObject() returned %lu, "
+ "expected WAIT_OBJECT_0\n",
+ ret );
+ goto cleanup;
+ }
+
+
+ /* check that the thread executed successfully */
+ if( bThreadResult == FAIL )
+ {
+ goto cleanup;
+ }
+
+
+ /* check the result buffer */
+ if (strcmp(ExpectedResults, ResultBuffer) != 0)
+ {
+ Trace( "FAIL:Expected the APC function calls to produce a result of "
+ " \"%s\", got \"%s\"\n",
+ ExpectedResults,
+ ResultBuffer );
+ goto cleanup;
+ }
+
+ /* success if we get here */
+ bResult = PASS;
+
+cleanup:
+ /* wait for the other thread to finish */
+ if( hThread != NULL )
+ {
+ ret = WaitForSingleObject( hThread, INFINITE );
+ if (ret == WAIT_FAILED)
+ {
+ Trace( "ERROR:%lu:WaitForSingleObject() returned %lu, "
+ "expected WAIT_OBJECT_0\n",
+ ret );
+ bResult = FAIL;
+ }
+ }
+
+ /* close our synchronization handles */
+ if( hSyncEvent1 != NULL )
+ {
+ if( ! CloseHandle( hSyncEvent1 ) )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ bResult = FAIL;
+ }
+ }
+
+ if( hSyncEvent2 != NULL )
+ {
+ if( ! CloseHandle( hSyncEvent2 ) )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ bResult = FAIL;
+ }
+ }
+
+ if( bResult == FAIL )
+ {
+ Fail( "test failed\n" );
+ }
+
+ /* terminate the PAL */
+ PAL_Terminate();
+
+ /* return success */
+ return PASS;
+}
+
+VOID PALAPI APCFuncA(ULONG_PTR dwParam)
+{
+ char val = (int) dwParam;
+
+ if (GetCurrentThreadId() != ChildThread)
+ {
+ Fail("Executing APC in thread %d, should be in %d!\n",
+ GetCurrentThreadId(), ChildThread);
+ }
+
+ *ResultPtr++ = 'A';
+ *ResultPtr++ = val;
+ *ResultPtr = 0;
+}
+
+VOID PALAPI APCFuncB(ULONG_PTR dwParam)
+{
+ char val = (int) dwParam;
+
+ if (GetCurrentThreadId() != ChildThread)
+ {
+ Fail("Executing APC in thread %d, should be in %d!\n",
+ GetCurrentThreadId(), ChildThread);
+ }
+
+ *ResultPtr++ = 'B';
+ *ResultPtr++ = val;
+ *ResultPtr = 0;
+}
+
+VOID PALAPI APCFuncC(ULONG_PTR dwParam)
+{
+ char val = (int) dwParam;
+
+ if (GetCurrentThreadId() != ChildThread)
+ {
+ Fail("Executing APC in thread %d, should be in %d!\n",
+ GetCurrentThreadId(), ChildThread);
+ }
+
+ *ResultPtr++ = 'C';
+ *ResultPtr++ = val;
+ *ResultPtr = 0;
+}
+
+VOID PALAPI APCFuncD(ULONG_PTR dwParam)
+{
+ char val = (int) dwParam;
+
+ if (GetCurrentThreadId() != ChildThread)
+ {
+ Fail("Executing APC in thread %d, should be in %d!\n",
+ GetCurrentThreadId(), ChildThread);
+ }
+
+ *ResultPtr++ = 'D';
+ *ResultPtr++ = val;
+ *ResultPtr = 0;
+}
+
+/* Entry Point for child thread. All it does is call SleepEx. */
+DWORD PALAPI SleeperProc(LPVOID lpParameter)
+{
+ DWORD ret;
+
+ /* signal the main thread that we're ready to proceed */
+ if( ! SetEvent( hSyncEvent1 ) )
+ {
+ Trace( "ERROR:%lu:SetEvent() call failed\n", GetLastError() );
+ bThreadResult = FAIL;
+ goto done;
+ }
+
+ /* wait for notification from the main thread */
+ ret = WaitForSingleObject( hSyncEvent2, 20000 );
+ if( ret != WAIT_OBJECT_0 )
+ {
+ Trace( "ERROR:WaitForSingleObject() returned %lu, "
+ "expected WAIT_OBJECT_0\n",
+ ret );
+ bThreadResult = FAIL;
+ goto done;
+ }
+
+ /* call SleepEx to activate any queued APCs */
+ ret = SleepEx(ChildThreadSleepTime, TRUE);
+ if (ret != WAIT_IO_COMPLETION)
+ {
+ Trace( "ERROR:SleepEx() call returned %lu, "
+ "expected WAIT_IO_COMPLETION\n",
+ ret );
+ bThreadResult = FAIL;
+ goto done;
+ }
+
+ /* everything passed here */
+ bThreadResult = PASS;
+
+
+done:
+ /* signal the main thread that we're finished */
+ if( ! SetEvent( hSyncEvent1 ) )
+ {
+ Trace( "ERROR:%lu:SetEvent() call failed\n", GetLastError() );
+ bThreadResult = FAIL;
+ }
+
+ /* return success or failure */
+ return bThreadResult;
+}
diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test1/testinfo.dat b/src/pal/tests/palsuite/threading/QueueUserAPC/test1/testinfo.dat
new file mode 100644
index 0000000000..fbe8343d81
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/QueueUserAPC/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = QueueUserAPC
+Name = Test #1 for QueueUserAPC
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Tests that APCs sent to a thread in an alertable state via
+=QueueUserAPC are executed in FIFO order. Also tests that the APC
+=function is executed within the context of the correct thread and
+=that the dwData parameter gets sent correctly.
diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/QueueUserAPC/test2/CMakeLists.txt
new file mode 100644
index 0000000000..88cda5f7b1
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/QueueUserAPC/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_queueuserapc_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_queueuserapc_test2 coreclrpal)
+
+target_link_libraries(paltest_queueuserapc_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test2/test2.c b/src/pal/tests/palsuite/threading/QueueUserAPC/test2/test2.c
new file mode 100644
index 0000000000..dc2bfdb173
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/QueueUserAPC/test2/test2.c
@@ -0,0 +1,224 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test2.c
+**
+** Purpose: Tests that APCs are not executed if a thread never enters an
+** alertable state after they are queued.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+const int ChildThreadSleepTime = 2000;
+const int InterruptTime = 1000;
+
+DWORD ChildThread;
+BOOL InAPC;
+
+/* synchronization events */
+static HANDLE hSyncEvent1 = NULL;
+static HANDLE hSyncEvent2 = NULL;
+
+/* thread result because we have no GetExitCodeThread() API */
+static BOOL bThreadResult = FAIL;
+
+
+VOID PALAPI APCFunc(ULONG_PTR dwParam)
+{
+ InAPC = TRUE;
+}
+
+DWORD PALAPI SleeperProc(LPVOID lpParameter)
+{
+ DWORD ret;
+
+ /* signal the main thread that we're ready to proceed */
+ if( ! SetEvent( hSyncEvent1 ) )
+ {
+ Trace( "ERROR:%lu:SetEvent() call failed\n", GetLastError() );
+ bThreadResult = FAIL;
+ goto done;
+ }
+
+ /* wait for notification from the main thread */
+ ret = WaitForSingleObject( hSyncEvent2, 20000 );
+ if( ret != WAIT_OBJECT_0 )
+ {
+ Trace( "ERROR:WaitForSingleObject() returned %lu, "
+ "expected WAIT_OBJECT_0\n",
+ ret );
+ bThreadResult = FAIL;
+ goto done;
+ }
+
+ /* call our sleep function */
+ Sleep( ChildThreadSleepTime );
+
+ /* success if we reach here */
+ bThreadResult = PASS;
+
+
+done:
+
+ /* signal the main thread that we're finished */
+ if( ! SetEvent( hSyncEvent1 ) )
+ {
+ Trace( "ERROR:%lu:SetEvent() call failed\n", GetLastError() );
+ bThreadResult = FAIL;
+ }
+
+ /* return success or failure */
+ return bThreadResult;
+}
+
+
+int __cdecl main (int argc, char **argv)
+{
+ /* local variables */
+ HANDLE hThread = 0;
+ int ret;
+ BOOL bResult = FAIL;
+
+ /* initialize the PAL */
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ InAPC = FALSE;
+
+ /* create a pair of synchronization events to coordinate our threads */
+ hSyncEvent1 = CreateEvent( NULL, FALSE, FALSE, NULL );
+ if( hSyncEvent1 == NULL )
+ {
+ Trace( "ERROR:%lu:CreateEvent() call failed\n", GetLastError() );
+ goto cleanup;
+ }
+
+ hSyncEvent2 = CreateEvent( NULL, FALSE, FALSE, NULL );
+ if( hSyncEvent2 == NULL )
+ {
+ Trace( "ERROR:%lu:CreateEvent() call failed\n", GetLastError() );
+ goto cleanup;
+ }
+
+ /* create a child thread */
+ hThread = CreateThread( NULL,
+ 0,
+ (LPTHREAD_START_ROUTINE)SleeperProc,
+ 0,
+ 0,
+ &ChildThread);
+
+ if (hThread == NULL)
+ {
+ Trace( "ERROR:%lu:CreateThread() call failed\n",
+ GetLastError());
+ goto cleanup;
+ }
+
+
+ /* wait on our synchronization event to ensure the thread is running */
+ ret = WaitForSingleObject( hSyncEvent1, 20000 );
+ if( ret != WAIT_OBJECT_0 )
+ {
+ Trace( "ERROR:WaitForSingleObject() returned %lu, "
+ "expected WAIT_OBJECT_0\n",
+ ret );
+ goto cleanup;
+ }
+
+ /* queue a user APC on the child thread */
+ ret = QueueUserAPC(APCFunc, hThread, 0);
+ if (ret == 0)
+ {
+ Trace( "ERROR:%lu:QueueUserAPC() call failed\n",
+ GetLastError());
+ goto cleanup;
+ }
+
+ /* signal the child thread to continue */
+ if( ! SetEvent( hSyncEvent2 ) )
+ {
+ Trace( "ERROR:%lu:SetEvent() call failed\n", GetLastError() );
+ goto cleanup;
+ }
+
+ /* wait on our synchronization event to ensure the other thread is done */
+ ret = WaitForSingleObject( hSyncEvent1, 20000 );
+ if( ret != WAIT_OBJECT_0 )
+ {
+ Trace( "ERROR:WaitForSingleObject() returned %lu, "
+ "expected WAIT_OBJECT_0\n",
+ ret );
+ goto cleanup;
+ }
+
+ /* check that the thread executed successfully */
+ if( bThreadResult == FAIL )
+ {
+ goto cleanup;
+ }
+
+
+ /* check whether the APC function was executed */
+ if( InAPC )
+ {
+ Trace( "FAIL:APC function was executed but shouldn't have been\n" );
+ goto cleanup;
+ }
+
+ /* success if we reach here */
+ bResult = PASS;
+
+
+cleanup:
+ /* wait for the other thread to finish */
+ if( hThread != NULL )
+ {
+ ret = WaitForSingleObject( hThread, INFINITE );
+ if (ret == WAIT_FAILED)
+ {
+ Trace( "ERROR:%lu:WaitForSingleObject() returned %lu, "
+ "expected WAIT_OBJECT_0\n",
+ ret );
+ bResult = FAIL;
+ }
+ }
+
+ /* close our synchronization handles */
+ if( hSyncEvent1 != NULL )
+ {
+ if( ! CloseHandle( hSyncEvent1 ) )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ bResult = FAIL;
+ }
+ }
+
+ if( hSyncEvent2 != NULL )
+ {
+ if( ! CloseHandle( hSyncEvent2 ) )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ bResult = FAIL;
+ }
+ }
+
+ if( bResult == FAIL )
+ {
+ Fail( "test failed\n" );
+ }
+
+
+ /* terminate the PAL */
+ PAL_Terminate();
+
+ /* return success */
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test2/testinfo.dat b/src/pal/tests/palsuite/threading/QueueUserAPC/test2/testinfo.dat
new file mode 100644
index 0000000000..42d942df36
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/QueueUserAPC/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = QueueUserAPC
+Name = Test #2 for QueueUserAPC
+TYPE = DEFAULT
+EXE1 = test2
+Description
+=Tests that APCs are not executed if a thread never enters an
+=alertable state after they are queued.
diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test3/CMakeLists.txt b/src/pal/tests/palsuite/threading/QueueUserAPC/test3/CMakeLists.txt
new file mode 100644
index 0000000000..8475dcb03e
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/QueueUserAPC/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_queueuserapc_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_queueuserapc_test3 coreclrpal)
+
+target_link_libraries(paltest_queueuserapc_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test3/test3.c b/src/pal/tests/palsuite/threading/QueueUserAPC/test3/test3.c
new file mode 100644
index 0000000000..933f41a5b4
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/QueueUserAPC/test3/test3.c
@@ -0,0 +1,33 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test3.c
+**
+** Purpose: Tests how QueueUserAPC handles an invalid thread.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main (int argc, char **argv)
+{
+ int ret;
+
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ ret = QueueUserAPC(NULL, NULL, 0);
+ if (ret != 0)
+ {
+ Fail("QueueUserAPC passed with an invalid thread!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test3/testinfo.dat b/src/pal/tests/palsuite/threading/QueueUserAPC/test3/testinfo.dat
new file mode 100644
index 0000000000..0b96349f15
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/QueueUserAPC/test3/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = QueueUserAPC
+Name = Test #3 for QueueUserAPC
+TYPE = DEFAULT
+EXE1 = test3
+Description
+=Tests how QueueUserAPC handles an invalid thread.
diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test4/CMakeLists.txt b/src/pal/tests/palsuite/threading/QueueUserAPC/test4/CMakeLists.txt
new file mode 100644
index 0000000000..2552738b50
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/QueueUserAPC/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_queueuserapc_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_queueuserapc_test4 coreclrpal)
+
+target_link_libraries(paltest_queueuserapc_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test4/test4.c b/src/pal/tests/palsuite/threading/QueueUserAPC/test4/test4.c
new file mode 100644
index 0000000000..c28709db81
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/QueueUserAPC/test4/test4.c
@@ -0,0 +1,72 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test4.c
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** GetCurrentThread
+** SleepEx
+**
+** Purpose:
+**
+** Test to ensure proper operation of the QueueUserAPC()
+** API by trying to queue APC functions on the current
+** thread.
+**
+**
+**===========================================================================*/
+#include <palsuite.h>
+
+
+static BOOL bAPCExecuted = FALSE;
+
+VOID PALAPI APCFunc( ULONG_PTR dwParam )
+{
+ bAPCExecuted = TRUE;
+}
+
+int __cdecl main( int argc, char **argv )
+
+{
+ /* local variables */
+ HANDLE hThread = NULL;
+ DWORD ret;
+
+ /* PAL initialization */
+ if( (PAL_Initialize(argc, argv)) != 0 )
+ {
+ return( FAIL );
+ }
+
+ /* get the current thread */
+ hThread = GetCurrentThread();
+ ret = QueueUserAPC( APCFunc, hThread, 0 );
+ if( ret == 0 )
+ {
+ Fail( "ERROR:%lu:QueueUserAPC call failed\n", GetLastError() );
+ }
+
+ /* call SleepEx() to put the thread in an alertable state */
+ ret = SleepEx( 2000, TRUE );
+ if( ret != WAIT_IO_COMPLETION )
+ {
+ Fail( "ERROR:Expected sleep to return WAIT_IO_COMPLETION, got %lu\n",
+ ret );
+ }
+
+ /* check that the APC function was executed */
+ if( bAPCExecuted == FALSE )
+ {
+ Fail( "ERROR:APC function was not executed\n" );
+ }
+
+ /* PAL termination */
+ PAL_Terminate();
+
+ /* return success */
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test4/testinfo.dat b/src/pal/tests/palsuite/threading/QueueUserAPC/test4/testinfo.dat
new file mode 100644
index 0000000000..cd7b7c2f21
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/QueueUserAPC/test4/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = QueueUserAPC
+Name = Positive test for QueueUserAPC
+TYPE = DEFAULT
+EXE1 = test4
+Description
+= Test to ensure proper operation of the QueueUserAPC()
+= API by trying to queue APC functions on the current
+= thread.
diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test5/CMakeLists.txt b/src/pal/tests/palsuite/threading/QueueUserAPC/test5/CMakeLists.txt
new file mode 100644
index 0000000000..c2fa10de12
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/QueueUserAPC/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test5.c
+)
+
+add_executable(paltest_queueuserapc_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_queueuserapc_test5 coreclrpal)
+
+target_link_libraries(paltest_queueuserapc_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test5/test5.c b/src/pal/tests/palsuite/threading/QueueUserAPC/test5/test5.c
new file mode 100644
index 0000000000..3d26a55f59
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/QueueUserAPC/test5/test5.c
@@ -0,0 +1,200 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test5.c
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** CreateEvent
+** SetEvent
+** CreateThread
+** ResumeThread
+** WaitForSingleObject
+** CloseHandle
+**
+** Purpose:
+**
+** Test to ensure proper operation of the QueueUserAPC()
+** API by trying to queue and activate APC functions on
+** a thread that was created suspended, prior to resuming
+** it. We're verifying the following behavior:
+**
+** "If an application queues an APC before the thread begins
+** running, the thread begins by calling the APC function.
+** After the thread calls an APC function, it calls the APC
+** functions for all APCs in its APC queue."
+**
+**
+**===========================================================================*/
+#include <palsuite.h>
+
+
+static HANDLE hEvent = NULL;
+static BOOL bAPCExecuted = FALSE;
+
+VOID PALAPI APCFunc( ULONG_PTR dwParam )
+{
+ bAPCExecuted = TRUE;
+}
+
+/**
+ * ThreadFunc
+ *
+ * Dummy thread function for APC queuing.
+ */
+DWORD PALAPI ThreadFunc( LPVOID param )
+{
+ DWORD ret = 0;
+
+ /* alertable wait until the global event is signalled */
+ ret = WaitForSingleObject( hEvent, INFINITE );
+ if( ret != WAIT_OBJECT_0 )
+ {
+ Fail( "ERROR:WaitForSingleObject() returned %lu, "
+ "expected WAIT_OBJECT_0\n",
+ ret );
+ }
+
+ return 0;
+}
+
+
+int __cdecl main( int argc, char **argv )
+
+{
+ /* local variables */
+ HANDLE hThread = NULL;
+ DWORD IDThread;
+ DWORD ret;
+ BOOL bResult = FALSE;
+
+ /* PAL initialization */
+ if( (PAL_Initialize(argc, argv)) != 0 )
+ {
+ return( FAIL );
+ }
+
+ /* create an event for the other thread to wait on */
+ hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
+ if( hEvent == NULL )
+ {
+ Fail( "ERROR:%lu:CreateEvent() call failed\n", GetLastError() );
+ }
+
+ /* run another dummy thread to cause notification of the library */
+ hThread = CreateThread( NULL, /* no security attributes */
+ 0, /* use default stack size */
+ (LPTHREAD_START_ROUTINE) ThreadFunc, /* thread function */
+ (LPVOID) NULL, /* pass thread index as */
+ /* function argument */
+ CREATE_SUSPENDED, /* create suspended */
+ &IDThread ); /* returns thread id */
+
+ /* Check the return value for success. */
+ if( hThread == NULL )
+ {
+ /* error creating thread */
+ Trace( "ERROR:%lu:CreateThread call failed\n", GetLastError() );
+ if( ! CloseHandle( hEvent ) )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ }
+ Fail( "test failed\n" );
+ }
+
+ /* queue our APC on the suspended thread */
+ ret = QueueUserAPC( APCFunc, hThread, 0 );
+ if( ret == 0 )
+ {
+ Fail( "ERROR:%lu:QueueUserAPC call failed\n", GetLastError() );
+ }
+
+ /* wait on the suspended thread */
+ ret = WaitForSingleObject( hThread, 2000 );
+ if( ret != WAIT_TIMEOUT )
+ {
+ Trace( "ERROR:WaitForSingleObject() returned %lu, "
+ "expected WAIT_TIMEOUT\n",
+ ret );
+ goto cleanup;
+ }
+
+ /* verify that the APC function was not executed */
+ if( bAPCExecuted == TRUE )
+ {
+ Trace( "ERROR:APC function was executed for a suspended thread\n" );
+ goto cleanup;
+ }
+
+ /* Resume the suspended thread */
+ ResumeThread( hThread );
+
+ /* do another wait on the resumed thread */
+ ret = WaitForSingleObject( hThread, 2000 );
+
+ /* verify that we got a WAIT_TIMEOUT result */
+ if( ret != WAIT_TIMEOUT )
+ {
+ Trace( "ERROR:WaitForSingleObject() returned %lu, "
+ "expected WAIT_TIMEOUT\n",
+ ret );
+ goto cleanup;
+ }
+
+ /* check that the APC function was actually executed */
+ if( bAPCExecuted == FALSE )
+ {
+ Trace( "ERROR:APC function was not executed\n" );
+ goto cleanup;
+ }
+
+ /* set the success flag */
+ bResult = PASS;
+
+cleanup:
+ /* signal the event so the other thread will exit */
+ if( ! SetEvent( hEvent ) )
+ {
+ Trace( "ERROR:%lu:SetEvent() call failed\n", GetLastError() );
+ bResult = FAIL;
+ }
+
+ /* close the global event handle */
+ if( ! CloseHandle( hEvent ) )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ bResult = FAIL;
+ }
+
+ /* wait on the other thread to complete */
+ ret = WaitForSingleObject( hThread, 2000 );
+ if( ret != WAIT_OBJECT_0 )
+ {
+ Trace( "ERROR:WaitForSingleObject() returned %lu, "
+ "expected WAIT_OBJECT_0\n",
+ ret );
+ bResult = FAIL;
+ }
+
+ /* close the thread handle */
+ if( ! CloseHandle( hThread ) )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ bResult = FAIL;
+ }
+
+ /* output final failure result for failure case */
+ if( bResult == FAIL )
+ {
+ Fail( "test failed\n" );
+ }
+
+ /* PAL termination */
+ PAL_Terminate();
+
+ /* return success */
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test5/testinfo.dat b/src/pal/tests/palsuite/threading/QueueUserAPC/test5/testinfo.dat
new file mode 100644
index 0000000000..f1775aabe8
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/QueueUserAPC/test5/testinfo.dat
@@ -0,0 +1,20 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = QueueUserAPC
+Name = Positive test for QueueUserAPC
+TYPE = DEFAULT
+EXE1 = test5
+Description
+= Test to ensure proper operation of the QueueUserAPC()
+= API by trying to queue and activate APC functions on
+= a thread that was created suspended, prior to resuming
+= it. We're verifying the following behavior:
+=
+= "If an application queues an APC before the thread begins
+= running, the thread begins by calling the APC function.
+= After the thread calls an APC function, it calls the APC
+= functions for all APCs in its APC queue."
diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test6/CMakeLists.txt b/src/pal/tests/palsuite/threading/QueueUserAPC/test6/CMakeLists.txt
new file mode 100644
index 0000000000..3fd1b1a08e
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/QueueUserAPC/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test6.c
+)
+
+add_executable(paltest_queueuserapc_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_queueuserapc_test6 coreclrpal)
+
+target_link_libraries(paltest_queueuserapc_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test6/test6.c b/src/pal/tests/palsuite/threading/QueueUserAPC/test6/test6.c
new file mode 100644
index 0000000000..e2e2464726
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/QueueUserAPC/test6/test6.c
@@ -0,0 +1,129 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test6.c
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** CreateEvent
+** SetEvent
+** CreateThread
+** ResumeThread
+** WaitForMultipleObjectsEx
+** CloseHandle
+**
+** Purpose:
+**
+** Test to ensure proper operation of the QueueUserAPC()
+** API by trying to queue APC functions on a thread that
+** has already terminated.
+**
+**
+**===========================================================================*/
+#include <palsuite.h>
+
+
+static BOOL bAPCExecuted = FALSE;
+
+VOID PALAPI APCFunc( ULONG_PTR dwParam )
+{
+ bAPCExecuted = TRUE;
+}
+
+/**
+ * ThreadFunc
+ *
+ * Dummy thread function for APC queuing.
+ */
+DWORD PALAPI ThreadFunc( LPVOID param )
+{
+ int i;
+
+ /* simulate some activity */
+ for( i=0; i<250000; i++ )
+ ;
+
+ return 0;
+}
+
+
+int __cdecl main( int argc, char **argv )
+
+{
+ /* local variables */
+ HANDLE hThread = NULL;
+ DWORD IDThread;
+ DWORD ret;
+
+ /* PAL initialization */
+ if( (PAL_Initialize(argc, argv)) != 0 )
+ {
+ return( FAIL );
+ }
+
+ /* run another dummy thread to cause notification of the library */
+ hThread = CreateThread( NULL, /* no security attributes */
+ 0, /* use default stack size */
+ (LPTHREAD_START_ROUTINE) ThreadFunc, /* thread function */
+ (LPVOID) NULL, /* pass thread index as */
+ /* function argument */
+ CREATE_SUSPENDED, /* create suspended */
+ &IDThread ); /* returns thread id */
+
+ /* Check the return value for success. */
+ if( hThread == NULL )
+ {
+ /* error creating thread */
+ Fail( "ERROR:%lu:CreateThread call failed\n", GetLastError() );
+ }
+
+ /* Resume the suspended thread */
+ ResumeThread( hThread );
+
+ /* wait on the other thread to complete */
+ ret = WaitForSingleObject( hThread, INFINITE );
+ if( ret != WAIT_OBJECT_0 )
+ {
+ Trace( "ERROR:WaitForSingleObject() returned %lu, "
+ "expected WAIT_OBJECT_0\n",
+ ret );
+ if( ! CloseHandle( hThread ) )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ }
+ Fail( "test failed\n" );
+ }
+
+ /* queue our APC on the finished thread */
+ ret = QueueUserAPC( APCFunc, hThread, 0 );
+ if( ret != 0 )
+ {
+ Trace( "ERROR:QueueUserAPC call succeeded on a terminated thread\n" );
+ if( ! CloseHandle( hThread ) )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ }
+ Fail( "test failed\n" );
+ }
+
+ if( ! CloseHandle( hThread ) )
+ {
+ Fail( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ }
+
+ /* dummy check that the APC function wasn't actually executed */
+ if( bAPCExecuted != FALSE )
+ {
+ Fail( "ERROR:APC function was executed\n" );
+ }
+
+
+ /* PAL termination */
+ PAL_Terminate();
+
+ /* return success */
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test6/testinfo.dat b/src/pal/tests/palsuite/threading/QueueUserAPC/test6/testinfo.dat
new file mode 100644
index 0000000000..4d806184ee
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/QueueUserAPC/test6/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = QueueUserAPC
+Name = Negative test for QueueUserAPC
+TYPE = DEFAULT
+EXE1 = test6
+Description
+= Test to ensure proper operation of the QueueUserAPC()
+= API by trying to queue APC functions on a thread that
+= has already terminated.
diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test7/CMakeLists.txt b/src/pal/tests/palsuite/threading/QueueUserAPC/test7/CMakeLists.txt
new file mode 100644
index 0000000000..751f3894f4
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/QueueUserAPC/test7/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test7.c
+)
+
+add_executable(paltest_queueuserapc_test7
+ ${SOURCES}
+)
+
+add_dependencies(paltest_queueuserapc_test7 coreclrpal)
+
+target_link_libraries(paltest_queueuserapc_test7
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test7/test7.c b/src/pal/tests/palsuite/threading/QueueUserAPC/test7/test7.c
new file mode 100644
index 0000000000..54a63982fe
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/QueueUserAPC/test7/test7.c
@@ -0,0 +1,253 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test7.c
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** CreateEvent
+** SetEvent
+** CreateThread
+** ResumeThread
+** WaitForMultipleObjectsEx
+** CloseHandle
+**
+** Purpose:
+**
+** Test to ensure proper operation of the QueueUserAPC()
+** API by trying to queue an APC function on a thread and
+** activating it with WaitForMultipleObjectsEx.
+**
+**
+**===========================================================================*/
+#include <palsuite.h>
+
+
+static HANDLE hSyncEvent = NULL;
+static HANDLE hTestEvent = NULL;
+static int nAPCExecuted = 0;
+static BOOL bThreadResult = FALSE;
+
+VOID PALAPI APCFunc( ULONG_PTR dwParam )
+{
+ ++nAPCExecuted;
+}
+
+/**
+ * ThreadFunc
+ *
+ * Dummy thread function for APC queuing.
+ */
+DWORD PALAPI ThreadFunc( LPVOID param )
+{
+ DWORD ret = 0;
+
+ /* pessimism */
+ bThreadResult = FALSE;
+
+ /* set the sync event to notify the main thread */
+ if( ! SetEvent( hSyncEvent ) )
+ {
+ Trace( "ERROR:%lu:SetEvent() call failed\n", GetLastError() );
+ goto done;
+ }
+
+ /* wait until the test event is signalled */
+ ret = WaitForSingleObject( hTestEvent, INFINITE );
+ if( ret != WAIT_OBJECT_0 )
+ {
+ Trace( "ERROR:WaitForSingleObject() returned %lu, "
+ "expected WAIT_OBJECT_0\n",
+ ret );
+ goto done;
+ }
+
+ /* now do an alertable wait on the same event, which is now
+ in an unsignalled state */
+ ret = WaitForMultipleObjectsEx( 1, &hTestEvent, TRUE, 2000, TRUE );
+
+ /* verify that we got a WAIT_IO_COMPLETION result */
+ if( ret != WAIT_IO_COMPLETION )
+ {
+ Trace( "ERROR:WaitForMultipleObjectsEx returned %lu, "
+ "expected WAIT_IO_COMPLETION\n",
+ ret );
+ goto done;
+ }
+
+ /* set the event again */
+ if( ! SetEvent( hTestEvent ) )
+ {
+ Trace( "ERROR:%lu:SetEvent() call failed\n", GetLastError() );
+ goto done;
+ }
+
+ /* do a non-alertable wait on the same event */
+ ret = WaitForMultipleObjectsEx( 1, &hTestEvent, TRUE, INFINITE, FALSE );
+
+ /* verify that we got a WAIT_OBJECT_0 result */
+ if( ret != WAIT_OBJECT_0 )
+ {
+ Trace( "ERROR:WaitForMultipleObjectsEx returned %lu, "
+ "expected WAIT_OBJECT_0\n",
+ ret );
+ goto done;
+ }
+
+ /* success at this point */
+ bThreadResult = TRUE;
+
+
+done:
+ return bThreadResult;
+}
+
+
+int __cdecl main( int argc, char **argv )
+
+{
+ /* local variables */
+ HANDLE hThread = NULL;
+ DWORD IDThread;
+ DWORD ret;
+ BOOL bResult = FALSE;
+
+ /* PAL initialization */
+ if( (PAL_Initialize(argc, argv)) != 0 )
+ {
+ return( FAIL );
+ }
+
+ /* create an auto-reset event for the other thread to wait on */
+ hTestEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
+ if( hTestEvent == NULL )
+ {
+ Fail( "ERROR:%lu:CreateEvent() call failed\n", GetLastError() );
+ }
+
+ /* create an auto-reset event for synchronization */
+ hSyncEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
+ if( hSyncEvent == NULL )
+ {
+ Trace( "ERROR:%lu:CreateEvent() call failed\n", GetLastError() );
+ if( ! CloseHandle( hTestEvent ) )
+ {
+ Trace( "ERROR:%lu:CreateEvent() call failed\n", GetLastError() );
+ }
+ Fail( "test failed\n" );
+ }
+
+ /* run another dummy thread to cause notification of the library */
+ hThread = CreateThread( NULL, /* no security attributes */
+ 0, /* use default stack size */
+ (LPTHREAD_START_ROUTINE) ThreadFunc, /* thread function */
+ (LPVOID) NULL, /* pass thread index as */
+ /* function argument */
+ CREATE_SUSPENDED, /* create suspended */
+ &IDThread ); /* returns thread id */
+
+ /* Check the return value for success. */
+ if( hThread == NULL )
+ {
+ /* error creating thread */
+ Trace( "ERROR:%lu:CreateThread call failed\n", GetLastError() );
+ if( ! CloseHandle( hTestEvent ) )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ }
+ Fail( "test failed\n" );
+ }
+
+ /* Resume the suspended thread */
+ ResumeThread( hThread );
+
+ /* wait until the other thread is ready to proceed */
+ ret = WaitForSingleObject( hSyncEvent, 10000 );
+ if( ret != WAIT_OBJECT_0 )
+ {
+ Trace( "ERROR:WaitForSingleObject returned %lu, "
+ "expected WAIT_OBJECT_0\n",
+ ret );
+ goto cleanup;
+ }
+
+
+ /* now queue our APC on the test thread */
+ ret = QueueUserAPC( APCFunc, hThread, 0 );
+ if( ret == 0 )
+ {
+ Trace( "ERROR:%lu:QueueUserAPC call failed\n", GetLastError() );
+ goto cleanup;
+ }
+
+ /* signal the test event so the other thread will proceed */
+ if( ! SetEvent( hTestEvent ) )
+ {
+ Trace( "ERROR:%lu:SetEvent() call failed\n", GetLastError() );
+ goto cleanup;
+ }
+
+ /* wait on the other thread to complete */
+ ret = WaitForSingleObject( hThread, INFINITE );
+ if( ret != WAIT_OBJECT_0 )
+ {
+ Trace( "ERROR:WaitForSingleObject() returned %lu, "
+ "expected WAIT_OBJECT_0\n",
+ ret );
+ goto cleanup;
+ }
+
+ /* check the result of the other thread */
+ if( bThreadResult == FALSE )
+ {
+ goto cleanup;
+ }
+
+ /* check that the APC function was actually executed exactly one time */
+ if( nAPCExecuted != 1 )
+ {
+ Trace( "ERROR:APC function was executed %d times, "
+ "expected once\n", nAPCExecuted );
+ goto cleanup;
+ }
+
+ /* set the success flag */
+ bResult = PASS;
+
+
+cleanup:
+ /* close the global event handles */
+ if( ! CloseHandle( hTestEvent ) )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ bResult = FAIL;
+ }
+
+ if( ! CloseHandle( hSyncEvent ) )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ bResult = FAIL;
+ }
+
+ /* close the thread handle */
+ if( ! CloseHandle( hThread ) )
+ {
+ Trace( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ bResult = FAIL;
+ }
+
+ /* output final failure result for failure case */
+ if( bResult == FAIL )
+ {
+ Fail( "test failed\n" );
+ }
+
+ /* PAL termination */
+ PAL_Terminate();
+
+ /* return success */
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test7/testinfo.dat b/src/pal/tests/palsuite/threading/QueueUserAPC/test7/testinfo.dat
new file mode 100644
index 0000000000..d92d9496d7
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/QueueUserAPC/test7/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = QueueUserAPC
+Name = Positive test for QueueUserAPC
+TYPE = DEFAULT
+EXE1 = test7
+Description
+= Test to ensure proper operation of the QueueUserAPC()
+= API by trying to queue an APC function on a thread and
+= activating it with WaitForMultipleObjectsEx.
diff --git a/src/pal/tests/palsuite/threading/ReleaseMutex/CMakeLists.txt b/src/pal/tests/palsuite/threading/ReleaseMutex/CMakeLists.txt
new file mode 100644
index 0000000000..f9524196e0
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ReleaseMutex/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test3)
+
diff --git a/src/pal/tests/palsuite/threading/ReleaseMutex/test3/CMakeLists.txt b/src/pal/tests/palsuite/threading/ReleaseMutex/test3/CMakeLists.txt
new file mode 100644
index 0000000000..8e64c28242
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ReleaseMutex/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ ReleaseMutex.c
+)
+
+add_executable(paltest_releasemutex_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_releasemutex_test3 coreclrpal)
+
+target_link_libraries(paltest_releasemutex_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/ReleaseMutex/test3/ReleaseMutex.c b/src/pal/tests/palsuite/threading/ReleaseMutex/test3/ReleaseMutex.c
new file mode 100644
index 0000000000..5f6adb0419
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ReleaseMutex/test3/ReleaseMutex.c
@@ -0,0 +1,103 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: ReleaseMutex/test3/ReleaseMutex.c
+**
+** Purpose: Test failure code for ReleaseMutex.
+**
+** Dependencies: CreateMutex
+** ReleaseMutex
+** CreateThread
+**
+
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+DWORD dwTestResult; /* global for test result */
+
+DWORD dwThreadId; /* consumer thread identifier */
+
+HANDLE hMutex; /* handle to mutex */
+
+HANDLE hThread; /* handle to thread */
+
+/*
+ * Thread function.
+ */
+DWORD
+PALAPI
+ThreadFunction( LPVOID lpNoArg )
+{
+
+ dwTestResult = ReleaseMutex(hMutex);
+
+ return 0;
+}
+
+int __cdecl main (int argc, char **argv)
+{
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return (FAIL);
+ }
+
+ /*
+ * set dwTestResult so test fails even if ReleaseMutex is not called
+ */
+ dwTestResult = 1;
+
+ /*
+ * Create mutex
+ */
+ hMutex = CreateMutexW (
+ NULL,
+ TRUE,
+ NULL);
+
+ if ( NULL == hMutex )
+ {
+ Fail ( "hMutex = CreateMutex () - returned NULL\n"
+ "Failing Test.\nGetLastError returned %d\n", GetLastError());
+ }
+
+ /*
+ * Create ThreadFunction
+ */
+ hThread = CreateThread(
+ NULL,
+ 0,
+ ThreadFunction,
+ NULL,
+ 0,
+ &dwThreadId);
+
+ if ( NULL == hThread )
+ {
+
+ Fail ( "CreateThread() returned NULL. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+ /*
+ * Wait for ThreadFunction to complete
+ */
+ WaitForSingleObject (hThread, INFINITE);
+
+ if (dwTestResult)
+ {
+ Fail ("ReleaseMutex() test was expected to return 0.\n"
+ "It returned %d. Failing test.\n", dwTestResult );
+ }
+
+ Trace ("ReleaseMutex() test returned 0.\nTest passed.\n");
+
+ PAL_Terminate();
+ return ( PASS );
+
+}
diff --git a/src/pal/tests/palsuite/threading/ReleaseMutex/test3/testinfo.dat b/src/pal/tests/palsuite/threading/ReleaseMutex/test3/testinfo.dat
new file mode 100644
index 0000000000..3f06757eb6
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ReleaseMutex/test3/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = ReleaseMutex
+Name = Positive Test for ReleaseMutex
+TYPE = DEFAULT
+EXE1 = releasemutex
+Description
+= Calls ReleaseMutex from a thread which should not have ownership of the
+= mutex. If ReleaseMutex fails correctly this test will succeed.
diff --git a/src/pal/tests/palsuite/threading/ResetEvent/CMakeLists.txt b/src/pal/tests/palsuite/threading/ResetEvent/CMakeLists.txt
new file mode 100644
index 0000000000..a3847f8ca9
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ResetEvent/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+
diff --git a/src/pal/tests/palsuite/threading/ResetEvent/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/ResetEvent/test1/CMakeLists.txt
new file mode 100644
index 0000000000..78e84da2b9
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ResetEvent/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_resetevent_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_resetevent_test1 coreclrpal)
+
+target_link_libraries(paltest_resetevent_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/ResetEvent/test1/test1.c b/src/pal/tests/palsuite/threading/ResetEvent/test1/test1.c
new file mode 100644
index 0000000000..20a0d5dffa
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ResetEvent/test1/test1.c
@@ -0,0 +1,99 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test1.c
+**
+** Purpose: Test for ResetEvent. Create an event with an intial
+** state signaled. Then reset that signal, and check to see that
+** the event is now not signaled.
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+BOOL ResetEventTest()
+{
+ BOOL bRet = FALSE;
+ DWORD dwRet = 0;
+
+ LPSECURITY_ATTRIBUTES lpEventAttributes = 0;
+ BOOL bManualReset = TRUE;
+ BOOL bInitialState = TRUE;
+
+ /* Create an Event, ensure it is valid */
+ HANDLE hEvent = CreateEvent( lpEventAttributes,
+ bManualReset, bInitialState, NULL);
+
+ if (hEvent != INVALID_HANDLE_VALUE)
+ {
+ /* Check that WaitFor returns WAIT_OBJECT_0, indicating that
+ the event is signaled.
+ */
+
+ dwRet = WaitForSingleObject(hEvent,0);
+
+ if (dwRet != WAIT_OBJECT_0)
+ {
+ Fail("ResetEventTest:WaitForSingleObject failed (%x)\n", GetLastError());
+ }
+ else
+ {
+ /* Call ResetEvent, which will reset the signal */
+ bRet = ResetEvent(hEvent);
+
+ if (!bRet)
+ {
+ Fail("ResetEventTest:ResetEvent failed (%x)\n", GetLastError());
+ }
+ else
+ {
+ /* Call WaitFor again, and since it has been reset,
+ the return value should now be WAIT_TIMEOUT
+ */
+ dwRet = WaitForSingleObject(hEvent,0);
+
+ if (dwRet != WAIT_TIMEOUT)
+ {
+ Fail("ResetEventTest:WaitForSingleObject %s failed (%x)\n", GetLastError());
+ }
+ else
+ {
+ bRet = CloseHandle(hEvent);
+
+ if (!bRet)
+ {
+ Fail("ResetEventTest:CloseHandle failed (%x)\n", GetLastError());
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ Fail("ResetEventTest:CreateEvent failed (%x)\n", GetLastError());
+ }
+
+ return bRet;
+}
+
+int __cdecl main(int argc, char **argv)
+{
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ if(!ResetEventTest())
+ {
+ Fail ("Test failed\n");
+ }
+
+ PAL_Terminate();
+ return ( PASS );
+
+}
diff --git a/src/pal/tests/palsuite/threading/ResetEvent/test1/testinfo.dat b/src/pal/tests/palsuite/threading/ResetEvent/test1/testinfo.dat
new file mode 100644
index 0000000000..ed27f13dba
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ResetEvent/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = ResetEvent
+Name = Positive Test for ResetEvent
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Test for ResetEvent. Create an event with an intial
+= state signaled. Then reset that signal, and check to see that
+= the event is now not signaled.
diff --git a/src/pal/tests/palsuite/threading/ResetEvent/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/ResetEvent/test2/CMakeLists.txt
new file mode 100644
index 0000000000..ad0fe9b4a1
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ResetEvent/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_resetevent_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_resetevent_test2 coreclrpal)
+
+target_link_libraries(paltest_resetevent_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/ResetEvent/test2/test2.c b/src/pal/tests/palsuite/threading/ResetEvent/test2/test2.c
new file mode 100644
index 0000000000..8117f44353
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ResetEvent/test2/test2.c
@@ -0,0 +1,89 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test2.c
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** CreateEvent
+** CloseHandle
+** WaitForSingleObject
+**
+** Purpose: Test to ensure proper operation of the ResetEvent()
+** API by calling it on an event handle that's already
+** unsignalled.
+**
+
+**
+**===========================================================================*/
+#include <palsuite.h>
+
+
+
+int __cdecl main( int argc, char **argv )
+
+{
+ /* local variables */
+ DWORD dwRet = 0;
+ HANDLE hEvent = NULL;
+ LPSECURITY_ATTRIBUTES lpEventAttributes = NULL;
+ BOOL bManualReset = TRUE;
+ BOOL bInitialState = FALSE;
+
+
+ /* PAL initialization */
+ if( (PAL_Initialize(argc, argv)) != 0 )
+ {
+ return( FAIL );
+ }
+
+
+ /* create an unsignalled event which we can use with ResetEvent */
+ hEvent = CreateEvent( lpEventAttributes,
+ bManualReset,
+ bInitialState,
+ NULL );
+
+ if( hEvent == INVALID_HANDLE_VALUE )
+ {
+ /* ERROR */
+ Fail( "ERROR:%lu:CreateEvent() call failed\n", GetLastError() );
+ }
+
+ /* verify that the event isn't signalled yet */
+ dwRet = WaitForSingleObject( hEvent, 0 );
+ if( dwRet != WAIT_TIMEOUT )
+ {
+ /* ERROR */
+ Trace( "ERROR:WaitForSingleObject() call returned %lu, "
+ "expected WAIT_TIMEOUT\n",
+ dwRet );
+ CloseHandle( hEvent );
+ Fail( "Test failed\n" );
+ }
+
+ /* try to reset the event */
+ if( ! ResetEvent( hEvent ) )
+ {
+ /* ERROR */
+ Trace( "FAIL:%lu:ResetEvent() call failed\n", GetLastError() );
+ CloseHandle( hEvent );
+ Fail( "Test failed\n" );
+ }
+
+ /* close the event handle */
+ if( ! CloseHandle( hEvent ) )
+ {
+ Fail( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ }
+
+
+ /* PAL termination */
+ PAL_Terminate();
+
+ /* return success */
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/threading/ResetEvent/test2/testinfo.dat b/src/pal/tests/palsuite/threading/ResetEvent/test2/testinfo.dat
new file mode 100644
index 0000000000..4af1769cd4
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ResetEvent/test2/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = ResetEvent
+Name = Positive test for ResetEvent
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Test to ensure proper operation of the ResetEvent()
+= API by calling it on an event handle that's already
+= unsignalled.
diff --git a/src/pal/tests/palsuite/threading/ResetEvent/test3/CMakeLists.txt b/src/pal/tests/palsuite/threading/ResetEvent/test3/CMakeLists.txt
new file mode 100644
index 0000000000..3c4ea1f249
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ResetEvent/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_resetevent_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_resetevent_test3 coreclrpal)
+
+target_link_libraries(paltest_resetevent_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/ResetEvent/test3/test3.c b/src/pal/tests/palsuite/threading/ResetEvent/test3/test3.c
new file mode 100644
index 0000000000..9bc068ea72
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ResetEvent/test3/test3.c
@@ -0,0 +1,86 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test3.c
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** CreateEvent
+** CloseHandle
+**
+** Purpose:
+**
+** Test to ensure proper operation of the ResetEvent()
+** API by calling it on an event handle that's been
+** closed. We expect it to return an appropriate error
+** result.
+**
+**
+
+**
+**===========================================================================*/
+#include <palsuite.h>
+
+
+
+int __cdecl main( int argc, char **argv )
+
+{
+ /* local variables */
+ HANDLE hEvent = NULL;
+ LPSECURITY_ATTRIBUTES lpEventAttributes = NULL;
+ BOOL bManualReset = TRUE;
+ BOOL bInitialState = FALSE;
+
+
+ /* PAL initialization */
+ if( (PAL_Initialize(argc, argv)) != 0 )
+ {
+ return( FAIL );
+ }
+
+
+ /* create an event which we can use with ResetEvent */
+ hEvent = CreateEvent( lpEventAttributes,
+ bManualReset,
+ bInitialState,
+ NULL );
+
+ if( hEvent == INVALID_HANDLE_VALUE )
+ {
+ /* ERROR */
+ Fail( "ERROR:%lu:CreateEvent() call failed\n", GetLastError() );
+ }
+
+ /* close the event handle */
+ if( ! CloseHandle( hEvent ) )
+ {
+ Fail( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ }
+
+ /* try to reset the event */
+ if( ResetEvent( hEvent ) )
+ {
+ /* ERROR */
+ Fail( "FAIL:ResetEvent() call succeeded on a closed event handle\n" );
+ }
+
+ /* verify the result of GetLastError() */
+ if( GetLastError() != ERROR_INVALID_HANDLE )
+ {
+ /* ERROR */
+ Fail( "FAIL:ResetEvent() call failed on a closed event handle "
+ "but returned an unexpected error result %lu\n" );
+ }
+
+
+
+ /* PAL termination */
+ PAL_Terminate();
+
+ /* return success */
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/threading/ResetEvent/test3/testinfo.dat b/src/pal/tests/palsuite/threading/ResetEvent/test3/testinfo.dat
new file mode 100644
index 0000000000..4abeeded00
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ResetEvent/test3/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = ResetEvent
+Name = Negative test for ResetEvent
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Test to ensure proper operation of the ResetEvent()
+= API by calling it on an event handle that's been
+= closed. We expect it to return an appropriate error
+= result.
diff --git a/src/pal/tests/palsuite/threading/ResetEvent/test4/CMakeLists.txt b/src/pal/tests/palsuite/threading/ResetEvent/test4/CMakeLists.txt
new file mode 100644
index 0000000000..68ee20bc95
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ResetEvent/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_resetevent_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_resetevent_test4 coreclrpal)
+
+target_link_libraries(paltest_resetevent_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/ResetEvent/test4/test4.c b/src/pal/tests/palsuite/threading/ResetEvent/test4/test4.c
new file mode 100644
index 0000000000..0cc68fd9aa
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ResetEvent/test4/test4.c
@@ -0,0 +1,161 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test4.c
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** CreateEvent
+** CloseHandle
+** WaitForSingleObject
+** DuplicateHandle
+** GetCurrentProcess
+**
+** Purpose:
+**
+** Test to ensure proper operation of the ResetEvent()
+** API by calling it on an event handle that's the
+** result of a DuplicateHandle() call on another event
+** handle.
+**
+
+**
+**===========================================================================*/
+#include <palsuite.h>
+
+
+
+int __cdecl main( int argc, char **argv )
+
+{
+ /* local variables */
+ DWORD dwRet = 0;
+ HANDLE hEvent = NULL;
+ HANDLE hDupEvent = NULL;
+ LPSECURITY_ATTRIBUTES lpEventAttributes = NULL;
+ BOOL bManualReset = TRUE;
+ BOOL bInitialState = TRUE;
+
+
+ /* PAL initialization */
+ if( (PAL_Initialize(argc, argv)) != 0 )
+ {
+ return( FAIL );
+ }
+
+
+ /* create an event which we can use with ResetEvent */
+ hEvent = CreateEvent( lpEventAttributes,
+ bManualReset,
+ bInitialState,
+ NULL );
+
+ if( hEvent == INVALID_HANDLE_VALUE )
+ {
+ /* ERROR */
+ Fail( "ERROR:%lu:CreateEvent() call failed\n", GetLastError() );
+ }
+
+ /* verify that the event is signalled already */
+ dwRet = WaitForSingleObject( hEvent, 0 );
+ if( dwRet != WAIT_OBJECT_0 )
+ {
+ /* ERROR */
+ Trace( "ERROR:WaitForSingleObject() call returned %lu, "
+ "expected WAIT_OBJECT_0\n",
+ dwRet );
+ CloseHandle( hEvent );
+ Fail( "Test failed\n" );
+ }
+
+
+ /* duplicate the event handle */
+ if( ! (DuplicateHandle(
+ GetCurrentProcess(),
+ hEvent,
+ GetCurrentProcess(),
+ &hDupEvent,
+ GENERIC_READ|GENERIC_WRITE, /* ignored in PAL */
+ FALSE,
+ DUPLICATE_SAME_ACCESS ) ) )
+ {
+ Trace("ERROR:%u:DuplicateHandle() call failed\n",
+ GetLastError() );
+ CloseHandle( hEvent );
+ Fail("Test failed\n");
+ }
+
+ /* verify that the event is signalled with the duplicate handle */
+ dwRet = WaitForSingleObject( hDupEvent, 0 );
+ if( dwRet != WAIT_OBJECT_0 )
+ {
+ /* ERROR */
+ Trace( "ERROR:WaitForSingleObject() call returned %lu, "
+ "expected WAIT_OBJECT_0\n",
+ dwRet );
+ CloseHandle( hEvent );
+ CloseHandle( hDupEvent );
+ Fail( "Test failed\n" );
+ }
+
+
+ /* reset the event using the duplicate handle */
+ if( ! ResetEvent( hDupEvent ) )
+ {
+ /* ERROR */
+ Trace( "ERROR:%lu:ResetEvent() call failed\n", GetLastError() );
+ CloseHandle( hEvent );
+ CloseHandle( hDupEvent );
+ Fail( "Test failed\n" );
+ }
+
+ /* verify that the event isn't signalled using the duplicate handle*/
+ dwRet = WaitForSingleObject( hDupEvent, 0 );
+ if( dwRet != WAIT_TIMEOUT )
+ {
+ /* ERROR */
+ Trace( "ERROR:WaitForSingleObject() call returned %lu, "
+ "expected WAIT_TIMEOUT\n",
+ dwRet );
+ CloseHandle( hEvent );
+ Fail( "Test failed\n" );
+ }
+
+ /* check that the event isn't signalled using the original event handle */
+ dwRet = WaitForSingleObject( hEvent, 0 );
+ if( dwRet != WAIT_TIMEOUT )
+ {
+ /* ERROR */
+ Trace( "ERROR:WaitForSingleObject() call returned %lu, "
+ "expected WAIT_TIMEOUT\n",
+ dwRet );
+ CloseHandle( hEvent );
+ Fail( "Test failed\n" );
+ }
+
+
+ /* close the duplicate event handle */
+ if( ! CloseHandle( hDupEvent ) )
+ {
+ Fail( "ERROR:%lu:CloseHandle() call failed for duplicate handle\n",
+ GetLastError() );
+ }
+
+
+ /* close the event handle */
+ if( ! CloseHandle( hEvent ) )
+ {
+ Fail( "ERROR:%lu:CloseHandle() call failed for original handle\n",
+ GetLastError() );
+ }
+
+
+ /* PAL termination */
+ PAL_Terminate();
+
+ /* return success */
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/threading/ResetEvent/test4/testinfo.dat b/src/pal/tests/palsuite/threading/ResetEvent/test4/testinfo.dat
new file mode 100644
index 0000000000..0223246c6f
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ResetEvent/test4/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = ResetEvent
+Name = Positive test for ResetEvent
+TYPE = DEFAULT
+EXE1 = test4
+Description
+= Test to ensure proper operation of the ResetEvent()
+= API by calling it on an event handle that's the
+= result of a DuplicateHandle() call on another event
+= handle.
diff --git a/src/pal/tests/palsuite/threading/ResumeThread/CMakeLists.txt b/src/pal/tests/palsuite/threading/ResumeThread/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ResumeThread/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/threading/ResumeThread/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/ResumeThread/test1/CMakeLists.txt
new file mode 100644
index 0000000000..2c83dfd3d5
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ResumeThread/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_resumethread_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_resumethread_test1 coreclrpal)
+
+target_link_libraries(paltest_resumethread_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/ResumeThread/test1/test1.c b/src/pal/tests/palsuite/threading/ResumeThread/test1/test1.c
new file mode 100644
index 0000000000..037f79f7a3
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ResumeThread/test1/test1.c
@@ -0,0 +1,141 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test1.c
+**
+** Purpose: Test for ResumeThread. Create a suspended Thread.
+** First, ensure that it is indeed suspended. Then call resumethread
+** and check to ensure that the function has now run.
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+DWORD dwResumeThreadTestParameter = 0;
+
+DWORD PALAPI ResumeThreadTestThread( LPVOID lpParameter)
+{
+ DWORD dwRet = 0;
+
+ /* Save parameter so we can check and ensure this function ran
+ properly.
+ */
+
+ dwResumeThreadTestParameter = (DWORD)lpParameter;
+
+ return dwRet;
+}
+
+BOOL ResumeThreadTest()
+{
+ BOOL bRet = FALSE;
+ DWORD dwRet = 0;
+
+ LPSECURITY_ATTRIBUTES lpThreadAttributes = NULL;
+ DWORD dwStackSize = 0;
+ LPTHREAD_START_ROUTINE lpStartAddress = &ResumeThreadTestThread;
+ LPVOID lpParameter = lpStartAddress;
+ DWORD dwCreationFlags = CREATE_SUSPENDED;
+ DWORD dwThreadId = 0;
+
+ HANDLE hThread = 0;
+
+ dwResumeThreadTestParameter = 0;
+
+ /* Create a thread, with CREATE_SUSPENDED, so we can resume it! */
+
+ hThread = CreateThread( lpThreadAttributes,
+ dwStackSize, lpStartAddress, lpParameter,
+ dwCreationFlags, &dwThreadId );
+
+ if (hThread != INVALID_HANDLE_VALUE)
+ {
+ /* Wait for one second. This should return WAIT_TIMEOUT */
+ dwRet = WaitForSingleObject(hThread,1000);
+
+ if (dwRet != WAIT_TIMEOUT)
+ {
+ Trace("ResumeThreadTest:WaitForSingleObject "
+ "failed (%x)\n",GetLastError());
+ }
+ else
+ {
+ /* Check to ensure the parameter hasn't changed. The
+ function shouldn't have occurred yet.
+ */
+ if (dwResumeThreadTestParameter != 0)
+ {
+ Trace("ResumeThreadTest:parameter error\n");
+ }
+ else
+ {
+ /* Call ResumeThread and ensure the return value is
+ correct.
+ */
+
+ dwRet = ResumeThread(hThread);
+
+ if (dwRet != 1)
+ {
+ Trace("ResumeThreadTest:ResumeThread "
+ "failed (%x)\n",GetLastError());
+ }
+ else
+ {
+ /* Wait again, now that the thread has been
+ resumed, and the return should be WAIT_OBJECT_0
+ */
+ dwRet = WaitForSingleObject(hThread,INFINITE);
+
+ if (dwRet != WAIT_OBJECT_0)
+ {
+ Trace("ResumeThreadTest:WaitForSingleObject "
+ "failed (%x)\n",GetLastError());
+ }
+ else
+ {
+ /* Check the param now and it should have been
+ set.
+ */
+ if (dwResumeThreadTestParameter != (DWORD)lpParameter)
+ {
+ Trace("ResumeThreadTest:parameter error\n");
+ }
+ else
+ {
+ bRet = TRUE;
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ Trace("ResumeThreadTest:CreateThread failed (%x)\n",GetLastError());
+ }
+
+ return bRet;
+}
+
+int __cdecl main(int argc, char **argv)
+{
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ if(!ResumeThreadTest())
+ {
+ Fail("Test Failed\n");
+ }
+
+ PAL_Terminate();
+ return (PASS);
+
+}
diff --git a/src/pal/tests/palsuite/threading/ResumeThread/test1/testinfo.dat b/src/pal/tests/palsuite/threading/ResumeThread/test1/testinfo.dat
new file mode 100644
index 0000000000..8472165d5d
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ResumeThread/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = ResumeThread
+Name = Positive Test for ResumeThread
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Test for ResumeThread. Create a suspended Thread.
+= First, ensure that it is indeed suspended. Then call resumethread
+= and check to ensure that the function has now run.
diff --git a/src/pal/tests/palsuite/threading/SetErrorMode/CMakeLists.txt b/src/pal/tests/palsuite/threading/SetErrorMode/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/SetErrorMode/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/threading/SetErrorMode/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/SetErrorMode/test1/CMakeLists.txt
new file mode 100644
index 0000000000..cfdeb31950
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/SetErrorMode/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_seterrormode_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_seterrormode_test1 coreclrpal)
+
+target_link_libraries(paltest_seterrormode_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/SetErrorMode/test1/test1.c b/src/pal/tests/palsuite/threading/SetErrorMode/test1/test1.c
new file mode 100644
index 0000000000..238cec4421
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/SetErrorMode/test1/test1.c
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c (SetErrorMode)
+**
+** Purpose: Tests the PAL implementation of the SetErrorMode function.
+** This test will set the error mode and then read the error
+** set with GetLastError().
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ DWORD dErrorReturn;
+ UINT dErrorModes[] = {SEM_NOOPENFILEERRORBOX, SEM_FAILCRITICALERRORS, 0};
+ int i;
+
+ /*
+ * Initialize the Pal
+ */
+ if ((PAL_Initialize(argc,argv)) != 0)
+ {
+ return (FAIL);
+ }
+
+ /*
+ * Loop through the supported Error Modes and verify
+ * that GetLastError() returns the correct Error Mode
+ */
+ for (i=0; i < (sizeof(dErrorModes) / sizeof(UINT)); i++)
+ {
+ SetLastError(dErrorModes[i]);
+ if ((dErrorReturn = GetLastError()) != dErrorModes[i])
+ {
+ Fail("ERROR: SetLastError was set to 0x%4.4x but,"
+ " GetLastError returned 0x%4.4x\n",
+ dErrorModes[i],
+ dErrorReturn);
+ }
+ }
+
+ PAL_Terminate();
+ return (PASS);
+}
diff --git a/src/pal/tests/palsuite/threading/SetErrorMode/test1/testinfo.dat b/src/pal/tests/palsuite/threading/SetErrorMode/test1/testinfo.dat
new file mode 100644
index 0000000000..875ac2a223
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/SetErrorMode/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Threading
+Function = SetErrorMode
+Name = Positive Test for SetErrorMode
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Tests the PAL implementation of the SetErrorMode function.
+= This test will set the error mode and then read the error
+= set with GetLastError().
+
+
diff --git a/src/pal/tests/palsuite/threading/SetEvent/CMakeLists.txt b/src/pal/tests/palsuite/threading/SetEvent/CMakeLists.txt
new file mode 100644
index 0000000000..a3847f8ca9
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/SetEvent/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+
diff --git a/src/pal/tests/palsuite/threading/SetEvent/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/SetEvent/test1/CMakeLists.txt
new file mode 100644
index 0000000000..9be8d5a421
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/SetEvent/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_setevent_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setevent_test1 coreclrpal)
+
+target_link_libraries(paltest_setevent_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/SetEvent/test1/test1.c b/src/pal/tests/palsuite/threading/SetEvent/test1/test1.c
new file mode 100644
index 0000000000..d5a29ce3f3
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/SetEvent/test1/test1.c
@@ -0,0 +1,94 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test1.c
+**
+** Purpose: Test for SetEvent. Create an Event and then set
+** this event, checking the return value. Ensure that it returns
+** positive.
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+BOOL SetEventTest()
+{
+ int bRet = 0;
+ DWORD dwRet = 0;
+
+ LPSECURITY_ATTRIBUTES lpEventAttributes = 0;
+ BOOL bManualReset = TRUE;
+ BOOL bInitialState = FALSE;
+
+ /* Create an event which we can use with SetEvent */
+ HANDLE hEvent = CreateEvent( lpEventAttributes,
+ bManualReset, bInitialState, NULL);
+
+ if (hEvent != INVALID_HANDLE_VALUE)
+ {
+ dwRet = WaitForSingleObject(hEvent,0);
+
+ if (dwRet != WAIT_TIMEOUT)
+ {
+ Trace("SetEventTest:WaitForSingleObject failed (%x)\n", GetLastError());
+ }
+ else
+ {
+ /* Set the event to the previously created event and check
+ the return value.
+ */
+ bRet = SetEvent(hEvent);
+
+ if (!bRet)
+ {
+ Trace("SetEventTest:SetEvent failed (%x)\n", GetLastError());
+ }
+ else
+ {
+ dwRet = WaitForSingleObject(hEvent,0);
+
+ if (dwRet != WAIT_OBJECT_0)
+ {
+ Trace("SetEventTest:WaitForSingleObject failed (%x)\n", GetLastError());
+ }
+ else
+ {
+ dwRet = CloseHandle(hEvent);
+
+ if (!dwRet)
+ {
+ Trace("SetEventTest:CloseHandle failed (%x)\n", GetLastError());
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ Trace("SetEventTest:CreateEvent failed (%x)\n", GetLastError());
+ }
+
+ return bRet;
+}
+
+
+int __cdecl main(int argc, char **argv)
+{
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ if(SetEventTest() == 0)
+ {
+ Fail ("Test failed\n");
+ }
+
+ PAL_Terminate();
+ return ( PASS );
+
+}
diff --git a/src/pal/tests/palsuite/threading/SetEvent/test1/testinfo.dat b/src/pal/tests/palsuite/threading/SetEvent/test1/testinfo.dat
new file mode 100644
index 0000000000..9bfd80829c
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/SetEvent/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = SetEvent
+Name = Positive Test for SetEvent
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Test for SetEvent. Create an Event and then set
+=this event, checking the return value. Ensure that it returns
+=positive.
diff --git a/src/pal/tests/palsuite/threading/SetEvent/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/SetEvent/test2/CMakeLists.txt
new file mode 100644
index 0000000000..87522b3ffc
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/SetEvent/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_setevent_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setevent_test2 coreclrpal)
+
+target_link_libraries(paltest_setevent_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/SetEvent/test2/test2.c b/src/pal/tests/palsuite/threading/SetEvent/test2/test2.c
new file mode 100644
index 0000000000..5fd2833957
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/SetEvent/test2/test2.c
@@ -0,0 +1,125 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test2.c
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** CreateEvent
+** CloseHandle
+** WaitForSingleObject
+**
+** Purpose:
+**
+** Test to ensure proper operation of the SetEvent()
+** API by calling it on an event handle that's already set.
+**
+
+**
+**===========================================================================*/
+#include <palsuite.h>
+
+
+
+int __cdecl main( int argc, char **argv )
+
+{
+ /* local variables */
+ DWORD dwRet = 0;
+ HANDLE hEvent = NULL;
+ LPSECURITY_ATTRIBUTES lpEventAttributes = NULL;
+ BOOL bManualReset = TRUE;
+ BOOL bInitialState = FALSE;
+
+
+ /* PAL initialization */
+ if( (PAL_Initialize(argc, argv)) != 0 )
+ {
+ return( FAIL );
+ }
+
+
+ /* create an event which we can use with SetEvent */
+ hEvent = CreateEvent( lpEventAttributes,
+ bManualReset,
+ bInitialState,
+ NULL );
+
+ if( hEvent == INVALID_HANDLE_VALUE )
+ {
+ /* ERROR */
+ Fail( "ERROR:%lu:CreateEvent() call failed\n", GetLastError() );
+ }
+
+ /* verify that the event isn't signalled yet */
+ dwRet = WaitForSingleObject( hEvent, 0 );
+ if( dwRet != WAIT_TIMEOUT )
+ {
+ /* ERROR */
+ Trace( "ERROR:WaitForSingleObject() call returned %lu, "
+ "expected WAIT_TIMEOUT\n",
+ dwRet );
+ CloseHandle( hEvent );
+ Fail( "Test failed\n" );
+ }
+
+ /* set the event */
+ if( ! SetEvent( hEvent ) )
+ {
+ /* ERROR */
+ Trace( "ERROR:%lu:SetEvent() call failed\n", GetLastError() );
+ CloseHandle( hEvent );
+ Fail( "Test failed\n" );
+ }
+
+ /* verify that the event is signalled */
+ dwRet = WaitForSingleObject( hEvent, 0 );
+ if( dwRet != WAIT_OBJECT_0 )
+ {
+ /* ERROR */
+ Trace( "ERROR:WaitForSingleObject() call returned %lu, "
+ "expected WAIT_OBJECT_0\n",
+ dwRet );
+ CloseHandle( hEvent );
+ Fail( "Test failed\n" );
+ }
+
+ /* try to set the event again */
+ if( ! SetEvent( hEvent ) )
+ {
+ /* ERROR */
+ Trace( "FAIL:%lu:SetEvent() call failed on signalled event\n",
+ GetLastError() );
+ CloseHandle( hEvent );
+ Fail( "Test failed\n" );
+ }
+
+ /* verify that the event is still signalled */
+ dwRet = WaitForSingleObject( hEvent, 0 );
+ if( dwRet != WAIT_OBJECT_0 )
+ {
+ /* ERROR */
+ Trace( "ERROR:WaitForSingleObject() call returned %lu, "
+ "expected WAIT_OBJECT_0\n",
+ dwRet );
+ CloseHandle( hEvent );
+ Fail( "Test failed\n" );
+ }
+
+
+ /* close the event handle */
+ if( ! CloseHandle( hEvent ) )
+ {
+ Fail( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ }
+
+
+ /* PAL termination */
+ PAL_Terminate();
+
+ /* return success */
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/threading/SetEvent/test2/testinfo.dat b/src/pal/tests/palsuite/threading/SetEvent/test2/testinfo.dat
new file mode 100644
index 0000000000..f2153052bb
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/SetEvent/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = SetEvent
+Name = Positive test for SetEvent
+TYPE = DEFAULT
+EXE1 = test2
+Description
+= Test to ensure proper operation of the SetEvent()
+= API by calling it on an event handle that's already set.
diff --git a/src/pal/tests/palsuite/threading/SetEvent/test3/CMakeLists.txt b/src/pal/tests/palsuite/threading/SetEvent/test3/CMakeLists.txt
new file mode 100644
index 0000000000..d09239b3e4
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/SetEvent/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_setevent_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setevent_test3 coreclrpal)
+
+target_link_libraries(paltest_setevent_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/SetEvent/test3/test3.c b/src/pal/tests/palsuite/threading/SetEvent/test3/test3.c
new file mode 100644
index 0000000000..21601f00b8
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/SetEvent/test3/test3.c
@@ -0,0 +1,85 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test3.c
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** CreateEvent
+** CloseHandle
+**
+** Purpose:
+**
+** Test to ensure proper operation of the SetEvent()
+** API by calling it on an event handle that's been
+** closed. We expect it to return an appropriate error
+** result.
+**
+
+**
+**===========================================================================*/
+#include <palsuite.h>
+
+
+
+int __cdecl main( int argc, char **argv )
+
+{
+ /* local variables */
+ HANDLE hEvent = NULL;
+ LPSECURITY_ATTRIBUTES lpEventAttributes = NULL;
+ BOOL bManualReset = TRUE;
+ BOOL bInitialState = FALSE;
+
+
+ /* PAL initialization */
+ if( (PAL_Initialize(argc, argv)) != 0 )
+ {
+ return( FAIL );
+ }
+
+
+ /* create an event which we can use with SetEvent */
+ hEvent = CreateEvent( lpEventAttributes,
+ bManualReset,
+ bInitialState,
+ NULL );
+
+ if( hEvent == INVALID_HANDLE_VALUE )
+ {
+ /* ERROR */
+ Fail( "ERROR:%lu:CreateEvent() call failed\n", GetLastError() );
+ }
+
+ /* close the event handle */
+ if( ! CloseHandle( hEvent ) )
+ {
+ Fail( "ERROR:%lu:CloseHandle() call failed\n", GetLastError() );
+ }
+
+ /* try to set the event */
+ if( SetEvent( hEvent ) )
+ {
+ /* ERROR */
+ Fail( "FAIL:SetEvent() call succeeded on a closed event handle\n" );
+ }
+
+ /* verify the result of GetLastError() */
+ if( GetLastError() != ERROR_INVALID_HANDLE )
+ {
+ /* ERROR */
+ Fail( "FAIL:SetEvent() call failed on a closed event handle"
+ "but returned an unexpected error result %lu\n" );
+ }
+
+
+
+ /* PAL termination */
+ PAL_Terminate();
+
+ /* return success */
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/threading/SetEvent/test3/testinfo.dat b/src/pal/tests/palsuite/threading/SetEvent/test3/testinfo.dat
new file mode 100644
index 0000000000..7b8f43013a
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/SetEvent/test3/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = SetEvent
+Name = Negative test for SetEvent
+TYPE = DEFAULT
+EXE1 = test3
+Description
+= Test to ensure proper operation of the SetEvent()
+= API by calling it on an event handle that's been
+= closed. We expect it to return an appropriate error
+= result.
diff --git a/src/pal/tests/palsuite/threading/SetEvent/test4/CMakeLists.txt b/src/pal/tests/palsuite/threading/SetEvent/test4/CMakeLists.txt
new file mode 100644
index 0000000000..3f1d344292
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/SetEvent/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_setevent_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setevent_test4 coreclrpal)
+
+target_link_libraries(paltest_setevent_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/SetEvent/test4/test4.c b/src/pal/tests/palsuite/threading/SetEvent/test4/test4.c
new file mode 100644
index 0000000000..7a79a9d708
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/SetEvent/test4/test4.c
@@ -0,0 +1,161 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test4.c
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** CreateEvent
+** CloseHandle
+** WaitForSingleObject
+** DuplicateHandle
+** GetCurrentProcess
+**
+** Purpose:
+**
+** Test to ensure proper operation of the SetEvent()
+** API by calling it on an event handle that's the
+** result of a DuplicateHandle() call on another event
+** handle.
+**
+
+**
+**===========================================================================*/
+#include <palsuite.h>
+
+
+
+int __cdecl main( int argc, char **argv )
+
+{
+ /* local variables */
+ DWORD dwRet = 0;
+ HANDLE hEvent = NULL;
+ HANDLE hDupEvent = NULL;
+ LPSECURITY_ATTRIBUTES lpEventAttributes = NULL;
+ BOOL bManualReset = TRUE;
+ BOOL bInitialState = FALSE;
+
+
+ /* PAL initialization */
+ if( (PAL_Initialize(argc, argv)) != 0 )
+ {
+ return( FAIL );
+ }
+
+
+ /* create an event which we can use with SetEvent */
+ hEvent = CreateEvent( lpEventAttributes,
+ bManualReset,
+ bInitialState,
+ NULL );
+
+ if( hEvent == INVALID_HANDLE_VALUE )
+ {
+ /* ERROR */
+ Fail( "ERROR:%lu:CreateEvent() call failed\n", GetLastError() );
+ }
+
+ /* verify that the event isn't signalled yet */
+ dwRet = WaitForSingleObject( hEvent, 0 );
+ if( dwRet != WAIT_TIMEOUT )
+ {
+ /* ERROR */
+ Trace( "ERROR:WaitForSingleObject() call returned %lu, "
+ "expected WAIT_TIMEOUT\n",
+ dwRet );
+ CloseHandle( hEvent );
+ Fail( "Test failed\n" );
+ }
+
+
+ /* duplicate the event handle */
+ if( ! (DuplicateHandle(
+ GetCurrentProcess(),
+ hEvent,
+ GetCurrentProcess(),
+ &hDupEvent,
+ GENERIC_READ|GENERIC_WRITE, /* ignored in PAL */
+ FALSE,
+ DUPLICATE_SAME_ACCESS ) ) )
+ {
+ Trace("ERROR:%u:DuplicateHandle() call failed\n",
+ GetLastError() );
+ CloseHandle( hEvent );
+ Fail("Test failed\n");
+ }
+
+ /* verify that the event isn't signalled yet with the duplicate handle */
+ dwRet = WaitForSingleObject( hDupEvent, 0 );
+ if( dwRet != WAIT_TIMEOUT )
+ {
+ /* ERROR */
+ Trace( "ERROR:WaitForSingleObject() call returned %lu, "
+ "expected WAIT_TIMEOUT\n",
+ dwRet );
+ CloseHandle( hEvent );
+ CloseHandle( hDupEvent );
+ Fail( "Test failed\n" );
+ }
+
+
+ /* set the event using the duplicate handle */
+ if( ! SetEvent( hDupEvent ) )
+ {
+ /* ERROR */
+ Trace( "ERROR:%lu:SetEvent() call failed\n", GetLastError() );
+ CloseHandle( hEvent );
+ CloseHandle( hDupEvent );
+ Fail( "Test failed\n" );
+ }
+
+ /* verify that the event is signalled using the duplicate handle*/
+ dwRet = WaitForSingleObject( hDupEvent, 0 );
+ if( dwRet != WAIT_OBJECT_0 )
+ {
+ /* ERROR */
+ Trace( "ERROR:WaitForSingleObject() call returned %lu, "
+ "expected WAIT_OBJECT_0\n",
+ dwRet );
+ CloseHandle( hEvent );
+ Fail( "Test failed\n" );
+ }
+
+ /* verify that the event is signalled using the original event handle */
+ dwRet = WaitForSingleObject( hEvent, 0 );
+ if( dwRet != WAIT_OBJECT_0 )
+ {
+ /* ERROR */
+ Trace( "ERROR:WaitForSingleObject() call returned %lu, "
+ "expected WAIT_OBJECT_0\n",
+ dwRet );
+ CloseHandle( hEvent );
+ Fail( "Test failed\n" );
+ }
+
+
+ /* close the duplicate event handle */
+ if( ! CloseHandle( hDupEvent ) )
+ {
+ Fail( "ERROR:%lu:CloseHandle() call failed for duplicate handle\n",
+ GetLastError() );
+ }
+
+
+ /* close the event handle */
+ if( ! CloseHandle( hEvent ) )
+ {
+ Fail( "ERROR:%lu:CloseHandle() call failed for original handle\n",
+ GetLastError() );
+ }
+
+
+ /* PAL termination */
+ PAL_Terminate();
+
+ /* return success */
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/threading/SetEvent/test4/testinfo.dat b/src/pal/tests/palsuite/threading/SetEvent/test4/testinfo.dat
new file mode 100644
index 0000000000..9a7f7ddb3b
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/SetEvent/test4/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = SetEvent
+Name = Positive test for SetEvent
+TYPE = DEFAULT
+EXE1 = test4
+Description
+= Test to ensure proper operation of the SetEvent()
+= API by calling it on an event handle that's the
+= result of a DuplicateHandle() call on another event
+= handle.
diff --git a/src/pal/tests/palsuite/threading/Sleep/CMakeLists.txt b/src/pal/tests/palsuite/threading/Sleep/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/Sleep/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/threading/Sleep/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/Sleep/test1/CMakeLists.txt
new file mode 100644
index 0000000000..b0d8db28a2
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/Sleep/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ Sleep.c
+)
+
+add_executable(paltest_sleep_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sleep_test1 coreclrpal)
+
+target_link_libraries(paltest_sleep_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/Sleep/test1/Sleep.c b/src/pal/tests/palsuite/threading/Sleep/test1/Sleep.c
new file mode 100644
index 0000000000..f7f7c91730
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/Sleep/test1/Sleep.c
@@ -0,0 +1,80 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: Sleep.c
+**
+** Purpose: Test to establish whether the Sleep function stops the thread from
+** executing for the specified times.
+**
+** Dependencies: GetSystemTime
+** Fail
+** Trace
+**
+
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+DWORD SleepTimes[] =
+{
+ 0,
+ 50,
+ 100,
+ 500,
+ 2000
+};
+
+/* Milliseconds of error which are acceptable Function execution time, etc. */
+DWORD AcceptableTimeError = 150;
+
+int __cdecl main( int argc, char **argv )
+{
+ UINT64 OldTimeStamp;
+ UINT64 NewTimeStamp;
+ DWORD MaxDelta;
+ DWORD TimeDelta;
+ DWORD i;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ LARGE_INTEGER performanceFrequency;
+ if (!QueryPerformanceFrequency(&performanceFrequency))
+ {
+ return FAIL;
+ }
+
+ for( i = 0; i < sizeof(SleepTimes) / sizeof(DWORD); i++)
+ {
+ OldTimeStamp = GetHighPrecisionTimeStamp(performanceFrequency);
+ Sleep(SleepTimes[i]);
+ NewTimeStamp = GetHighPrecisionTimeStamp(performanceFrequency);
+
+ TimeDelta = NewTimeStamp - OldTimeStamp;
+
+ /* For longer intervals use a 10 percent tolerance */
+ if ((SleepTimes[i] * 0.1) > AcceptableTimeError)
+ {
+ MaxDelta = SleepTimes[i] + (DWORD)(SleepTimes[i] * 0.1);
+ }
+ else
+ {
+ MaxDelta = SleepTimes[i] + AcceptableTimeError;
+ }
+
+ if ( TimeDelta<SleepTimes[i] || TimeDelta>MaxDelta )
+ {
+ Fail("The sleep function slept for %d ms when it should have "
+ "slept for %d ms\n", TimeDelta, SleepTimes[i]);
+ }
+ }
+ PAL_Terminate();
+ return ( PASS );
+
+}
diff --git a/src/pal/tests/palsuite/threading/Sleep/test1/testinfo.dat b/src/pal/tests/palsuite/threading/Sleep/test1/testinfo.dat
new file mode 100644
index 0000000000..433a061f2c
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/Sleep/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = Sleep
+Name = Positive Test for Sleep
+TYPE = DEFAULT
+EXE1 = sleep
+Description
+= Test to see if the Sleep function stops the thread from executing for the
+= specified amount of time.
diff --git a/src/pal/tests/palsuite/threading/Sleep/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/Sleep/test2/CMakeLists.txt
new file mode 100644
index 0000000000..832e8ab42d
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/Sleep/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ sleep.c
+)
+
+add_executable(paltest_sleep_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sleep_test2 coreclrpal)
+
+target_link_libraries(paltest_sleep_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/Sleep/test2/sleep.c b/src/pal/tests/palsuite/threading/Sleep/test2/sleep.c
new file mode 100644
index 0000000000..eb30e34f2f
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/Sleep/test2/sleep.c
@@ -0,0 +1,73 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: Sleep.c
+**
+** Purpose: Test to establish whether the Sleep function stops the thread from
+** executing for the specified times.
+**
+** Dependencies: GetTickCount
+**
+
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+/*
+ * times in 10^(-3) seconds
+ */
+
+DWORD SleepTimes[] =
+{
+ 60000,
+ 300000,
+ 1800000,
+ 3200000
+};
+
+/* Milliseconds of error which are acceptable Function execution time, etc. */
+DWORD AcceptableTimeError = 150;
+
+int __cdecl main( int argc, char **argv )
+{
+ UINT64 OldTimeStamp;
+ UINT64 NewTimeStamp;
+ DWORD MaxDelta;
+ DWORD TimeDelta;
+ DWORD i;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ LARGE_INTEGER performanceFrequency;
+ if (!QueryPerformanceFrequency(&performanceFrequency))
+ {
+ return FAIL;
+ }
+
+ for( i = 0; i < sizeof(SleepTimes) / sizeof(DWORD); i++)
+ {
+ OldTimeStamp = GetHighPrecisionTimeStamp(performanceFrequency);
+ Sleep(SleepTimes[i]);
+ NewTimeStamp = GetHighPrecisionTimeStamp(performanceFrequency);
+
+ TimeDelta = NewTimeStamp - OldTimeStamp;
+
+ MaxDelta = SleepTimes[i] + AcceptableTimeError;
+
+ if ( TimeDelta<SleepTimes[i] || TimeDelta>MaxDelta )
+ {
+ Fail("The sleep function slept for %u ms when it should have "
+ "slept for %u ms\n", TimeDelta, SleepTimes[i]);
+ }
+ }
+ PAL_Terminate();
+ return ( PASS );
+
+}
diff --git a/src/pal/tests/palsuite/threading/Sleep/test2/testinfo.dat b/src/pal/tests/palsuite/threading/Sleep/test2/testinfo.dat
new file mode 100644
index 0000000000..433a061f2c
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/Sleep/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = Sleep
+Name = Positive Test for Sleep
+TYPE = DEFAULT
+EXE1 = sleep
+Description
+= Test to see if the Sleep function stops the thread from executing for the
+= specified amount of time.
diff --git a/src/pal/tests/palsuite/threading/SleepEx/CMakeLists.txt b/src/pal/tests/palsuite/threading/SleepEx/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/SleepEx/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/threading/SleepEx/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/SleepEx/test1/CMakeLists.txt
new file mode 100644
index 0000000000..de562755fc
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/SleepEx/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_sleepex_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sleepex_test1 coreclrpal)
+
+target_link_libraries(paltest_sleepex_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/SleepEx/test1/test1.c b/src/pal/tests/palsuite/threading/SleepEx/test1/test1.c
new file mode 100644
index 0000000000..7ccfe0ce87
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/SleepEx/test1/test1.c
@@ -0,0 +1,89 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests that SleepEx correctly sleeps for a given amount of time,
+** regardless of the alertable flag.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+typedef struct
+{
+ DWORD SleepTime;
+ BOOL Alertable;
+} testCase;
+
+testCase testCases[] =
+{
+ {0, FALSE},
+ {50, FALSE},
+ {100, FALSE},
+ {500, FALSE},
+ {2000, FALSE},
+
+ {0, TRUE},
+ {50, TRUE},
+ {100, TRUE},
+ {500, TRUE},
+ {2000, TRUE},
+};
+
+/* Milliseconds of error which are acceptable Function execution time, etc. */
+DWORD AcceptableTimeError = 150;
+
+int __cdecl main( int argc, char **argv )
+{
+ UINT64 OldTimeStamp;
+ UINT64 NewTimeStamp;
+ DWORD MaxDelta;
+ DWORD TimeDelta;
+ DWORD i;
+
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ LARGE_INTEGER performanceFrequency;
+ if (!QueryPerformanceFrequency(&performanceFrequency))
+ {
+ return FAIL;
+ }
+
+ for (i = 0; i<sizeof(testCases) / sizeof(testCases[0]); i++)
+ {
+ OldTimeStamp = GetHighPrecisionTimeStamp(performanceFrequency);
+
+ SleepEx(testCases[i].SleepTime, testCases[i].Alertable);
+
+ NewTimeStamp = GetHighPrecisionTimeStamp(performanceFrequency);
+
+ TimeDelta = NewTimeStamp - OldTimeStamp;
+
+ /* For longer intervals use a 10 percent tolerance */
+ if ((testCases[i].SleepTime * 0.1) > AcceptableTimeError)
+ {
+ MaxDelta = testCases[i].SleepTime + (DWORD)(testCases[i].SleepTime * 0.1);
+ }
+ else
+ {
+ MaxDelta = testCases[i].SleepTime + AcceptableTimeError;
+ }
+
+ if (TimeDelta < testCases[i].SleepTime || TimeDelta > MaxDelta)
+ {
+ Fail("The sleep function slept for %d ms when it should have "
+ "slept for %d ms\n", TimeDelta, testCases[i].SleepTime);
+ }
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/threading/SleepEx/test1/testinfo.dat b/src/pal/tests/palsuite/threading/SleepEx/test1/testinfo.dat
new file mode 100644
index 0000000000..1242768743
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/SleepEx/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = SleepEx
+Name = Test #1 for SleepEx
+TYPE = DEFAULT
+EXE1 = test1
+Description
+=Tests that SleepEx correctly sleeps for a given amount of time,
+=regardless of the alertable flag.
diff --git a/src/pal/tests/palsuite/threading/SleepEx/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/SleepEx/test2/CMakeLists.txt
new file mode 100644
index 0000000000..0ea4a44449
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/SleepEx/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_sleepex_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_sleepex_test2 coreclrpal)
+
+target_link_libraries(paltest_sleepex_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/SleepEx/test2/test2.c b/src/pal/tests/palsuite/threading/SleepEx/test2/test2.c
new file mode 100644
index 0000000000..c2ba4e704d
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/SleepEx/test2/test2.c
@@ -0,0 +1,183 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test2.c
+**
+** Purpose: Tests that a child thread in the middle of a SleepEx call will be
+** interrupted by QueueUserAPC if the alert flag was set.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+const int ChildThreadSleepTime = 2000;
+const int InterruptTime = 1000;
+/* We need to keep in mind that BSD has a timer resolution of 10ms, so
+ we need to adjust our delta to keep that in mind. Besides we need some
+ tolerance to account for different scheduling strategies, heavy load
+ scenarios, etc.
+
+ Real-world data also tells us we can expect a big difference between
+ values when run on real iron vs run in a hypervisor.
+
+ Thread-interruption times when run on bare metal will typically yield
+ around 0ms on Linux and between 0 and 16ms on FreeBSD. However, when run
+ in a hypervisor (like VMWare ESXi) we may get values around an order of
+ magnitude higher, up to 110 ms for some tests.
+*/
+const DWORD AcceptableDelta = 150;
+
+const int Iterations = 5;
+
+void RunTest(BOOL AlertThread);
+VOID PALAPI APCFunc(ULONG_PTR dwParam);
+DWORD PALAPI SleeperProc(LPVOID lpParameter);
+
+DWORD ThreadSleepDelta;
+
+int __cdecl main( int argc, char **argv )
+{
+ int i;
+ DWORD dwAvgDelta;
+
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /*
+ On some platforms (e.g. FreeBSD 4.9) the first call to some synch objects
+ (such as conditions) involves some pthread internal initialization that
+ can make the first wait slighty longer, potentially going above the
+ acceptable delta for this test. Let's add a dummy wait to preinitialize
+ internal structures
+ */
+ Sleep(100);
+
+ /*
+ * Check that Queueing an APC in the middle of a sleep does interrupt
+ * it, if it's in an alertable state.
+ */
+ dwAvgDelta = 0;
+ for (i=0;i<Iterations;i++)
+ {
+ RunTest(TRUE);
+ dwAvgDelta += ThreadSleepDelta - InterruptTime;
+ }
+ dwAvgDelta /= Iterations;
+
+ if (dwAvgDelta > AcceptableDelta)
+ {
+ Fail("Expected thread to sleep for %d ms (and get interrupted).\n"
+ "Average delta: %u ms, acceptable delta: %u\n",
+ InterruptTime, dwAvgDelta, AcceptableDelta);
+ }
+
+ /*
+ * Check that Queueing an APC in the middle of a sleep does NOT interrupt
+ * it, if it is not in an alertable state.
+ */
+ dwAvgDelta = 0;
+ for (i=0;i<Iterations;i++)
+ {
+ RunTest(FALSE);
+ dwAvgDelta += ThreadSleepDelta - ChildThreadSleepTime;
+ }
+ dwAvgDelta /= Iterations;
+
+ if (dwAvgDelta > AcceptableDelta)
+ {
+ Fail("Expected thread to sleep for %d ms (and not be interrupted).\n"
+ "Average delta: %u ms, acceptable delta: %u\n",
+ ChildThreadSleepTime, dwAvgDelta, AcceptableDelta);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+void RunTest(BOOL AlertThread)
+{
+ HANDLE hThread = 0;
+ DWORD dwThreadId = 0;
+ int ret;
+
+ hThread = CreateThread( NULL,
+ 0,
+ (LPTHREAD_START_ROUTINE)SleeperProc,
+ (LPVOID) AlertThread,
+ 0,
+ &dwThreadId);
+
+ if (hThread == NULL)
+ {
+ Fail("ERROR: Was not able to create the thread to test SleepEx!\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+ if (SleepEx(InterruptTime, FALSE) != 0)
+ {
+ Fail("The creating thread did not sleep!\n");
+ }
+
+ ret = QueueUserAPC(APCFunc, hThread, 0);
+ if (ret == 0)
+ {
+ Fail("QueueUserAPC failed! GetLastError returned %d\n", GetLastError());
+ }
+
+ ret = WaitForSingleObject(hThread, INFINITE);
+ if (ret == WAIT_FAILED)
+ {
+ Fail("Unable to wait on child thread!\nGetLastError returned %d.",
+ GetLastError());
+ }
+}
+
+/* Function doesn't do anything, just needed to interrupt SleepEx */
+VOID PALAPI APCFunc(ULONG_PTR dwParam)
+{
+
+}
+
+/* Entry Point for child thread. */
+DWORD PALAPI SleeperProc(LPVOID lpParameter)
+{
+ UINT64 OldTimeStamp;
+ UINT64 NewTimeStamp;
+ BOOL Alertable;
+ DWORD ret;
+
+ Alertable = (BOOL) lpParameter;
+
+ LARGE_INTEGER performanceFrequency;
+ if (!QueryPerformanceFrequency(&performanceFrequency))
+ {
+ return FAIL;
+ }
+
+ OldTimeStamp = GetHighPrecisionTimeStamp(performanceFrequency);
+
+ ret = SleepEx(ChildThreadSleepTime, Alertable);
+
+ NewTimeStamp = GetHighPrecisionTimeStamp(performanceFrequency);
+
+ if (Alertable && ret != WAIT_IO_COMPLETION)
+ {
+ Fail("Expected the interrupted sleep to return WAIT_IO_COMPLETION.\n"
+ "Got %d\n", ret);
+ }
+ else if (!Alertable && ret != 0)
+ {
+ Fail("Sleep did not timeout. Expected return of 0, got %d.\n", ret);
+ }
+
+
+ ThreadSleepDelta = NewTimeStamp - OldTimeStamp;
+
+ return 0;
+}
diff --git a/src/pal/tests/palsuite/threading/SleepEx/test2/testinfo.dat b/src/pal/tests/palsuite/threading/SleepEx/test2/testinfo.dat
new file mode 100644
index 0000000000..52f3ce0af6
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/SleepEx/test2/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = SleepEx
+Name = Test #2 for SleepEx
+TYPE = DEFAULT
+EXE1 = test2
+Description
+=Tests that a child thread in the middle of a SleepEx call will be
+=interrupted by QueueUserAPC if the alert flag was set.
+
diff --git a/src/pal/tests/palsuite/threading/SwitchToThread/CMakeLists.txt b/src/pal/tests/palsuite/threading/SwitchToThread/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/SwitchToThread/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/threading/SwitchToThread/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/SwitchToThread/test1/CMakeLists.txt
new file mode 100644
index 0000000000..40ecc910b0
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/SwitchToThread/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_switchtothread_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_switchtothread_test1 coreclrpal)
+
+target_link_libraries(paltest_switchtothread_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/SwitchToThread/test1/test1.c b/src/pal/tests/palsuite/threading/SwitchToThread/test1/test1.c
new file mode 100644
index 0000000000..76ecdd3572
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/SwitchToThread/test1/test1.c
@@ -0,0 +1,97 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test to ensure SwitchToThread works, without
+** causing test to hang
+**
+** Dependencies: PAL_Initialize
+** Fail
+** SwitchToThread
+** WaitForMultipleObject
+** CreateThread
+** GetLastError
+**
+
+**
+**===========================================================================*/
+
+
+#include <palsuite.h>
+#define THREAD_COUNT 10
+#define REPEAT_COUNT 1000
+#define TIMEOUT 60000
+void PALAPI Run_Thread(LPVOID lpParam);
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+INT __cdecl main( INT argc, CHAR **argv )
+{
+ DWORD dwParam;
+ HANDLE hThread[THREAD_COUNT];
+ DWORD threadId[THREAD_COUNT];
+
+ int i = 0;
+ int returnCode = 0;
+
+ /*PAL initialization */
+ if( (PAL_Initialize(argc, argv)) != 0 )
+ {
+ return FAIL;
+ }
+
+
+ for( i = 0; i < THREAD_COUNT; i++ )
+ {
+ dwParam = (int) i;
+ //Create thread
+ hThread[i] = CreateThread(
+ NULL, /* no security attributes */
+ 0, /* use default stack size */
+ (LPTHREAD_START_ROUTINE)Run_Thread,/* thread function */
+ (LPVOID)dwParam, /* argument to thread function */
+ 0, /* use default creation flags */
+ &threadId[i] /* returns the thread identifier*/
+ );
+
+ if(hThread[i] == NULL)
+ {
+ Fail("Create Thread failed for iteration %d GetLastError value is %d\n", i, GetLastError());
+ }
+
+ }
+
+
+ returnCode = WaitForMultipleObjects(THREAD_COUNT, hThread, TRUE, TIMEOUT);
+ if( WAIT_OBJECT_0 != returnCode )
+ {
+ Trace("Wait for Object(s) returned %d, expected value is %d, and GetLastError value is %d\n", returnCode, WAIT_OBJECT_0, GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+void PALAPI Run_Thread (LPVOID lpParam)
+{
+ int i = 0;
+ int Id=(int)lpParam;
+
+ for(i=0; i < REPEAT_COUNT; i++ )
+ {
+ // No Last Error is set..
+ if(!SwitchToThread())
+ {
+ Trace( "The operating system did not switch execution to another thread,"
+ "for thread id[%d], iteration [%d]\n", Id, i );
+ }
+ }
+}
diff --git a/src/pal/tests/palsuite/threading/SwitchToThread/test1/testinfo.dat b/src/pal/tests/palsuite/threading/SwitchToThread/test1/testinfo.dat
new file mode 100644
index 0000000000..15ee8d4d4e
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/SwitchToThread/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = SwitchToThread
+Name = Test for SwitchToThread
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Purpose: Test to ensure SwitchToThread is
+= working properly on supported platforms
diff --git a/src/pal/tests/palsuite/threading/TLS/CMakeLists.txt b/src/pal/tests/palsuite/threading/TLS/CMakeLists.txt
new file mode 100644
index 0000000000..bffdf7f714
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/TLS/CMakeLists.txt
@@ -0,0 +1,9 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+
+
diff --git a/src/pal/tests/palsuite/threading/TLS/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/TLS/test1/CMakeLists.txt
new file mode 100644
index 0000000000..ff1a866eb9
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/TLS/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ TLS.c
+)
+
+add_executable(paltest_tls_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_tls_test1 coreclrpal)
+
+target_link_libraries(paltest_tls_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/TLS/test1/TLS.c b/src/pal/tests/palsuite/threading/TLS/test1/TLS.c
new file mode 100644
index 0000000000..4300c3f98b
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/TLS/test1/TLS.c
@@ -0,0 +1,182 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: tls.c
+**
+** Purpose: Test to ensure TlsAlloc, TlsGetValue, TlsSetValue
+** and TlsFree are working properly together.
+**
+** Dependencies: PAL_Initialize
+** Fail
+** Sleep
+** LocalAlloc
+** LocalFree
+** WaitForSingleObject
+** CreateThread
+** GetLastError
+**
+
+**
+**===========================================================================*/
+#include <palsuite.h>
+
+#define NUM_OF_THREADS 10
+
+DWORD dwTlsIndex; /* TLS index */
+
+/**
+ * CommonFunction
+ *
+ * Helper function that calls TlsGetValue
+ */
+VOID CommonFunction(VOID)
+{
+ LPVOID lpvData;
+ DWORD dwError;
+
+ /* Retrieve a data pointer for the current thread. */
+ lpvData = TlsGetValue(dwTlsIndex);
+
+ if ( (lpvData == 0) &&
+ ((dwError = GetLastError()) != NO_ERROR) )
+ {/*ERROR */
+ Fail("TlsGetValue(%d) returned 0 with error %d\n",
+ dwTlsIndex,
+ dwError);
+ }
+
+ Sleep(5000);
+}
+
+/**
+ * ThreadFunc
+ *
+ * Thread function that stores a value in the thread's tls slot
+ * for the predefined tls index
+ */
+DWORD PALAPI ThreadFunc(LPVOID lpThreadParameter)
+{
+ LPVOID lpvData;
+ DWORD dwError;
+
+ /* Initialize the TLS index for this thread.*/
+ lpvData = (LPVOID) LocalAlloc(0, 256);
+
+ if( lpvData == NULL )
+ {/*ERROR */
+ dwError = GetLastError();
+ Fail("Unexpected LocalAlloc(0, 256) failure with error %d\n",
+ dwError);
+ }
+
+
+ if ( TlsSetValue(dwTlsIndex, lpvData) == 0 )
+ {/*ERROR */
+ dwError = GetLastError();
+ Fail("TlsSetValue(%d, %x) returned 0 with error %d\n",
+ dwTlsIndex,
+ lpvData,
+ dwError);
+ }
+
+ CommonFunction();
+
+ /* Release the dynamic memory. */
+ lpvData = TlsGetValue(dwTlsIndex);
+
+ if ( (lpvData == 0) &&
+ ((dwError = GetLastError()) != NO_ERROR) )
+ {/*ERROR */
+ Fail("TlsGetValue(%d) returned 0 with error %d\n",
+ dwTlsIndex,
+ dwError);
+ }
+ else
+ {
+ if( LocalFree((HLOCAL) lpvData) != NULL )
+ {
+ dwError = GetLastError();
+ Fail("Unexpected LocalFree(%x) failure with error %d\n",
+ lpvData,
+ dwError);
+ }
+ }
+
+ return PASS;
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+INT __cdecl main( INT argc, CHAR **argv )
+{
+ DWORD IDThread;
+ HANDLE hThread[NUM_OF_THREADS];
+ int i;
+
+ /*PAL initialization */
+ if( (PAL_Initialize(argc, argv)) != 0 )
+ {
+ return FAIL;
+ }
+
+ /*Allocate a TLS index. */
+ if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
+ {/*RROR*/
+ DWORD dwError = GetLastError();
+ Fail("TlsAlloc() returned error %d\n",
+ dwError);
+ }
+
+ /*Create multiple threads.*/
+
+ for (i = 0; i < NUM_OF_THREADS; i++)
+ {
+ hThread[i] = CreateThread(NULL, /* no security attributes*/
+ 0, /* use default stack size */
+ ThreadFunc, /* thread function */
+ NULL, /* no thread function argument */
+ 0, /* use default creation flags */
+ &IDThread); /* returns thread identifier */
+
+ /* Check the return value for success. */
+ if (hThread[i] == NULL)
+ {/* ERROR */
+ DWORD dwError = GetLastError();
+ Fail("Unexpected CreateThread error %d\n",
+ dwError);
+ }
+ }
+
+ /* Wait for all threads to finish */
+ for (i = 0; i < NUM_OF_THREADS; i++)
+ {
+ DWORD dwRet;
+
+ dwRet = WaitForSingleObject(hThread[i], INFINITE);
+
+ if( dwRet == WAIT_FAILED )
+ {/* ERROR */
+ DWORD dwError = GetLastError();
+ Fail("Unexpected WaitForSingleObject error %d\n",
+ dwError);
+ }
+ }
+
+ /* Release the TLS index */
+ if( TlsFree( dwTlsIndex ) == 0 )
+ {/* ERROR */
+ DWORD dwError = GetLastError();
+ Fail("TlsFree() returned 0 with error %d\n",
+ dwError);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/threading/TLS/test1/testinfo.dat b/src/pal/tests/palsuite/threading/TLS/test1/testinfo.dat
new file mode 100644
index 0000000000..544e391266
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/TLS/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = TLS
+Name = Test for TlsAlloc, TlsGetValue, TlsSetValue and TlsFree
+TYPE = DEFAULT
+EXE1 = tls
+Description
+= Test to ensure TlsAlloc, TlsGetValue, TlsSetValue
+= and TlsFree are working properly together.
diff --git a/src/pal/tests/palsuite/threading/TLS/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/TLS/test2/CMakeLists.txt
new file mode 100644
index 0000000000..5afe82b4a6
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/TLS/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ TLS.c
+)
+
+add_executable(paltest_tls_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_tls_test2 coreclrpal)
+
+target_link_libraries(paltest_tls_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/TLS/test2/TLS.c b/src/pal/tests/palsuite/threading/TLS/test2/TLS.c
new file mode 100644
index 0000000000..96a6011f96
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/TLS/test2/TLS.c
@@ -0,0 +1,66 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: tls.c
+**
+** Purpose: Test to ensure TlsAlloc and TlsFree are working when we try
+** to allocate the guaranted minimum number of indicies.
+**
+
+**
+**===========================================================================*/
+#include <palsuite.h>
+
+#define NUM_OF_INDEX 64
+/* Minimum guaranteed is at least 64 for all systems.*/
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+INT __cdecl main( INT argc, CHAR **argv )
+{
+ DWORD dwIndexes[NUM_OF_INDEX];
+ int i,j;
+
+ /* PAL initialization */
+ if( (PAL_Initialize(argc, argv)) != 0 )
+ {
+ return FAIL;
+ }
+
+ /* Allocate a bunch of TLS indexes. */
+ for( i = 0; i < NUM_OF_INDEX; i++ )
+ {
+ if( (dwIndexes[i] = TlsAlloc()) == TLS_OUT_OF_INDEXES )
+ {/*ERROR */
+ DWORD dwError = GetLastError();
+ Fail("TlsAlloc() returned -1 with error %d"
+ "when trying to allocate %d index\n",
+ dwError,
+ i);
+ }
+ }
+
+ /* Free the TLS indexes.*/
+ for( j = 0; j < NUM_OF_INDEX; j++ )
+ {
+ if( TlsFree(dwIndexes[j]) == 0 )
+ {/* ERROR */
+ DWORD dwError = GetLastError();
+ Fail("TlsFree() returned 0 with error %d"
+ "when trying to free %d index\n",
+ dwError,
+ i);
+ }
+ }
+
+ PAL_Terminate();
+
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/threading/TLS/test2/testinfo.dat b/src/pal/tests/palsuite/threading/TLS/test2/testinfo.dat
new file mode 100644
index 0000000000..3a672a5f38
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/TLS/test2/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = TLS
+Name = Test for TlsAlloc and TlsFree
+TYPE = DEFAULT
+EXE1 = tls
+Description
+= Test to ensure TlsAlloc and TlsFree are working when we try
+= to allocate the guaranted minimum number of index.
diff --git a/src/pal/tests/palsuite/threading/TLS/test3/CMakeLists.txt b/src/pal/tests/palsuite/threading/TLS/test3/CMakeLists.txt
new file mode 100644
index 0000000000..0964d33d2c
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/TLS/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ TLS.c
+)
+
+add_executable(paltest_tls_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_tls_test3 coreclrpal)
+
+target_link_libraries(paltest_tls_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/TLS/test3/TLS.c b/src/pal/tests/palsuite/threading/TLS/test3/TLS.c
new file mode 100644
index 0000000000..4acaef5020
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/TLS/test3/TLS.c
@@ -0,0 +1,90 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: tls.c
+**
+** Purpose: Test to ensure TlsGetValue, TlsSetValue and TlsFree
+** are not working with an invalid index
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** LocalAlloc
+** LocalFree
+**
+
+**
+**===========================================================================*/
+#include <palsuite.h>
+
+DWORD dwTlsIndex; /* TLS index */
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+INT __cdecl main( INT argc, CHAR **argv )
+{
+ CHAR lpstrData[256] = "";
+ LPVOID lpvData = NULL;
+ BOOL bRet;
+
+ /* PAL initialization */
+ if( (PAL_Initialize(argc, argv)) != 0 )
+ {
+ return FAIL;
+ }
+
+ /* Invalid TLS index */
+ dwTlsIndex = -1;
+
+ /*
+ * Set some data in the invalid TLS index
+ *Should return 0 and an error
+ */
+ bRet = TlsSetValue(dwTlsIndex, (LPVOID)lpstrData);
+
+ if ( bRet != 0)
+ {/*ERROR */
+ Fail("TlsSetValue(%d, %x) returned %d "
+ "when it should have returned 0 and an error\n",
+ dwTlsIndex,
+ lpvData,
+ bRet);
+ }
+
+ /*
+ * Get the data at the invalid index
+ * Should return 0 and an error
+ */
+ lpvData = TlsGetValue(dwTlsIndex);
+
+ if ( lpvData != 0 )
+ {/* ERROR */
+ Fail("TlsGetValue(%d) returned %d "
+ "when it should have returned 0 and an error\n",
+ dwTlsIndex,
+ lpvData);
+ }
+
+ /*
+ * Release the invalid TLS index
+ * Should return 0 and an error
+ */
+ bRet = TlsFree( dwTlsIndex );
+
+ if( bRet != 0 )
+ {/* ERROR */
+ Fail("TlsFree() returned %d "
+ "when it should have returned 0 and an error\n",
+ bRet);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+
diff --git a/src/pal/tests/palsuite/threading/TLS/test3/testinfo.dat b/src/pal/tests/palsuite/threading/TLS/test3/testinfo.dat
new file mode 100644
index 0000000000..63ce59f351
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/TLS/test3/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = TLS
+Name = TlsGetValue, TlsSetValue and TlsFree
+TYPE = DEFAULT
+EXE1 = tls
+Description
+= Test to ensure TlsGetValue, TlsSetValue and TlsFree
+= are not working with an invalid index
diff --git a/src/pal/tests/palsuite/threading/TLS/test4/CMakeLists.txt b/src/pal/tests/palsuite/threading/TLS/test4/CMakeLists.txt
new file mode 100644
index 0000000000..7e7b47786a
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/TLS/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_tls_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_tls_test4 coreclrpal)
+
+target_link_libraries(paltest_tls_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/TLS/test4/test4.c b/src/pal/tests/palsuite/threading/TLS/test4/test4.c
new file mode 100644
index 0000000000..8c3603cdb0
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/TLS/test4/test4.c
@@ -0,0 +1,137 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test4.c (threading/tls)
+**
+** Purpose: Test to ensure that upon key creation, the value NULL
+** is associated with the new key in all active threads.
+** Upon thread creation, the value NULL is associated
+** with all defined keys in the new thread.
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** LocalAlloc
+** LocalFree
+**
+
+**
+**===========================================================================*/
+#include <palsuite.h>
+
+#define NUM_OF_THREADS 10
+
+DWORD dwTlsIndex; /* TLS index */
+
+/**
+ * ThreadFunc
+ *
+ * Thread function that checks that NULL is associated with the tls index
+ */
+DWORD PALAPI ThreadFunc(VOID)
+{
+ LPVOID lpvData;
+ DWORD dwError;
+
+ /* Retrieve a data pointer for the current thread.
+ The return value should be NULL since no data has been
+ set in the index */
+ lpvData = TlsGetValue(dwTlsIndex);
+
+ if ( (lpvData != NULL) &&
+ ((dwError = GetLastError()) == NO_ERROR) )
+ {/*ERROR */
+ Fail("TlsGetValue(%d) returned data "
+ "even if no data was associated with the index\n",
+ dwTlsIndex);
+ }
+
+ return PASS;
+}
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+INT __cdecl main( INT argc, CHAR **argv )
+{
+ DWORD IDThread;
+ LPVOID lpvData;
+ DWORD dwError;
+ HANDLE hThread[NUM_OF_THREADS];
+ int i;
+
+ /*PAL initialization */
+ if( (PAL_Initialize(argc, argv)) != 0 )
+ {
+ return FAIL;
+ }
+
+ /*Allocate a TLS index. */
+ if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
+ {/*ERROR*/
+ DWORD dwError = GetLastError();
+ Fail("TlsAlloc() returned error %d\n",
+ dwError);
+ }
+
+ /*Check that the value associated with the tls index is NULL*/
+ lpvData = TlsGetValue(dwTlsIndex);
+
+ if ( (lpvData != NULL) &&
+ ((dwError = GetLastError()) == NO_ERROR) )
+ {/*ERROR */
+ Fail("TlsGetValue(%d) returned non-null data "
+ "even if no data was associated with the index\n",
+ dwTlsIndex);
+ }
+
+ /*Create multiple threads.*/
+ for (i = 0; i < NUM_OF_THREADS; i++)
+ {
+ hThread[i] = CreateThread(NULL, /* no security attributes*/
+ 0, /* use default stack size */
+ (LPTHREAD_START_ROUTINE) ThreadFunc, /* thread function */
+ NULL, /* no thread function argument */
+ 0, /* use default creation flags */
+ &IDThread); /* returns thread identifier */
+
+ /* Check the return value for success. */
+ if (hThread[i] == NULL)
+ {/* ERROR */
+ DWORD dwError = GetLastError();
+ Fail("Unexpected CreateThread error %d\n",
+ dwError);
+ }
+ }
+
+ /* Wait for all threads to finish */
+ for (i = 0; i < NUM_OF_THREADS; i++)
+ {
+ DWORD dwRet;
+
+ dwRet = WaitForSingleObject(hThread[i], INFINITE);
+
+ if( dwRet == WAIT_FAILED )
+ {/* ERROR */
+ DWORD dwError = GetLastError();
+ Fail("Unexpected WaitForSingleObject error %d\n",
+ dwError);
+ }
+ }
+
+ /* Release the TLS index */
+ if( TlsFree( dwTlsIndex ) == 0 )
+ {/* ERROR */
+ DWORD dwError = GetLastError();
+ Fail("TlsFree() returned 0 with error %d\n",
+ dwError);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/threading/TLS/test4/testinfo.dat b/src/pal/tests/palsuite/threading/TLS/test4/testinfo.dat
new file mode 100644
index 0000000000..6001770642
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/TLS/test4/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = TLS
+Name = TlsAlloc, TlsGetValue
+TYPE = DEFAULT
+EXE1 = test4
+Description
+=Test to ensure that upon key creation, the value NULL
+=is associated with the new key in all active threads.
+=Upon thread creation, the value NULL is associated
+=with all defined keys in the new thread.
diff --git a/src/pal/tests/palsuite/threading/TLS/test5/CMakeLists.txt b/src/pal/tests/palsuite/threading/TLS/test5/CMakeLists.txt
new file mode 100644
index 0000000000..5fb5c9ddfd
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/TLS/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test5.c
+)
+
+add_executable(paltest_tls_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_tls_test5 coreclrpal)
+
+target_link_libraries(paltest_tls_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/TLS/test5/test5.c b/src/pal/tests/palsuite/threading/TLS/test5/test5.c
new file mode 100644
index 0000000000..c1cd132937
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/TLS/test5/test5.c
@@ -0,0 +1,108 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test5.c (threading/tls)
+**
+** Purpose: Test that creates a key, sets its value, deletes the key,
+** creates a new key, and gets its value to make sure its NULL.
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** LocalAlloc
+** LocalFree
+**
+
+**
+**===========================================================================*/
+#include <palsuite.h>
+
+DWORD dwTlsIndex; /* TLS index */
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+INT __cdecl main( INT argc, CHAR **argv )
+{
+ LPVOID lpvData;
+ DWORD dwError;
+
+ /*PAL initialization */
+ if( (PAL_Initialize(argc, argv)) != 0 )
+ {
+ return FAIL;
+ }
+
+ /**
+ * create a key, set its value, delete the key
+ */
+
+ /*Allocate a TLS index. */
+ if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
+ {/*ERROR*/
+ DWORD dwError = GetLastError();
+ Fail("TlsAlloc() returned error %d\n",
+ dwError);
+ }
+
+ /* Initialize the TLS index for this thread.*/
+ lpvData = (LPVOID) LocalAlloc(0, 256);
+
+ if( lpvData == NULL )
+ {/*ERROR */
+ dwError = GetLastError();
+ Fail("Unexpected LocalAlloc(0, 256) failure with error %d\n",
+ dwError);
+ }
+
+ if ( TlsSetValue(dwTlsIndex, lpvData) == 0 )
+ {/*ERROR */
+ dwError = GetLastError();
+ Fail("TlsSetValue(%d, %x) returned 0 with error %d\n",
+ dwTlsIndex,
+ lpvData,
+ dwError);
+ }
+
+ /* Release the TLS index */
+ if( TlsFree( dwTlsIndex ) == 0 )
+ {/* ERROR */
+ DWORD dwError = GetLastError();
+ Fail("TlsFree() returned 0 with error %d\n",
+ dwError);
+ }
+
+
+ /**
+ * create a new key, and get its value
+ */
+
+ /*Allocate a TLS index. */
+ if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
+ {/*ERROR*/
+ DWORD dwError = GetLastError();
+ Fail("TlsAlloc() returned error %d\n",
+ dwError);
+ }
+
+ /* Retrieve a data pointer for the current thread.
+ The return value should be NULL since no data has been
+ set in the index */
+ lpvData = TlsGetValue(dwTlsIndex);
+
+ if ( (lpvData != NULL) &&
+ ((dwError = GetLastError()) == NO_ERROR) )
+ {/*ERROR */
+ Fail("TlsGetValue(%d) returned data "
+ "even if no data was associated with the index\n",
+ dwTlsIndex);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
diff --git a/src/pal/tests/palsuite/threading/TLS/test5/testinfo.dat b/src/pal/tests/palsuite/threading/TLS/test5/testinfo.dat
new file mode 100644
index 0000000000..4b3e2a64c5
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/TLS/test5/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = TLS
+Name = TlsAlloc and TlsGetValue
+TYPE = DEFAULT
+EXE1 = test5
+Description
+= Test that creates a key, sets its value, deletes the key,
+= creates a new key, and gets its value to make sure its NULL.
diff --git a/src/pal/tests/palsuite/threading/TLS/test6_optimizedtls/CMakeLists.txt b/src/pal/tests/palsuite/threading/TLS/test6_optimizedtls/CMakeLists.txt
new file mode 100644
index 0000000000..8b3a4ed64a
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/TLS/test6_optimizedtls/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_tls_test6_optimizedtls
+ ${SOURCES}
+)
+
+add_dependencies(paltest_tls_test6_optimizedtls coreclrpal)
+
+target_link_libraries(paltest_tls_test6_optimizedtls
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/TLS/test6_optimizedtls/test.c b/src/pal/tests/palsuite/threading/TLS/test6_optimizedtls/test.c
new file mode 100644
index 0000000000..02419dc90c
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/TLS/test6_optimizedtls/test.c
@@ -0,0 +1,190 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test.c
+**
+** Purpose: Test to ensure TlsAlloc, PAL_MakeOptimizedTlsGetter,
+** PAL_FreeOptimizedTlsGetter and TlsFree are working properly
+** on supported platforms
+**
+** Dependencies: PAL_Initialize
+** Fail
+** Sleep
+** LocalAlloc
+** LocalFree
+** WaitForSingleObject
+** CreateThread
+** GetLastError
+**
+
+**
+**===========================================================================*/
+
+
+#include <palsuite.h>
+#define THREAD_COUNT 5
+DWORD dwTlsIndex; /* TLS index */
+
+void PALAPI Run_Thread(LPVOID lpParam);
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+INT __cdecl main( INT argc, CHAR **argv )
+{
+ DWORD dwParam;
+ DWORD dwError;
+ HANDLE hThread[THREAD_COUNT];
+ DWORD threadId[THREAD_COUNT];
+
+ int i = 0;
+ int returnCode = 0;
+
+ /*PAL initialization */
+ if( (PAL_Initialize(argc, argv)) != 0 )
+ {
+ return FAIL;
+ }
+
+ /*Allocate a TLS index. */
+ if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
+ {
+ /*ERROR*/
+ dwError = GetLastError();
+ Fail("TlsAlloc() returned error %d\n",
+ dwError);
+ }
+
+
+ for( i = 0; i < THREAD_COUNT; i++ )
+ {
+ dwParam = (int) i;
+ //Create thread
+ hThread[i] = CreateThread(
+ NULL, /* no security attributes */
+ 0, /* use default stack size */
+ (LPTHREAD_START_ROUTINE)Run_Thread,/* thread function */
+ (LPVOID)dwParam, /* argument to thread function */
+ 0, /* use default creation flags */
+ &threadId[i] /* returns the thread identifier*/
+ );
+
+ if(hThread[i] == NULL)
+ {
+ Fail("Create Thread failed for iteration %d GetLastError value is %d\n", i, GetLastError());
+ }
+
+ }
+
+
+ returnCode = WaitForMultipleObjects(THREAD_COUNT, hThread, TRUE, INFINITE);
+ if( WAIT_OBJECT_0 != returnCode )
+ {
+ Trace("Wait for Object(s) returned %d, expected value is %d, and GetLastError value is %d\n", returnCode, WAIT_OBJECT_0, GetLastError());
+ }
+
+ /* Release the TLS index */
+ if( TlsFree( dwTlsIndex ) == 0 )
+ {
+ /* ERROR */
+ dwError = GetLastError();
+ Fail("TlsFree() returned 0 with error %d\n",
+ dwError);
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+void PALAPI Run_Thread (LPVOID lpParam)
+{
+ unsigned int i = 0;
+
+ LPVOID lpvData;
+ DWORD dwError;
+ PAL_POPTIMIZEDTLSGETTER ptrOptimizedTlsGetter;
+
+ int Id=(int)lpParam;
+
+
+ lpvData = TlsGetValue(dwTlsIndex);
+ if ( (lpvData != NULL) &&
+ ((dwError = GetLastError()) == NO_ERROR) )
+ {
+ /*ERROR */
+ Fail("Error:%d:TlsGetValue(%d) returned data "
+ "even if data was not associated with the index, for thread id [%d]\n",
+ dwError, dwTlsIndex, Id);
+ }
+
+
+ /* Initialize the TLS index for this thread.*/
+ lpvData = (LPVOID) LocalAlloc(0, 256);
+
+ if( lpvData == NULL )
+ {
+ /*ERROR */
+ dwError = GetLastError();
+ Fail("Unexpected LocalAlloc(0, 256) failure with error %d\n",
+ dwError);
+ }
+
+ if ( TlsSetValue(dwTlsIndex, lpvData) == 0 )
+ {
+ /*ERROR */
+ dwError = GetLastError();
+ Fail("TlsSetValue(%d, %x) returned 0 with error %d\n",
+ dwTlsIndex,
+ lpvData,
+ dwError);
+ }
+
+ ptrOptimizedTlsGetter = PAL_MakeOptimizedTlsGetter(dwTlsIndex);
+ if( ptrOptimizedTlsGetter == NULL )
+ {
+ /* Retrieve a data pointer for the current thread.
+ The return value should be NULL since no data has been
+ set in the index */
+ lpvData = TlsGetValue(dwTlsIndex);
+ Trace("Not Inside the optimizer loop for thread [%d]\n", Id);
+
+ if ( (lpvData == NULL) &&
+ ((dwError = GetLastError()) == NO_ERROR) )
+ {
+ /*ERROR */
+ Fail("Error:%d:TlsGetValue(%d) returned data "
+ "as NULL even if data was associated with the index, for thread id [%d]\n",
+ dwError, dwTlsIndex, Id);
+ }
+ }
+ else
+ {
+ /* Retrieve a data pointer for the current thread.
+ The return value should be NULL since no data has been
+ set in the index */
+ lpvData = ptrOptimizedTlsGetter();
+
+ if ( (lpvData == NULL) &&
+ ((dwError = GetLastError()) == NO_ERROR) )
+ {
+ /*ERROR */
+ Fail(" Error:%d: MakeOptimizedTlsGetter for dwTlsIndex (%d) returned data "
+ "as NULL even if no data was associated with the index, for thread id [%d]\n",
+ dwError, dwTlsIndex, Id);
+ }
+
+ Trace("Inside the optimizer loop for thread [%d]\n", Id);
+ PAL_FreeOptimizedTlsGetter(ptrOptimizedTlsGetter);
+ }
+
+
+
+
+}
+
diff --git a/src/pal/tests/palsuite/threading/TLS/test6_optimizedtls/testinfo.dat b/src/pal/tests/palsuite/threading/TLS/test6_optimizedtls/testinfo.dat
new file mode 100644
index 0000000000..2193edcab3
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/TLS/test6_optimizedtls/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = PAL_MakeOptimizedTlsGetter and PAL_FreeOptimizedTlsGetter
+Name = Test for PAL_MakeOptimizedTlsGetterandPAL_FreeOptimizedTlsGetter
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Purpose: Test to ensure TlsAlloc, PAL_MakeOptimizedTlsGetter,
+= PAL_FreeOptimizedTlsGetter and TlsFree are working properly
+= on supported platforms
diff --git a/src/pal/tests/palsuite/threading/TerminateProcess/CMakeLists.txt b/src/pal/tests/palsuite/threading/TerminateProcess/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/TerminateProcess/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/threading/TerminateProcess/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/TerminateProcess/test1/CMakeLists.txt
new file mode 100644
index 0000000000..37d575952f
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/TerminateProcess/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ TerminateProcess.c
+)
+
+add_executable(paltest_terminateprocess_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_terminateprocess_test1 coreclrpal)
+
+target_link_libraries(paltest_terminateprocess_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/TerminateProcess/test1/TerminateProcess.c b/src/pal/tests/palsuite/threading/TerminateProcess/test1/TerminateProcess.c
new file mode 100644
index 0000000000..6feedfce76
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/TerminateProcess/test1/TerminateProcess.c
@@ -0,0 +1,41 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: terminateprocess/test1/terminateprocess.c
+**
+** Purpose: Test to see if TerminateProcess will
+** terminate the current process.
+**
+** Dependencies: GetCurrentProcess
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+INT __cdecl main( int argc, char **argv )
+{
+
+ HANDLE hProcess;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return (FAIL);
+ }
+
+ hProcess = GetCurrentProcess();
+
+ Trace ("Testing TerminateProcess function.\n");
+
+ if ( 0 == ( TerminateProcess ( hProcess, PASS ) ) )
+ {
+ Fail ("TerminateProcess failed.\n");
+ }
+
+ PAL_TerminateEx(FAIL);
+ return (FAIL);
+
+}
diff --git a/src/pal/tests/palsuite/threading/TerminateProcess/test1/testinfo.dat b/src/pal/tests/palsuite/threading/TerminateProcess/test1/testinfo.dat
new file mode 100644
index 0000000000..7ee69bfa29
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/TerminateProcess/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = TerminateProcess
+Name = Positive Test for TerminateProcess
+TYPE = DEFAULT
+EXE1 = terminateprocess
+Description
+= Test to see if the function TerminateProcess terminates the currently
+= running process and passes the appropriate value through uExitCode.
+
diff --git a/src/pal/tests/palsuite/threading/ThreadPriority/CMakeLists.txt b/src/pal/tests/palsuite/threading/ThreadPriority/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ThreadPriority/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/threading/ThreadPriority/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/ThreadPriority/test1/CMakeLists.txt
new file mode 100644
index 0000000000..e341ca7435
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ThreadPriority/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ ThreadPriority.c
+)
+
+add_executable(paltest_threadpriority_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_threadpriority_test1 coreclrpal)
+
+target_link_libraries(paltest_threadpriority_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/ThreadPriority/test1/ThreadPriority.c b/src/pal/tests/palsuite/threading/ThreadPriority/test1/ThreadPriority.c
new file mode 100644
index 0000000000..95bcdac52a
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ThreadPriority/test1/ThreadPriority.c
@@ -0,0 +1,83 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: threadpriority.c
+**
+** Purpose: Test to ensure GetThreadPriority works properly.
+**
+** Dependencies: PAL_Initialize
+** PAL_Terminate
+** Fail
+** CreateThread
+** WaitForSingleObject
+** GetLastError
+** time()
+**
+
+**
+**===========================================================================*/
+#include <palsuite.h>
+
+/**
+ * CheckThreadPriority
+ *
+ * Helper function that checks the current thread priority
+ * against an expected value.
+ */
+static VOID CheckThreadPriority( HANDLE hThread, int expectedPriority )
+{
+ int priority;
+ DWORD dwError = 0;
+
+ /* get the current thread priority */
+ priority = GetThreadPriority( hThread );
+ if( priority == THREAD_PRIORITY_ERROR_RETURN )
+ {
+ /* GetThreadPriority call failed */
+ dwError = GetLastError();
+ Fail( "Unexpected GetThreadPriority() failure "
+ "with error %d\n", dwError );
+ }
+ else if( priority != expectedPriority )
+ {
+ /* unexpected thread priority detected */
+ Fail( "Unexpected initial thread priority value %d reported\n",
+ priority );
+ }
+}
+
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+INT __cdecl main( INT argc, CHAR **argv )
+{
+
+ /* PAL initialization */
+ if( (PAL_Initialize(argc, argv)) != 0 )
+ {
+ return( FAIL );
+ }
+
+ /* set the thread priority of the main to the highest possible value
+ this will give the chance to the main thread to create all the
+ other threads */
+ if(!SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_NORMAL))
+ {
+ DWORD dwError;
+
+ dwError = GetLastError();
+ Fail( "Unexpected SetThreadPriority() failure with error %d\n",
+ dwError );
+ }
+
+ CheckThreadPriority( GetCurrentThread(), THREAD_PRIORITY_NORMAL );
+ //Add verification of timing out here..
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/threading/ThreadPriority/test1/testinfo.dat b/src/pal/tests/palsuite/threading/ThreadPriority/test1/testinfo.dat
new file mode 100644
index 0000000000..0abd9c1e06
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/ThreadPriority/test1/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = ThreadPriority
+Name = Test for GetThreadPriority and SetThreadPriority
+TYPE = DEFAULT
+EXE1 = threadpriority
+Description
+= Test to ensure proper operation of the GetThreadPriority
+= and SetThreadPriority APIs. The test launches several threads
+= of varying priorities, and verifies that the correct priority
+= is reported for each. It also verifies that the processing
+= time for each test thread is consistent with the priority
+= that's set for it.
diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjects/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForMultipleObjects/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjects/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/CMakeLists.txt
new file mode 100644
index 0000000000..2b1f946b26
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_waitformultipleobjects_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_waitformultipleobjects_test1 coreclrpal)
+
+target_link_libraries(paltest_waitformultipleobjects_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/test1.c b/src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/test1.c
new file mode 100644
index 0000000000..8249c38d9d
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/test1.c
@@ -0,0 +1,224 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test1.c
+**
+** Purpose: Test for WaitForMultipleObjects. Call the function
+** on an array of 4 events, and ensure that it returns correct
+** results when we do so.
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+/* Number of events in array */
+#define MAX_EVENTS 4
+
+BOOL WaitForMultipleObjectsTest()
+{
+ BOOL bRet = TRUE;
+ DWORD dwRet = 0;
+
+ DWORD i = 0, j = 0;
+
+ LPSECURITY_ATTRIBUTES lpEventAttributes = NULL;
+ BOOL bManualReset = TRUE;
+ BOOL bInitialState = TRUE;
+
+ HANDLE hEvent[MAX_EVENTS];
+
+ /* Run through this for loop and create 4 events */
+ for (i = 0; i < MAX_EVENTS; i++)
+ {
+ hEvent[i] = CreateEvent( lpEventAttributes,
+ bManualReset, bInitialState, NULL);
+
+ if (hEvent[i] == INVALID_HANDLE_VALUE)
+ {
+ Trace("WaitForMultipleObjectsTest:CreateEvent %u failed (%x)\n", i, GetLastError());
+ bRet = FALSE;
+ break;
+ }
+
+ /* Set the current event */
+ bRet = SetEvent(hEvent[i]);
+
+ if (!bRet)
+ {
+ Trace("WaitForMultipleObjectsTest:SetEvent %u failed (%x)\n", i, GetLastError());
+ bRet = FALSE;
+ break;
+ }
+
+ /* Ensure that this returns the correct value */
+ dwRet = WaitForSingleObject(hEvent[i],0);
+
+ if (dwRet != WAIT_OBJECT_0)
+ {
+ Trace("WaitForMultipleObjectsTest:WaitForSingleObject %u failed (%x)\n", i, GetLastError());
+ bRet = FALSE;
+ break;
+ }
+
+ /* Reset the event, and again ensure that the return value of
+ WaitForSingle is correct.
+ */
+ bRet = ResetEvent(hEvent[i]);
+
+ if (!bRet)
+ {
+ Trace("WaitForMultipleObjectsTest:ResetEvent %u failed (%x)\n", i, GetLastError());
+ bRet = FALSE;
+ break;
+ }
+
+ dwRet = WaitForSingleObject(hEvent[i],0);
+
+ if (dwRet != WAIT_TIMEOUT)
+ {
+ Trace("WaitForMultipleObjectsTest:WaitForSingleObject %u failed (%x)\n", i, GetLastError());
+ bRet = FALSE;
+ break;
+ }
+ }
+
+ /*
+ * If the first section of the test passed, move on to the
+ * second.
+ */
+
+ if (bRet)
+ {
+ BOOL bWaitAll = TRUE;
+ DWORD nCount = MAX_EVENTS;
+ CONST HANDLE *lpHandles = &hEvent[0];
+
+ /* Call WaitForMultipleOjbects on all the events, the return
+ should be WAIT_TIMEOUT
+ */
+ dwRet = WaitForMultipleObjects( nCount,
+ lpHandles,
+ bWaitAll,
+ 0);
+
+ if (dwRet != WAIT_TIMEOUT)
+ {
+ Trace("WaitForMultipleObjectsTest:WaitForMultipleObjects failed (%x)\n", GetLastError());
+ }
+ else
+ {
+ /* Step through each event and one at a time, set the
+ currect test, while reseting all the other tests
+ */
+
+ for (i = 0; i < MAX_EVENTS; i++)
+ {
+ for (j = 0; j < MAX_EVENTS; j++)
+ {
+ if (j == i)
+ {
+
+ bRet = SetEvent(hEvent[j]);
+
+ if (!bRet)
+ {
+ Trace("WaitForMultipleObjectsTest:SetEvent %u failed (%x)\n", j, GetLastError());
+ break;
+ }
+ }
+ else
+ {
+ bRet = ResetEvent(hEvent[j]);
+
+ if (!bRet)
+ {
+ Trace("WaitForMultipleObjectsTest:ResetEvent %u failed (%x)\n", j, GetLastError());
+ }
+ }
+ }
+
+ bWaitAll = FALSE;
+
+ /* Check that WaitFor returns WAIT_OBJECT + i */
+ dwRet = WaitForMultipleObjects( nCount,
+ lpHandles, bWaitAll, 0);
+
+ if (dwRet != WAIT_OBJECT_0+i)
+ {
+ Trace("WaitForMultipleObjectsTest:WaitForMultipleObjects failed (%x)\n", GetLastError());
+ bRet = FALSE;
+ break;
+ }
+ }
+ }
+
+ for (i = 0; i < MAX_EVENTS; i++)
+ {
+ bRet = CloseHandle(hEvent[i]);
+
+ if (!bRet)
+ {
+ Trace("WaitForMultipleObjectsTest:CloseHandle %u failed (%x)\n", i, GetLastError());
+ }
+ }
+ }
+
+ return bRet;
+}
+
+BOOL WaitMultipleDuplicateHandleTest()
+{
+ BOOL testResult = TRUE;
+ const HANDLE eventHandle = CreateEvent(NULL, TRUE, TRUE, NULL);
+ HANDLE eventHandles[] = {eventHandle, eventHandle};
+
+ // WaitAny - Wait for any of the events (no error expected)
+ DWORD result = WaitForMultipleObjects(sizeof(eventHandles) / sizeof(eventHandles[0]), eventHandles, FALSE, 0);
+ if (result != WAIT_OBJECT_0)
+ {
+ Trace("WaitMultipleDuplicateHandleTest:WaitAny failed (%x)\n", GetLastError());
+ testResult = FALSE;
+ }
+
+ // WaitAll - Wait for all of the events (error expected)
+ result = WaitForMultipleObjects(sizeof(eventHandles) / sizeof(eventHandles[0]), eventHandles, TRUE, 0);
+ if (result != WAIT_FAILED)
+ {
+ Trace("WaitMultipleDuplicateHandleTest:WaitAll failed: call unexpectedly succeeded\n");
+ testResult = FALSE;
+ }
+ else if (GetLastError() != ERROR_INVALID_PARAMETER)
+ {
+ Trace("WaitMultipleDuplicateHandleTest:WaitAll failed: unexpected last error (%x)\n");
+ testResult = FALSE;
+ }
+
+ return testResult;
+}
+
+int __cdecl main(int argc, char **argv)
+{
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ if(!WaitForMultipleObjectsTest())
+ {
+ Fail ("Test failed\n");
+ }
+
+ if (!WaitMultipleDuplicateHandleTest())
+ {
+ Fail("Test failed\n");
+ }
+
+ PAL_Terminate();
+ return ( PASS );
+
+}
diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/testinfo.dat b/src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/testinfo.dat
new file mode 100644
index 0000000000..38bd350d64
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = WaitForMultipleObjects
+Name = Positive Test for WaitForMultipleObjects
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Test for WaitForMultipleObjects. Call the function
+= on an array of 4 events, and ensure that it returns correct
+= results when we do so.
diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/CMakeLists.txt
new file mode 100644
index 0000000000..7c20179353
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/CMakeLists.txt
@@ -0,0 +1,9 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+
diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/CMakeLists.txt
new file mode 100644
index 0000000000..d035021bb9
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_waitformultipleobjectsex_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_waitformultipleobjectsex_test1 coreclrpal)
+
+target_link_libraries(paltest_waitformultipleobjectsex_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/test1.c b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/test1.c
new file mode 100644
index 0000000000..df3233fa50
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/test1.c
@@ -0,0 +1,226 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test1.c
+**
+** Purpose: Test for WaitForMultipleObjectsEx. Call the function
+** on an array of 4 events, and ensure that it returns correct
+** results when we do so.
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+/* Originally written as WaitForMultipleObjects/test1 */
+
+
+/* Number of events in array */
+#define MAX_EVENTS 4
+
+BOOL WaitForMultipleObjectsExTest()
+{
+ BOOL bRet = TRUE;
+ DWORD dwRet = 0;
+ DWORD i = 0, j = 0;
+
+ LPSECURITY_ATTRIBUTES lpEventAttributes = NULL;
+ BOOL bManualReset = TRUE;
+ BOOL bInitialState = TRUE;
+
+ HANDLE hEvent[MAX_EVENTS];
+
+ /* Run through this for loop and create 4 events */
+ for (i = 0; i < MAX_EVENTS; i++)
+ {
+ hEvent[i] = CreateEvent( lpEventAttributes,
+ bManualReset, bInitialState, NULL);
+
+ if (hEvent[i] == INVALID_HANDLE_VALUE)
+ {
+ Trace("WaitForMultipleObjectsExTest:CreateEvent %u failed (%x)\n", i, GetLastError());
+ bRet = FALSE;
+ break;
+ }
+
+ /* Set the current event */
+ bRet = SetEvent(hEvent[i]);
+
+ if (!bRet)
+ {
+ Trace("WaitForMultipleObjectsExTest:SetEvent %u failed (%x)\n", i, GetLastError());
+ bRet = FALSE;
+ break;
+ }
+
+ /* Ensure that this returns the correct value */
+ dwRet = WaitForSingleObject(hEvent[i],0);
+
+ if (dwRet != WAIT_OBJECT_0)
+ {
+ Trace("WaitForMultipleObjectsExTest:WaitForSingleObject %u failed (%x)\n", i, GetLastError());
+ bRet = FALSE;
+ break;
+ }
+
+ /* Reset the event, and again ensure that the return value of
+ WaitForSingle is correct.
+ */
+ bRet = ResetEvent(hEvent[i]);
+
+ if (!bRet)
+ {
+ Trace("WaitForMultipleObjectsExTest:ResetEvent %u failed (%x)\n", i, GetLastError());
+ bRet = FALSE;
+ break;
+ }
+
+ dwRet = WaitForSingleObject(hEvent[i],0);
+
+ if (dwRet != WAIT_TIMEOUT)
+ {
+ Trace("WaitForMultipleObjectsExTest:WaitForSingleObject %u failed (%x)\n", i, GetLastError());
+ bRet = FALSE;
+ break;
+ }
+ }
+
+ /*
+ * If the first section of the test passed, move on to the
+ * second.
+ */
+
+ if (bRet)
+ {
+ BOOL bWaitAll = TRUE;
+ DWORD nCount = MAX_EVENTS;
+ CONST HANDLE *lpHandles = &hEvent[0];
+
+ /* Call WaitForMultipleObjectsEx on all the events, the return
+ should be WAIT_TIMEOUT
+ */
+ dwRet = WaitForMultipleObjectsEx(nCount,
+ lpHandles,
+ bWaitAll,
+ 0,
+ FALSE);
+
+ if (dwRet != WAIT_TIMEOUT)
+ {
+ Trace("WaitForMultipleObjectsExTest: WaitForMultipleObjectsEx failed (%x)\n", GetLastError());
+ }
+ else
+ {
+ /* Step through each event and one at a time, set the
+ currect test, while reseting all the other tests
+ */
+
+ for (i = 0; i < MAX_EVENTS; i++)
+ {
+ for (j = 0; j < MAX_EVENTS; j++)
+ {
+ if (j == i)
+ {
+
+ bRet = SetEvent(hEvent[j]);
+
+ if (!bRet)
+ {
+ Trace("WaitForMultipleObjectsExTest:SetEvent %j failed (%x)\n", j, GetLastError());
+ break;
+ }
+ }
+ else
+ {
+ bRet = ResetEvent(hEvent[j]);
+
+ if (!bRet)
+ {
+ Trace("WaitForMultipleObjectsExTest:ResetEvent %u failed (%x)\n", j, GetLastError());
+ }
+ }
+ }
+
+ bWaitAll = FALSE;
+
+ /* Check that WaitFor returns WAIT_OBJECT + i */
+ dwRet = WaitForMultipleObjectsEx( nCount,
+ lpHandles, bWaitAll, 0, FALSE);
+
+ if (dwRet != WAIT_OBJECT_0+i)
+ {
+ Trace("WaitForMultipleObjectsExTest: WaitForMultipleObjectsEx failed (%x)\n", GetLastError());
+ bRet = FALSE;
+ break;
+ }
+ }
+ }
+
+ for (i = 0; i < MAX_EVENTS; i++)
+ {
+ bRet = CloseHandle(hEvent[i]);
+
+ if (!bRet)
+ {
+ Trace("WaitForMultipleObjectsExTest:CloseHandle %u failed (%x)\n", i, GetLastError());
+ }
+ }
+ }
+
+ return bRet;
+}
+
+BOOL WaitMultipleDuplicateHandleTest()
+{
+ BOOL testResult = TRUE;
+ const HANDLE eventHandle = CreateEvent(NULL, TRUE, TRUE, NULL);
+ HANDLE eventHandles[] = {eventHandle, eventHandle};
+
+ // WaitAny - Wait for any of the events (no error expected)
+ DWORD result = WaitForMultipleObjects(sizeof(eventHandles) / sizeof(eventHandles[0]), eventHandles, FALSE, 0);
+ if (result != WAIT_OBJECT_0)
+ {
+ Trace("WaitMultipleDuplicateHandleTest:WaitAny failed (%x)\n", GetLastError());
+ testResult = FALSE;
+ }
+
+ // WaitAll - Wait for all of the events (error expected)
+ result = WaitForMultipleObjects(sizeof(eventHandles) / sizeof(eventHandles[0]), eventHandles, TRUE, 0);
+ if (result != WAIT_FAILED)
+ {
+ Trace("WaitMultipleDuplicateHandleTest:WaitAll failed: call unexpectedly succeeded\n");
+ testResult = FALSE;
+ }
+ else if (GetLastError() != ERROR_INVALID_PARAMETER)
+ {
+ Trace("WaitMultipleDuplicateHandleTest:WaitAll failed: unexpected last error (%x)\n");
+ testResult = FALSE;
+ }
+
+ return testResult;
+}
+
+int __cdecl main(int argc, char **argv)
+{
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ if(!WaitForMultipleObjectsExTest())
+ {
+ Fail ("Test failed\n");
+ }
+
+ if (!WaitMultipleDuplicateHandleTest())
+ {
+ Fail("Test failed\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/testinfo.dat b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/testinfo.dat
new file mode 100644
index 0000000000..596c4bbf32
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = WaitForMultipleObjectsEx
+Name = Test #1 for WaitForMultipleObjectsEx
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Test for WaitForMultipleObjectsEx. Call the function
+= on an array of 4 events, and ensure that it returns correct
+= results when we do so.
diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/CMakeLists.txt
new file mode 100644
index 0000000000..ab47c6f2e7
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_waitformultipleobjectsex_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_waitformultipleobjectsex_test2 coreclrpal)
+
+target_link_libraries(paltest_waitformultipleobjectsex_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/test2.c b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/test2.c
new file mode 100644
index 0000000000..b2bc301128
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/test2.c
@@ -0,0 +1,188 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test2.c
+**
+** Purpose: Tests that a child thread in the middle of a
+** WaitForMultipleObjectsEx call will be interrupted by QueueUserAPC
+** if the alert flag was set.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+/* Based on SleepEx/test2 */
+
+const unsigned int ChildThreadWaitTime = 1000;
+const unsigned int InterruptTime = 500;
+
+#define TOLERANCE 10
+
+void RunTest(BOOL AlertThread);
+VOID PALAPI APCFunc(ULONG_PTR dwParam);
+DWORD PALAPI WaiterProc(LPVOID lpParameter);
+
+DWORD ThreadWaitDelta;
+
+int __cdecl main( int argc, char **argv )
+{
+
+ DWORD delta = 0;
+
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /*
+ On some platforms (e.g. FreeBSD 4.9) the first call to some synch objects
+ (such as conditions) involves some pthread internal initialization that
+ can make the first wait slighty longer, potentially going above the
+ acceptable delta for this test. Let's add a dummy wait to preinitialize
+ internal structures
+ */
+ Sleep(100);
+
+
+ /*
+ * Check that Queueing an APC in the middle of a wait does interrupt
+ * it, if it's in an alertable state.
+ */
+ RunTest(TRUE);
+ // Make sure that the wait returns in time greater than interrupt and less than
+ // wait timeout
+ if (
+ ((ThreadWaitDelta >= ChildThreadWaitTime) && (ThreadWaitDelta - ChildThreadWaitTime) > TOLERANCE)
+ || (( ThreadWaitDelta < InterruptTime) && (ThreadWaitDelta - InterruptTime) > TOLERANCE)
+ )
+ {
+ Fail("Expected thread to wait for %d ms (and get interrupted).\n"
+ "Interrupt Time: %d ms, ThreadWaitDelta %u\n",
+ ChildThreadWaitTime, InterruptTime, ThreadWaitDelta);
+ }
+
+ /*
+ * Check that Queueing an APC in the middle of a wait does NOT interrupt
+ * it, if it is not in an alertable state.
+ */
+ RunTest(FALSE);
+
+ // Make sure that time taken for thread to return from wait is more than interrupt
+ // and also not less than the complete child thread wait time
+
+ delta = ThreadWaitDelta - ChildThreadWaitTime;
+ if( (ThreadWaitDelta < ChildThreadWaitTime) && ( delta > TOLERANCE) )
+ {
+ Fail("Expected thread to wait for %d ms (and not get interrupted).\n"
+ "Interrupt Time: %d ms, ThreadWaitDelta %u\n",
+ ChildThreadWaitTime, InterruptTime, ThreadWaitDelta);
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+void RunTest(BOOL AlertThread)
+{
+ HANDLE hThread = 0;
+ DWORD dwThreadId = 0;
+ int ret;
+
+ hThread = CreateThread( NULL,
+ 0,
+ (LPTHREAD_START_ROUTINE)WaiterProc,
+ (LPVOID) AlertThread,
+ 0,
+ &dwThreadId);
+
+ if (hThread == NULL)
+ {
+ Fail("ERROR: Was not able to create the thread to test!\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+ Sleep(InterruptTime);
+
+ ret = QueueUserAPC(APCFunc, hThread, 0);
+ if (ret == 0)
+ {
+ Fail("QueueUserAPC failed! GetLastError returned %d\n",
+ GetLastError());
+ }
+
+ ret = WaitForSingleObject(hThread, INFINITE);
+ if (ret == WAIT_FAILED)
+ {
+ Fail("Unable to wait on child thread!\nGetLastError returned %d.\n",
+ GetLastError());
+ }
+}
+
+/* Function doesn't do anything, just needed to interrupt the wait*/
+VOID PALAPI APCFunc(ULONG_PTR dwParam)
+{
+}
+
+/* Entry Point for child thread. */
+DWORD PALAPI WaiterProc(LPVOID lpParameter)
+{
+ HANDLE Semaphore;
+ UINT64 OldTimeStamp;
+ UINT64 NewTimeStamp;
+ BOOL Alertable;
+ DWORD ret;
+
+ /* Create a semaphore that is not in the signalled state */
+ Semaphore = CreateSemaphoreW(NULL, 0, 1, NULL);
+
+ if (Semaphore == NULL)
+ {
+ Fail("Failed to create semaphore! GetLastError returned %d.\n",
+ GetLastError());
+ }
+
+ Alertable = (BOOL) lpParameter;
+
+ LARGE_INTEGER performanceFrequency;
+ if (!QueryPerformanceFrequency(&performanceFrequency))
+ {
+ Fail("Failed to query performance frequency!");
+ }
+
+ OldTimeStamp = GetHighPrecisionTimeStamp(performanceFrequency);
+
+ ret = WaitForMultipleObjectsEx(1, &Semaphore, FALSE, ChildThreadWaitTime,
+ Alertable);
+
+ NewTimeStamp = GetHighPrecisionTimeStamp(performanceFrequency);
+
+
+ if (Alertable && ret != WAIT_IO_COMPLETION)
+ {
+ Fail("Expected the interrupted wait to return WAIT_IO_COMPLETION.\n"
+ "Got %d\n", ret);
+ }
+ else if (!Alertable && ret != WAIT_TIMEOUT)
+ {
+ Fail("WaitForMultipleObjectsEx did not timeout.\n"
+ "Expected return of WAIT_TIMEOUT, got %d.\n", ret);
+ }
+
+ ThreadWaitDelta = NewTimeStamp - OldTimeStamp;
+
+ ret = CloseHandle(Semaphore);
+ if (!ret)
+ {
+ Fail("Unable to close handle to semaphore!\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+ return 0;
+}
+
+
diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/testinfo.dat b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/testinfo.dat
new file mode 100644
index 0000000000..e8e781a7f2
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = WaitForMultipleObjectsEx
+Name = Test #2 for WaitForMultipleObjectsEx
+TYPE = DEFAULT
+EXE1 = test2
+Description
+=Tests that a child thread in the middle of a
+=WaitForMultipleObjectsEx call will be interrupted by QueueUserAPC
+=if the alert flag was set.
diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/CMakeLists.txt
new file mode 100644
index 0000000000..645b86719d
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_waitformultipleobjectsex_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_waitformultipleobjectsex_test3 coreclrpal)
+
+target_link_libraries(paltest_waitformultipleobjectsex_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/test3.c b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/test3.c
new file mode 100644
index 0000000000..b78b0540dc
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/test3.c
@@ -0,0 +1,106 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test3.c
+**
+** Purpose: Tests that waiting on an open mutex will a return
+** WAIT_OBJECT_0. Does this by creating a child thread that
+** acquires the mutex, releases it, and exits.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+const int ChildThreadWaitTime = 1000;
+const int ParentDelayTime = 2000;
+
+DWORD PALAPI AcquiringProc(LPVOID lpParameter);
+
+int __cdecl main( int argc, char **argv)
+{
+ HANDLE Mutex;
+ HANDLE hThread = 0;
+ DWORD dwThreadId = 0;
+ int ret;
+
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ Mutex = CreateMutexW(NULL, FALSE, NULL);
+ if (Mutex == NULL)
+ {
+ Fail("Unable to create the mutex. GetLastError returned %d\n",
+ GetLastError());
+ }
+
+ hThread = CreateThread( NULL,
+ 0,
+ (LPTHREAD_START_ROUTINE)AcquiringProc,
+ (LPVOID) Mutex,
+ 0,
+ &dwThreadId);
+
+ if (hThread == NULL)
+ {
+ Fail("ERROR: Was not able to create the thread to test!\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+ Sleep(ParentDelayTime);
+
+ ret = WaitForMultipleObjectsEx(1, &Mutex, FALSE, INFINITE, FALSE);
+ if (ret != WAIT_OBJECT_0)
+ {
+ Fail("Expected WaitForMultipleObjectsEx to return WAIT_OBJECT_0\n"
+ "Got %d\n", ret);
+ }
+
+ if (!CloseHandle(Mutex))
+ {
+ Fail("CloseHandle on the mutex failed!\n");
+ }
+
+ if (!CloseHandle(hThread))
+ {
+ Fail("CloseHandle on the thread failed!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+/*
+ * Entry Point for child thread. Acquries a mutex, releases it, and exits.
+ */
+DWORD PALAPI AcquiringProc(LPVOID lpParameter)
+{
+ HANDLE Mutex;
+ DWORD ret;
+
+ Mutex = (HANDLE) lpParameter;
+
+ Sleep(ChildThreadWaitTime);
+
+ ret = WaitForSingleObject(Mutex, 0);
+ if (ret != WAIT_OBJECT_0)
+ {
+ Fail("Expected the WaitForSingleObject call on the mutex to succeed\n"
+ "Expected return of WAIT_OBJECT_0, got %d\n", ret);
+ }
+
+ ret = ReleaseMutex(Mutex);
+ if (!ret)
+ {
+ Fail("Unable to release mutex! GetLastError returned %d\n",
+ GetLastError());
+ }
+
+ return 0;
+}
diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/testinfo.dat b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/testinfo.dat
new file mode 100644
index 0000000000..991b93489d
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = WaitForMultipleObjectsEx
+Name = Test #3 for WaitForMultipleObjectsEx
+TYPE = DEFAULT
+EXE1 = test3
+Description
+=Tests that waiting on an open mutex will a return
+=WAIT_OBJECT_0. Does this by creating a child thread that
+=acquires the mutex, releases it, and exits.
diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/CMakeLists.txt
new file mode 100644
index 0000000000..3cd7f72b98
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_waitformultipleobjectsex_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_waitformultipleobjectsex_test4 coreclrpal)
+
+target_link_libraries(paltest_waitformultipleobjectsex_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/test4.c b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/test4.c
new file mode 100644
index 0000000000..15d0a386d1
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/test4.c
@@ -0,0 +1,101 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test4.c
+**
+** Purpose: Tests that waiting on an abandonded mutex will a return
+** WAIT_ABANDONED_0. Does this by creating a child thread that
+** acquires the mutex and exits.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+
+const int ChildThreadWaitTime = 1000;
+const int ParentDelayTime = 2000;
+
+DWORD PALAPI AbandoningProc(LPVOID lpParameter);
+
+int __cdecl main( int argc, char **argv )
+{
+ HANDLE Mutex;
+ HANDLE hThread = 0;
+ DWORD dwThreadId = 0;
+ int ret;
+
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ Mutex = CreateMutexW(NULL, FALSE, NULL);
+ if (Mutex == NULL)
+ {
+ Fail("Unable to create the mutex. GetLastError returned %d\n",
+ GetLastError());
+ }
+
+ hThread = CreateThread( NULL,
+ 0,
+ (LPTHREAD_START_ROUTINE)AbandoningProc,
+ (LPVOID) Mutex,
+ 0,
+ &dwThreadId);
+
+ if (hThread == NULL)
+ {
+ Fail("ERROR: Was not able to create the thread to test!\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+ Sleep(ParentDelayTime);
+
+ ret = WaitForMultipleObjectsEx(1, &Mutex, FALSE, INFINITE, FALSE);
+ if (ret != WAIT_ABANDONED_0)
+ {
+ Fail("Expected WaitForMultipleObjectsEx to return WAIT_ABANDONED_0\n"
+ "Got %d\n", ret);
+ }
+
+ ReleaseMutex(Mutex);
+ if (!CloseHandle(Mutex))
+ {
+ Fail("CloseHandle on the mutex failed!\n");
+ }
+
+ if (!CloseHandle(hThread))
+ {
+ Fail("CloseHandle on the thread failed!\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+/*
+ * Entry Point for child thread. Acquries a mutex and exit's without
+ * releasing it.
+ */
+DWORD PALAPI AbandoningProc(LPVOID lpParameter)
+{
+ HANDLE Mutex;
+ DWORD ret;
+
+ Mutex = (HANDLE) lpParameter;
+
+ Sleep(ChildThreadWaitTime);
+
+ ret = WaitForSingleObject(Mutex, 0);
+ if (ret != WAIT_OBJECT_0)
+ {
+ Fail("Expected the WaitForSingleObject call on the mutex to succeed\n"
+ "Expected return of WAIT_OBJECT_0, got %d\n", ret);
+ }
+
+ return 0;
+}
diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/testinfo.dat b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/testinfo.dat
new file mode 100644
index 0000000000..16f3468ac2
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = WaitForMultipleObjectsEx
+Name = Test #4 for WaitForMultipleObjectsEx
+TYPE = DEFAULT
+EXE1 = test4
+Description
+=Tests that waiting on an abandonded mutex will a return
+=WAIT_ABANDONED_0. Does this by creating a child thread that
+=acquires the mutex and exits.
diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/CMakeLists.txt
new file mode 100644
index 0000000000..50147e9bf3
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/CMakeLists.txt
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(TESTSOURCES
+ test5.c
+)
+
+add_executable(paltest_waitformultipleobjectsex_test5
+ ${TESTSOURCES}
+)
+
+add_dependencies(paltest_waitformultipleobjectsex_test5 coreclrpal)
+
+target_link_libraries(paltest_waitformultipleobjectsex_test5
+ pthread
+ m
+ coreclrpal
+)
+
+
+set(HELPERSOURCES
+ helper.c
+)
+
+add_executable(paltest_waitformultipleobjectsex_test5_helper
+ ${HELPERSOURCES}
+)
+
+add_dependencies(paltest_waitformultipleobjectsex_test5_helper coreclrpal)
+
+target_link_libraries(paltest_waitformultipleobjectsex_test5_helper
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/commonconsts.h b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/commonconsts.h
new file mode 100644
index 0000000000..b746616b58
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/commonconsts.h
@@ -0,0 +1,42 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: commonconsts.h
+**
+**
+**============================================================*/
+
+#ifndef _COMMONCONSTS_H_
+#define _COMMONCONSTS_H_
+
+#include <pal.h>
+
+const int TIMEOUT = 60 * 5 * 1000;
+
+char *szcHelperProcessStartEvName = "start";
+char *szcHelperProcessReadyEvName = "ready";
+char *szcHelperProcessFinishEvName = "finish";
+
+/* PEDANTIC and PEDANTIC0 is a helper macro that just grumps about any
+ * zero return codes in a generic way. with little typing */
+#define PEDANTIC(function, parameters) \
+{ \
+ if (! (function parameters) ) \
+ { \
+ Trace("%s: NonFatal failure of %s%s for reasons %u and %u\n", \
+ __FILE__, #function, #parameters, GetLastError(), errno); \
+ } \
+}
+#define PEDANTIC1(function, parameters) \
+{ \
+ if ( (function parameters) ) \
+ { \
+ Trace("%s: NonFatal failure of %s%s for reasons %u and %u\n", \
+ __FILE__, #function, #parameters, GetLastError(), errno); \
+ } \
+}
+
+#endif
diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/helper.c b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/helper.c
new file mode 100644
index 0000000000..274780a216
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/helper.c
@@ -0,0 +1,122 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: helper.c
+**
+** Purpose: This helper process sets up signals to communicate
+** with the test thread in the parent process, and let the test
+** thread signal this process when to exit.
+**
+**
+**============================================================*/
+
+#include "commonconsts.h"
+
+#include <palsuite.h>
+
+HANDLE hProcessStartEvent;
+HANDLE hProcessReadyEvent;
+HANDLE hProcessFinishEvent;
+HANDLE hProcessCleanupEvent;
+
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ BOOL success = TRUE; /* assume success */
+ DWORD dwRet;
+ DWORD dwProcessId;
+ char szEventName[MAX_LONGPATH];
+ PWCHAR uniString;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Open the event to let test thread tell us to get started. */
+ uniString = convert(szcHelperProcessStartEvName);
+ hProcessStartEvent = OpenEventW(EVENT_ALL_ACCESS, 0, uniString);
+ free(uniString);
+ if (!hProcessStartEvent)
+ {
+ Fail("helper.main: OpenEvent of '%S' failed (%u). "
+ "(the event should already exist!)\n",
+ szcHelperProcessStartEvName, GetLastError());
+ }
+
+ /* Wait for signal from test thread. */
+ dwRet = WaitForSingleObject(hProcessStartEvent, TIMEOUT);
+ if (dwRet != WAIT_OBJECT_0)
+ {
+ Fail("helper.main: WaitForSingleObject '%s' failed\n"
+ "LastError:(%u)\n", szcHelperProcessStartEvName, GetLastError());
+ }
+
+ dwProcessId = GetCurrentProcessId();
+
+ if ( 0 >= dwProcessId )
+ {
+ Fail ("helper.main: %s has invalid pid %d\n", argv[0], dwProcessId );
+ }
+
+ /* Open the event to tell test thread we are ready. */
+ if (_snprintf(szEventName, MAX_LONGPATH-1, "%s%d", szcHelperProcessReadyEvName, dwProcessId) < 0)
+ {
+ Fail ("helper.main: Insufficient event name string length for pid=%d\n", dwProcessId);
+ }
+
+ uniString = convert(szEventName);
+
+ hProcessReadyEvent = OpenEventW(EVENT_ALL_ACCESS, 0, uniString);
+ free(uniString);
+ if (!hProcessReadyEvent)
+ {
+ Fail("helper.main: OpenEvent of '%s' failed (%u). "
+ "(the event should already exist!)\n",
+ szEventName, GetLastError());
+ }
+
+ /* Open the event to let test thread tell us to exit. */
+ if (_snprintf(szEventName, MAX_LONGPATH-1, "%s%d", szcHelperProcessFinishEvName, dwProcessId) < 0)
+ {
+ Fail ("helper.main: Insufficient event name string length for pid=%d\n", dwProcessId);
+ }
+
+ uniString = convert(szEventName);
+
+ hProcessFinishEvent = OpenEventW(EVENT_ALL_ACCESS, 0, uniString);
+ free(uniString);
+ if (!hProcessFinishEvent)
+ {
+ Fail("helper.main: OpenEvent of '%s' failed LastError:(%u).\n",
+ szEventName, GetLastError());
+ }
+
+ /* Tell the test thread we are ready. */
+ if (!SetEvent(hProcessReadyEvent))
+ {
+ Fail("helper.main: SetEvent '%s' failed LastError:(%u)\n",
+ hProcessReadyEvent, GetLastError());
+ }
+
+ /* Wait for signal from test thread before exit. */
+ dwRet = WaitForSingleObject(hProcessFinishEvent, TIMEOUT);
+ if (WAIT_OBJECT_0 != dwRet)
+ {
+ Fail("helper.main: WaitForSingleObject '%s' failed pid=%d\n"
+ "LastError:(%u)\n",
+ szcHelperProcessFinishEvName, dwProcessId, GetLastError());
+ }
+
+ PEDANTIC(CloseHandle, (hProcessStartEvent));
+ PEDANTIC(CloseHandle, (hProcessReadyEvent));
+ PEDANTIC(CloseHandle, (hProcessFinishEvent));
+
+ PAL_Terminate();
+
+ return success ? PASS : FAIL;
+}
diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/test5.c b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/test5.c
new file mode 100644
index 0000000000..d19978c103
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/test5.c
@@ -0,0 +1,506 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test5.c
+**
+** Purpose: Test the functionality of simultaneously waiting
+** on multiple processes. Create the same number of helper
+** processes and helper threads.
+** Helper threads wait on helper processes to finish.
+** Helper processes wait on the event signal from test
+** thread before exit.
+** The test thread can wake up one helper
+** thread at a time by signaling the corresponding helper
+** process to finish.
+** The test thread can also wake up all helper threads at once
+** by signaling help process 0 to exit.
+**
+**
+**============================================================*/
+
+#define UNICODE
+
+#include "commonconsts.h"
+
+#include <palsuite.h>
+
+/* The maximum number of objects a thread can wait is MAXIMUM_WAIT_OBJECTS.
+ The last helper thread in this test case will wait on all helper processes
+ plus a thread finish event so the maximum number of helper processes
+ can be created in this test case is (MAXIMUM_WAIT_OBJECTS-1). */
+#define MAX_HELPER_PROCESS (MAXIMUM_WAIT_OBJECTS-1)
+
+int MaxNumHelperProcess = MAX_HELPER_PROCESS;
+
+/* indicate how the test thread wake up helper thread. */
+typedef enum _TestCaseType {
+ WakeUpOneThread, /* wake up one helper thread at a time. */
+ WakeUpAllThread /* wake up all helper threads at once */
+} TestCaseType;
+
+TestCaseType TestCase = WakeUpOneThread;
+
+/* When the test thread wakes up one thread at a time,
+ ThreadIndexOfThreadFinishEvent specifies the index of the thread that
+ should be waked up using hThreadFinishEvent instead of helper process. */
+DWORD ThreadIndexOfThreadFinishEvent = 0;
+
+struct helper_process_t
+{
+ PROCESS_INFORMATION pi;
+ HANDLE hProcessReadyEvent;
+ HANDLE hProcessFinishEvent;
+} helper_process[MAX_HELPER_PROCESS];
+
+HANDLE hProcessStartEvent;
+
+struct helper_thread_t
+{
+ HANDLE hThread;
+ DWORD dwThreadId;
+ HANDLE hThreadReadyEvent;
+ HANDLE hThreadFinishEvent;
+} helper_thread[MAX_HELPER_PROCESS];
+
+/*
+ * Entry Point for helper thread.
+ */
+DWORD PALAPI WaitForProcess(LPVOID lpParameter)
+{
+ DWORD index, i;
+ DWORD dwRet;
+ HANDLE handles[MAX_HELPER_PROCESS+1];
+
+ index = (DWORD) lpParameter;
+
+ /* The helper thread 0 will wait for helper process 0, helper thread 1 will
+ wait for helper process 0 and 1, helper thread 2 will wait for helper
+ process 0, 1, and 2, and so on ..., and the last helper thread will wait
+ on all helper processes.
+ Each helper thread also waits on hThreadFinishEvent so that
+ it can exit without waiting on any process to finish. */
+
+ for (i = 0; i <= index; i++)
+ {
+ handles[i] = helper_process[i].pi.hProcess;
+ }
+
+ handles[index+1] = helper_thread[index].hThreadFinishEvent;
+
+ if(!SetEvent(helper_thread[index].hThreadReadyEvent))
+ {
+ Fail("test5.WaitProcess: SetEvent of hThreadReadyEvent failed for thread %d. "
+ "GetLastError() returned %d.\n", index,
+ GetLastError());
+ }
+
+ dwRet = WaitForMultipleObjectsEx(index+2, &handles[0], FALSE, TIMEOUT, TRUE);
+ if (WakeUpAllThread == TestCase)
+ {
+ /* If the test thread signals helper process 0 to exit, all threads will be waked up,
+ and the return value must be (WAIT_OBJECT_0+0) because the handle of helper process 0
+ is in handle[0]. */
+ if (dwRet != (WAIT_OBJECT_0+0))
+ {
+ Fail("test5.WaitForProcess: invalid return value %d for WakupAllThread from WaitForMultipleObjectsEx for thread %d\n"
+ "LastError:(%u)\n",
+ dwRet, index,
+ GetLastError());
+ }
+ }
+ else if (WakeUpOneThread == TestCase)
+ {
+ /* If the test thread wakes up one helper thread at a time,
+ the return value must be either (WAIT_OBJECT_0+index) if the helper thread
+ wakes up because the corresponding help process exits,
+ or (index+1) if the helper thread wakes up because of hThreadReadyEvent. */
+ if ((index != ThreadIndexOfThreadFinishEvent && dwRet != (WAIT_OBJECT_0+index)) ||
+ (index == ThreadIndexOfThreadFinishEvent && dwRet != (index+1)))
+ {
+ Fail("test5.WaitForProcess: invalid return value %d for WakupOneThread from WaitForMultipleObjectsEx for thread %d\n"
+ "LastError:(%u)\n",
+ dwRet, index,
+ GetLastError());
+ }
+ }
+ else
+ {
+ Fail("Unknown TestCase %d\n", TestCase);
+ }
+ return 0;
+}
+
+/*
+ * Setup the helper processes and helper threads.
+ */
+void
+Setup()
+{
+
+ STARTUPINFO si;
+ DWORD dwRet;
+ int i;
+
+ char szEventName[MAX_PATH];
+ PWCHAR uniStringHelper;
+ PWCHAR uniString;
+
+ /* Create the event to start helper process after it was created. */
+ uniString = convert(szcHelperProcessStartEvName);
+ hProcessStartEvent = CreateEvent(NULL, TRUE, FALSE, uniString);
+ free(uniString);
+ if (!hProcessStartEvent)
+ {
+ Fail("test5.Setup: CreateEvent of '%s' failed. "
+ "GetLastError() returned %d.\n", szcHelperProcessStartEvName,
+ GetLastError());
+ }
+
+ /* Create the helper processes. */
+ ZeroMemory( &si, sizeof(si) );
+ si.cb = sizeof(si);
+ uniStringHelper = convert("helper");
+ for (i = 0; i < MaxNumHelperProcess; i++)
+ {
+ ZeroMemory( &helper_process[i].pi, sizeof(PROCESS_INFORMATION));
+
+ if(!CreateProcess( NULL, uniStringHelper, NULL, NULL,
+ FALSE, 0, NULL, NULL, &si, &helper_process[i].pi))
+ {
+ Fail("test5.Setup: CreateProcess failed to load executable for helper process %d. "
+ "GetLastError() returned %u.\n",
+ i, GetLastError());
+ }
+
+ /* Create the event to let helper process tell us it is ready. */
+ if (_snprintf(szEventName, MAX_PATH-1, "%s%d",
+ szcHelperProcessReadyEvName, helper_process[i].pi.dwProcessId) < 0)
+ {
+ Fail ("test5.Setup: Insufficient event name string length for %s\n", szcHelperProcessReadyEvName);
+ }
+
+ uniString = convert(szEventName);
+
+ helper_process[i].hProcessReadyEvent = CreateEvent(NULL, FALSE, FALSE, uniString);
+ free(uniString);
+ if (!helper_process[i].hProcessReadyEvent)
+ {
+ Fail("test5.Setup: CreateEvent of '%s' failed. "
+ "GetLastError() returned %d.\n", szEventName,
+ GetLastError());
+ }
+
+ /* Create the event to tell helper process to exit. */
+ if (_snprintf(szEventName, MAX_PATH-1, "%s%d",
+ szcHelperProcessFinishEvName, helper_process[i].pi.dwProcessId) < 0)
+ {
+ Fail ("test5.Setup: Insufficient event name string length for %s\n", szcHelperProcessFinishEvName);
+ }
+
+ uniString = convert(szEventName);
+
+ helper_process[i].hProcessFinishEvent = CreateEvent(NULL, TRUE, FALSE, uniString);
+ free(uniString);
+ if (!helper_process[i].hProcessFinishEvent)
+ {
+ Fail("test5.Setup: CreateEvent of '%s' failed. "
+ "GetLastError() returned %d.\n", szEventName,
+ GetLastError());
+ }
+
+ }
+ free(uniStringHelper);
+
+ /* Signal all helper processes to start. */
+ if (!SetEvent(hProcessStartEvent))
+ {
+ Fail("test5.Setup: SetEvent '%s' failed\n",
+ "LastError:(%u)\n",
+ szcHelperProcessStartEvName, GetLastError());
+ }
+
+ /* Wait for ready signals from all helper processes. */
+ for (i = 0; i < MaxNumHelperProcess; i++)
+ {
+ dwRet = WaitForSingleObject(helper_process[i].hProcessReadyEvent, TIMEOUT);
+ if (dwRet != WAIT_OBJECT_0)
+ {
+ Fail("test5.Setup: WaitForSingleObject %s failed for helper process %d\n"
+ "LastError:(%u)\n",
+ szcHelperProcessReadyEvName, i, GetLastError());
+ }
+ }
+
+ /* Create the same number of helper threads as helper processes. */
+ for (i = 0; i < MaxNumHelperProcess; i++)
+ {
+ /* Create the event to let helper thread tell us it is ready. */
+ helper_thread[i].hThreadReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (!helper_thread[i].hThreadReadyEvent)
+ {
+ Fail("test5.Setup: CreateEvent of hThreadReadyEvent failed for thread %d\n"
+ "LastError:(%u)\n", i, GetLastError());
+ }
+
+ /* Create the event to tell helper thread to exit without waiting for helper process. */
+ helper_thread[i].hThreadFinishEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (!helper_thread[i].hThreadFinishEvent)
+ {
+ Fail("test5.Setup: CreateEvent of hThreadFinishEvent failed for thread %d\n"
+ "LastError:(%u)\n", i, GetLastError());
+ }
+
+ /* Create the helper thread. */
+ helper_thread[i].hThread = CreateThread( NULL,
+ 0,
+ (LPTHREAD_START_ROUTINE)WaitForProcess,
+ (LPVOID)i,
+ 0,
+ &helper_thread[i].dwThreadId);
+ if (NULL == helper_thread[i].hThread)
+ {
+ Fail("test5.Setup: Unable to create the helper thread %d\n"
+ "LastError:(%u)\n", i, GetLastError());
+ }
+ }
+
+ /* Wait for ready signals from all helper threads. */
+ for (i = 0; i < MaxNumHelperProcess; i++)
+ {
+ dwRet = WaitForSingleObject(helper_thread[i].hThreadReadyEvent, TIMEOUT);
+ if (dwRet != WAIT_OBJECT_0)
+ {
+ Fail("test5.Setup: WaitForSingleObject hThreadReadyEvent for thread %d\n"
+ "LastError:(%u)\n", i, GetLastError());
+ }
+ }
+}
+
+/*
+ * Cleanup the helper processes and helper threads.
+ */
+DWORD
+Cleanup()
+{
+ DWORD dwExitCode;
+ DWORD dwRet;
+ int i;
+
+ /* Wait for all helper process to finish and close their handles
+ and associated events. */
+ for (i = 0; i < MaxNumHelperProcess; i++)
+ {
+
+ /* wait for the child process to complete */
+ dwRet = WaitForSingleObject ( helper_process[i].pi.hProcess, TIMEOUT );
+ if (WAIT_OBJECT_0 != dwRet)
+ {
+ Fail("test5.Cleanup: WaitForSingleObject hThreadReadyEvent failed for thread %d\n"
+ "LastError:(%u)\n", i, GetLastError());
+ }
+
+ /* check the exit code from the process */
+ if (!GetExitCodeProcess(helper_process[i].pi.hProcess, &dwExitCode))
+ {
+ Trace( "test5.Cleanup: GetExitCodeProcess %d call failed LastError:(%u)\n",
+ i, GetLastError());
+ dwExitCode = FAIL;
+ }
+ PEDANTIC(CloseHandle, (helper_process[i].pi.hThread));
+ PEDANTIC(CloseHandle, (helper_process[i].pi.hProcess));
+ PEDANTIC(CloseHandle, (helper_process[i].hProcessReadyEvent));
+ PEDANTIC(CloseHandle, (helper_process[i].hProcessFinishEvent));
+ }
+
+ /* Close all helper threads' handles */
+ for (i = 0; i < MaxNumHelperProcess; i++)
+ {
+ PEDANTIC(CloseHandle, (helper_thread[i].hThread));
+ PEDANTIC(CloseHandle, (helper_thread[i].hThreadReadyEvent));
+ PEDANTIC(CloseHandle, (helper_thread[i].hThreadFinishEvent));
+ }
+
+ /* Close all process start event. */
+ PEDANTIC(CloseHandle, (hProcessStartEvent));
+
+ return dwExitCode;
+}
+
+/*
+ * In this test case, the test thread will signal one helper
+ * process to exit at a time starting from the last helper
+ * process and then wait for the corresponding helper thread to exit.
+ * The ThreadIndexOfThreadFinishEvent specifies the index of the thread that
+ * should be waked up using hThreadFinishEvent instead of helper process.
+ */
+void
+TestWakeupOneThread()
+{
+ DWORD dwRet;
+ int i;
+
+ TestCase = WakeUpOneThread;
+
+ if (((LONG)ThreadIndexOfThreadFinishEvent) < 0 ||
+ ThreadIndexOfThreadFinishEvent >= MAX_HELPER_PROCESS)
+ Fail("test5.TestWaitOnOneThread: Invalid ThreadIndexOfThreadFinishEvent %d\n", ThreadIndexOfThreadFinishEvent);
+
+ /* Since helper thread 0 waits on helper process 0,
+ thread 1 waits on on process 0, and 1,
+ thread 2 waits on process 0, 1, and 2, and so on ...,
+ and the last helper thread will wait on all helper processes,
+ the helper thread can be waked up one at a time by
+ waking up the help process one at a time starting from the
+ last helper process. */
+ for (i = MaxNumHelperProcess-1; i >= 0; i--)
+ {
+ /* make sure the helper thread has not exited yet. */
+ dwRet = WaitForSingleObject(helper_thread[i].hThread, 0);
+ if (WAIT_TIMEOUT != dwRet)
+ {
+ Fail("test5.TestWaitOnOneThread: helper thread %d already exited %d\n", i);
+ }
+
+ /* Decide how to wakeup the helper thread:
+ using event or using helper process. */
+ if (i == ThreadIndexOfThreadFinishEvent)
+ {
+ if (!SetEvent(helper_thread[i].hThreadFinishEvent))
+ {
+ Fail("test5.TestWaitOnOneThread: SetEvent hThreadFinishEvent failed for thread %d\n",
+ "LastError:(%u)\n", i, GetLastError());
+ }
+ }
+ else
+ {
+ if (!SetEvent(helper_process[i].hProcessFinishEvent))
+ {
+ Fail("test5.TestWaitOnOneThread: SetEvent %s%d failed for helper process %d\n",
+ "LastError:(%u)\n",
+ szcHelperProcessFinishEvName, helper_process[i].pi.dwProcessId, i,
+ GetLastError());
+ }
+ }
+
+ dwRet = WaitForSingleObject(helper_thread[i].hThread, TIMEOUT);
+ if (WAIT_OBJECT_0 != dwRet)
+ {
+ Fail("test5.TestWaitOnOneThread: WaitForSingleObject helper thread %d"
+ "LastError:(%u)\n",
+ i, GetLastError());
+ }
+ }
+
+ /* Finally, need to wake up the helper process which the test thread
+ skips waking up in the last loop. */
+ if (!SetEvent(helper_process[ThreadIndexOfThreadFinishEvent].hProcessFinishEvent))
+ {
+ Fail("test5.TestWaitOnOneThread: SetEvent %s%d failed\n",
+ "LastError:(%u)\n",
+ szcHelperProcessFinishEvName, helper_process[ThreadIndexOfThreadFinishEvent].pi.dwProcessId,
+ GetLastError());
+ }
+}
+
+/*
+ * In this test case, the test thread will signal the helper
+ * process 0 to exit. Since all helper threads wait on process 0,
+ * all helper threads will wake up and exit, and the test thread
+ * will wait for all of them to exit.
+ */
+void
+TestWakeupAllThread()
+{
+ DWORD dwRet;
+ int i;
+
+ TestCase = WakeUpAllThread;
+
+ /* make sure none of the helper thread exits. */
+ for (i = 0; i < MaxNumHelperProcess; i++)
+ {
+ dwRet = WaitForSingleObject(helper_thread[i].hThread, 0);
+ if (WAIT_TIMEOUT != dwRet)
+ {
+ Fail("test5.TestWaitOnAllThread: helper thread %d already exited %d\n", i);
+ }
+ }
+
+ /* Signal helper process 0 to exit. */
+ if (!SetEvent(helper_process[0].hProcessFinishEvent))
+ {
+ Fail("test5.TestWaitOnAllThread: SetEvent %s%d failed\n",
+ "LastError:(%u)\n",
+ szcHelperProcessFinishEvName, helper_process[0].pi.dwProcessId,
+ GetLastError());
+ }
+
+ /* Wait for all helper threads to exit. */
+ for (i = 0; i < MaxNumHelperProcess; i++)
+ {
+
+ dwRet = WaitForSingleObject(helper_thread[i].hThread, TIMEOUT);
+ if (WAIT_OBJECT_0 != dwRet)
+ {
+ Fail("test5.TestWaitOnAllThread: WaitForSingleObject failed for helper thread %d\n"
+ "LastError:(%u)\n",
+ i, GetLastError());
+ }
+ }
+
+ /* Signal the rest of helper processes to exit. */
+ for (i = 1; i < MaxNumHelperProcess; i++)
+ {
+ if (!SetEvent(helper_process[i].hProcessFinishEvent))
+ {
+ Fail("test5.TestWaitOnAllThread: SetEvent %s%d failed\n",
+ "LastError:(%u)\n",
+ szcHelperProcessFinishEvName, helper_process[i].pi.dwProcessId,
+ GetLastError());
+ }
+ }
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ DWORD dwExitCode;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ switch (argc)
+ {
+ case 1:
+ MaxNumHelperProcess = MAX_HELPER_PROCESS;
+ break;
+ case 2:
+ MaxNumHelperProcess = atol(argv[1]);
+ break;
+ default:
+ Fail("Invalid number of arguments\n");
+ }
+
+ if (MaxNumHelperProcess < 1 ||
+ MaxNumHelperProcess > MAX_HELPER_PROCESS)
+ Fail("test5.main: Invalid MaxNumHelperProcess %d\n", MaxNumHelperProcess);
+
+ Setup();
+ ThreadIndexOfThreadFinishEvent = 3;
+ TestWakeupOneThread();
+ dwExitCode = Cleanup();
+
+ if (PASS == dwExitCode)
+ {
+ Setup();
+ TestWakeupAllThread();
+ dwExitCode = Cleanup();
+ }
+
+ PAL_TerminateEx(dwExitCode);
+ return dwExitCode;
+}
diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/testinfo.dat b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/testinfo.dat
new file mode 100644
index 0000000000..5efc75f77e
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/testinfo.dat
@@ -0,0 +1,18 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = WaitForMultipleObjectsEx
+Name = Check simultaneously waiting on multiple processes.
+TYPE = DEFAULT
+EXE1 = test5
+EXE2 = helper
+Description
+= Create a number of helper processes and helper threads.
+= Helper threads wait on helper processes to finish.
+= Helper processes wait on the event signal from test
+= thread before exit. The test thread then selectively
+= signals helper process to finish and then wait on the
+= selected helper thread to finish.
diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/CMakeLists.txt
new file mode 100644
index 0000000000..ce75cadbff
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/CMakeLists.txt
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(TESTSOURCES
+ test6.c
+)
+
+add_executable(paltest_waitformultipleobjectsex_test6
+ ${TESTSOURCES}
+)
+
+add_dependencies(paltest_waitformultipleobjectsex_test6 coreclrpal)
+
+target_link_libraries(paltest_waitformultipleobjectsex_test6
+ pthread
+ m
+ coreclrpal
+)
+
+
+set(HELPERSOURCES
+ child6.c
+)
+
+add_executable(paltest_waitformultipleobjectsex_test6_child
+ ${HELPERSOURCES}
+)
+
+add_dependencies(paltest_waitformultipleobjectsex_test6_child coreclrpal)
+
+target_link_libraries(paltest_waitformultipleobjectsex_test6_child
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/child6.c b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/child6.c
new file mode 100644
index 0000000000..1a95815ddf
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/child6.c
@@ -0,0 +1,211 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: child6.c
+**
+** Purpose: Test for WaitForMultipleObjectsEx in multiple
+** scenarios - child process
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+ int i, iRet;
+ BOOL bRet;
+ BOOL bNamedEvent = 0;
+ BOOL bMutex = 0;
+ BOOL bMutexAndNamedEvent = 0;
+ BOOL bSemaphore = 0;
+ DWORD dwRet;
+ HANDLE hNamedEvent;
+ HANDLE hMutex;
+ char szTestName[256];
+ WCHAR wszTestName[256] = { 0 };
+ char szEventName[128] = { 0 };
+ char szMutexName[128] = { 0 };
+ char szSemName[128] = { 0 };
+ WCHAR wszEventName[128];
+ WCHAR wszMutexName[128];
+ WCHAR wszSemName[128];
+ DWORD iExitCode = 0;
+ HANDLE hSemaphore;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ Trace("[child] Starting\n");
+
+ for (i=1; i<argc; i++)
+ {
+ if (0 == strcmp(argv[i],"-event"))
+ {
+ bNamedEvent = 1;
+ }
+ else if (0 == strcmp(argv[i],"-mutex"))
+ {
+ bMutex = 1;
+ }
+ else if (0 == strcmp(argv[i],"-mutex_and_named_event"))
+ {
+ bMutexAndNamedEvent = 1;
+ }
+ else if (0 == strcmp(argv[i],"-semaphore"))
+ {
+ bSemaphore = 1;
+ }
+ else if (0 == strcmp(argv[i],"-exitcode") && i < argc-1 )
+ {
+ i++;
+ iExitCode = atoi(argv[i]);
+ Trace("[child] My exit code is %d\n", iExitCode);
+ }
+
+ else if ('-' != *argv[i])
+ {
+ strncpy(szTestName, argv[i], 256);
+ szTestName[255] = 0;
+ iRet = MultiByteToWideChar(CP_ACP, 0, szTestName, strlen(szTestName)+1, wszTestName, 256);
+ if (0 == iRet)
+ {
+ Fail("Failed to convert test string\n");
+ }
+ }
+ }
+
+ _snprintf(szEventName, 128, "%s_Event", szTestName);
+ szEventName[127] = 0;
+ _snprintf(szMutexName, 128, "%s_Mutex", szTestName);
+ szMutexName[127] = 0;
+ _snprintf(szSemName, 128, "%s_Semaphore", szTestName);
+ szSemName[127] = 0;
+
+ iRet = MultiByteToWideChar(CP_ACP, 0, szEventName, strlen(szEventName)+1, wszEventName, 128);
+ iRet &= MultiByteToWideChar(CP_ACP, 0, szMutexName, strlen(szMutexName)+1, wszMutexName, 128);
+ iRet &= MultiByteToWideChar(CP_ACP, 0, szSemName, strlen(szSemName)+1, wszSemName, 128);
+ if (0 == iRet)
+ {
+ Fail("[child] Failed to convert strings\n");
+ }
+
+ Trace("[child] TestName=%s Event: %S, Mutex: %S, Semaphore = %S\n",
+ szTestName, wszEventName, wszMutexName, wszSemName);
+
+ hNamedEvent = OpenEventW(0, FALSE, wszEventName);
+ if (NULL == hNamedEvent)
+ {
+ Fail("[child] OpenEventW failed [szEventName=%s GetLastError()=%u]\n",
+ szEventName, GetLastError());
+ }
+ hMutex = OpenMutexW(0, FALSE, wszMutexName);
+ if (NULL == hMutex)
+ {
+ Fail("[child] OpenMutexW failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+ hSemaphore = CreateSemaphoreW(NULL, 0, 256, wszSemName);
+ if (NULL == hSemaphore)
+ {
+ Fail("[child] CreateSemaphore failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+
+
+ if (bMutex)
+ {
+ Trace("[child] Going to wait on mutex %s\n", szMutexName);
+ dwRet = WaitForSingleObject(hMutex, INFINITE);
+ if (WAIT_FAILED == dwRet)
+ {
+ Fail("[child] WaitForMultipleObjects failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+
+ Trace("[child] Setting event %s\n", szEventName);
+ bRet = SetEvent(hNamedEvent);
+ if (FALSE == bRet)
+ {
+ Fail("[child] SetEvent failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+
+ // mutex will be abandoned
+ }
+ else if (bMutexAndNamedEvent)
+ {
+ dwRet = WaitForSingleObject(hMutex, INFINITE);
+ if (WAIT_FAILED == dwRet)
+ {
+ Fail("[child] WaitForMultipleObjects failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+
+ Sleep(2000);
+
+ bRet = ReleaseMutex(hMutex);
+ if (FALSE == bRet)
+ {
+ Fail("[child] ReleaseMutex failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+
+ Sleep(1000);
+
+ bRet = SetEvent(hNamedEvent);
+ if (FALSE == bRet)
+ {
+ Fail("[child] SetEvent failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+ }
+ else if (bSemaphore)
+ {
+ LONG lPrevCount = 42;
+
+
+ Trace("[child] Going to wait on event %s\n", szEventName);
+ dwRet = WaitForSingleObject(hNamedEvent, INFINITE);
+ if (WAIT_FAILED == dwRet)
+ {
+ Fail("[child] WaitForMultipleObjects failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+
+ Trace("[child] Releasing semaphore %s\n", szSemName);
+ bRet = ReleaseSemaphore(hSemaphore, 10, &lPrevCount);
+ if (FALSE == bRet)
+ {
+ Fail("ReleaseMutex failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+ if (0 != lPrevCount)
+ {
+ Fail("Previous count from semaphore=%d, expected 0\n", lPrevCount);
+ }
+ }
+ else if (bNamedEvent)
+ {
+ Sleep(1000);
+
+ bRet = SetEvent(hNamedEvent);
+ if (FALSE == bRet)
+ {
+ Fail("[child] SetEvent failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+ }
+
+ Sleep(1000);
+
+ Trace("[child] Done\n");
+
+ PAL_TerminateEx(iExitCode);
+ return iExitCode;
+}
diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/test6.c b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/test6.c
new file mode 100644
index 0000000000..399d2c3bff
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/test6.c
@@ -0,0 +1,709 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test6.c
+**
+** Purpose: Test for WaitForMultipleObjectsEx in multiple
+** scenarios
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+#define MAX_COUNT 10000
+#define MAX_THREADS 256
+
+BOOL g_bMutex = 0;
+BOOL g_bEvent = 0;
+BOOL g_bNamedEvent = 0;
+BOOL g_bSemaphore = 0;
+BOOL g_bProcess = 0;
+BOOL g_bLocalWaitAll = 0;
+BOOL g_bRemoteWaitAll = 0;
+BOOL g_bRandom = 0;
+
+int iCount = 1;
+int iThreads = 1;
+HANDLE hThreads[MAX_THREADS];
+
+#ifndef MIN
+#define MIN(a,b) (((a)<(b)) ? (a) : (b))
+#endif
+
+DWORD PALAPI EventTestThread(PVOID pArg)
+{
+ BOOL bRet;
+ DWORD dwRet;
+ HANDLE hEvent[2];
+ HANDLE (*prgHandles)[] = (HANDLE (*)[])pArg;
+
+ Trace("[EventTestThread] Starting\n");
+
+ bRet = DuplicateHandle(GetCurrentProcess(), (*prgHandles)[0], GetCurrentProcess(),
+ &hEvent[0], 0, FALSE, DUPLICATE_SAME_ACCESS);
+ bRet &= DuplicateHandle(GetCurrentProcess(), (*prgHandles)[1], GetCurrentProcess(),
+ &hEvent[1], 0, FALSE, DUPLICATE_SAME_ACCESS);
+ if (FALSE == bRet)
+ {
+ Fail("[EventTestThread] Failed to duplicate handles\n");
+ }
+
+ Sleep(1000);
+ bRet = SetEvent(hEvent[1]);
+ if (FALSE == bRet)
+ {
+ Fail("SetEvent failed\n");
+ Fail("[EventTestThread] SetEvent failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+
+ dwRet = WaitForSingleObject(hEvent[1], INFINITE);
+ if (WAIT_FAILED == dwRet)
+ {
+ Fail("[EventTestThread] WaitForMultipleObjects failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+
+ Sleep(1000);
+ bRet = SetEvent(hEvent[0]);
+ if (FALSE == bRet)
+ {
+ Fail("[EventTestThread] SetEvent failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+
+ Sleep(1000);
+ bRet = SetEvent(hEvent[1]);
+ if (FALSE == bRet)
+ {
+ Fail("[EventTestThread] SetEvent failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+
+ CloseHandle(hEvent[0]);
+ CloseHandle(hEvent[1]);
+
+ Trace("[EventTestThread] Done\n");
+ return 0;
+}
+
+DWORD PALAPI MutexTestThread(PVOID pArg)
+{
+ BOOL bRet;
+ DWORD dwRet;
+ HANDLE hMutex;
+
+ Trace("[MutexTestThread] Starting\n");
+
+ bRet = DuplicateHandle(GetCurrentProcess(), (HANDLE)pArg, GetCurrentProcess(), &hMutex,
+ 0, FALSE, DUPLICATE_SAME_ACCESS);
+ if (FALSE == bRet)
+ {
+ Fail("[EventTestThread] DuplicateHandle failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+
+ dwRet = WaitForSingleObject(hMutex, INFINITE);
+ if (WAIT_FAILED == dwRet)
+ {
+ Fail("[EventTestThread] WaitForMultipleObjects failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+
+ Sleep(1000);
+ CloseHandle(hMutex);
+
+ Trace("[MutexTestThread] Done\n");
+
+ return 0;
+}
+
+DWORD PALAPI TestThread(PVOID pArg)
+{
+ BOOL bRet;
+ DWORD dwRet;
+ PROCESS_INFORMATION pi;
+ STARTUPINFO si;
+ HANDLE hNamedEvent;
+ HANDLE hEvent[2] = { 0, 0 };
+ HANDLE hMutex = 0;
+ HANDLE hSemaphore = 0;
+ HANDLE hObjs[2];
+ DWORD dwThreadNum;
+ DWORD dwSlaveThreadTid = 0;
+ HANDLE hThread;
+ int i, iCnt, iRet;
+ char szTestName[128];
+ char szCmd[128];
+ char szEventName[128] = { 0 };
+ char szMutexName[128] = { 0 };
+ char szSemName[128] = { 0 };
+ WCHAR wszEventName[128] = { 0 };
+ WCHAR wszMutexName[128] = { 0 };
+ WCHAR wszSemName[128] = { 0 };
+ BOOL bMutex = g_bMutex;
+ BOOL bEvent = g_bEvent;
+ BOOL bNamedEvent = g_bNamedEvent;
+ BOOL bSemaphore = g_bSemaphore;
+ BOOL bProcess = g_bProcess;
+ BOOL bLocalWaitAll = g_bLocalWaitAll;
+ BOOL bRemoteWaitAll = g_bRemoteWaitAll;
+ int iDesiredExitCode;
+
+ dwThreadNum = (DWORD)pArg;
+
+ _snprintf (szTestName, 128, "Test6_%u", dwThreadNum);
+ szTestName[127] = 0;
+
+ _snprintf(szEventName, 128, "%s_Event", szTestName);
+ szEventName[127] = 0;
+ _snprintf(szMutexName, 128, "%s_Mutex", szTestName);
+ szMutexName[127] = 0;
+ _snprintf(szSemName, 128, "%s_Semaphore", szTestName);
+ szSemName[127] = 0;
+
+ iRet = MultiByteToWideChar(CP_ACP, 0, szEventName, strlen(szEventName)+1, wszEventName, 128);
+ iRet &= MultiByteToWideChar(CP_ACP, 0, szMutexName, strlen(szMutexName)+1, wszMutexName, 128);
+ iRet &= MultiByteToWideChar(CP_ACP, 0, szSemName, strlen(szSemName)+1, wszSemName, 128);
+
+ if (0 == iRet)
+ {
+ Fail("[TestThread] Failed to convert strings\n");
+ }
+
+ Trace("[TestThread] TestName=%s Event: %S, Mutex: %S, Semaphore = %S\n",
+ szTestName, wszEventName, wszMutexName, wszSemName);
+
+ hEvent[0] = CreateEventA(NULL, FALSE, FALSE, NULL);
+ hEvent[1] = CreateEventA(NULL, FALSE, FALSE, NULL);
+
+ hNamedEvent = CreateEventW(NULL, FALSE, FALSE, wszEventName);
+ hMutex = CreateMutexW(NULL, FALSE, wszMutexName);
+ hSemaphore = CreateSemaphoreW(NULL, 0, 256, wszSemName);
+
+ if (NULL == hEvent[0] || NULL == hEvent[1] || NULL == hMutex ||
+ NULL == hNamedEvent || NULL == hSemaphore)
+ {
+ Fail("[TestThread] Failed to create objects "
+ "[hNamedEvent=%p hMutex=%p hSemaphore=%p]\n",
+ (VOID*)hNamedEvent, (VOID*)hMutex, (VOID*)hSemaphore);
+ }
+
+ for (iCnt=0; iCnt<iCount; iCnt++)
+ {
+ if (g_bRandom)
+ {
+ int iRnd;
+
+ bMutex = 0;
+ bEvent = 0;
+ bNamedEvent = 0;
+ bSemaphore = 0;
+ bProcess = 0;
+ bLocalWaitAll = 0;
+ bRemoteWaitAll = 0;
+
+ iRnd = rand() % 7;
+ switch(iRnd)
+ {
+ case 0:
+ bMutex = 1;
+ break;
+ case 1:
+ bEvent = 1;
+ break;
+ case 2:
+ bNamedEvent = 1;
+ break;
+ case 3:
+ bSemaphore = 1;
+ break;
+ case 4:
+ bProcess = 1;
+ break;
+ case 5:
+ bLocalWaitAll = 1;
+ break;
+ case 6:
+ bRemoteWaitAll = 1;
+ break;
+ }
+ }
+
+ if (bEvent)
+ {
+ Trace("======================================================================\n");
+ Trace("Local unnamed event test\n");
+ Trace("----------------------------------------\n");
+ hThread = CreateThread(NULL, 0, EventTestThread, (PVOID)hEvent, 0, &dwSlaveThreadTid);
+ if (NULL == hThread)
+ {
+ Fail("Failed to create thread\n");
+ }
+
+ hObjs[0] = hEvent[0];
+ dwRet = WaitForMultipleObjects(1, hObjs, FALSE, INFINITE);
+ if (WAIT_FAILED == dwRet)
+ {
+ Fail("WaitForMultipleObjects failed\n");
+ }
+
+ hObjs[0] = hThread;
+ dwRet = WaitForMultipleObjects(1, hObjs, FALSE, INFINITE);
+ if (WAIT_FAILED == dwRet)
+ {
+ Fail("WaitForMultipleObjects failed\n");
+ }
+
+ CloseHandle(hThread);
+ Trace("Local unnamed event test done \n");
+ Trace("======================================================================\n");
+ }
+
+ if (bMutex)
+ {
+ Trace("======================================================================\n");
+ Trace("Mutex with remote thread awakening test\n");
+ Trace("----------------------------------------\n");
+
+ hThread = CreateThread(NULL, 0, MutexTestThread, (PVOID)hMutex, 0, &dwSlaveThreadTid);
+ if (NULL == hThread)
+ {
+ Fail("Failed to create thread\n");
+ }
+
+ Sleep(1000);
+
+ hObjs[0] = hMutex;
+
+ for (i=0;i<10;i++)
+ {
+ dwRet = WaitForMultipleObjects(1, hObjs, FALSE, INFINITE);
+ if (WAIT_FAILED == dwRet)
+ {
+ Fail("WaitForMultipleObjects failed [dwRet=%x GetLastError()=%d\n",
+ dwRet, GetLastError());
+ }
+ }
+
+ hObjs[0] = hThread;
+ dwRet = WaitForMultipleObjects(1, hObjs, FALSE, INFINITE);
+ if (WAIT_FAILED == dwRet)
+ {
+ Fail("WaitForMultipleObjects failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+
+ for (i=0;i<10;i++)
+ {
+ bRet = ReleaseMutex(hMutex);
+ if (FALSE == bRet)
+ {
+ Fail("ReleaseMutex failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+ }
+
+ CloseHandle(hThread);
+ Trace("Mutex with remote thread awakening test done\n");
+ Trace("======================================================================\n");
+ }
+
+ if (bNamedEvent)
+ {
+ Trace("======================================================================\n");
+ Trace("Named event with remote thread awakening test\n");
+ Trace("----------------------------------------\n");
+
+ ZeroMemory ( &si, sizeof(si) );
+ si.cb = sizeof(si);
+ ZeroMemory ( &pi, sizeof(pi) );
+
+ _snprintf (szCmd, 128, "child6 -event %s", szTestName);
+ szCmd[127] = 0;
+
+ bRet = CreateProcessA(NULL, szCmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
+ if (FALSE == bRet)
+ {
+ Fail("CreateProcess failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+
+ hObjs[0] = pi.hProcess;
+ hObjs[1] = hNamedEvent;
+
+ dwRet = WaitForMultipleObjects(2, hObjs, FALSE, INFINITE);
+ if (1 != dwRet)
+ {
+ Fail("WaitForMultipleObjects failed [dwRet=%u GetLastError()=%u]\n",
+ dwRet, GetLastError());
+ }
+
+ dwRet = WaitForSingleObject(pi.hProcess, INFINITE);
+ if (WAIT_FAILED == dwRet)
+ {
+ Fail("WaitForMultipleObjects failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+ Trace("Named event with remote thread awakening test done\n");
+ Trace("======================================================================\n");
+ }
+
+ if (bSemaphore)
+ {
+ Trace("======================================================================\n");
+ Trace("Semaphore with remote thread awakening test\n");
+ Trace("----------------------------------------\n");
+
+ ZeroMemory ( &si, sizeof(si) );
+ si.cb = sizeof(si);
+ ZeroMemory ( &pi, sizeof(pi) );
+
+ _snprintf (szCmd, 128, "child6 -semaphore %s", szTestName);
+ szCmd[127] = 0;
+
+ bRet = CreateProcessA(NULL, szCmd, NULL, NULL, FALSE,
+ 0, NULL, NULL, &si, &pi);
+ if (FALSE == bRet)
+ {
+ Fail("CreateProcessA failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+
+ Trace("Setting event %s\n", szEventName);
+ bRet = SetEvent(hNamedEvent);
+ if (FALSE == bRet)
+ {
+ Fail("[child] SetEvent failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+
+ Trace("Going to wait on semaphore %s\n", szSemName);
+
+
+ hObjs[0] = pi.hProcess;
+ hObjs[0] = hEvent[0];
+ hObjs[1] = hSemaphore;
+ for (i=0;i<10;i++)
+ {
+ dwRet = WaitForMultipleObjects(2, hObjs, FALSE, INFINITE);
+ if (1 != dwRet)
+ {
+ Trace("WaitForMultipleObjects failed [tid=%u dwRet=%u GetLastError()=%u]\n",
+ GetCurrentThreadId(), dwRet, GetLastError());
+ DebugBreak();
+ }
+ }
+
+ dwRet = WaitForSingleObject(pi.hProcess, INFINITE);
+ if (WAIT_FAILED == dwRet)
+ {
+ Fail("WaitForMultipleObjects failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+ Trace("Semaphore with remote thread awakening test done\n");
+ Trace("======================================================================\n");
+ }
+
+ if (bProcess)
+ {
+ DWORD dwExitCode;
+
+ Trace("======================================================================\n");
+ Trace("Process wait test\n");
+ Trace("----------------------------------------\n");
+
+ iDesiredExitCode = rand() % 0xFF;
+
+ ZeroMemory ( &si, sizeof(si) );
+ si.cb = sizeof(si);
+ ZeroMemory ( &pi, sizeof(pi) );
+
+ _snprintf (szCmd, 128, "child6 -mutex %s -exitcode %d", szTestName, iDesiredExitCode);
+ szCmd[127] = 0;
+
+ bRet = CreateProcessA(NULL, szCmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
+ if (FALSE == bRet)
+ {
+ Fail("CreateProcess failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+
+ Trace("Going to wait on event %s\n", szEventName);
+ dwRet = WaitForSingleObject(hNamedEvent, INFINITE);
+ if (WAIT_FAILED == dwRet)
+ {
+ Fail("WaitForMultipleObjects failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+
+ hObjs[0] = hEvent[0]; // dummy, this is a local event
+ hObjs[1] = hMutex;
+
+ dwRet = WaitForMultipleObjects(2, hObjs, FALSE, INFINITE);
+ if (WAIT_FAILED == dwRet)
+ {
+ Fail("WaitForMultipleObjects failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+ if (1 == dwRet || (1 + WAIT_ABANDONED_0) == dwRet)
+ {
+ bRet = ReleaseMutex(hMutex);
+ if (FALSE == bRet)
+ {
+ Fail("ReleaseMutex failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+ }
+
+ dwRet = WaitForSingleObject(pi.hProcess, INFINITE);
+ if (WAIT_FAILED == dwRet)
+ {
+ Fail("WaitForMultipleObjects failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+
+ if (!GetExitCodeProcess(pi.hProcess, &dwExitCode))
+ {
+ Trace("GetExitCodeProcess call failed LastError:(%u)\n",
+ GetLastError());
+ dwExitCode = FAIL;
+ }
+
+ if (iDesiredExitCode != dwExitCode)
+ {
+ Fail("Wrong return code: %u [%d]\n", dwExitCode, iDesiredExitCode);
+ }
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ Trace("Process wait test done\n");
+ Trace("======================================================================\n");
+ }
+
+ if (bLocalWaitAll)
+ {
+ Trace("======================================================================\n");
+ Trace("WaitAll with local thread awakening test\n");
+ Trace("----------------------------------------\n");
+
+ hThread = CreateThread(NULL, 0, EventTestThread, (PVOID)hEvent, 0, &dwSlaveThreadTid);
+ if (NULL == hThread)
+ {
+ Fail("CreateThread failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+
+ dwRet = WaitForMultipleObjects(2, hEvent, TRUE, INFINITE);
+ if (WAIT_FAILED == dwRet)
+ {
+ Fail("WaitForMultipleObjects failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+
+ hObjs[0] = hThread;
+ dwRet = WaitForMultipleObjects(1, hObjs, FALSE, INFINITE);
+ if (WAIT_FAILED == dwRet)
+ {
+ Fail("WaitForMultipleObjects failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+
+ CloseHandle(hThread);
+ Trace("WaitAll with local thread awakening test done\n");
+ Trace("======================================================================\n");
+ }
+
+ if (bRemoteWaitAll)
+ {
+ Trace("======================================================================\n");
+ Trace("WaitAll with remote thread awakening test\n");
+ Trace("----------------------------------------\n");
+
+ ZeroMemory ( &si, sizeof(si) );
+ si.cb = sizeof(si);
+ ZeroMemory ( &pi, sizeof(pi) );
+
+ _snprintf (szCmd, 128, "child6 -mutex_and_named_event %s", szTestName);
+ szCmd[127] = 0;
+
+ bRet = CreateProcessA(NULL, szCmd, NULL, NULL, FALSE,
+ 0, NULL, NULL, &si, &pi);
+ if (FALSE == bRet)
+ {
+ Fail("CreateProcess failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+
+ Sleep(1000);
+
+ hObjs[0] = hMutex;
+ hObjs[1] = hNamedEvent;
+
+ dwRet = WaitForMultipleObjects(2, hObjs, TRUE, INFINITE);
+ if (WAIT_FAILED == dwRet)
+ {
+ Fail("WaitForMultipleObjects failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+
+ bRet = ReleaseMutex(hMutex);
+ if (FALSE == bRet)
+ {
+ Fail("ReleaseMutex failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+
+ dwRet = WaitForSingleObject(pi.hProcess, INFINITE);
+ if (WAIT_FAILED == dwRet)
+ {
+ Fail("WaitForMultipleObjects failed [GetLastError()=%u]\n",
+ GetLastError());
+ }
+
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ Trace("WaitAll with remote thread awakening test done\n");
+ Trace("======================================================================\n");
+ }
+ }
+
+ return 0;
+}
+
+int __cdecl main(int argc, char **argv)
+{
+ DWORD dwRet;
+ DWORD dwSlaveThreadTid = 0;
+ int i, iCnt;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ srand(time(NULL) * GetCurrentProcessId());
+
+ if (argc == 1)
+ {
+ g_bMutex = 1;
+ g_bEvent = 1;
+ g_bNamedEvent = 1;
+ g_bSemaphore = 1;
+ g_bProcess = 1;
+ g_bLocalWaitAll = 1;
+ g_bRemoteWaitAll = 1;
+ }
+ else
+ {
+ for (i=1;i<argc;i++)
+ {
+ if (0 == strcmp(argv[i], "-mutex"))
+ {
+ g_bMutex = 1;
+ }
+ else if (0 == strcmp(argv[i], "-event"))
+ {
+ g_bEvent = 1;
+ }
+ else if (0 == strcmp(argv[i], "-namedevent"))
+ {
+ g_bNamedEvent = 1;
+ }
+ else if (0 == strcmp(argv[i], "-semaphore"))
+ {
+ g_bSemaphore = 1;
+ }
+ else if (0 == strcmp(argv[i], "-process"))
+ {
+ g_bProcess = 1;
+ }
+ else if (0 == strcmp(argv[i], "-localwaitall"))
+ {
+ g_bLocalWaitAll = 1;
+ }
+ else if (0 == strcmp(argv[i], "-remotewaitall"))
+ {
+ g_bRemoteWaitAll = 1;
+ }
+ else if (0 == strcmp(argv[i], "-all"))
+ {
+ g_bMutex = 1;
+ g_bEvent = 1;
+ g_bNamedEvent = 1;
+ g_bSemaphore = 1;
+ g_bProcess = 1;
+ g_bLocalWaitAll = 1;
+ g_bRemoteWaitAll = 1;
+ }
+ else if (0 == strcmp(argv[i], "-random"))
+ {
+ g_bRandom = 1;
+ }
+ else if ((0 == strcmp(argv[i], "-count")) && (argc > i+1))
+ {
+ i++;
+ iCnt = atoi(argv[i]);
+ if (iCnt > 0 && iCnt < MAX_COUNT)
+ {
+ iCount = iCnt;
+ }
+ }
+ else if ((0 == strcmp(argv[i], "-threads")) && (argc > i+1))
+ {
+ i++;
+ iCnt = atoi(argv[i]);
+ if (iCnt > 0 && iCnt <= MAX_THREADS)
+ {
+ iThreads = iCnt;
+ }
+ }
+ else
+ {
+ Trace("Unknown option %s ignored\n", argv[i]);
+ }
+ }
+ }
+
+
+ iCnt = 0;
+ for (i=0;i<iThreads;i++)
+ {
+ hThreads[iCnt] = CreateThread(NULL, 0, TestThread, (VOID*)iCnt, 0, &dwSlaveThreadTid);
+ if (NULL == hThreads[iCnt])
+ {
+ Trace("Failed to create thread\n");
+ }
+ else
+ {
+ iCnt++;
+ }
+ }
+
+ if (0 == iCnt)
+ {
+ Fail("Can't create any thread\n");
+ }
+
+ for (i=0; i<iCnt; i+=64)
+ {
+ dwRet = WaitForMultipleObjects(MIN(64, iCnt-i), &hThreads[i], TRUE, INFINITE);
+ if (WAIT_FAILED == dwRet)
+ {
+ Fail("WaitForMultipleObjects failed [dwRet=%u GetLastError()=%u iCnt=%d i=%d]\n",
+ dwRet, GetLastError(), iCnt, i);
+ }
+ }
+
+
+ for (i=0; i<iCnt; i++)
+ {
+ CloseHandle(hThreads[i]);
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/thistest.dat b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/thistest.dat
new file mode 100644
index 0000000000..8d36162752
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/thistest.dat
@@ -0,0 +1,2 @@
+
+PAL,threading,palsuite\threading\waitformultipleobjectsex\test6,Test6forWaitForMultipleObjectsEx=test6.c child6.c,<SUPPORTEXE>
diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForSingleObject/CMakeLists.txt
new file mode 100644
index 0000000000..94bd51caa6
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/CMakeLists.txt
@@ -0,0 +1,11 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(WFSOExMutexTest)
+add_subdirectory(WFSOExSemaphoreTest)
+add_subdirectory(WFSOExThreadTest)
+add_subdirectory(WFSOMutexTest)
+add_subdirectory(WFSOProcessTest)
+add_subdirectory(WFSOSemaphoreTest)
+add_subdirectory(WFSOThreadTest)
+
diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExMutexTest/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExMutexTest/CMakeLists.txt
new file mode 100644
index 0000000000..65fa0abe14
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExMutexTest/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ WFSOExMutexTest.c
+)
+
+add_executable(paltest_waitforsingleobject_wfsoexmutextest
+ ${SOURCES}
+)
+
+add_dependencies(paltest_waitforsingleobject_wfsoexmutextest coreclrpal)
+
+target_link_libraries(paltest_waitforsingleobject_wfsoexmutextest
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExMutexTest/WFSOExMutexTest.c b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExMutexTest/WFSOExMutexTest.c
new file mode 100644
index 0000000000..3737f9cc10
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExMutexTest/WFSOExMutexTest.c
@@ -0,0 +1,214 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: WFSOExMutex.c
+**
+** Purpose: Tests a child thread in the middle of a
+** WaitForSingleObjectEx call will be interrupted by QueueUserAPC
+** if the alert flag was set.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+/*Based on SleepEx/test2 */
+
+const int ChildThreadWaitTime = 4000;
+const int InterruptTime = 2000;
+const DWORD AcceptableDelta = 300;
+
+void RunTest(BOOL AlertThread);
+VOID PALAPI APCFunc(ULONG_PTR dwParam);
+DWORD PALAPI WaiterProc(LPVOID lpParameter);
+
+DWORD ThreadWaitDelta;
+HANDLE hMutex;
+
+
+
+int __cdecl main( int argc, char **argv )
+{
+ int ret=0;
+
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /*
+ On some platforms (e.g. FreeBSD 4.9) the first call to some synch objects
+ (such as conditions) involves some pthread internal initialization that
+ can make the first wait slighty longer, potentially going above the
+ acceptable delta for this test. Let's add a dummy wait to preinitialize
+ internal structures
+ */
+ Sleep(100);
+
+ /*
+ The state of a mutex object is signaled when it is not owned by any thread.
+ The creating thread can use the bInitialOwner flag to request immediate ownership
+ of the mutex. Otherwise, a thread must use one of the wait functions to request
+ ownership. When the mutex's state is signaled, one waiting thread is granted
+ ownership, the mutex's state changes to nonsignaled, and the wait function returns.
+ Only one thread can own a mutex at any given time. The owning thread uses the
+ ReleaseMutex function to release its ownership.
+ */
+
+ /* Create a mutex that is not in the signalled state */
+ hMutex = CreateMutex(NULL, //No security attributes
+ TRUE, //Iniitally owned
+ NULL); //Name of mutex
+
+ if (hMutex == NULL)
+ {
+ Fail("Failed to create mutex! GetLastError returned %d.\n",
+ GetLastError());
+ }
+ /*
+ * Check that Queueing an APC in the middle of a wait does interrupt
+ * it, if it's in an alertable state.
+ */
+
+ RunTest(TRUE);
+ if ((ThreadWaitDelta - InterruptTime) > AcceptableDelta)
+ {
+ Fail("Expected thread to wait for %d ms (and get interrupted).\n"
+ "Thread waited for %d ms! (Acceptable delta: %d)\n",
+ InterruptTime, ThreadWaitDelta, AcceptableDelta);
+ }
+
+
+ /*
+ * Check that Queueing an APC in the middle of a wait does NOT interrupt
+ * it, if it is not in an alertable state.
+ */
+ RunTest(FALSE);
+ if ((ThreadWaitDelta - ChildThreadWaitTime) > AcceptableDelta)
+ {
+ Fail("Expected thread to wait for %d ms (and not be interrupted).\n"
+ "Thread waited for %d ms! (Acceptable delta: %d)\n",
+ ChildThreadWaitTime, ThreadWaitDelta, AcceptableDelta);
+ }
+
+
+
+ //Release Mutex
+ ret = ReleaseMutex(hMutex);
+ if (0==ret)
+ {
+ Fail("Unable to Release Mutex!\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+ //Close Mutex Handle
+ ret = CloseHandle(hMutex);
+ if (!ret)
+ {
+ Fail("Unable to close handle to Mutex!\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
+
+void RunTest(BOOL AlertThread)
+{
+
+ HANDLE hThread = 0;
+ DWORD dwThreadId = 0;
+
+ int ret=0;
+
+ hThread = CreateThread( NULL,
+ 0,
+ (LPTHREAD_START_ROUTINE)WaiterProc,
+ (LPVOID) AlertThread,
+ 0,
+ &dwThreadId);
+
+ if (hThread == NULL)
+ {
+ Fail("ERROR: Was not able to create the thread to test!\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+
+
+ Sleep(InterruptTime);
+
+ ret = QueueUserAPC(APCFunc, hThread, 0);
+
+ if (ret == 0)
+ {
+ Fail("QueueUserAPC failed! GetLastError returned %d\n",
+ GetLastError());
+ }
+
+ ret = WaitForSingleObject(hThread, INFINITE);
+
+ if (ret == WAIT_FAILED)
+ {
+ Fail("Unable to wait on child thread!\nGetLastError returned %d.\n",
+ GetLastError());
+ }
+
+
+ if (0==CloseHandle(hThread))
+ {
+ Trace("Could not close Thread handle\n");
+ Fail ( "GetLastError returned %d\n", GetLastError());
+ }
+}
+
+/* Function doesn't do anything, just needed to interrupt the wait*/
+VOID PALAPI APCFunc(ULONG_PTR dwParam)
+{
+}
+
+/* Entry Point for child thread. */
+DWORD PALAPI WaiterProc(LPVOID lpParameter)
+{
+ UINT64 OldTimeStamp;
+ UINT64 NewTimeStamp;
+ BOOL Alertable;
+ DWORD ret;
+
+ Alertable = (BOOL) lpParameter;
+
+ LARGE_INTEGER performanceFrequency;
+ if (!QueryPerformanceFrequency(&performanceFrequency))
+ {
+ Fail("Failed to query performance frequency!");
+ }
+
+ OldTimeStamp = GetHighPrecisionTimeStamp(performanceFrequency);
+
+ ret = WaitForSingleObjectEx( hMutex,
+ ChildThreadWaitTime,
+ Alertable);
+
+ NewTimeStamp = GetHighPrecisionTimeStamp(performanceFrequency);
+
+ if (Alertable && ret != WAIT_IO_COMPLETION)
+ {
+ Fail("Expected the interrupted wait to return WAIT_IO_COMPLETION.\n"
+ "Got %d\n", ret);
+ }
+ else if (!Alertable && ret != WAIT_TIMEOUT)
+ {
+ Fail("WaitForSingleObjectEx did not timeout.\n"
+ "Expected return of WAIT_TIMEOUT, got %d.\n", ret);
+ }
+
+ ThreadWaitDelta = NewTimeStamp - OldTimeStamp;
+
+ return 0;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExSemaphoreTest/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExSemaphoreTest/CMakeLists.txt
new file mode 100644
index 0000000000..12517e31e0
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExSemaphoreTest/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ WFSOExSemaphoreTest.c
+)
+
+add_executable(paltest_waitforsingleobject_wfsoexsemaphoretest
+ ${SOURCES}
+)
+
+add_dependencies(paltest_waitforsingleobject_wfsoexsemaphoretest coreclrpal)
+
+target_link_libraries(paltest_waitforsingleobject_wfsoexsemaphoretest
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExSemaphoreTest/WFSOExSemaphoreTest.c b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExSemaphoreTest/WFSOExSemaphoreTest.c
new file mode 100644
index 0000000000..793c50995c
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExSemaphoreTest/WFSOExSemaphoreTest.c
@@ -0,0 +1,184 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: WFSOExSemaphore.c
+**
+** Purpose: Tests a child thread in the middle of a
+** WaitForSingleObjectEx call will be interrupted by QueueUserAPC
+** if the alert flag was set.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+/*Based on SleepEx/test2 */
+
+const int ChildThreadWaitTime = 4000;
+const int InterruptTime = 2000;
+const DWORD AcceptableDelta = 300;
+
+void RunTest(BOOL AlertThread);
+VOID PALAPI APCFunc(ULONG_PTR dwParam);
+DWORD PALAPI WaiterProc(LPVOID lpParameter);
+
+DWORD ThreadWaitDelta;
+
+int __cdecl main( int argc, char **argv )
+{
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /*
+ On some platforms (e.g. FreeBSD 4.9) the first call to some synch objects
+ (such as conditions) involves some pthread internal initialization that
+ can make the first wait slighty longer, potentially going above the
+ acceptable delta for this test. Let's add a dummy wait to preinitialize
+ internal structures
+ */
+ Sleep(100);
+
+ /*
+ * Check that Queueing an APC in the middle of a wait does interrupt
+ * it, if it's in an alertable state.
+ */
+
+ RunTest(TRUE);
+ if ((ThreadWaitDelta - InterruptTime) > AcceptableDelta)
+ {
+ Fail("Expected thread to wait for %d ms (and get interrupted).\n"
+ "Thread waited for %d ms! (Acceptable delta: %d)\n",
+ InterruptTime, ThreadWaitDelta, AcceptableDelta);
+ }
+
+
+ /*
+ * Check that Queueing an APC in the middle of a wait does NOT interrupt
+ * it, if it is not in an alertable state.
+ */
+ RunTest(FALSE);
+ if ((ThreadWaitDelta - ChildThreadWaitTime) > AcceptableDelta)
+ {
+ Fail("Expected thread to wait for %d ms (and not be interrupted).\n"
+ "Thread waited for %d ms! (Acceptable delta: %d)\n",
+ ChildThreadWaitTime, ThreadWaitDelta, AcceptableDelta);
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+void RunTest(BOOL AlertThread)
+{
+ HANDLE hThread = 0;
+ DWORD dwThreadId = 0;
+ int ret;
+
+ hThread = CreateThread( NULL,
+ 0,
+ (LPTHREAD_START_ROUTINE)WaiterProc,
+ (LPVOID) AlertThread,
+ 0,
+ &dwThreadId);
+
+ if (hThread == NULL)
+ {
+ Fail("ERROR: Was not able to create the thread to test!\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+ Sleep(InterruptTime);
+
+ ret = QueueUserAPC(APCFunc, hThread, 0);
+ if (ret == 0)
+ {
+ Fail("QueueUserAPC failed! GetLastError returned %d\n",
+ GetLastError());
+ }
+
+ ret = WaitForSingleObject(hThread, INFINITE);
+ if (ret == WAIT_FAILED)
+ {
+ Fail("Unable to wait on child thread!\nGetLastError returned %d.\n",
+ GetLastError());
+ }
+
+ if (0==CloseHandle(hThread))
+ {
+ Trace("Could not close Thread handle\n");
+ Fail ( "GetLastError returned %d\n", GetLastError());
+ }
+}
+
+/* Function doesn't do anything, just needed to interrupt the wait*/
+VOID PALAPI APCFunc(ULONG_PTR dwParam)
+{
+}
+
+/* Entry Point for child thread. */
+DWORD PALAPI WaiterProc(LPVOID lpParameter)
+{
+ HANDLE hSemaphore;
+ UINT64 OldTimeStamp;
+ UINT64 NewTimeStamp;
+ BOOL Alertable;
+ DWORD ret;
+
+ LARGE_INTEGER performanceFrequency;
+ if (!QueryPerformanceFrequency(&performanceFrequency))
+ {
+ Fail("Failed to query performance frequency!");
+ }
+
+ /* Create a semaphore that is not in the signalled state */
+ hSemaphore = CreateSemaphoreW(NULL, 0, 1, NULL);
+
+ if (hSemaphore == NULL)
+ {
+ Fail("Failed to create semaphore! GetLastError returned %d.\n",
+ GetLastError());
+ }
+
+ Alertable = (BOOL) lpParameter;
+
+ OldTimeStamp = GetHighPrecisionTimeStamp(performanceFrequency);
+
+ ret = WaitForSingleObjectEx( hSemaphore,
+ ChildThreadWaitTime,
+ Alertable);
+
+ NewTimeStamp = GetHighPrecisionTimeStamp(performanceFrequency);
+
+
+ if (Alertable && ret != WAIT_IO_COMPLETION)
+ {
+ Fail("Expected the interrupted wait to return WAIT_IO_COMPLETION.\n"
+ "Got %d\n", ret);
+ }
+ else if (!Alertable && ret != WAIT_TIMEOUT)
+ {
+ Fail("WaitForSingleObjectEx did not timeout.\n"
+ "Expected return of WAIT_TIMEOUT, got %d.\n", ret);
+ }
+
+
+ ThreadWaitDelta = NewTimeStamp - OldTimeStamp;
+
+ ret = CloseHandle(hSemaphore);
+ if (!ret)
+ {
+ Fail("Unable to close handle to semaphore!\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+ return 0;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExThreadTest/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExThreadTest/CMakeLists.txt
new file mode 100644
index 0000000000..f3d868f082
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExThreadTest/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ WFSOExThreadTest.c
+)
+
+add_executable(paltest_waitforsingleobject_wfsoexthreadtest
+ ${SOURCES}
+)
+
+add_dependencies(paltest_waitforsingleobject_wfsoexthreadtest coreclrpal)
+
+target_link_libraries(paltest_waitforsingleobject_wfsoexthreadtest
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExThreadTest/WFSOExThreadTest.c b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExThreadTest/WFSOExThreadTest.c
new file mode 100644
index 0000000000..894d2804aa
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExThreadTest/WFSOExThreadTest.c
@@ -0,0 +1,204 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: WFSOExThreadTest.c
+**
+** Purpose: Tests a child thread in the middle of a
+** WaitForSingleObjectEx call will be interrupted by QueueUserAPC
+** if the alert flag was set.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+/*Based on SleepEx/test2 */
+
+const int ChildThreadWaitTime = 4000;
+const int InterruptTime = 2000;
+const DWORD AcceptableDelta = 300;
+
+void RunTest(BOOL AlertThread);
+VOID PALAPI APCFunc(ULONG_PTR dwParam);
+DWORD PALAPI WaiterProc(LPVOID lpParameter);
+void WorkerThread(void);
+
+int ThreadWaitDelta;
+
+int __cdecl main( int argc, char **argv )
+{
+ if (0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /*
+ On some platforms (e.g. FreeBSD 4.9) the first call to some synch objects
+ (such as conditions) involves some pthread internal initialization that
+ can make the first wait slighty longer, potentially going above the
+ acceptable delta for this test. Let's add a dummy wait to preinitialize
+ internal structures
+ */
+ Sleep(100);
+
+ /*
+ * Check that Queueing an APC in the middle of a wait does interrupt
+ * it, if it's in an alertable state.
+ */
+
+ RunTest(TRUE);
+ if (abs(ThreadWaitDelta - InterruptTime) > AcceptableDelta)
+ {
+ Fail("Expected thread to wait for %d ms (and get interrupted).\n"
+ "Thread waited for %d ms! (Acceptable delta: %d)\n",
+ InterruptTime, ThreadWaitDelta, AcceptableDelta);
+ }
+
+
+ /*
+ * Check that Queueing an APC in the middle of a wait does NOT interrupt
+ * it, if it is not in an alertable state.
+ */
+ RunTest(FALSE);
+ if (abs(ThreadWaitDelta - ChildThreadWaitTime) > AcceptableDelta)
+ {
+ Fail("Expected thread to wait for %d ms (and not be interrupted).\n"
+ "Thread waited for %d ms! (Acceptable delta: %d)\n",
+ ChildThreadWaitTime, ThreadWaitDelta, AcceptableDelta);
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+}
+
+void RunTest(BOOL AlertThread)
+{
+ HANDLE hThread = 0;
+ DWORD dwThreadId = 0;
+ int ret;
+
+ //Create thread
+ hThread = CreateThread( NULL,
+ 0,
+ (LPTHREAD_START_ROUTINE)WaiterProc,
+ (LPVOID) AlertThread,
+ 0,
+ &dwThreadId);
+
+ if (hThread == NULL)
+ {
+ Fail("ERROR: Was not able to create the thread to test!\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+ Sleep(InterruptTime);
+
+ ret = QueueUserAPC(APCFunc, hThread, 0);
+ if (ret == 0)
+ {
+ Fail("QueueUserAPC failed! GetLastError returned %d\n",
+ GetLastError());
+ }
+
+
+ ret = WaitForSingleObject(hThread, INFINITE);
+ if (ret == WAIT_FAILED)
+ {
+ Fail("Unable to wait on child thread!\nGetLastError returned %d.\n",
+ GetLastError());
+ }
+
+ if (0==CloseHandle(hThread))
+ {
+ Trace("Could not close Thread handle\n");
+ Fail ( "GetLastError returned %d\n", GetLastError());
+ }
+}
+
+/* Function doesn't do anything, just needed to interrupt the wait*/
+VOID PALAPI APCFunc(ULONG_PTR dwParam)
+{
+}
+
+/* Entry Point for child thread. */
+DWORD PALAPI WaiterProc(LPVOID lpParameter)
+{
+ HANDLE hWaitThread;
+ UINT64 OldTimeStamp;
+ UINT64 NewTimeStamp;
+ BOOL Alertable;
+ DWORD ret;
+ DWORD dwThreadId = 0;
+
+/*
+When a thread terminates, the thread object attains a signaled state,
+satisfying any threads that were waiting on the object.
+*/
+
+/* Create a thread that does not return immediately to maintain a non signaled test*/
+ hWaitThread = CreateThread( NULL,
+ 0,
+ (LPTHREAD_START_ROUTINE)WorkerThread,
+ NULL,
+ 0,
+ &dwThreadId);
+
+ if (hWaitThread == NULL)
+ {
+ Fail("ERROR: Was not able to create worker thread to wait on!\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+ Alertable = (BOOL) lpParameter;
+
+ LARGE_INTEGER performanceFrequency;
+ if (!QueryPerformanceFrequency(&performanceFrequency))
+ {
+ Fail("Failed to query performance frequency!");
+ }
+
+ OldTimeStamp = GetHighPrecisionTimeStamp(performanceFrequency);
+
+ ret = WaitForSingleObjectEx( hWaitThread,
+ ChildThreadWaitTime,
+ Alertable);
+
+ NewTimeStamp = GetHighPrecisionTimeStamp(performanceFrequency);
+
+
+ if (Alertable && ret != WAIT_IO_COMPLETION)
+ {
+ Fail("Expected the interrupted wait to return WAIT_IO_COMPLETION.\n"
+ "Got %d\n", ret);
+ }
+ else if (!Alertable && ret != WAIT_TIMEOUT)
+ {
+ Fail("WaitForSingleObjectEx did not timeout.\n"
+ "Expected return of WAIT_TIMEOUT, got %d.\n", ret);
+ }
+
+ ThreadWaitDelta = NewTimeStamp - OldTimeStamp;
+
+ ret = CloseHandle(hWaitThread);
+ if (!ret)
+ {
+ Fail("Unable to close handle to Thread!\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+ return 0;
+}
+
+
+void WorkerThread(void)
+{
+
+ //Make the worker thread sleep to test WFSOEx Functionality
+
+ Sleep(2*ChildThreadWaitTime);
+}
+
diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOMutexTest/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOMutexTest/CMakeLists.txt
new file mode 100644
index 0000000000..374880e90f
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOMutexTest/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ WFSOMutexTest.c
+)
+
+add_executable(paltest_waitforsingleobject_wfsomutextest
+ ${SOURCES}
+)
+
+add_dependencies(paltest_waitforsingleobject_wfsomutextest coreclrpal)
+
+target_link_libraries(paltest_waitforsingleobject_wfsomutextest
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOMutexTest/WFSOMutexTest.c b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOMutexTest/WFSOMutexTest.c
new file mode 100644
index 0000000000..5ecf517c2a
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOMutexTest/WFSOMutexTest.c
@@ -0,0 +1,184 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: WFSOMutexTest.c
+**
+** Purpose: Test for WaitForSingleObjectTest.
+** Create Mutex Object
+** Create Two Threads, Each Threads does WFSO for the Mutex Object
+** Increments Counter
+** Releases Mutex
+** Test Passes if the above operations are successful
+**
+**
+**
+**=========================================================*/
+
+
+
+#include <palsuite.h>
+
+
+#define NUMBER_OF_WORKER_THREADS 2
+
+//Declaring Variables
+HANDLE hMutex = NULL;
+unsigned int globalcounter =0;
+int testReturnCode = PASS;
+
+//Declaring Function Prototypes
+DWORD WFSOMutexTest(LPVOID params);
+void incrementCounter(void);
+
+
+
+int __cdecl main(int argc, char **argv)
+{
+
+ //Declare local variables
+ int i =0;
+
+ // 2 dimensional array to hold thread handles for each worker thread
+ HANDLE hThread[NUMBER_OF_WORKER_THREADS];
+ DWORD dwThreadId=0;
+ int returnCode = 0;
+
+ //Initialize PAL
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ //Create Mutex
+ hMutex = CreateMutex(NULL, // no security attributes
+ FALSE, // initially not owned
+ NULL); // name of mutex
+
+ //Check for Mutex Creation
+
+ if (hMutex == NULL)
+ {
+ Fail("Create Mutex Failed, GetLastError: %d\n", GetLastError());
+ }
+
+
+ //Spawn 2 worker threads
+ for (i=0;i<NUMBER_OF_WORKER_THREADS;i++)
+ {
+ //Create Thread
+
+ hThread[i] = CreateThread(
+ NULL,
+ 0,
+ WFSOMutexTest,
+ NULL,
+ 0,
+ &dwThreadId);
+
+ if ( NULL == hThread[i] )
+ {
+ Fail ( "CreateThread() returned NULL. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+ }
+
+ /* Test running */
+ returnCode = WaitForMultipleObjects( NUMBER_OF_WORKER_THREADS, hThread, TRUE, 5000);
+ if( WAIT_OBJECT_0 != returnCode )
+ {
+ Trace("Wait for Object(s) returned %d, and GetLastError value is %d\n", returnCode, GetLastError());
+ testReturnCode = FAIL;
+ }
+
+//Close thread handles
+for (i=0;i<NUMBER_OF_WORKER_THREADS;i++)
+ {
+
+ if (0==CloseHandle(hThread[i]))
+ {
+ Trace("Could not Close thread handle\n");
+ Fail ( "GetLastError returned %d\n", GetLastError());
+ }
+ }
+
+//Close Mutex Handle
+if (0==CloseHandle(hMutex))
+ {
+ Trace("Could not close mutex handle\n");
+ Fail ( "GetLastError returned %d\n", GetLastError());
+ }
+
+
+PAL_TerminateEx(testReturnCode);
+return ( testReturnCode );
+
+}
+
+
+void incrementCounter(void)
+{
+ if (INT_MAX == globalcounter)
+ {
+ globalcounter = 0;
+ }
+
+ globalcounter++;
+ Trace("Global Counter Value: %d \n", globalcounter);
+}
+
+
+DWORD WFSOMutexTest(LPVOID params)
+{
+
+ DWORD dwWaitResult;
+
+ // Request ownership of mutex.
+
+ dwWaitResult = WaitForSingleObject(
+ hMutex, // handle to mutex
+ 5000L); // five-second time-out interval
+
+ switch (dwWaitResult)
+ {
+ // The thread got mutex ownership.
+ case WAIT_OBJECT_0:
+ {
+
+ incrementCounter();
+
+ //Release ownership of the mutex object.
+ if (! ReleaseMutex(hMutex))
+ {
+ Fail ( "ReleaseMutex() returned NULL. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+ break;
+ }
+
+ // Cannot get mutex ownership due to time-out.
+ case WAIT_TIMEOUT:
+ {
+ Fail ( "Cannot get mutex ownership due to time-out. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ return FALSE;
+ }
+
+ // Got ownership of the abandoned mutex object.
+ case WAIT_ABANDONED:
+ {
+ Fail ( "Got ownership of the abandoned mutex object. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ return FALSE;
+ }
+ }
+
+ return 1;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOProcessTest/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOProcessTest/CMakeLists.txt
new file mode 100644
index 0000000000..a70b101988
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOProcessTest/CMakeLists.txt
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(TESTSOURCES
+ WFSOProcessTest.c
+)
+
+add_executable(paltest_waitforsingleobject_wfsoprocesstest
+ ${TESTSOURCES}
+)
+
+add_dependencies(paltest_waitforsingleobject_wfsoprocesstest coreclrpal)
+
+target_link_libraries(paltest_waitforsingleobject_wfsoprocesstest
+ pthread
+ m
+ coreclrpal
+)
+
+
+set(HELPERSOURCES
+ ChildProcess.c
+)
+
+add_executable(paltest_waitforsingleobject_wfsoprocesstest_child
+ ${HELPERSOURCES}
+)
+
+add_dependencies(paltest_waitforsingleobject_wfsoprocesstest_child coreclrpal)
+
+target_link_libraries(paltest_waitforsingleobject_wfsoprocesstest_child
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOProcessTest/ChildProcess.c b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOProcessTest/ChildProcess.c
new file mode 100644
index 0000000000..91c24d87bb
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOProcessTest/ChildProcess.c
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: ChildProcess.c
+**
+** Purpose: Dummy Process which does some work on which the Main Test case waits
+**
+**
+
+**
+**=========================================================*/
+
+
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+
+//Declare local variables
+int i =0;
+
+
+
+//Initialize PAL
+if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+//Do some work
+for (i=0; i<100000; i++);
+
+Trace("Counter Value was incremented to %d \n ",i);
+
+PAL_Terminate();
+return ( PASS );
+
+}
+
+
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOProcessTest/WFSOProcessTest.c b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOProcessTest/WFSOProcessTest.c
new file mode 100644
index 0000000000..2711e26c29
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOProcessTest/WFSOProcessTest.c
@@ -0,0 +1,119 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: WFSOProcessTest.c
+**
+** Purpose: Test for WaitForSingleObjectTest.
+** Create One Process and do some work
+** Use WFSO For the Process to finish
+**
+** Test Passes if the above operations are successful
+**
+**
+**
+**=========================================================*/
+
+
+
+#include <palsuite.h>
+
+int __cdecl main(int argc, char **argv)
+{
+
+//Declare local variables
+STARTUPINFO si;
+PROCESS_INFORMATION pi;
+
+DWORD dwWaitResult=0;
+
+//Initialize PAL
+if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+
+ZeroMemory( &si, sizeof(si) );
+si.cb = sizeof(si);
+ZeroMemory( &pi, sizeof(pi) );
+
+// Start the child process.
+if( !CreateProcess( NULL, // No module name (use command line).
+ "childprocess", // Command line.
+ NULL, // Process handle not inheritable.
+ NULL, // Thread handle not inheritable.
+ FALSE, // Set handle inheritance to FALSE.
+ 0, // No creation flags.
+ NULL, // Use parent's environment block.
+ NULL, // Use parent's starting directory.
+ &si, // Pointer to STARTUPINFO structure.
+ &pi ) // Pointer to PROCESS_INFORMATION structure.
+)
+
+{
+Fail ( "Create Process Failed. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+}
+
+// Wait until child process exits.
+ dwWaitResult = WaitForSingleObject( pi.hProcess, INFINITE );
+switch (dwWaitResult)
+ {
+ // The Process wait was successful
+ case WAIT_OBJECT_0:
+ {
+
+ Trace("Wait for Process was successful\n");
+ break;
+ }
+
+ // Time-out.
+ case WAIT_TIMEOUT:
+ {
+ Fail ( "Time -out. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ return FALSE;
+ }
+
+ // Got ownership of the abandoned process object.
+ case WAIT_ABANDONED:
+ {
+ Fail ( "Got ownership of the abandoned Process object. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ return FALSE;
+ }
+
+ //Error condition
+ case WAIT_FAILED:
+ {
+ Fail ( "Wait for Process Failed. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ return FALSE;
+ }
+
+}
+
+
+
+// Close process handle
+if (0==CloseHandle(pi.hProcess))
+ {
+ Trace("Could not close process handle\n");
+ Fail ( "GetLastError returned %d\n", GetLastError());
+ }
+
+
+PAL_Terminate();
+return ( PASS );
+
+}
+
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOSemaphoreTest/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOSemaphoreTest/CMakeLists.txt
new file mode 100644
index 0000000000..171e0583e5
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOSemaphoreTest/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ WFSOSemaphoreTest.c
+)
+
+add_executable(paltest_waitforsingleobject_wfsosemaphoretest
+ ${SOURCES}
+)
+
+add_dependencies(paltest_waitforsingleobject_wfsosemaphoretest coreclrpal)
+
+target_link_libraries(paltest_waitforsingleobject_wfsosemaphoretest
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOSemaphoreTest/WFSOSemaphoreTest.c b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOSemaphoreTest/WFSOSemaphoreTest.c
new file mode 100644
index 0000000000..9902d448cd
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOSemaphoreTest/WFSOSemaphoreTest.c
@@ -0,0 +1,183 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: WFSOMutexTest.c
+**
+** Purpose: Test for WaitForSingleObjectTest.
+** Create Semaphore Object
+** Create Two Threads, Each Threads does WFSO for the Semaphore Object
+** Increments Counter
+** Releases Semaphore
+** Test Passes if the above operations are successful
+**
+**
+**
+**=========================================================*/
+
+
+
+#include <palsuite.h>
+
+
+#define NUMBER_OF_WORKER_THREADS 2
+
+
+//Declaring Variables
+HANDLE hSemaphore = NULL;
+unsigned int globalcounter =0;
+int testReturnCode = PASS;
+
+//Declaring Function Prototypes
+DWORD WFSOSemaphoreTest(LPVOID params);
+void incrementCounter(void);
+
+int __cdecl main(int argc, char **argv)
+{
+
+ //Declare local variables
+ int i =0;
+ int cMax = 2;
+
+ int returnCode = 0;
+
+ // 2 dimensional array to hold thread handles for each worker thread
+ HANDLE hThread[NUMBER_OF_WORKER_THREADS];
+ DWORD dwThreadId=0;
+
+ //Initialize PAL
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ //Create Semaphore
+ hSemaphore = CreateSemaphore(
+ NULL, // no security attributes
+ cMax, // initial count
+ cMax, // maximum count
+ NULL); // unnamed semaphore
+
+ if (hSemaphore == NULL)
+ {
+ // Check for error.
+ Fail("Create Semaphore Failed, GetLastError: %d\n", GetLastError());
+ }
+
+
+
+ //Spawn 2 worker threads
+ for (i=0;i<NUMBER_OF_WORKER_THREADS;i++)
+ {
+ //Create Thread
+
+ hThread[i] = CreateThread(
+ NULL,
+ 0,
+ WFSOSemaphoreTest,
+ NULL,
+ 0,
+ &dwThreadId);
+
+ if ( NULL == hThread[i] )
+ {
+ Fail ( "CreateThread() returned NULL. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+ }
+
+
+ /* Test running */
+ returnCode = WaitForMultipleObjects( NUMBER_OF_WORKER_THREADS, hThread, TRUE, 5000);
+ if( WAIT_OBJECT_0 != returnCode )
+ {
+ Trace("Wait for Object(s) returned %d, and GetLastError value is %d\n", returnCode, GetLastError());
+ testReturnCode = FAIL;
+ }
+
+//Close thread handles
+for (i=0;i<NUMBER_OF_WORKER_THREADS;i++)
+ {
+
+ if (0==CloseHandle(hThread[i]))
+ {
+ Trace("Could not Close thread handle\n");
+ Fail ( "GetLastError returned %d\n", GetLastError());
+ }
+ }
+
+//Close Semaphore Handle
+if (0==CloseHandle(hSemaphore))
+ {
+ Trace("Could not close semaphore handle\n");
+ Fail ( "GetLastError returned %d\n", GetLastError());
+ }
+
+PAL_TerminateEx(testReturnCode);
+return ( testReturnCode );
+
+}
+
+
+void incrementCounter(void)
+{
+ if (INT_MAX == globalcounter)
+ {
+ globalcounter = 0;
+ }
+
+ globalcounter++;
+ Trace("Global Counter Value: %d \n", globalcounter);
+}
+
+
+DWORD WFSOSemaphoreTest(LPVOID params)
+{
+
+ DWORD dwWaitResult;
+
+ // Request ownership of Semaphore
+
+ dwWaitResult = WaitForSingleObject(
+ hSemaphore, // handle to semaphore
+ 0L); // zero-second time-out interval
+
+
+ switch (dwWaitResult)
+ {
+ // The semaphore object was signaled.
+ case WAIT_OBJECT_0:
+ {
+
+ incrementCounter();
+ // Increment the count of the semaphore.
+
+ if (!ReleaseSemaphore(
+ hSemaphore, // handle to semaphore
+ 1, // increase count by one
+ NULL) ) // not interested in previous count
+ {
+ Fail ( "ReleaseSemaphore() returned NULL. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+ break;
+ }
+
+ // Semaphore was nonsignaled, so a time-out occurred.
+ case WAIT_TIMEOUT:
+ {
+ Fail ( "Semaphore was nonsignaled, so a time-out occurred. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ return FALSE;
+ }
+ }
+
+ return 1;
+}
+
+
+
diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOThreadTest/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOThreadTest/CMakeLists.txt
new file mode 100644
index 0000000000..18701a9da5
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOThreadTest/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ WFSOThreadTest.c
+)
+
+add_executable(paltest_waitforsingleobject_wfsothreadtest
+ ${SOURCES}
+)
+
+add_dependencies(paltest_waitforsingleobject_wfsothreadtest coreclrpal)
+
+target_link_libraries(paltest_waitforsingleobject_wfsothreadtest
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOThreadTest/WFSOThreadTest.c b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOThreadTest/WFSOThreadTest.c
new file mode 100644
index 0000000000..378350671a
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOThreadTest/WFSOThreadTest.c
@@ -0,0 +1,179 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: WFSOThreadTest.c
+**
+** Purpose: Test for WaitForSingleObjectTest.
+** Create One Thread and do some work
+** Use WFSO For the Thread to finish
+**
+** Test Passes if the above operations are successful
+**
+**
+**
+**=========================================================*/
+
+
+
+#include <palsuite.h>
+
+
+//Declaring Variables
+HANDLE hThread = NULL;
+HANDLE hEvent = NULL;
+
+unsigned int globalcounter =0;
+
+//Declaring Function Prototypes
+DWORD incrementCounter(LPVOID params);
+
+int __cdecl main(int argc, char **argv)
+{
+
+ //Declare local variables
+ DWORD dwThreadId=0;
+ DWORD dwWaitResult=0;
+
+ //Initialize PAL
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+
+ //Create Event
+ hEvent = CreateEvent(NULL,TRUE,FALSE, NULL);
+ if(hEvent == NULL)
+ {
+ Fail("Create Event Failed\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+
+ //Create Thread
+ hThread = CreateThread(
+ NULL,
+ 0,
+ incrementCounter,
+ NULL,
+ 0,
+ &dwThreadId);
+
+ if ( NULL == hThread )
+ {
+ Fail ( "CreateThread() returned NULL. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+
+ //Wait For Thread to signal start
+ dwWaitResult = WaitForSingleObject(hEvent,INFINITE);
+
+ switch (dwWaitResult)
+ {
+ // The thread wait was successful
+ case WAIT_OBJECT_0:
+ {
+
+ Trace ("Wait for Single Object (hEvent) was successful.\n");
+ break;
+ }
+
+ // Time-out.
+ case WAIT_TIMEOUT:
+ {
+ Fail ( "Time -out. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ return FALSE;
+ }
+
+ // Got ownership of the abandoned event object.
+ case WAIT_ABANDONED:
+ {
+ Fail ( "Got ownership of the abandoned event object. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ return FALSE;
+ }
+
+ }
+
+
+ //Wait for Thread to finish
+ dwWaitResult = WaitForSingleObject(
+ hThread, //handle to thread
+ 5000L); //Wait Indefinitely
+
+
+ switch (dwWaitResult)
+ {
+ // The thread wait was successful
+ case WAIT_OBJECT_0:
+ {
+
+ Trace("Wait for thread was successful\n");
+
+ break;
+ }
+
+ // Time-out.
+ case WAIT_TIMEOUT:
+ {
+ Fail ( "Time -out. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ return FALSE;
+ }
+
+ // Got ownership of the abandoned thread object.
+ case WAIT_ABANDONED:
+ {
+ Fail ( "Got ownership of the abandoned thread object. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ return FALSE;
+ }
+
+ }
+
+
+//Close Handles
+if (0==CloseHandle(hEvent))
+ {
+ Trace("Could not Close event handle\n");
+ Fail ( "GetLastError returned %d\n", GetLastError());
+ }
+if (0==CloseHandle(hThread))
+ {
+ Trace("Could not Close thread handle\n");
+ Fail ( "GetLastError returned %d\n", GetLastError());
+ }
+
+PAL_Terminate();
+return ( PASS );
+
+}
+
+DWORD incrementCounter(LPVOID params)
+{
+
+ //Signal Event so that main thread can start to wait for thread object
+ if (0==SetEvent(hEvent))
+ {
+ Fail ( "SetEvent returned Zero. Failing test.\n"
+ "GetLastError returned %d\n", GetLastError());
+ }
+
+ for (globalcounter=0;globalcounter<100000;globalcounter++);
+
+ //Sleep(5000);
+
+ Trace("Global Counter Value: %d \n", globalcounter);
+ return 0;
+}
+
+
+
+
+
+
diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/CMakeLists.txt
new file mode 100644
index 0000000000..0a71330ba1
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_waitforsingleobject_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_waitforsingleobject_test1 coreclrpal)
+
+target_link_libraries(paltest_waitforsingleobject_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/test1.c b/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/test1.c
new file mode 100644
index 0000000000..2af80df677
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/test1.c
@@ -0,0 +1,121 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Source: test1.c
+**
+** Purpose: Test for WaitForSingleObjectTest. Create two events, one
+** with a TRUE and one with FALSE intial state. Ensure that WaitForSingle
+** returns correct values for each of these.
+**
+**
+**=========================================================*/
+
+#include <palsuite.h>
+
+BOOL WaitForSingleObjectTest()
+{
+
+ BOOL bRet = FALSE;
+ DWORD dwRet = 0;
+
+ LPSECURITY_ATTRIBUTES lpEventAttributes = 0;
+ BOOL bManualReset = TRUE;
+ BOOL bInitialState = TRUE;
+
+ HANDLE hEvent;
+
+ /* Create an event, and ensure the HANDLE is valid */
+ hEvent = CreateEvent(lpEventAttributes, bManualReset,
+ bInitialState, NULL);
+
+ if (hEvent != INVALID_HANDLE_VALUE)
+ {
+
+ /* Call WaitForSingleObject with 0 time on the event. It
+ should return WAIT_OBJECT_0
+ */
+
+ dwRet = WaitForSingleObject(hEvent,0);
+
+ if (dwRet != WAIT_OBJECT_0)
+ {
+ Trace("WaitForSingleObjectTest:WaitForSingleObject failed (%x)\n", GetLastError());
+ }
+ else
+ {
+ bRet = CloseHandle(hEvent);
+
+ if (!bRet)
+ {
+ Trace("WaitForSingleObjectTest:CloseHandle failed (%x)\n", GetLastError());
+ }
+ }
+ }
+ else
+ {
+ Trace("WaitForSingleObjectTest:CreateEvent failed (%x)\n", GetLastError());
+ }
+
+ /* If the first section passed, Create another event, with the
+ intial state being FALSE this time.
+ */
+
+ if (bRet)
+ {
+ bRet = FALSE;
+
+ bInitialState = FALSE;
+
+ hEvent = CreateEvent( lpEventAttributes,
+ bManualReset, bInitialState, NULL);
+
+ if (hEvent != INVALID_HANDLE_VALUE)
+ {
+
+ /* Test WaitForSingleObject and ensure that it returns
+ WAIT_TIMEOUT in this case.
+ */
+
+ dwRet = WaitForSingleObject(hEvent,0);
+
+ if (dwRet != WAIT_TIMEOUT)
+ {
+ Trace("WaitForSingleObjectTest:WaitForSingleObject failed (%x)\n", GetLastError());
+ }
+ else
+ {
+ bRet = CloseHandle(hEvent);
+
+ if (!bRet)
+ {
+ Trace("WaitForSingleObjectTest:CloseHandle failed (%x)\n", GetLastError());
+ }
+ }
+ }
+ else
+ {
+ Trace("WaitForSingleObjectTest::CreateEvent failed (%x)\n", GetLastError());
+ }
+ }
+ return bRet;
+}
+
+int __cdecl main(int argc, char **argv)
+{
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return ( FAIL );
+ }
+
+ if(!WaitForSingleObjectTest())
+ {
+ Fail ("Test failed\n");
+ }
+
+ PAL_Terminate();
+ return ( PASS );
+
+}
diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/testinfo.dat b/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/testinfo.dat
new file mode 100644
index 0000000000..89193d1c20
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = WaitForSingleObject
+Name = Positive Test for WaitForSingleObject
+TYPE = DEFAULT
+EXE1 = test1
+Description
+= Test for WaitForSingleObject. Create two events, one
+= with a TRUE and one with FALSE intial state. Ensure that WaitForSingle
+= returns correct values for each of these.
diff --git a/src/pal/tests/palsuite/threading/YieldProcessor/CMakeLists.txt b/src/pal/tests/palsuite/threading/YieldProcessor/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/YieldProcessor/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/threading/YieldProcessor/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/YieldProcessor/test1/CMakeLists.txt
new file mode 100644
index 0000000000..5002bf763d
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/YieldProcessor/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_yieldprocessor_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_yieldprocessor_test1 coreclrpal)
+
+target_link_libraries(paltest_yieldprocessor_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/YieldProcessor/test1/test1.c b/src/pal/tests/palsuite/threading/YieldProcessor/test1/test1.c
new file mode 100644
index 0000000000..6adbe989c2
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/YieldProcessor/test1/test1.c
@@ -0,0 +1,92 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Source: test1.c
+**
+** Purpose: Test to ensure YieldProcessor works, without
+** causing test to hang
+**
+** Dependencies: PAL_Initialize
+** Fail
+** YieldProcessor
+** WaitForMultipleObject
+** CreateThread
+** GetLastError
+**
+
+**
+**===========================================================================*/
+
+
+#include <palsuite.h>
+#define THREAD_COUNT 10
+#define REPEAT_COUNT 1000
+#define TIMEOUT 60000
+void PALAPI Run_Thread(LPVOID lpParam);
+
+/**
+ * main
+ *
+ * executable entry point
+ */
+INT __cdecl main( INT argc, CHAR **argv )
+{
+ DWORD dwParam;
+ HANDLE hThread[THREAD_COUNT];
+ DWORD threadId[THREAD_COUNT];
+
+ int i = 0;
+ int returnCode = 0;
+
+ /*PAL initialization */
+ if( (PAL_Initialize(argc, argv)) != 0 )
+ {
+ return FAIL;
+ }
+
+
+ for( i = 0; i < THREAD_COUNT; i++ )
+ {
+ dwParam = (int) i;
+ //Create thread
+ hThread[i] = CreateThread(
+ NULL, /* no security attributes */
+ 0, /* use default stack size */
+ (LPTHREAD_START_ROUTINE)Run_Thread,/* thread function */
+ (LPVOID)dwParam, /* argument to thread function */
+ 0, /* use default creation flags */
+ &threadId[i] /* returns the thread identifier*/
+ );
+
+ if(hThread[i] == NULL)
+ {
+ Fail("Create Thread failed for iteration %d GetLastError value is %d\n", i, GetLastError());
+ }
+
+ }
+
+
+ returnCode = WaitForMultipleObjects(THREAD_COUNT, hThread, TRUE, TIMEOUT);
+ if( WAIT_OBJECT_0 != returnCode )
+ {
+ Trace("Wait for Object(s) returned %d, expected value is %d, and GetLastError value is %d\n", returnCode, WAIT_OBJECT_0, GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+void PALAPI Run_Thread (LPVOID lpParam)
+{
+ int i = 0;
+
+ for(i=0; i < REPEAT_COUNT; i++ )
+ {
+ // No error code set nor does it have any return code
+ YieldProcessor();
+ }
+}
diff --git a/src/pal/tests/palsuite/threading/YieldProcessor/test1/testinfo.dat b/src/pal/tests/palsuite/threading/YieldProcessor/test1/testinfo.dat
new file mode 100644
index 0000000000..6d12110c34
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/YieldProcessor/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = YieldProcessor
+Name = Test for YieldProcessor
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Purpose: Test to ensure YieldProcessor is
+= working properly on supported platforms
diff --git a/src/pal/tests/palsuite/threading/releasesemaphore/CMakeLists.txt b/src/pal/tests/palsuite/threading/releasesemaphore/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/releasesemaphore/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/threading/releasesemaphore/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/releasesemaphore/test1/CMakeLists.txt
new file mode 100644
index 0000000000..e415f91fb2
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/releasesemaphore/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.c
+)
+
+add_executable(paltest_releasesemaphore_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_releasesemaphore_test1 coreclrpal)
+
+target_link_libraries(paltest_releasesemaphore_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/threading/releasesemaphore/test1/test.c b/src/pal/tests/palsuite/threading/releasesemaphore/test1/test.c
new file mode 100644
index 0000000000..4d736b7d9a
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/releasesemaphore/test1/test.c
@@ -0,0 +1,68 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================================
+**
+** Source: releasesemaphore/test1/createsemaphore.c
+**
+** Purpose: Check that ReleaseSemaphore fails when using a semaphore handle
+** which has been closed by a call to CloseHandle. Check that
+** ReleaseSemaphore fails when using a ReleaseCount of zero or less than
+** zero.
+**
+**
+**==========================================================================*/
+
+#include <palsuite.h>
+
+HANDLE hSemaphore;
+
+int __cdecl main (int argc, char **argv)
+{
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return (FAIL);
+ }
+ hSemaphore = CreateSemaphoreA (NULL, 1, 2, NULL);
+
+ if (NULL == hSemaphore)
+ {
+ Fail("PALSUITE ERROR: CreateSemaphoreA ('%p' '%ld' '%ld' "
+ "'%p') returned NULL.\nGetLastError returned %d.\n",
+ NULL, 1, 2, NULL, GetLastError());
+ }
+
+ if(ReleaseSemaphore(hSemaphore, 0, NULL))
+ {
+ Fail("PALSUITE ERROR: ReleaseSemaphore('%p' '%ld' '%p') "
+ "call returned %d\nwhen it should have returned "
+ "%d.\nGetLastError returned %d.\n",
+ hSemaphore, 0, NULL, FALSE, TRUE, GetLastError());
+ }
+
+ if(ReleaseSemaphore(hSemaphore, -1, NULL))
+ {
+ Fail("PALSUITE ERROR: ReleaseSemaphore('%p' '%ld' '%p') "
+ "call returned %d\nwhen it should have returned "
+ "%d.\nGetLastError returned %d.\n",
+ hSemaphore, -1, NULL, TRUE, FALSE, GetLastError());
+ }
+
+ if(!CloseHandle(hSemaphore))
+ {
+ Fail("PALSUITE ERROR: CloseHandle(%p) call failed. GetLastError "
+ "returned %d.\n", hSemaphore, GetLastError());
+ }
+
+ if(ReleaseSemaphore(hSemaphore, 1, NULL))
+ {
+ Fail("PALSUITE ERROR: ReleaseSemaphore('%p' '%ld' '%p') "
+ "call incremented semaphore %p count\nafter the handle "
+ "was closed by a call to CloseHandle.\n GetLastError returned "
+ "%d.\n", hSemaphore, -1, NULL, hSemaphore, GetLastError());
+ }
+
+ PAL_Terminate();
+ return (PASS);
+}
diff --git a/src/pal/tests/palsuite/threading/releasesemaphore/test1/testinfo.dat b/src/pal/tests/palsuite/threading/releasesemaphore/test1/testinfo.dat
new file mode 100644
index 0000000000..b4d647a592
--- /dev/null
+++ b/src/pal/tests/palsuite/threading/releasesemaphore/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = threading
+Function = ReleaseSemaphore
+Name = Positive Test for ReleaseSemaphore
+TYPE = DEFAULT
+EXE1 = test
+Description
+= Check that ReleaseSemaphore fails when using a semaphore handle
+= which has been closed by a call to CloseHandle. Check that
+= ReleaseSemaphore fails when using a ReleaseCount of zero or less than
+= zero.