dispatch_select.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /*
  2. * Copyright (c) 2010-2011 Apple Inc. All rights reserved.
  3. *
  4. * @APPLE_APACHE_LICENSE_HEADER_START@
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. *
  18. * @APPLE_APACHE_LICENSE_HEADER_END@
  19. */
  20. #include <stdio.h>
  21. #include <fcntl.h>
  22. #include <stdlib.h>
  23. #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
  24. #include <unistd.h>
  25. #endif
  26. #include <sys/stat.h>
  27. #include <dispatch/dispatch.h>
  28. #include "dispatch_test.h"
  29. #include <bsdtests.h>
  30. static ssize_t actual;
  31. void stage1(int stage);
  32. void stage2(void);
  33. void finish(void* cxt);
  34. void
  35. stage1(int stage)
  36. {
  37. #if defined(_WIN32)
  38. char *path = dispatch_test_get_large_file();
  39. dispatch_fd_t fd = dispatch_test_fd_open(path, O_RDONLY);
  40. if (fd == -1)
  41. {
  42. perror(path);
  43. exit(EXIT_FAILURE);
  44. }
  45. dispatch_test_release_large_file(path);
  46. free(path);
  47. #else
  48. const char *path = "/dev/random";
  49. int fd = open(path, O_RDONLY);
  50. if (fd == -1)
  51. {
  52. perror(path);
  53. exit(EXIT_FAILURE);
  54. }
  55. #endif
  56. dispatch_queue_t main_q = dispatch_get_main_queue();
  57. test_ptr_notnull("main_q", main_q);
  58. dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, (uintptr_t)fd, 0, main_q);
  59. test_ptr_notnull("select source", source);
  60. dispatch_source_set_event_handler(source, ^{
  61. size_t buffer_size = 500*1024;
  62. char buffer[500*1024];
  63. ssize_t sz = dispatch_test_fd_read(fd, buffer, buffer_size);
  64. test_sizet_less_than_or_equal("kevent read 1", sz, buffer_size+1);
  65. dispatch_source_cancel(source);
  66. });
  67. dispatch_source_set_cancel_handler(source, ^{
  68. int res = dispatch_test_fd_close(fd);
  69. test_errno("close", res == -1 ? errno : 0, 0);
  70. dispatch_release(source);
  71. if (stage == 1)
  72. {
  73. dispatch_async(dispatch_get_main_queue(), ^{
  74. stage2();
  75. });
  76. }
  77. });
  78. if (stage == 3)
  79. {
  80. dispatch_set_context(source, source);
  81. dispatch_set_finalizer_f(source, finish);
  82. }
  83. dispatch_resume(source);
  84. }
  85. void
  86. stage2(void)
  87. {
  88. char *path = dispatch_test_get_large_file();
  89. dispatch_fd_t fd = dispatch_test_fd_open(path, O_RDONLY);
  90. if (fd == -1)
  91. {
  92. perror(path);
  93. exit(EXIT_FAILURE);
  94. }
  95. dispatch_test_release_large_file(path);
  96. free(path);
  97. if (!dispatch_test_check_evfilt_read_for_fd(fd)) {
  98. test_skip("EVFILT_READ kevent not firing for test file");
  99. dispatch_test_fd_close(fd);
  100. dispatch_async(dispatch_get_main_queue(), ^{
  101. stage1(3);
  102. });
  103. return;
  104. }
  105. ssize_t expected = dispatch_test_fd_lseek(fd, 0, SEEK_END);
  106. dispatch_test_fd_lseek(fd, 0, SEEK_SET);
  107. actual = 0;
  108. dispatch_queue_t main_q = dispatch_get_main_queue();
  109. test_ptr_notnull("main_q", main_q);
  110. dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, (uintptr_t)fd, 0, main_q);
  111. test_ptr_notnull("kevent source", source);
  112. dispatch_source_set_event_handler(source, ^{
  113. size_t est = dispatch_source_get_data(source);
  114. test_sizet_less_than_or_equal("estimated", est, expected - actual);
  115. char buffer[500*1024];
  116. ssize_t sz = dispatch_test_fd_read(fd, buffer, sizeof(buffer));
  117. actual += sz;
  118. if (sz < (ssize_t)sizeof(buffer))
  119. {
  120. sz = dispatch_test_fd_read(fd, buffer, sizeof(buffer));
  121. actual += sz;
  122. test_long("EOF", sz, 0);
  123. dispatch_source_cancel(source);
  124. }
  125. });
  126. dispatch_source_set_cancel_handler(source, ^{
  127. test_long("bytes read", actual, expected);
  128. int res = dispatch_test_fd_close(fd);
  129. test_errno("close", res == -1 ? errno : 0, 0);
  130. dispatch_release(source);
  131. dispatch_async(dispatch_get_main_queue(), ^{
  132. stage1(3);
  133. });
  134. });
  135. dispatch_resume(source);
  136. }
  137. void
  138. finish(void* cxt)
  139. {
  140. test_ptr("finish", cxt, cxt);
  141. test_stop();
  142. }
  143. int
  144. main(void)
  145. {
  146. dispatch_test_start("Dispatch select workaround test"); // <rdar://problem/7678012>
  147. dispatch_async(dispatch_get_main_queue(), ^{
  148. stage1(1);
  149. });
  150. dispatch_main();
  151. }