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
|
import os
import os.notify
// make a pipe and return the (read, write) file descriptors
fn make_pipe() ?(int, int) {
$if linux {
pipefd := [2]int{}
if C.pipe(&pipefd[0]) != 0 {
return error('error $C.errno: ' + os.posix_get_error_msg(C.errno))
}
return pipefd[0], pipefd[1]
}
return -1, -1
}
fn test_level_trigger() ? {
// currently only linux is supported
$if linux {
mut notifier := notify.new() ?
reader, writer := make_pipe() ?
defer {
os.fd_close(reader)
os.fd_close(writer)
notifier.close() or {}
}
notifier.add(reader, .read) ?
os.fd_write(writer, 'foobar')
check_read_event(notifier, reader, 'foo')
check_read_event(notifier, reader, 'bar')
assert notifier.wait(0).len == 0
}
}
fn test_edge_trigger() ? {
// currently only linux is supported
$if linux {
mut notifier := notify.new() ?
reader, writer := make_pipe() ?
defer {
os.fd_close(reader)
os.fd_close(writer)
notifier.close() or {}
}
notifier.add(reader, .read, .edge_trigger) ?
os.fd_write(writer, 'foobar')
check_read_event(notifier, reader, 'foo')
assert notifier.wait(0).len == 0
os.fd_write(writer, 'baz')
// we do not get an event because there is still data
// to be read
assert notifier.wait(0).len == 0
}
}
fn test_one_shot() ? {
$if linux {
mut notifier := notify.new() ?
reader, writer := make_pipe() ?
defer {
os.fd_close(reader)
os.fd_close(writer)
notifier.close() or {}
}
notifier.add(reader, .read, .one_shot) ?
os.fd_write(writer, 'foobar')
check_read_event(notifier, reader, 'foo')
os.fd_write(writer, 'baz')
assert notifier.wait(0).len == 0
// rearm
notifier.modify(reader, .read) ?
check_read_event(notifier, reader, 'barbaz')
}
}
fn test_hangup() ? {
$if linux {
mut notifier := notify.new() ?
reader, writer := make_pipe() ?
defer {
os.fd_close(reader)
notifier.close() or {}
}
notifier.add(reader, .hangup) ?
assert notifier.wait(0).len == 0
// closing on the writer end of the pipe will
// cause a hangup on the reader end
os.fd_close(writer)
events := notifier.wait(0)
assert events.len == 1
assert events[0].fd == reader
assert events[0].kind.has(.hangup)
}
}
fn test_write() ? {
$if linux {
mut notifier := notify.new() ?
reader, writer := make_pipe() ?
defer {
os.fd_close(reader)
os.fd_close(writer)
notifier.close() or {}
}
notifier.add(reader, .write) ?
assert notifier.wait(0).len == 0
notifier.add(writer, .write) ?
events := notifier.wait(0)
assert events.len == 1
assert events[0].fd == writer
assert events[0].kind.has(.write)
}
}
fn test_remove() ? {
$if linux {
mut notifier := notify.new() ?
reader, writer := make_pipe() ?
defer {
os.fd_close(reader)
os.fd_close(writer)
notifier.close() or {}
}
// level triggered - will keep getting events while
// there is data to read
notifier.add(reader, .read) ?
os.fd_write(writer, 'foobar')
assert notifier.wait(0).len == 1
assert notifier.wait(0).len == 1
notifier.remove(reader) ?
assert notifier.wait(0).len == 0
}
}
fn check_read_event(notifier notify.FdNotifier, reader_fd int, expected string) {
events := notifier.wait(0)
assert events.len == 1
assert events[0].fd == reader_fd
assert events[0].kind.has(.read)
s, _ := os.fd_read(events[0].fd, expected.len)
assert s == expected
}
|