7165d09cc7d6014c2c95f179129fdb2397701a3d
[mruby.git] / mrbgems / mruby-io / test / mruby_io_test.c
blob7165d09cc7d6014c2c95f179129fdb2397701a3d
1 #include <mruby/common.h>
2 #include <sys/types.h>
3 #include <errno.h>
4 #include <string.h>
6 #if defined(_WIN32) || defined(_WIN64)
8 #include <winsock.h>
9 #include <io.h>
10 #include <fcntl.h>
11 #include <direct.h>
12 #include <stdlib.h>
13 #include <malloc.h>
15 #if (!defined __MINGW64__) && (!defined __MINGW32__)
16 typedef int mode_t;
17 #endif
19 #define open _open
20 #define close _close
22 #if defined(_MSC_VER) || \
23 (defined(MRB_MINGW32_VERSION) && MRB_MINGW32_VERSION < 3021) || \
24 (defined(MRB_MINGW64_VERSION) && MRB_MINGW64_VERSION < 4000)
25 #include <sys/stat.h>
27 static int
28 mkstemp(char *p)
30 int fd;
31 char* fname = _mktemp(p);
32 if (fname == NULL)
33 return -1;
34 fd = open(fname, O_RDWR | O_CREAT | O_EXCL, _S_IREAD | _S_IWRITE);
35 if (fd >= 0)
36 return fd;
37 return -1;
39 #endif
41 static char*
42 mkdtemp(char *temp)
44 char *path = _mktemp(temp);
45 if (path[0] == 0) return NULL;
46 if (_mkdir(path) < 0) return NULL;
47 return path;
50 #define umask(mode) _umask(mode)
51 #define rmdir(path) _rmdir(path)
52 #else
53 #include <sys/socket.h>
54 #include <unistd.h>
55 #include <sys/un.h>
56 #include <assert.h>
57 #include <fcntl.h>
58 #endif
60 #include <sys/stat.h>
61 #include <stdlib.h>
63 #include "mruby.h"
64 #include "mruby/array.h"
65 #include "mruby/error.h"
66 #include "mruby/string.h"
67 #include "mruby/variable.h"
68 #include <mruby/ext/io.h>
70 int wd_save;
71 int socket_available_p;
73 #if !defined(_WIN32) && !defined(_WIN64)
74 static int mrb_io_socket_available()
76 int fd, retval = 0;
77 struct sockaddr_un sun0;
78 char socketname[] = "tmp.mruby-io-socket-ok.XXXXXXXX";
79 if (!(fd = mkstemp(socketname))) {
80 goto sock_test_out;
82 unlink(socketname);
83 close(fd);
84 fd = socket(AF_UNIX, SOCK_STREAM, 0);
85 if (fd == -1) {
86 goto sock_test_out;
88 sun0.sun_family = AF_UNIX;
89 strncpy(sun0.sun_path, socketname, sizeof(sun0.sun_path));
90 if (bind(fd, (struct sockaddr *)&sun0, sizeof(sun0)) == 0) {
91 retval = 1;
93 sock_test_out:
94 unlink(socketname);
95 close(fd);
96 return retval;
98 #endif
100 static mrb_value
101 mrb_io_test_io_setup(mrb_state *mrb, mrb_value self)
103 char rfname[] = "tmp.mruby-io-test-r.XXXXXXXX";
104 char wfname[] = "tmp.mruby-io-test-w.XXXXXXXX";
105 char symlinkname[] = "tmp.mruby-io-test-l.XXXXXXXX";
106 char socketname[] = "tmp.mruby-io-test-s.XXXXXXXX";
107 char msg[] = "mruby io test\n";
108 mode_t mask;
109 int fd0, fd1;
110 FILE *fp;
112 #if !defined(_WIN32) && !defined(_WIN64)
113 int fd2, fd3;
114 struct sockaddr_un sun0;
116 if(!(socket_available_p = mrb_io_socket_available())) {
117 char *tmpdir;
118 wd_save = open(".", O_DIRECTORY);
119 tmpdir = getenv("TMPDIR");
120 if (tmpdir)
121 assert(!chdir(tmpdir));
122 else
123 assert(!chdir("/tmp"));
125 #endif
127 mask = umask(077);
128 fd0 = mkstemp(rfname);
129 fd1 = mkstemp(wfname);
130 if (fd0 == -1 || fd1 == -1) {
131 mrb_raise(mrb, E_RUNTIME_ERROR, "can't create temporary file");
132 return mrb_nil_value();
134 close(fd0);
135 close(fd1);
137 #if !defined(_WIN32) && !defined(_WIN64)
138 fd2 = mkstemp(symlinkname);
139 fd3 = mkstemp(socketname);
140 if (fd2 == -1 || fd3 == -1) {
141 mrb_raise(mrb, E_RUNTIME_ERROR, "can't create temporary file");
142 return mrb_nil_value();
144 #endif
145 umask(mask);
147 mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_rfname"), mrb_str_new_cstr(mrb, rfname));
148 mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_wfname"), mrb_str_new_cstr(mrb, wfname));
149 mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_symlinkname"), mrb_str_new_cstr(mrb, symlinkname));
150 mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_socketname"), mrb_str_new_cstr(mrb, socketname));
151 mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_msg"), mrb_str_new_cstr(mrb, msg));
153 fp = fopen(rfname, "wb");
154 if (fp == NULL) {
155 mrb_raise(mrb, E_RUNTIME_ERROR, "can't open temporary file");
156 return mrb_nil_value();
158 fputs(msg, fp);
159 fclose(fp);
161 fp = fopen(wfname, "wb");
162 if (fp == NULL) {
163 mrb_raise(mrb, E_RUNTIME_ERROR, "can't open temporary file");
164 return mrb_nil_value();
166 fclose(fp);
168 #if !defined(_WIN32) && !defined(_WIN64)
169 unlink(symlinkname);
170 close(fd2);
171 if (symlink(rfname, symlinkname) == -1) {
172 mrb_raise(mrb, E_RUNTIME_ERROR, "can't make a symbolic link");
175 unlink(socketname);
176 close(fd3);
177 fd3 = socket(AF_UNIX, SOCK_STREAM, 0);
178 if (fd3 == -1) {
179 mrb_raise(mrb, E_RUNTIME_ERROR, "can't make a socket");
181 sun0.sun_family = AF_UNIX;
182 strncpy(sun0.sun_path, socketname, sizeof(sun0.sun_path));
183 if (bind(fd3, (struct sockaddr *)&sun0, sizeof(sun0)) == -1) {
184 mrb_raisef(mrb, E_RUNTIME_ERROR, "can't bind AF_UNIX socket to %s: %d",
185 sun0.sun_path,
186 errno);
188 close(fd3);
189 #endif
191 return mrb_true_value();
194 static mrb_value
195 mrb_io_test_io_cleanup(mrb_state *mrb, mrb_value self)
197 mrb_value rfname = mrb_gv_get(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_rfname"));
198 mrb_value wfname = mrb_gv_get(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_wfname"));
199 mrb_value symlinkname = mrb_gv_get(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_symlinkname"));
200 mrb_value socketname = mrb_gv_get(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_socketname"));
202 if (mrb_string_p(rfname)) {
203 remove(RSTRING_PTR(rfname));
205 if (mrb_string_p(wfname)) {
206 remove(RSTRING_PTR(wfname));
208 if (mrb_string_p(symlinkname)) {
209 remove(RSTRING_PTR(symlinkname));
211 if (mrb_string_p(socketname)) {
212 remove(RSTRING_PTR(socketname));
215 mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_rfname"), mrb_nil_value());
216 mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_wfname"), mrb_nil_value());
217 mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_symlinkname"), mrb_nil_value());
218 mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_socketname"), mrb_nil_value());
219 mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_msg"), mrb_nil_value());
221 #if !defined(_WIN32) && !defined(_WIN64)
222 if(!socket_available_p) {
223 assert(!fchdir(wd_save));
224 close(wd_save);
226 #endif
228 return mrb_nil_value();
231 static mrb_value
232 mrb_io_test_mkdtemp(mrb_state *mrb, mrb_value klass)
234 mrb_value str;
235 char *cp;
237 mrb_get_args(mrb, "S", &str);
238 cp = mrb_str_to_cstr(mrb, str);
239 if (mkdtemp(cp) == NULL) {
240 mrb_sys_fail(mrb, "mkdtemp");
242 return mrb_str_new_cstr(mrb, cp);
245 static mrb_value
246 mrb_io_test_rmdir(mrb_state *mrb, mrb_value klass)
248 const char *cp;
250 mrb_get_args(mrb, "z", &cp);
251 if (rmdir(cp) == -1) {
252 mrb_sys_fail(mrb, "rmdir");
254 return mrb_true_value();
257 mrb_value
258 mrb_io_win_p(mrb_state *mrb, mrb_value klass)
260 #if defined(_WIN32) || defined(_WIN64)
261 # if defined(__CYGWIN__) || defined(__CYGWIN32__)
262 return mrb_false_value();
263 # else
264 return mrb_true_value();
265 # endif
266 #else
267 return mrb_false_value();
268 #endif
271 #ifdef MRB_WITH_IO_PREAD_PWRITE
272 # define MRB_WITH_IO_PREAD_PWRITE_ENABLED TRUE
273 #else
274 # define MRB_WITH_IO_PREAD_PWRITE_ENABLED FALSE
275 #endif
277 void
278 mrb_mruby_io_gem_test(mrb_state* mrb)
280 struct RClass *io_test = mrb_define_module(mrb, "MRubyIOTestUtil");
281 mrb_define_class_method(mrb, io_test, "io_test_setup", mrb_io_test_io_setup, MRB_ARGS_NONE());
282 mrb_define_class_method(mrb, io_test, "io_test_cleanup", mrb_io_test_io_cleanup, MRB_ARGS_NONE());
284 mrb_define_class_method(mrb, io_test, "mkdtemp", mrb_io_test_mkdtemp, MRB_ARGS_REQ(1));
285 mrb_define_class_method(mrb, io_test, "rmdir", mrb_io_test_rmdir, MRB_ARGS_REQ(1));
286 mrb_define_class_method(mrb, io_test, "win?", mrb_io_win_p, MRB_ARGS_NONE());
288 mrb_define_const(mrb, io_test, "MRB_WITH_IO_PREAD_PWRITE", mrb_bool_value(MRB_WITH_IO_PREAD_PWRITE_ENABLED));