1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
|
(*
* Copyright (c) 2013 Jeremy Yallop.
*
* This file is distributed under the terms of the MIT License.
* See the file LICENSE for details.
*)
open OUnit
open Ctypes
open Unsigned
open Foreign
(*
Call the functions
int isisalnum(int)
int isisalpha(int)
int isiscntrl(int)
int isisdigit(int)
int isisgraph(int)
int isislower(int)
int isisprint(int)
int isispunct(int)
int isisspace(int)
int isisupper(int)
int isisxdigit(int)
*)
let test_isX_functions () =
let cchar = view ~read:Char.chr ~write:Char.code int in
let bool = view ~read:((<>)0) ~write:(fun b -> if b then 1 else 0) int in
let t = (cchar @-> returning bool) in
let isalnum = foreign "isalnum" t
and isalpha = foreign "isalpha" t
and iscntrl = foreign "iscntrl" t
and isdigit = foreign "isdigit" t
and isgraph = foreign "isgraph" t
and islower = foreign "islower" t
and isprint = foreign "isprint" t
and ispunct = foreign "ispunct" t
and isspace = foreign "isspace" t
and isupper = foreign "isupper" t
and isxdigit = foreign "isxdigit" t
in begin
assert_bool "" (isalnum 'a');
assert_bool "" (not (isalnum ' '));
assert_bool "" (isalpha 'x');
assert_bool "" (not (isalpha ';'));
assert_bool "" (iscntrl '\r');
assert_bool "" (not (iscntrl 'a'));
assert_bool "" (isdigit '2');
assert_bool "" (not (isdigit 'a'));
assert_bool "" (isgraph '?');
assert_bool "" (not (isgraph ' '));
assert_bool "" (islower 's');
assert_bool "" (not (islower 'S'));
assert_bool "" (isprint ' ');
assert_bool "" (not (isprint '\b'));
assert_bool "" (ispunct '.');
assert_bool "" (not (ispunct 'a'));
assert_bool "" (isspace '\t');
assert_bool "" (not (isspace '~'));
assert_bool "" (isupper 'X');
assert_bool "" (not (isupper 'x'));
assert_bool "" (isxdigit 'f');
assert_bool "" (not (isxdigit 'g'));
end
(*
Call the functions
char *strchr(const char *str, int c);
int strcmp(const char *str1, const char *str2);
*)
let test_string_functions () =
(* char *strchr(const char *str, int c); *)
let strchr = foreign "strchr" (string @-> int @-> returning string) in
(* int strcmp(const char *str1, const char *str2); *)
let strcmp = foreign "strcmp" (string @-> string @-> returning int) in
(* int memcmp(const void *ptr1, const void *ptr2, size_t num) *)
let memcmp = foreign "memcmp"
(ptr void @-> ptr void @-> size_t @-> returning int) in
(* void *memset(void *ptr, int value, size_t num) *)
let memset = foreign "memset"
(ptr void @-> int @-> size_t @-> returning (ptr void)) in
assert_equal "efg" (strchr "abcdefg" (Char.code 'e'))
~printer:(fun x -> x);
(* non-word-aligned pointers do not trigger exceptions *)
assert_equal "defg" (strchr "abcdefg" (Char.code 'd'));
assert_bool "strcmp('abc', 'def') < 0"
(strcmp "abc" "def" < 0);
assert_bool "strcmp('def', 'abc') > 0"
(strcmp "def" "abc" > 0);
assert_bool "strcmp('abc', 'abc') == 0"
(strcmp "abc" "abc" = 0);
let p1 = allocate int 10 and p2 = allocate int 20 in
assert_bool "memcmp(&10, &20) < 0"
(memcmp (to_voidp p1) (to_voidp p2) (Size_t.of_int (sizeof int)) < 0);
let p = allocate_n uchar 12 in
let i = 44 in
let u = UChar.of_int i in begin
ignore (memset (to_voidp p) i (Size_t.of_int 12));
for i = 0 to 11 do
assert_equal u !@(p +@ i)
done
end
(*
Call the functions
div_t div(int numerator, int denominator)
where div_t is defined as follows:
typedef struct
{
int quot; /* Quotient. */
int rem; /* Remainder. */
} div_t;
*)
let test_div () =
let module M = struct
type div_t
let div_t : div_t structure typ = structure "div_t"
let (-:) ty label = field div_t label ty
let quot = int -: "quot"
let rem = int -: "rem"
let () = seal div_t
let div = foreign "div" (int @-> int @-> returning div_t)
let test ~num ~dem ~quotient ~remainder =
let v = div num dem in
let () = assert_equal quotient (getf v quot) in
let () = assert_equal remainder (getf v rem) in
()
let () = test ~num:10 ~dem:2 ~quotient:5 ~remainder:0
let () = test ~num:11 ~dem:2 ~quotient:5 ~remainder:1
end in ()
(*
Call the function
void qsort(void *base, size_t nmemb, size_t size,
int(*compar)(const void *, const void *));
*)
let test_qsort () =
let comparator = ptr void @-> ptr void @-> returning int in
let qsort = foreign "qsort"
(ptr void @-> size_t @-> size_t @-> funptr comparator @->
returning void) in
let sortby (type a) (typ : a typ) (f : a -> a -> int) (l : a list) =
let open Array in
let open Size_t in
let open Infix in
let arr = of_list typ l in
let len = of_int (length arr) in
let size = of_int (sizeof typ) in
let cmp xp yp =
let x = !@(from_voidp typ xp)
and y = !@(from_voidp typ yp) in
f x y
in
let () = qsort (to_voidp (start arr)) len size cmp in
to_list arr
in
assert_equal
[5; 4; 3; 2; 1]
(sortby int (fun x y -> - (compare x y)) [3; 4; 1; 2; 5]);
assert_equal
['o'; 'q'; 'r'; 's'; 't']
(sortby char compare ['q'; 's'; 'o'; 'r'; 't'])
(*
Call the function
void *bsearch(const void *key, const void *base,
size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
*)
let test_bsearch () =
let module M = struct
let comparator = ptr void @-> ptr void @-> returning int
let bsearch = foreign "bsearch"
(ptr void @-> ptr void @-> size_t @-> size_t @-> funptr comparator @->
returning (ptr void))
let qsort = foreign "qsort"
(ptr void @-> size_t @-> size_t @-> funptr comparator @->
returning void)
let strlen = foreign "strlen" (ptr char @-> returning size_t)
(*
struct mi {
int nr;
char *name;
} months[] = {
{ 1, "jan" }, { 2, "feb" }, { 3, "mar" }, { 4, "apr" },
{ 5, "may" }, { 6, "jun" }, { 7, "jul" }, { 8, "aug" },
{ 9, "sep" }, {10, "oct" }, {11, "nov" }, {12, "dec" }
};
*)
type mi
let mi = structure "mi"
let (-:) ty label = field mi label ty
let mr = int -: "mr"
let name = ptr char -: "name"
let () = seal (mi : mi structure typ)
let of_string : string -> char array =
fun s ->
let len = String.length s in
let arr = Array.make char (len + 1) in
for i = 0 to len - 1 do
arr.(i) <- s.[i];
done;
arr.(len) <- '\000';
arr
let as_string : char ptr -> string =
fun p ->
let len = Size_t.to_int (strlen p) in
let s = String.create len in
for i = 0 to len - 1 do
s.[i] <- !@(p +@ i);
done;
s
let mkmi n s =
let m = make mi in
setf m mr n;
setf m name (Array.start s);
m
let cmpi m1 m2 =
let mi1 = from_voidp mi m1 in
let mi2 = from_voidp mi m2 in
Pervasives.compare
(as_string (!@(mi1 |-> name)))
(as_string (!@(mi2 |-> name)))
let jan = of_string "jan"
let feb = of_string "feb"
let mar = of_string "mar"
let apr = of_string "apr"
let may = of_string "may"
let jun = of_string "jun"
let jul = of_string "jul"
let aug = of_string "aug"
let sep = of_string "sep"
let oct = of_string "oct"
let nov = of_string "nov"
let dec = of_string "dec"
let months = Array.of_list mi [
mkmi 1 jan;
mkmi 2 feb;
mkmi 3 mar;
mkmi 4 apr;
mkmi 5 may;
mkmi 6 jun;
mkmi 7 jul;
mkmi 8 aug;
mkmi 9 sep;
mkmi 10 oct;
mkmi 11 nov;
mkmi 12 dec;
]
let () = qsort
(to_voidp (Array.start months))
(Size_t.of_int (Array.length months))
(Size_t.of_int (sizeof mi))
cmpi
let search : mi structure -> mi structure array -> mi structure option
= fun key array ->
let len = Size_t.of_int (Array.length array) in
let size = Size_t.of_int (sizeof mi) in
let r : unit ptr =
bsearch
(to_voidp (addr key))
(to_voidp (Array.start array))
len size cmpi in
if r = null then None
else Some (!@(from_voidp mi r))
let find_month_by_name : char array -> mi structure option =
fun s -> search (mkmi 0 s) months
let () = match find_month_by_name dec with
Some m -> assert_equal 12 (getf m mr)
| _ -> assert false
let () = match find_month_by_name feb with
Some m -> assert_equal 2 (getf m mr)
| _ -> assert false
let () = match find_month_by_name jan with
Some m -> assert_equal 1 (getf m mr)
| _ -> assert false
let () = match find_month_by_name may with
Some m -> assert_equal 5 (getf m mr)
| _ -> assert false
let missing = of_string "missing"
let () =
assert_equal None (find_month_by_name missing)
let empty = of_string ""
let () =
assert_equal None (find_month_by_name empty)
end in ()
let suite = "C standard library tests" >:::
["test isX functions"
>:: test_isX_functions;
"test string function"
>:: test_string_functions;
"test div function"
>:: test_div;
"test qsort function"
>:: test_qsort;
"test bsearch function"
>:: test_bsearch;
]
let _ =
run_test_tt_main suite
|