Skip to content
Snippets Groups Projects
LinkFutureTest.cpp 3.44 KiB
Newer Older
  • Learn to ignore specific revisions
  • // SPDX-License-Identifier: LGPL-3.0-or-later
    // Copyright © 2020-2021 Florian Fischer
    
    #include <sys/eventfd.h>	// for eventfd
    #include <sys/types.h>		// for ssize_t
    
    
    #include <cassert>	// for assert
    #include <cerrno>		// for EBADF, ECANCELED
    #include <cstdint>	// for uint64_t, int32_t
    #include <cstdlib>	// for exit, EXIT_SUCCESS
    
    
    #include "Common.hpp"	 // for DIE_MSG_ERRNO, DIE_MSG
    #include "io.hpp"
    
    #include "io/Future.hpp"	// for ReadFuture, CloseFuture, WriteFuture
    
    using emper::io::CloseFuture;
    using emper::io::ReadFuture;
    using emper::io::WriteFuture;
    
    static void successChain() {
    	int efd = eventfd(0, 0);
    	if (efd == -1) {
    		DIE_MSG_ERRNO("eventfd failed");
    	}
    
    	uint64_t write_buf = 42;
    	WriteFuture writeFuture(efd, &write_buf, sizeof(write_buf), 0);
    
    	uint64_t read_buf;
    	ReadFuture readFuture(efd, &read_buf, sizeof(read_buf), 0);
    	readFuture.setDependency(writeFuture);
    
    	CloseFuture closeFuture(efd);
    	closeFuture.setDependency(readFuture);
    	ssize_t res = closeFuture.submitAndWait();
    
    	if (res == -1) {
    		DIE_MSG_ERRNO("linked requests chain failed");
    	}
    
    	if (read_buf != 42) {
    		DIE_MSG("dependent read value differs from written value");
    	}
    }
    
    
    static void successLoop() {
    	int efd = eventfd(0, 0);
    	if (efd == -1) {
    		DIE_MSG_ERRNO("eventfd failed");
    	}
    
    	const unsigned ITERATIONS = 10000;
    	for (unsigned i = 0; i < ITERATIONS; ++i) {
    		uint64_t write_buf = 42;
    		WriteFuture writeFuture(efd, &write_buf, sizeof(write_buf), 0);
    
    		uint64_t read_buf;
    		ReadFuture readFuture(efd, &read_buf, sizeof(read_buf), 0);
    		readFuture.setDependency(writeFuture);
    
    		ssize_t res = readFuture.submitAndWait();
    
    		if (res == -1) {
    			DIE_MSG_ERRNO("linked requests chain failed");
    		}
    
    		if (read_buf != 42) {
    			DIE_MSG("dependent read value differs from written value");
    		}
    	}
    
    	CloseFuture closeFuture(efd);
    	ssize_t res = closeFuture.submitAndWait();
    
    	if (res == -1) {
    		DIE_MSG_ERRNO("linked requests chain failed");
    	}
    }
    
    
    static void failureChainInvCor() {
    	std::array<char, 32> buf;
    	ReadFuture invalidReadFuture(-1, buf.data(), buf.size(), 0);
    
    	ReadFuture readFuture(0, buf.data(), buf.size(), 0);
    
    	readFuture.setDependency(invalidReadFuture);
    
    	int32_t res = readFuture.submitAndWait();
    	assert(res == -ECANCELED);
    
    	res = invalidReadFuture.wait();
    	assert(res == -EBADF);
    }
    
    
    static void failureChainCorInvCor() {
    	std::array<char, 32> buf;
    
    	int fd = emper::io::openAndWait("/dev/null", O_WRONLY);
    	// int fd = open("/dev/null", O_WRONLY, 0);
    	assert(fd != -1);
    
    	WriteFuture correctFuture1(fd, buf.data(), buf.size(), 0);
    
    	ReadFuture invalidFuture(-1, buf.data(), buf.size(), 0);
    	invalidFuture.setDependency(correctFuture1);
    
    	WriteFuture correctFuture2(fd, buf.data(), buf.size(), 0);
    	correctFuture2.setDependency(invalidFuture);
    
    	int32_t res = correctFuture2.submitAndWait();
    	assert(res == -ECANCELED);
    
    	res = invalidFuture.wait();
    	assert(res == -EBADF);
    
    	res = correctFuture1.wait();
    	assert(res == (int32_t)buf.size());
    
    	emper::io::close(fd);
    }
    
    
    	// This leaves the io_uring in a weird state because the successChain() afterwards
    	// fails because the write future is already completed with -ECANCELED but
    	// there is successful cqe in the CQ for this future
    	failureChainCorInvCor();
    
    
    	failureChainInvCor();
    
    	// failureChainInvCor left the io_uring in a weird state because
    	// the io_uring_submit of the openAndWait() never returns.
    	// failureChainCorInvCor();