run-07-break.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. #include <ccan/io/io.h>
  2. /* Include the C files directly. */
  3. #include <ccan/io/poll.c>
  4. #include <ccan/io/io.c>
  5. #include <ccan/tap/tap.h>
  6. #include <sys/wait.h>
  7. #include <stdio.h>
  8. #ifndef PORT
  9. #define PORT "65007"
  10. #endif
  11. struct data {
  12. int state;
  13. char buf[4];
  14. };
  15. static struct io_plan *read_done(struct io_conn *conn, struct data *d)
  16. {
  17. ok1(d->state == 1);
  18. d->state++;
  19. return io_close(conn);
  20. }
  21. static void finish_ok(struct io_conn *conn, struct data *d)
  22. {
  23. ok1(d->state == 2);
  24. d->state++;
  25. }
  26. static struct io_plan *init_conn(struct io_conn *conn, struct data *d)
  27. {
  28. ok1(d->state == 0);
  29. d->state++;
  30. io_set_finish(conn, finish_ok, d);
  31. io_break(d);
  32. return io_read(conn, d->buf, sizeof(d->buf), read_done, d);
  33. }
  34. static int make_listen_fd(const char *port, struct addrinfo **info)
  35. {
  36. int fd, on = 1;
  37. struct addrinfo *addrinfo, hints;
  38. memset(&hints, 0, sizeof(hints));
  39. hints.ai_family = AF_UNSPEC;
  40. hints.ai_socktype = SOCK_STREAM;
  41. hints.ai_flags = AI_PASSIVE;
  42. hints.ai_protocol = 0;
  43. if (getaddrinfo(NULL, port, &hints, &addrinfo) != 0)
  44. return -1;
  45. fd = socket(addrinfo->ai_family, addrinfo->ai_socktype,
  46. addrinfo->ai_protocol);
  47. if (fd < 0)
  48. return -1;
  49. setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
  50. if (bind(fd, addrinfo->ai_addr, addrinfo->ai_addrlen) != 0) {
  51. close(fd);
  52. return -1;
  53. }
  54. if (listen(fd, 1) != 0) {
  55. close(fd);
  56. return -1;
  57. }
  58. *info = addrinfo;
  59. return fd;
  60. }
  61. int main(void)
  62. {
  63. struct data *d = malloc(sizeof(*d));
  64. struct addrinfo *addrinfo;
  65. struct io_listener *l;
  66. int fd, status;
  67. /* This is how many tests you plan to run */
  68. plan_tests(13);
  69. d->state = 0;
  70. fd = make_listen_fd(PORT, &addrinfo);
  71. ok1(fd >= 0);
  72. l = io_new_listener(NULL, fd, init_conn, d);
  73. ok1(l);
  74. fflush(stdout);
  75. if (!fork()) {
  76. int i;
  77. io_close_listener(l);
  78. fd = socket(addrinfo->ai_family, addrinfo->ai_socktype,
  79. addrinfo->ai_protocol);
  80. if (fd < 0)
  81. exit(1);
  82. if (connect(fd, addrinfo->ai_addr, addrinfo->ai_addrlen) != 0)
  83. exit(2);
  84. signal(SIGPIPE, SIG_IGN);
  85. for (i = 0; i < strlen("hellothere"); i++) {
  86. if (write(fd, "hellothere" + i, 1) != 1)
  87. break;
  88. }
  89. close(fd);
  90. freeaddrinfo(addrinfo);
  91. free(d);
  92. exit(0);
  93. }
  94. freeaddrinfo(addrinfo);
  95. ok1(io_loop() == d);
  96. ok1(d->state == 1);
  97. io_close_listener(l);
  98. ok1(io_loop() == NULL);
  99. ok1(d->state == 3);
  100. ok1(memcmp(d->buf, "hellothere", sizeof(d->buf)) == 0);
  101. free(d);
  102. ok1(wait(&status));
  103. ok1(WIFEXITED(status));
  104. ok1(WEXITSTATUS(status) == 0);
  105. /* This exits depending on whether all tests passed */
  106. return exit_status();
  107. }