164 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			V
		
	
	
			
		
		
	
	
			164 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			V
		
	
	
// vtest retry: 3
 | 
						|
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')
 | 
						|
		mut n := ¬ifier
 | 
						|
		check_read_event(mut n, reader, 'foo')
 | 
						|
		check_read_event(mut n, 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) ?
 | 
						|
 | 
						|
		mut n := ¬ifier
 | 
						|
 | 
						|
		os.fd_write(writer, 'foobar')
 | 
						|
		check_read_event(mut n, 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
 | 
						|
		// TODO: investigage why the above assert suddenly started failing on the latest Ubuntu kernel update:
 | 
						|
		// 5.11.0-37-generic #41~20.04.2-Ubuntu SMP Fri Sep 24 09:06:38 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
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) ?
 | 
						|
 | 
						|
		mut n := ¬ifier
 | 
						|
 | 
						|
		os.fd_write(writer, 'foobar')
 | 
						|
		check_read_event(mut n, reader, 'foo')
 | 
						|
		os.fd_write(writer, 'baz')
 | 
						|
 | 
						|
		assert notifier.wait(0).len == 0
 | 
						|
 | 
						|
		// rearm
 | 
						|
		notifier.modify(reader, .read) ?
 | 
						|
		check_read_event(mut n, 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(mut 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
 | 
						|
}
 |