111 lines · cpp
1// RUN: %clangxx -g %s -o %t && %run %t | FileCheck %s2 3// CHECK: READ CALLED; len={{[0-9]*}}4// CHECK-NEXT: READ: test5// CHECK-NEXT: WRITE CALLED: test6// CHECK-NEXT: READ CALLED; len={{[0-9]*}}7// CHECK-NEXT: READ: test8// CHECK-NEXT: WRITE CALLED: test9// CHECK-NEXT: CLOSE CALLED10// CHECK-NEXT: SEEK CALLED; off=100, whence=011// CHECK-NEXT: READ CALLED; len={{[0-9]*}}12// CHECK-NEXT: READ: test13// CHECK-NEXT: WRITE CALLED: test14// CHECK-NEXT: FLUSH CALLED15// CHECK-NEXT: WRITE CALLED: test16// CHECK-NEXT: FLUSH CALLED17 18#include <assert.h>19#include <stdio.h>20#include <stdlib.h>21#include <string.h>22 23int cookie_var;24 25ssize_t f_read(void *cookie, void *buf, size_t len) {26 assert(cookie == &cookie_var);27 assert(len >= 6);28 printf("READ CALLED; len=%zd\n", len);29 return strlcpy((char*)buf, "test\n", len);30}31 32ssize_t f_write(void *cookie, const void *buf, size_t len) {33 assert(cookie == &cookie_var);34 char *data = strndup((char*)buf, len);35 assert(data);36 printf("WRITE CALLED: %s\n", data);37 free(data);38 return len;39}40 41off_t f_seek(void *cookie, off_t off, int whence) {42 assert(cookie == &cookie_var);43 assert(whence == SEEK_SET);44 printf("SEEK CALLED; off=%d, whence=%d\n", (int)off, whence);45 return off;46}47 48int f_flush(void *cookie) {49 assert(cookie == &cookie_var);50 printf("FLUSH CALLED\n");51 return 0;52}53 54int f_close(void *cookie) {55 assert(cookie == &cookie_var);56 printf("CLOSE CALLED\n");57 return 0;58}59 60int main(void) {61 FILE *fp;62 char buf[10];63 64 // 1. read-only variant65 fp = fropen2(&cookie_var, f_read);66 assert(fp);67 // verify that fileno() does not crash or report nonsense68 assert(fileno(fp) == -1);69 assert(fgets(buf, sizeof(buf), fp));70 printf("READ: %s", buf);71 assert(!fclose(fp));72 73 // 2. write-only variant74 fp = fwopen2(&cookie_var, f_write);75 assert(fp);76 assert(fileno(fp) == -1);77 assert(fputs("test", fp) >= 0);78 assert(!fclose(fp));79 80 // 3. read+write+close81 fp = funopen2(&cookie_var, f_read, f_write, NULL, NULL, f_close);82 assert(fp);83 assert(fileno(fp) == -1);84 assert(fgets(buf, sizeof(buf), fp));85 printf("READ: %s", buf);86 assert(fputs("test", fp) >= 0);87 assert(!fflush(fp));88 assert(!fclose(fp));89 90 // 4. read+seek91 fp = funopen2(&cookie_var, f_read, NULL, f_seek, NULL, NULL);92 assert(fp);93 assert(fileno(fp) == -1);94 assert(fseek(fp, 100, SEEK_SET) == 0);95 assert(fgets(buf, sizeof(buf), fp));96 printf("READ: %s", buf);97 assert(!fclose(fp));98 99 // 5. write+flush100 fp = funopen2(&cookie_var, NULL, f_write, NULL, f_flush, NULL);101 assert(fp);102 assert(fileno(fp) == -1);103 assert(fputs("test", fp) >= 0);104 assert(!fflush(fp));105 assert(fputs("test", fp) >= 0);106 // NB: fclose() also implicitly calls flush107 assert(!fclose(fp));108 109 return 0;110}111