├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── lib ├── CMakeLists.txt ├── Makefile.standalone ├── README.md ├── bw-tool.c ├── bw.c ├── bw.h ├── rationale.txt ├── signals.txt └── ux.c ├── src ├── CMakeLists.txt ├── internals.txt ├── shr.c └── shr.h ├── tests ├── CMakeLists.txt ├── Makefile.standalone ├── do_tests.py ├── perf-farm.c ├── perf.c ├── test1.ans ├── test1.c ├── test10.ans ├── test10.c ├── test100.ans ├── test100.c ├── test101.ans ├── test101.c ├── test102.ans ├── test102.c ├── test103.ans ├── test103.c ├── test104.ans ├── test104.c ├── test11.ans ├── test11.c ├── test12.ans ├── test12.c ├── test13.ans ├── test13.c ├── test14.ans ├── test14.c ├── test15.ans ├── test15.c ├── test16.ans ├── test16.c ├── test17.ans ├── test17.c ├── test18.ans ├── test18.c ├── test19.ans ├── test19.c ├── test2.ans ├── test2.c ├── test20.ans ├── test20.c ├── test21.ans ├── test21.c ├── test22.ans ├── test22.c ├── test23.ans ├── test23.c ├── test24.ans ├── test24.c ├── test25.ans ├── test25.c ├── test26.ans ├── test26.c ├── test27.ans ├── test27.c ├── test28.ans ├── test28.c ├── test29.ans ├── test29.c ├── test3.ans ├── test3.c ├── test30.ans ├── test30.c ├── test31.ans ├── test31.c ├── test32.ans ├── test32.c ├── test33.ans ├── test33.c ├── test34.ans ├── test34.c ├── test35.ans ├── test35.c ├── test36.ans ├── test36.c ├── test37.ans ├── test37.c ├── test38.ans ├── test38.c ├── test39.ans ├── test39.c ├── test4.ans ├── test4.c ├── test40.ans ├── test40.c ├── test41.ans ├── test41.c ├── test42.ans ├── test42.c ├── test43.ans ├── test43.c ├── test44.ans ├── test44.c ├── test45.ans ├── test45.c ├── test46.ans ├── test46.c ├── test47.ans ├── test47.c ├── test48.ans ├── test48.c ├── test49.ans ├── test49.c ├── test5.ans ├── test5.c ├── test50.ans ├── test50.c ├── test51.ans ├── test51.c ├── test52.ans ├── test52.c ├── test53.ans ├── test53.c ├── test54.ans ├── test54.c ├── test55.ans ├── test55.c ├── test56.ans ├── test56.c ├── test57.ans ├── test57.c ├── test58.ans ├── test58.c ├── test59.ans ├── test59.c ├── test6.ans ├── test6.c ├── test60.ans ├── test60.c ├── test61.ans ├── test61.c ├── test62.ans ├── test62.c ├── test63.ans ├── test63.c ├── test64.ans ├── test64.c ├── test65.ans ├── test65.c ├── test66.ans ├── test66.c ├── test67.ans ├── test67.c ├── test68.ans ├── test68.c ├── test69.ans ├── test69.c ├── test7.ans ├── test7.c ├── test70.ans ├── test70.c ├── test71.ans ├── test71.c ├── test72.ans ├── test72.c ├── test73.ans ├── test73.c ├── test74.ans ├── test74.c ├── test75.ans ├── test75.c ├── test76.ans ├── test76.c ├── test77.ans ├── test77.c ├── test78.ans ├── test78.c ├── test79.ans ├── test79.c ├── test8.ans ├── test8.c ├── test80.ans ├── test80.c ├── test81.ans ├── test81.c ├── test82.ans ├── test82.c ├── test83.ans ├── test83.c ├── test84.ans ├── test84.c ├── test85.ans ├── test85.c ├── test86.ans ├── test86.c ├── test87.ans ├── test87.c ├── test88.ans ├── test88.c ├── test89.ans ├── test89.c ├── test9.ans ├── test9.c ├── test90.ans ├── test90.c ├── test91.ans ├── test91.c ├── test92.ans ├── test92.c ├── test93.ans ├── test93.c ├── test94.ans ├── test94.c ├── test95.ans ├── test95.c ├── test96.ans ├── test96.c ├── test97.ans ├── test97.c ├── test98.ans ├── test98.c ├── test99.ans └── test99.c └── util ├── .gitignore ├── CMakeLists.txt ├── README.md └── shr-tool.c /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.a 3 | *.swp 4 | Makefile 5 | .gdb_history 6 | test[0-9] 7 | test[0-9][0-9] 8 | perf 9 | perf-farm 10 | *.ring 11 | build 12 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.11.4) 2 | project(SHR) 3 | set(CMAKE_CXX_STANDARD 11) 4 | 5 | add_subdirectory(lib) 6 | add_subdirectory(src) 7 | add_subdirectory(util) 8 | 9 | # "make test" builds and executes them 10 | add_subdirectory(tests EXCLUDE_FROM_ALL) 11 | add_custom_target(test DEPENDS run-tests) 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | © 2017 The Johns Hopkins University Applied Physics Laboratory LLC. All Rights Reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.11.4) 2 | set(CMAKE_CXX_STANDARD 11) 3 | 4 | # libbw is a convenience library. 5 | # Build as static, do not install. 6 | # PIC for inclusion in shared lib. 7 | add_library(bw STATIC EXCLUDE_FROM_ALL bw.c bw.h ux.c) 8 | set_target_properties(bw PROPERTIES POSITION_INDEPENDENT_CODE ON) 9 | 10 | # Add ourself as include directory to user (shr) 11 | target_include_directories(bw INTERFACE 12 | $ 13 | ) 14 | 15 | 16 | # bw-tool dev utility; do not install 17 | add_executable(bw-tool bw-tool.c) 18 | target_link_libraries(bw-tool bw) 19 | -------------------------------------------------------------------------------- /lib/Makefile.standalone: -------------------------------------------------------------------------------- 1 | all: bw.o ux.o bw-tool 2 | 3 | CFLAGS=-Wall -Wextra -g 4 | 5 | bw.o ux.o: %.o:%.c 6 | $(CC) $(CFLAGS) -c $< 7 | 8 | bw-tool: %:%.o 9 | $(CC) $(CFLAGS) -o $@ $< bw.o ux.o 10 | 11 | .PHONY: clean 12 | 13 | clean: 14 | rm -f *.o bw-tool 15 | -------------------------------------------------------------------------------- /lib/README.md: -------------------------------------------------------------------------------- 1 | Blocking / waking library 2 | 3 | Processes can use this library to convey resource availability. 4 | 5 | See rationale for why this library uses UNIX domain sockets in the 6 | abstract namespace as its implementation. 7 | 8 | 1. Embed `bw_handle` in to data structure containing shared resource 9 | 2. Lock the shared resource in which `bw_handle` is embedded, before 10 | calling `bw` functions, except those with ul ("unlocked") suffix. 11 | 3. Any number of processes can open the handle for waking others up. 12 | 4. Up to `BW_WAITMAX` processes can open the handle open for waiting. 13 | 5. A wakeup wakes up ALL the waiting processes 14 | 6. A waiting process can epoll to wait, on the descriptor from `bw_open`. 15 | Alternatively it can use the `bw_wait_ul` API call. 16 | 7. An awakened process can schedule immediate reawakening using `bw_force`. 17 | 8. An awakened process can discard remaining, pending wakeups using `bw_force`. 18 | 9. Trace can be enabled in `bw_open` flags. This logs "who wakes who" up. 19 | 10. Blocking in `bw_wait_ul` can monitor additional descriptors; see `bw_ctl` 20 | 21 | -------------------------------------------------------------------------------- /lib/bw.h: -------------------------------------------------------------------------------- 1 | #include 2 | #ifndef _BLOCK_WAKE_H_ 3 | #define _BLOCK_WAKE_H_ 4 | #if defined __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | /* CFLAG -DBW_SILENT silences error messages */ 9 | #ifndef BW_SILENT 10 | #include 11 | #define bw_log(...) do { fprintf(stderr, __VA_ARGS__); } while(0) 12 | #define bw_trace(w, ...) do { if ((w) & BW_TRACE) fprintf(stderr, __VA_ARGS__); } while(0) 13 | #else 14 | #define bw_log(...) do { } while(0) 15 | #define bw_trace(w, ...) do { } while(0) 16 | #endif 17 | 18 | /* bw_handle 19 | * 20 | * this structure must be free of pointers, as 21 | * we require it be usable when mapped into the 22 | * address space of N unrelated processes. 23 | */ 24 | #define BW_NAMELEN 8 25 | #define BW_WAITMAX 64 26 | struct bw_handle { 27 | int seqno; 28 | struct { 29 | pid_t pid; 30 | char name[BW_NAMELEN]; 31 | } wr[BW_WAITMAX]; 32 | }; 33 | 34 | struct bw_t; 35 | typedef struct bw_t bw_t; 36 | typedef struct bw_handle bw_handle; 37 | 38 | #define BW_WAKE (1U << 1) 39 | #define BW_WAIT (1U << 2) 40 | #define BW_TRACE (1U << 3) 41 | #define BW_POLLFD (1U << 4) /* bw_ctl flag */ 42 | 43 | /* API */ 44 | bw_t * bw_open(int flags, bw_handle *h, ...); /* CALL WITH HANDLE UNDER LOCK */ 45 | int bw_wake(bw_t *w); /* CALL WITH HANDLE UNDER LOCK */ 46 | void bw_close(bw_t *w); /* CALL WITH HANDLE UNDER LOCK */ 47 | int bw_force(bw_t *w, int ready); /* CALL WITH HANDLE UNDER LOCK */ 48 | int bw_ready_ul(bw_t *w); /* call WITHOUT lock on handle */ 49 | int bw_wait_ul(bw_t *w); /* call WITHOUT lock on handle */ 50 | int bw_ctl(bw_t *w, int flag, ...); /* call WITHOUT lock on handle */ 51 | 52 | #if defined __cplusplus 53 | } 54 | #endif 55 | #endif 56 | -------------------------------------------------------------------------------- /lib/rationale.txt: -------------------------------------------------------------------------------- 1 | This small library is for a set of unrelated processes to implement a blocking- 2 | awakening relationship. If the processes were related we could use an eventfd. 3 | For unrelated processes, tcp or udp or unix sockets or named pipes would all 4 | work, or POSIX sempahores or message queues. As explained below, I've chosen 5 | to use unix domain datagram sockets, in the linux abstract socket namespace. 6 | 7 | The use case for this library, is when two or more processes share some 8 | external resource, and need to communicate availability (say, of new 9 | data) in the resource. The process who puts the new data into the resource 10 | wakes up the processes waiting for it. In this use case, the shared resource is 11 | accessed under lock by only one process at a time. 12 | 13 | This little library is designed for loosely coupled processes. That means, the 14 | processes that block, and the process that wakes up the blockers, work fine if 15 | the peers go away, don't exist in the first place, or come into existence late. 16 | 17 | In this design, it's also fine if the waker wakes the blocker spuriously (too 18 | many times, or when there is no reason to be awakened); these things can happen 19 | due to messages being produced and consumed by multiple processes and in 20 | batches, etc. It is easier to design for spurious wakeups than to root out all 21 | ways they can happen. 22 | 23 | Besides loose coupling, my goals were: 24 | 25 | - epoll / select / poll compatibility 26 | - clean up of any resources/artifacts when the blockers/wakers exit 27 | - traceability for debugging (e.g. trace PID that sent a wakeup) 28 | 29 | These three goals exclude a sem_wait based solution. Besides, semaphores would 30 | also introduce a pthreads dependendency. 31 | 32 | POSIX message queues are epoll-compatible on Linux. Unfortunately they have 33 | kernel persistence. That conflicts with my goal of having the artifacts (in 34 | the case of semaphores, /dev/shm files) released automatically if the process 35 | exits abnormally. 36 | 37 | By using unix domain datagram sockets, with autobind, in the abstract 38 | namespace, the kernel generates a unique identity for each waiting caller. 39 | Furthermore an abstract socket goes away automatically when the caller exits. 40 | -------------------------------------------------------------------------------- /lib/signals.txt: -------------------------------------------------------------------------------- 1 | Signals 2 | 3 | This refers to an older version of bw-tool that did not use signalfd and epoll. 4 | It describes how signals affect a program blocked in select. 5 | 6 | Example 1 SIGHUP (termination in default signal handler) 7 | 8 | The HUP signal has a default signal handler that causes process termination. 9 | 10 | % bw-tool -r blob make 11 | % bw-tool -r blob wait # in terminal window 1 12 | % kill -HUP $(pidof bw-tool) # in terminal window 2 13 | 14 | Internally waitlib is blocked in select when the signal occurs. (Nowadays 15 | waitlib uses epoll, but the principle is the same). Under strace, this is 16 | observed: 17 | 18 | select(5, [4], NULL, ...) = ? ERESTARTNOHAND (To be restarted if no handler) 19 | --- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=45616, si_uid=1000} --- 20 | +++ killed by SIGHUP +++ 21 | 22 | The program terminated due to the default handler. 23 | 24 | Example 2 SIGWINCH (no signal handler, automatic restart of system call) 25 | 26 | % bw-tool -r blob make 27 | % bw-tool -r blob wait # in terminal window 1 28 | % kill -WINCH $(pidof bw-tool) # in terminal window 2 29 | 30 | An application has no signal handlers explicitly installed. Internally waitlib 31 | is blocked in select when the signal occurs. Under strace, this is observed: 32 | 33 | select(5, [4], NULL, ...) = ? ERESTARTNOHAND (To be restarted if no handler) 34 | --- SIGWINCH {si_signo=SIGWINCH, si_code=SI_USER, si_pid=45616, si_uid=1000} 35 | select(5, [4], NULL, NULL, NULL 36 | 37 | As strace shows, the select was restarted; it never returned. 38 | 39 | --- 40 | 41 | In new programs that use waitlib - the preferred strategy is to block all 42 | signals with sigprocmask. Establish a signal set that the application wants 43 | to receive and create a signalfd from it. Use epoll to monitor the signalfd 44 | and the descriptor from waitlib, for a wait-mode caller. If the application 45 | uses `bw_wait_ul` to block (rather than its own epoll loop), utilize bw_ctl 46 | ahead of time to provide the signalfd as a secondary descriptor to monitor. 47 | 48 | 49 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.11.4) 2 | set(CMAKE_CXX_STANDARD 11) 3 | 4 | # shr library 5 | # link with libbw.a 6 | add_library(shr SHARED shr.c) 7 | target_link_libraries(shr bw) 8 | 9 | # install shr library and its public header 10 | set_target_properties(shr PROPERTIES PUBLIC_HEADER shr.h) 11 | install(TARGETS shr) 12 | # run ldconfig 13 | if (UNIX) 14 | install(CODE "execute_process(COMMAND ldconfig)") 15 | endif() 16 | 17 | -------------------------------------------------------------------------------- /src/internals.txt: -------------------------------------------------------------------------------- 1 | Some notes on the internals 2 | 3 | The ring is structured as 4 | 5 | CONTROL - DATA - PADDING - MSGVEC - APPDATA 6 | 7 | The bulk of the ring is normally the DATA area. Messages are 8 | stored in it; their offsets are in the MSGVEC array of slots. 9 | From this we can already understand that the capacity of the 10 | ring is limited by size of the DATA region and the number of 11 | slots in MSGVEC. (DATA is given at the time of ring creation 12 | as the size argument, while MSGVEC slots are either guessed 13 | using a heuristic or explicitly as an optional MAXMSGS_2 14 | parameter to shr_init). 15 | 16 | The MSGVEC tracks which slot refers to the "eldest" message. 17 | The eldest is used for FARM mode readers, which start reads 18 | at the oldest message present in the ring. 19 | 20 | In versions of libshr prior to SHR_FARM mode, there was no 21 | MSGVEC and instead the messages were length-prefixed in the 22 | DATA region. While the code was straightforward this way, 23 | the disadvantage is that SHR_DROP mode had to reclaim space 24 | by "hopping" from message-to-message, finding their length 25 | prefixes before each message, in order to prepare for a 26 | write. If there are, say, 10,000 messages that have to be 27 | hopped through to free space, that is a lot of scattered 28 | memory access. Instead the MSGVEC now allows DROP mode to 29 | easily reclaim space by scanning a concise slot array. It 30 | also makes FARM mode possible (or even, random access for 31 | FARM readers, although there is no API for this right now). 32 | 33 | The slots have a sequence number associated with them. The 34 | first message ever to go into the ring has sequence number 35 | zero. The sequence numbers are not stored anywhere, they 36 | are implied from the "sequence number of the eldest slot". 37 | That is stored in r->q. The eldest slot has offset r->e 38 | in the MSGVEC. The eldest slot, and the sequence number 39 | concept, is only important for FARM mode, since the FARM 40 | readers all have their own positions, and need to jump to 41 | the newest message if they miss too many messages. 42 | 43 | The APPDATA is opaque and needs no API or code support 44 | except to store and read it. It is for storing caller 45 | data that it wants to keep with the ring. 46 | 47 | -------------------------------------------------------------------------------- /src/shr.h: -------------------------------------------------------------------------------- 1 | #ifndef _SHARED_RING_H_ 2 | #define _SHARED_RING_H_ 3 | 4 | #include /* struct timeval (for stats) */ 5 | #include /* struct iovec (for readv/writev) */ 6 | 7 | #if defined __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | /* -DSHR_SILENT silences error logging to stderr 12 | * from shr/bw libs; error codes still returned */ 13 | #ifndef SHR_SILENT 14 | #include 15 | #define shr_log(...) do { fprintf(stderr, __VA_ARGS__); } while(0) 16 | #else 17 | #define shr_log(...) do { } while(0) 18 | #define BW_SILENT 19 | #endif 20 | 21 | /* opaque data structure */ 22 | struct shr; 23 | typedef struct shr shr; 24 | 25 | /* stats structure */ 26 | struct shr_stat { 27 | 28 | /* stats for the current period. 29 | * caller resets these at will. 30 | */ 31 | struct timeval start; /* start of the stats period (last reset) */ 32 | size_t bw, br; /* bytes written to/read from ring in period */ 33 | size_t mw, mr; /* messages written to/read from ring in period */ 34 | size_t md, bd; /* in drop mode: messages dropped/bytes dropped */ 35 | 36 | /* this set of numbers describes the ring, 37 | * in terms of its size and unread content. 38 | * a reset has no bearing on these numbers. 39 | */ 40 | size_t bn; /* ring size in bytes */ 41 | size_t bu; /* current unread bytes (ready to read) in ring */ 42 | size_t mu; /* current unread messages (ready to read) in ring */ 43 | size_t mm; /* max number of messages ring can hold */ 44 | 45 | /* cache state in SHR_BUFFERED mode. 46 | * reflects the calling client only. 47 | */ 48 | size_t cn; /* cache size in bytes */ 49 | size_t cm; /* messages in cache */ 50 | size_t cb; /* bytes in cache */ 51 | 52 | /* ring attributes */ 53 | unsigned flags; 54 | }; 55 | 56 | int shr_init(char *file, size_t sz, unsigned flags, ...); 57 | shr *shr_open(const char *file, unsigned flags, ...); 58 | int shr_get_selectable_fd(shr *s); 59 | ssize_t shr_read(shr *s, char *buf, size_t len); 60 | ssize_t shr_write(shr *s, char *buf, size_t len); 61 | ssize_t shr_readv(shr *s, char *buf, size_t len, struct iovec *iov, size_t *iovcnt); 62 | ssize_t shr_writev(shr *s, struct iovec *iov, size_t iovcnt); 63 | ssize_t shr_flush(struct shr *s, int wait); 64 | void shr_close(shr *s); 65 | int shr_appdata(shr *s, void **get, void *set, size_t *sz); 66 | int shr_stat(shr *s, struct shr_stat *stat, struct timeval *reset); 67 | size_t shr_farm_stat(shr *s, int reset); 68 | int shr_ctl(shr *s, int flag, ...); 69 | 70 | /* flags */ 71 | 72 | #define SHR_KEEPEXIST (1U << 0) /* shr_init */ 73 | #define SHR_DROP (1U << 1) /* shr_init */ 74 | #define SHR_APPDATA_1 (1U << 2) /* shr_init */ 75 | #define SHR_FARM (1U << 3) /* shr_init */ 76 | #define SHR_MAXMSGS_2 (1U << 4) /* shr_init */ 77 | #define SHR_SYNC (1U << 5) /* shr_init */ 78 | #define SHR_MLOCK (1U << 6) /* shr_init */ 79 | #define SHR_OPEN_FENCE (1U << 12) /* barrier between init and open flags */ 80 | #define SHR_RDONLY (1U << 13) /* shr_open */ 81 | #define SHR_WRONLY (1U << 14) /* shr_open */ 82 | #define SHR_NONBLOCK (1U << 15) /* shr_open */ 83 | #define SHR_BUFFERED (1U << 16) /* shr_open */ 84 | #define SHR_POLLFD (1U << 17) /* shr_ctl */ 85 | 86 | #define SHR_APPDATA SHR_APPDATA_1 /* shr_init alias */ 87 | #define SHR_MESSAGES (0) /* shr_init obsolete / always enabled */ 88 | #define SHR_OVERWRITE (0) /* shr_init obsolete / default enabled */ 89 | 90 | #if defined __cplusplus 91 | } 92 | #endif 93 | #endif 94 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.11.4) 2 | set(CMAKE_CXX_STANDARD 11) 3 | 4 | file(GLOB tests test*.c) 5 | foreach (test IN LISTS tests) 6 | 7 | # Convert /abs/path/to/test10.c to test10.c */ 8 | file(RELATIVE_PATH test ${CMAKE_CURRENT_SOURCE_DIR} ${test}) 9 | # Form name of test executable; test10.c becomes test10 */ 10 | string(REGEX MATCH "^test[0-9]+" exe ${test}) 11 | 12 | list(APPEND exes ${exe}) 13 | add_executable(${exe} ${test}) 14 | target_link_libraries(${exe} shr) 15 | endforeach() 16 | 17 | add_custom_target(run-tests 18 | DEPENDS ${exes} 19 | COMMAND ./do_tests.py ${CMAKE_CURRENT_BINARY_DIR} 20 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 21 | ) 22 | -------------------------------------------------------------------------------- /tests/Makefile.standalone: -------------------------------------------------------------------------------- 1 | SRCS=$(wildcard test*.c) 2 | PROGS=$(patsubst %.c,%, $(SRCS)) 3 | OBJS =$(patsubst %.c,%.o,$(SRCS)) 4 | 5 | CFLAGS = -I../src -I../lib 6 | CFLAGS += -Wall -Wextra 7 | #CFLAGS += -g -O0 8 | CFLAGS += -O2 9 | 10 | STATIC_OBJS=shr.o bw.o ux.o 11 | 12 | all: $(STATIC_OBJS) $(PROGS) tests 13 | 14 | # rather than using libtool which turns our 15 | # tests into shell scripts, to dynamically 16 | # link the pre-installed ../src/libshr.so, 17 | # this Makefile builds the ../src/ objects 18 | # itself and links them right in statically 19 | $(STATIC_OBJS): 20 | $(CC) -c $(CFLAGS) ../src/shr.c 21 | $(CC) -c $(CFLAGS) ../lib/bw.c 22 | $(CC) -c $(CFLAGS) ../lib/ux.c 23 | 24 | perf perf-farm: $(STATIC_OBJS) 25 | $(CC) -o $@ $(CFLAGS) $@.c $(STATIC_OBJS) 26 | 27 | # static pattern rule: multiple targets 28 | $(OBJS): %.o: %.c 29 | $(CC) -c $(CFLAGS) $< 30 | 31 | $(PROGS): %: %.o $(STATIC_OBJS) 32 | $(CC) -o $@ $(CFLAGS) $< $(STATIC_OBJS) $(LDFLAGS) 33 | 34 | .PHONY: clean tests 35 | 36 | tests: 37 | ./do_tests.py 38 | 39 | clean: 40 | rm -f $(PROGS) *.out *.ring *.o 41 | -------------------------------------------------------------------------------- /tests/do_tests.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # 4 | # shr test harness 5 | # 6 | # This script should be run in the source directory shr/tests. 7 | # It expects, as a parameter, the path to the build directory. 8 | # 9 | # 10 | 11 | from sys import argv 12 | from os.path import isfile 13 | from glob import glob 14 | from subprocess import run 15 | 16 | def main(argv): 17 | bindir = argv[1] if (len(argv) > 1) else "../build/tests" 18 | 19 | # get list of compiled tests in binary dir 20 | all_tests = glob("test*[0-9]", root_dir=bindir) 21 | 22 | # use only the tests having .ans files 23 | ans_tests = [x for x in all_tests if isfile(x + ".ans")] 24 | 25 | # sort tests by numeric suffix 26 | tests = sorted(ans_tests, key=lambda name: int(name[4:])) 27 | 28 | # form path to each test in bindir so PATH isn't searched 29 | qualified_tests = [bindir + "/" + x for x in tests] 30 | 31 | # form a trio of lists that we can iterate through tuples 32 | paths = zip(tests, qualified_tests, [x+".ans" for x in tests]) 33 | 34 | for test, path, ans in paths: 35 | print(test, flush=True) 36 | out = run([path], capture_output=True, text=True) 37 | if (out.stderr): 38 | print(out.stderr) 39 | with open(ans, 'r') as ansfile: 40 | anstext = ansfile.read() 41 | if (out.stdout != anstext): 42 | print(test + " failed") 43 | 44 | if __name__ == "__main__": 45 | main(argv) 46 | -------------------------------------------------------------------------------- /tests/test1.ans: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/troydhanson/shr/c77e2709dcc7f81f4e2985ac7522993e3cde63d1/tests/test1.ans -------------------------------------------------------------------------------- /tests/test1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "shr.h" 4 | 5 | char *ring = __FILE__ ".ring"; 6 | 7 | int main() { 8 | setlinebuf(stdout); 9 | int rc = -1; 10 | 11 | unlink(ring); 12 | if (shr_init(ring, 1024, 0) < 0) goto done; 13 | 14 | rc = 0; 15 | 16 | done: 17 | unlink(ring); 18 | return rc; 19 | } 20 | -------------------------------------------------------------------------------- /tests/test10.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | f: do_open 3 | r: do_open 4 | w: do_fill 5 | w: wrote 10 messages (to seq 10) 6 | f: do_read_one 7 | 0 8 | r: do_read_half 9 | 0 10 | 1 11 | 2 12 | 3 13 | 4 14 | w: do_fill 15 | w: wrote 10 messages (to seq 20) 16 | f: do_read_one 17 | 10 18 | r: do_read_one 19 | 10 20 | f: do_farm_stat 21 | drops: 9 22 | r: do_farm_stat 23 | drops: 5 24 | w: do_close 25 | f: do_close 26 | r: do_close 27 | w: do_exit 28 | w: exiting 29 | f: do_exit 30 | f: exiting 31 | r: do_exit 32 | r: exiting 33 | end 34 | -------------------------------------------------------------------------------- /tests/test100.ans: -------------------------------------------------------------------------------- 1 | bw 6 br 0 mw 3 mr 0 md 0 bd 0 bn 6 bu 6 mu 3 2 | bw 12 br 0 mw 6 mr 0 md 3 bd 6 bn 6 bu 6 mu 3 3 | read gg 4 | read hh 5 | read ii 6 | -------------------------------------------------------------------------------- /tests/test100.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | char *ring = __FILE__ ".ring"; 14 | int ring_sz = 6; 15 | int nmsg = 100; 16 | 17 | void stats(struct shr *s) { 18 | struct shr_stat ss; 19 | int sc; 20 | 21 | sc = shr_stat(s, &ss, NULL); 22 | if (sc < 0) { 23 | fprintf(stderr, "shr_stat: error\n"); 24 | return; 25 | } 26 | 27 | printf("bw %ld br %ld mw %ld mr %ld md %ld bd %ld bn %ld bu %ld mu %ld\n", 28 | ss.bw, ss.br, ss.mw, ss.mr, ss.md, ss.bd, ss.bn, ss.bu, ss.mu); 29 | } 30 | 31 | int main() { 32 | struct shr *s=NULL; 33 | struct shr *r=NULL; 34 | int rc = -1, sc; 35 | char buf[5]; 36 | ssize_t nr; 37 | 38 | unlink(ring); 39 | sc = shr_init(ring, ring_sz, SHR_DROP|SHR_MAXMSGS_2, nmsg); 40 | if (sc < 0) { 41 | fprintf(stderr, "shr_init: error\n"); 42 | goto done; 43 | } 44 | 45 | s = shr_open(ring, SHR_WRONLY); 46 | r = shr_open(ring, SHR_RDONLY); 47 | 48 | nr = shr_write(s, "aa", 2); 49 | assert(nr == 2); 50 | nr = shr_write(s, "bb", 2); 51 | assert(nr == 2); 52 | nr = shr_write(s, "cc", 2); 53 | assert(nr == 2); 54 | stats(s); 55 | 56 | nr = shr_write(s, "gg", 2); 57 | assert(nr == 2); 58 | nr = shr_write(s, "hh", 2); 59 | assert(nr == 2); 60 | nr = shr_write(s, "ii", 2); 61 | assert(nr == 2); 62 | stats(s); 63 | 64 | nr = shr_read(r, buf, sizeof(buf)); 65 | assert(nr == 2); 66 | printf("read %.*s\n", (int)nr, buf); 67 | 68 | nr = shr_read(r, buf, sizeof(buf)); 69 | assert(nr == 2); 70 | printf("read %.*s\n", (int)nr, buf); 71 | 72 | nr = shr_read(r, buf, sizeof(buf)); 73 | assert(nr == 2); 74 | printf("read %.*s\n", (int)nr, buf); 75 | 76 | 77 | done: 78 | if (s) shr_close(s); 79 | if (r) shr_close(r); 80 | unlink(ring); 81 | return rc; 82 | } 83 | 84 | -------------------------------------------------------------------------------- /tests/test101.ans: -------------------------------------------------------------------------------- 1 | bw 6 br 0 mw 3 mr 0 md 0 bd 0 bn 7 bu 6 mu 3 2 | bw 12 br 0 mw 6 mr 0 md 3 bd 6 bn 7 bu 6 mu 3 3 | read dd 4 | read ee 5 | read ff 6 | -------------------------------------------------------------------------------- /tests/test101.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | char *ring = __FILE__ ".ring"; 14 | int ring_sz = 7; 15 | int nmsg = 100; 16 | 17 | void stats(struct shr *s) { 18 | struct shr_stat ss; 19 | int sc; 20 | 21 | sc = shr_stat(s, &ss, NULL); 22 | if (sc < 0) { 23 | fprintf(stderr, "shr_stat: error\n"); 24 | return; 25 | } 26 | 27 | printf("bw %ld br %ld mw %ld mr %ld md %ld bd %ld bn %ld bu %ld mu %ld\n", 28 | ss.bw, ss.br, ss.mw, ss.mr, ss.md, ss.bd, ss.bn, ss.bu, ss.mu); 29 | } 30 | 31 | int main() { 32 | struct shr *s=NULL; 33 | struct shr *r=NULL; 34 | int rc = -1, sc; 35 | char buf[5]; 36 | ssize_t nr; 37 | 38 | unlink(ring); 39 | sc = shr_init(ring, ring_sz, SHR_DROP|SHR_MAXMSGS_2, nmsg); 40 | if (sc < 0) { 41 | fprintf(stderr, "shr_init: error\n"); 42 | goto done; 43 | } 44 | 45 | s = shr_open(ring, SHR_WRONLY); 46 | r = shr_open(ring, SHR_RDONLY); 47 | 48 | nr = shr_write(s, "aa", 2); 49 | assert(nr == 2); 50 | nr = shr_write(s, "bb", 2); 51 | assert(nr == 2); 52 | nr = shr_write(s, "cc", 2); 53 | assert(nr == 2); 54 | stats(s); 55 | 56 | nr = shr_write(s, "dd", 2); /* dabbccd */ 57 | assert(nr == 2); 58 | nr = shr_write(s, "ee", 2); /* deebccd */ 59 | assert(nr == 2); 60 | nr = shr_write(s, "ff", 2); /* deeffcd */ 61 | assert(nr == 2); 62 | stats(s); 63 | 64 | nr = shr_read(r, buf, sizeof(buf)); 65 | assert(nr == 2); 66 | printf("read %.*s\n", (int)nr, buf); 67 | 68 | nr = shr_read(r, buf, sizeof(buf)); 69 | assert(nr == 2); 70 | printf("read %.*s\n", (int)nr, buf); 71 | 72 | nr = shr_read(r, buf, sizeof(buf)); 73 | assert(nr == 2); 74 | printf("read %.*s\n", (int)nr, buf); 75 | 76 | 77 | done: 78 | if (s) shr_close(s); 79 | if (r) shr_close(r); 80 | unlink(ring); 81 | return rc; 82 | } 83 | 84 | -------------------------------------------------------------------------------- /tests/test102.ans: -------------------------------------------------------------------------------- 1 | bw 7 br 0 mw 3 mr 0 md 0 bd 0 bn 7 bu 7 mu 3 2 | bw 13 br 0 mw 6 mr 0 md 3 bd 7 bn 7 bu 6 mu 3 3 | read dd 4 | read ee 5 | read ff 6 | -------------------------------------------------------------------------------- /tests/test102.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | char *ring = __FILE__ ".ring"; 14 | int ring_sz = 7; 15 | int nmsg = 100; 16 | 17 | void stats(struct shr *s) { 18 | struct shr_stat ss; 19 | int sc; 20 | 21 | sc = shr_stat(s, &ss, NULL); 22 | if (sc < 0) { 23 | fprintf(stderr, "shr_stat: error\n"); 24 | return; 25 | } 26 | 27 | printf("bw %ld br %ld mw %ld mr %ld md %ld bd %ld bn %ld bu %ld mu %ld\n", 28 | ss.bw, ss.br, ss.mw, ss.mr, ss.md, ss.bd, ss.bn, ss.bu, ss.mu); 29 | } 30 | 31 | int main() { 32 | struct shr *s=NULL; 33 | struct shr *r=NULL; 34 | int rc = -1, sc; 35 | char buf[5]; 36 | ssize_t nr; 37 | 38 | unlink(ring); 39 | sc = shr_init(ring, ring_sz, SHR_DROP|SHR_MAXMSGS_2, nmsg); 40 | if (sc < 0) { 41 | fprintf(stderr, "shr_init: error\n"); 42 | goto done; 43 | } 44 | 45 | s = shr_open(ring, SHR_WRONLY); 46 | r = shr_open(ring, SHR_RDONLY); 47 | 48 | nr = shr_write(s, "aa", 2); 49 | assert(nr == 2); 50 | nr = shr_write(s, "bb", 2); 51 | assert(nr == 2); 52 | nr = shr_write(s, "ccc", 3); 53 | assert(nr == 3); 54 | stats(s); 55 | 56 | nr = shr_write(s, "dd", 2); /* ddbbccc */ 57 | assert(nr == 2); 58 | nr = shr_write(s, "ee", 2); /* ddeeccc */ 59 | assert(nr == 2); 60 | nr = shr_write(s, "ff", 2); /* ddeeffc */ 61 | assert(nr == 2); 62 | stats(s); 63 | 64 | nr = shr_read(r, buf, sizeof(buf)); 65 | assert(nr == 2); 66 | printf("read %.*s\n", (int)nr, buf); 67 | 68 | nr = shr_read(r, buf, sizeof(buf)); 69 | assert(nr == 2); 70 | printf("read %.*s\n", (int)nr, buf); 71 | 72 | nr = shr_read(r, buf, sizeof(buf)); 73 | assert(nr == 2); 74 | printf("read %.*s\n", (int)nr, buf); 75 | 76 | 77 | done: 78 | if (s) shr_close(s); 79 | if (r) shr_close(r); 80 | unlink(ring); 81 | return rc; 82 | } 83 | 84 | -------------------------------------------------------------------------------- /tests/test103.ans: -------------------------------------------------------------------------------- 1 | bw 7 br 0 mw 3 mr 0 md 0 bd 0 bn 7 bu 7 mu 3 2 | bw 14 br 0 mw 7 mr 0 md 3 bd 7 bn 7 bu 7 mu 4 3 | read dd 4 | read ee 5 | read ff 6 | read g 7 | -------------------------------------------------------------------------------- /tests/test103.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | char *ring = __FILE__ ".ring"; 14 | int ring_sz = 7; 15 | int nmsg = 100; 16 | 17 | void stats(struct shr *s) { 18 | struct shr_stat ss; 19 | int sc; 20 | 21 | sc = shr_stat(s, &ss, NULL); 22 | if (sc < 0) { 23 | fprintf(stderr, "shr_stat: error\n"); 24 | return; 25 | } 26 | 27 | printf("bw %ld br %ld mw %ld mr %ld md %ld bd %ld bn %ld bu %ld mu %ld\n", 28 | ss.bw, ss.br, ss.mw, ss.mr, ss.md, ss.bd, ss.bn, ss.bu, ss.mu); 29 | } 30 | 31 | int main() { 32 | struct shr *s=NULL; 33 | struct shr *r=NULL; 34 | int rc = -1, sc; 35 | char buf[5]; 36 | ssize_t nr; 37 | 38 | unlink(ring); 39 | sc = shr_init(ring, ring_sz, SHR_DROP|SHR_MAXMSGS_2, nmsg); 40 | if (sc < 0) { 41 | fprintf(stderr, "shr_init: error\n"); 42 | goto done; 43 | } 44 | 45 | s = shr_open(ring, SHR_WRONLY); 46 | r = shr_open(ring, SHR_RDONLY); 47 | 48 | nr = shr_write(s, "aa", 2); 49 | assert(nr == 2); 50 | nr = shr_write(s, "bb", 2); 51 | assert(nr == 2); 52 | nr = shr_write(s, "ccc", 3); 53 | assert(nr == 3); 54 | stats(s); 55 | 56 | nr = shr_write(s, "dd", 2); /* ddbbccc */ 57 | assert(nr == 2); 58 | nr = shr_write(s, "ee", 2); /* ddeeccc */ 59 | assert(nr == 2); 60 | nr = shr_write(s, "ff", 2); /* ddeeffc */ 61 | assert(nr == 2); 62 | nr = shr_write(s, "g", 1); /* ddeeffg */ 63 | assert(nr == 1); 64 | stats(s); 65 | 66 | nr = shr_read(r, buf, sizeof(buf)); 67 | assert(nr == 2); 68 | printf("read %.*s\n", (int)nr, buf); 69 | 70 | nr = shr_read(r, buf, sizeof(buf)); 71 | assert(nr == 2); 72 | printf("read %.*s\n", (int)nr, buf); 73 | 74 | nr = shr_read(r, buf, sizeof(buf)); 75 | assert(nr == 2); 76 | printf("read %.*s\n", (int)nr, buf); 77 | 78 | nr = shr_read(r, buf, sizeof(buf)); 79 | assert(nr == 1); 80 | printf("read %.*s\n", (int)nr, buf); 81 | 82 | 83 | done: 84 | if (s) shr_close(s); 85 | if (r) shr_close(r); 86 | unlink(ring); 87 | return rc; 88 | } 89 | 90 | -------------------------------------------------------------------------------- /tests/test104.ans: -------------------------------------------------------------------------------- 1 | bw 7 br 0 mw 3 mr 0 md 0 bd 0 bn 7 bu 7 mu 3 2 | bw 15 br 0 mw 7 mr 0 md 4 bd 9 bn 7 bu 6 mu 3 3 | read ee 4 | read ff 5 | read gg 6 | -------------------------------------------------------------------------------- /tests/test104.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | char *ring = __FILE__ ".ring"; 14 | int ring_sz = 7; 15 | int nmsg = 100; 16 | 17 | void stats(struct shr *s) { 18 | struct shr_stat ss; 19 | int sc; 20 | 21 | sc = shr_stat(s, &ss, NULL); 22 | if (sc < 0) { 23 | fprintf(stderr, "shr_stat: error\n"); 24 | return; 25 | } 26 | 27 | printf("bw %ld br %ld mw %ld mr %ld md %ld bd %ld bn %ld bu %ld mu %ld\n", 28 | ss.bw, ss.br, ss.mw, ss.mr, ss.md, ss.bd, ss.bn, ss.bu, ss.mu); 29 | } 30 | 31 | int main() { 32 | struct shr *s=NULL; 33 | struct shr *r=NULL; 34 | int rc = -1, sc; 35 | char buf[5]; 36 | ssize_t nr; 37 | 38 | unlink(ring); 39 | sc = shr_init(ring, ring_sz, SHR_DROP|SHR_MAXMSGS_2, nmsg); 40 | if (sc < 0) { 41 | fprintf(stderr, "shr_init: error\n"); 42 | goto done; 43 | } 44 | 45 | s = shr_open(ring, SHR_WRONLY); 46 | r = shr_open(ring, SHR_RDONLY); 47 | 48 | nr = shr_write(s, "aa", 2); 49 | assert(nr == 2); 50 | nr = shr_write(s, "bb", 2); 51 | assert(nr == 2); 52 | nr = shr_write(s, "ccc", 3); 53 | assert(nr == 3); 54 | stats(s); 55 | 56 | nr = shr_write(s, "dd", 2); /* ddbbccc */ 57 | assert(nr == 2); 58 | nr = shr_write(s, "ee", 2); /* ddeeccc */ 59 | assert(nr == 2); 60 | nr = shr_write(s, "ff", 2); /* ddeeffc */ 61 | assert(nr == 2); 62 | nr = shr_write(s, "gg", 2); /* gdeeffg */ 63 | assert(nr == 2); 64 | stats(s); 65 | 66 | nr = shr_read(r, buf, sizeof(buf)); 67 | assert(nr == 2); 68 | printf("read %.*s\n", (int)nr, buf); 69 | 70 | nr = shr_read(r, buf, sizeof(buf)); 71 | assert(nr == 2); 72 | printf("read %.*s\n", (int)nr, buf); 73 | 74 | nr = shr_read(r, buf, sizeof(buf)); 75 | assert(nr == 2); 76 | printf("read %.*s\n", (int)nr, buf); 77 | 78 | done: 79 | if (s) shr_close(s); 80 | if (r) shr_close(r); 81 | unlink(ring); 82 | return rc; 83 | } 84 | 85 | -------------------------------------------------------------------------------- /tests/test11.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | f: do_open 3 | r: do_open 4 | w: do_fill 5 | w: wrote 10 messages (to seq 10) 6 | f: do_read_one 7 | 0 8 | r: do_read_half 9 | 0 10 | 1 11 | 2 12 | 3 13 | 4 14 | w: do_fill 15 | w: wrote 10 messages (to seq 20) 16 | f: do_farm_stat 17 | drops: 0 18 | r: do_farm_stat 19 | drops: 0 20 | f: do_read_one 21 | 10 22 | r: do_read_one 23 | 10 24 | f: do_farm_stat 25 | drops: 9 26 | r: do_farm_stat 27 | drops: 5 28 | f: do_farm_stat 29 | drops: 0 30 | r: do_farm_stat 31 | drops: 0 32 | w: do_close 33 | f: do_close 34 | r: do_close 35 | w: do_exit 36 | w: exiting 37 | f: do_exit 38 | f: exiting 39 | r: do_exit 40 | r: exiting 41 | end 42 | -------------------------------------------------------------------------------- /tests/test12.ans: -------------------------------------------------------------------------------- 1 | app_data: now 10 2 | app_data: was 10 3 | app_data: now 20 4 | app_data: now 20 5 | -------------------------------------------------------------------------------- /tests/test12.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "shr.h" 5 | 6 | char *ring = __FILE__ ".ring"; 7 | 8 | struct app_data { 9 | int counter; 10 | } ad, od; 11 | 12 | int main() { 13 | setlinebuf(stdout); 14 | struct shr *s = NULL; 15 | int rc = -1, sc; 16 | void *p; 17 | size_t sz = sizeof(ad); 18 | 19 | unlink(ring); 20 | 21 | sc = shr_init(ring, 8, SHR_APPDATA, &ad, sizeof(ad)); 22 | if (sc < 0) goto done; 23 | 24 | s = shr_open(ring, SHR_RDONLY); 25 | if (s == NULL) goto done; 26 | 27 | ad.counter = 10; 28 | sc = shr_appdata(s, NULL, &ad, &sz); /* no get, set to 10 */ 29 | if (sc < 0) goto done; 30 | 31 | p = &od; 32 | sc = shr_appdata(s, &p, NULL, &sz); /* get 10, no set */ 33 | if (sc < 0) goto done; 34 | printf("app_data: now %d\n", ad.counter); 35 | 36 | ad.counter = 20; 37 | sc = shr_appdata(s, &p, &ad, &sz); /* get 10, set to 20 */ 38 | if (sc < 0) goto done; 39 | printf("app_data: was %d\n", od.counter); 40 | printf("app_data: now %d\n", ad.counter); 41 | 42 | p = NULL; 43 | sz = 0; 44 | sc = shr_appdata(s, &p, NULL, &sz); /* get 20 in mallocd struct */ 45 | if (sc < 0) goto done; 46 | if (p == NULL) goto done; 47 | if (sizeof(struct app_data) != sz) goto done; 48 | printf("app_data: now %d\n", ((struct app_data*)p)->counter); 49 | free(p); 50 | 51 | rc = 0; 52 | 53 | done: 54 | if (s) shr_close(s); 55 | unlink(ring); 56 | return rc; 57 | } 58 | -------------------------------------------------------------------------------- /tests/test13.ans: -------------------------------------------------------------------------------- 1 | cache size: 13, bytes: 5, messages: 1 2 | -------------------------------------------------------------------------------- /tests/test13.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "shr.h" 5 | 6 | char *ring = __FILE__ ".ring"; 7 | 8 | int main() { 9 | setlinebuf(stdout); 10 | struct shr *s = NULL; 11 | int rc = -1, sc; 12 | ssize_t nr; 13 | struct shr_stat st; 14 | 15 | unlink(ring); 16 | 17 | sc = shr_init(ring, 8+5, 0); 18 | if (sc < 0) goto done; 19 | 20 | s = shr_open(ring, SHR_WRONLY | SHR_BUFFERED); 21 | if (s == NULL) goto done; 22 | 23 | nr = shr_write(s, "hello", 5); 24 | if (nr < 0) goto done; 25 | 26 | sc = shr_stat(s, &st, NULL); 27 | if (sc < 0) goto done; 28 | printf("cache size: %zu, bytes: %zu, messages: %zu\n", st.cn, st.cb, st.cm); 29 | 30 | rc = 0; 31 | 32 | done: 33 | if (s) shr_close(s); 34 | unlink(ring); 35 | return rc; 36 | } 37 | -------------------------------------------------------------------------------- /tests/test14.ans: -------------------------------------------------------------------------------- 1 | ring size: 5, bytes: 0, messages: 0 2 | cache size: 5, bytes: 5, messages: 1 3 | ring size: 5, bytes: 5, messages: 1 4 | cache size: 5, bytes: 0, messages: 0 5 | -------------------------------------------------------------------------------- /tests/test14.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "shr.h" 5 | 6 | char *ring = __FILE__ ".ring"; 7 | 8 | int main() { 9 | setlinebuf(stdout); 10 | struct shr *s = NULL; 11 | int rc = -1, sc; 12 | ssize_t nr; 13 | struct shr_stat st; 14 | 15 | unlink(ring); 16 | 17 | sc = shr_init(ring, 5, 0); 18 | if (sc < 0) goto done; 19 | 20 | s = shr_open(ring, SHR_WRONLY | SHR_BUFFERED); 21 | if (s == NULL) goto done; 22 | 23 | nr = shr_write(s, "hello", 5); 24 | if (nr < 0) goto done; 25 | 26 | sc = shr_stat(s, &st, NULL); 27 | if (sc < 0) goto done; 28 | printf("ring size: %zu, bytes: %zu, messages: %zu\n", st.bn, st.bu, st.mu); 29 | printf("cache size: %zu, bytes: %zu, messages: %zu\n", st.cn, st.cb, st.cm); 30 | 31 | /* test if shr_close flushes the cache */ 32 | shr_close(s); 33 | s = NULL; 34 | s = shr_open(ring, SHR_WRONLY | SHR_BUFFERED); 35 | if (s == NULL) goto done; 36 | sc = shr_stat(s, &st, NULL); 37 | if (sc < 0) goto done; 38 | printf("ring size: %zu, bytes: %zu, messages: %zu\n", st.bn, st.bu, st.mu); 39 | printf("cache size: %zu, bytes: %zu, messages: %zu\n", st.cn, st.cb, st.cm); 40 | 41 | rc = 0; 42 | 43 | done: 44 | if (s) shr_close(s); 45 | unlink(ring); 46 | return rc; 47 | } 48 | -------------------------------------------------------------------------------- /tests/test15.ans: -------------------------------------------------------------------------------- 1 | ring size: 5, bytes: 0, messages: 0 2 | cache size: 5, bytes: 5, messages: 1 3 | ring size: 5, bytes: 5, messages: 1 4 | cache size: 5, bytes: 5, messages: 1 5 | -------------------------------------------------------------------------------- /tests/test15.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "shr.h" 5 | 6 | char *ring = __FILE__ ".ring"; 7 | 8 | int main() { 9 | setlinebuf(stdout); 10 | struct shr *s = NULL; 11 | int rc = -1, sc; 12 | ssize_t nr; 13 | struct shr_stat st; 14 | 15 | unlink(ring); 16 | 17 | sc = shr_init(ring, 5, SHR_DROP); 18 | if (sc < 0) goto done; 19 | 20 | s = shr_open(ring, SHR_WRONLY | SHR_BUFFERED); 21 | if (s == NULL) goto done; 22 | 23 | nr = shr_write(s, "hello", 5); 24 | if (nr < 0) goto done; 25 | 26 | sc = shr_stat(s, &st, NULL); 27 | if (sc < 0) goto done; 28 | printf("ring size: %zu, bytes: %zu, messages: %zu\n", st.bn, st.bu, st.mu); 29 | printf("cache size: %zu, bytes: %zu, messages: %zu\n", st.cn, st.cb, st.cm); 30 | 31 | nr = shr_write(s, "world", 5); /* now this is in the cache */ 32 | if (nr < 0) goto done; 33 | 34 | sc = shr_stat(s, &st, NULL); 35 | if (sc < 0) goto done; 36 | printf("ring size: %zu, bytes: %zu, messages: %zu\n", st.bn, st.bu, st.mu); 37 | printf("cache size: %zu, bytes: %zu, messages: %zu\n", st.cn, st.cb, st.cm); 38 | 39 | rc = 0; 40 | 41 | done: 42 | if (s) shr_close(s); 43 | unlink(ring); 44 | return rc; 45 | } 46 | -------------------------------------------------------------------------------- /tests/test16.ans: -------------------------------------------------------------------------------- 1 | ring size: 5, bytes: 0, messages: 0 2 | cache size: 5, bytes: 5, messages: 1 3 | ring size: 5, bytes: 5, messages: 1 4 | cache size: 5, bytes: 5, messages: 1 5 | non-blocking write: would block 6 | ring size: 5, bytes: 5, messages: 1 7 | cache size: 5, bytes: 5, messages: 1 8 | shr_flush: 0 9 | -------------------------------------------------------------------------------- /tests/test16.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "shr.h" 5 | 6 | char *ring = __FILE__ ".ring"; 7 | 8 | int main() { 9 | setlinebuf(stdout); 10 | struct shr *s = NULL; 11 | int rc = -1, sc; 12 | ssize_t nr; 13 | struct shr_stat st; 14 | 15 | unlink(ring); 16 | 17 | sc = shr_init(ring, 5, 0); 18 | if (sc < 0) goto done; 19 | 20 | s = shr_open(ring, SHR_WRONLY | SHR_BUFFERED | SHR_NONBLOCK); 21 | if (s == NULL) goto done; 22 | 23 | nr = shr_write(s, "hello", 5); 24 | if (nr < 0) goto done; 25 | sc = shr_stat(s, &st, NULL); 26 | if (sc < 0) goto done; 27 | printf("ring size: %zu, bytes: %zu, messages: %zu\n", st.bn, st.bu, st.mu); 28 | printf("cache size: %zu, bytes: %zu, messages: %zu\n", st.cn, st.cb, st.cm); 29 | 30 | nr = shr_write(s, "world", 5); /* now this is in the cache */ 31 | if (nr < 0) goto done; 32 | sc = shr_stat(s, &st, NULL); 33 | if (sc < 0) goto done; 34 | printf("ring size: %zu, bytes: %zu, messages: %zu\n", st.bn, st.bu, st.mu); 35 | printf("cache size: %zu, bytes: %zu, messages: %zu\n", st.cn, st.cb, st.cm); 36 | 37 | nr = shr_write(s, "there", 5); /* this fails non-blocking write lacks space */ 38 | if (nr < 0) goto done; 39 | if (nr == 0) printf("non-blocking write: would block\n"); 40 | sc = shr_stat(s, &st, NULL); 41 | if (sc < 0) goto done; 42 | printf("ring size: %zu, bytes: %zu, messages: %zu\n", st.bn, st.bu, st.mu); 43 | printf("cache size: %zu, bytes: %zu, messages: %zu\n", st.cn, st.cb, st.cm); 44 | 45 | /* the thing that remained in the cache -- "world" 46 | * will be lost on shr_flush because the ring is in 47 | * non blocking mode, and nothing liberated space */ 48 | nr = shr_flush(s,0); 49 | printf("shr_flush: %zu\n", nr); 50 | 51 | rc = 0; 52 | 53 | done: 54 | if (s) shr_close(s); 55 | unlink(ring); 56 | return rc; 57 | } 58 | -------------------------------------------------------------------------------- /tests/test17.ans: -------------------------------------------------------------------------------- 1 | ring size: 5, bytes: 0, messages: 0 2 | cache size: 5, bytes: 5, messages: 1 3 | ring size: 5, bytes: 5, messages: 1 4 | cache size: 5, bytes: 5, messages: 1 5 | non-blocking write: would block 6 | ring size: 5, bytes: 5, messages: 1 7 | cache size: 5, bytes: 5, messages: 1 8 | shr_flush: 5 9 | -------------------------------------------------------------------------------- /tests/test17.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "shr.h" 5 | 6 | char *ring = __FILE__ ".ring"; 7 | 8 | int main() { 9 | setlinebuf(stdout); 10 | struct shr *s = NULL, *z=NULL; 11 | int rc = -1, sc; 12 | ssize_t nr; 13 | struct shr_stat st; 14 | 15 | unlink(ring); 16 | 17 | sc = shr_init(ring, 5, 0); 18 | if (sc < 0) goto done; 19 | 20 | s = shr_open(ring, SHR_WRONLY | SHR_BUFFERED | SHR_NONBLOCK); 21 | if (s == NULL) goto done; 22 | 23 | nr = shr_write(s, "hello", 5); 24 | if (nr < 0) goto done; 25 | sc = shr_stat(s, &st, NULL); 26 | if (sc < 0) goto done; 27 | printf("ring size: %zu, bytes: %zu, messages: %zu\n", st.bn, st.bu, st.mu); 28 | printf("cache size: %zu, bytes: %zu, messages: %zu\n", st.cn, st.cb, st.cm); 29 | 30 | nr = shr_write(s, "world", 5); /* now this is in the cache */ 31 | if (nr < 0) goto done; 32 | sc = shr_stat(s, &st, NULL); 33 | if (sc < 0) goto done; 34 | printf("ring size: %zu, bytes: %zu, messages: %zu\n", st.bn, st.bu, st.mu); 35 | printf("cache size: %zu, bytes: %zu, messages: %zu\n", st.cn, st.cb, st.cm); 36 | 37 | nr = shr_write(s, "there", 5); /* this fails non-blocking write lacks space */ 38 | if (nr < 0) goto done; 39 | if (nr == 0) printf("non-blocking write: would block\n"); 40 | sc = shr_stat(s, &st, NULL); 41 | if (sc < 0) goto done; 42 | printf("ring size: %zu, bytes: %zu, messages: %zu\n", st.bn, st.bu, st.mu); 43 | printf("cache size: %zu, bytes: %zu, messages: %zu\n", st.cn, st.cb, st.cm); 44 | 45 | /* liberate space in the ring */ 46 | char buf[5]; 47 | z = shr_open(ring, SHR_RDONLY); 48 | if (z == NULL) goto done; 49 | nr = shr_read(z, buf, sizeof(buf)); 50 | if (nr < 0) goto done; 51 | if (nr != 5) printf("read: %zu bytes\n", nr); 52 | 53 | nr = shr_flush(s,0); /* puts "world" in the ring; "there" never was cached */ 54 | printf("shr_flush: %zu\n", nr); 55 | 56 | rc = 0; 57 | 58 | done: 59 | if (s) shr_close(s); 60 | if (z) shr_close(z); 61 | unlink(ring); 62 | return rc; 63 | } 64 | -------------------------------------------------------------------------------- /tests/test18.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | f: do_open 3 | r: do_open 4 | w: do_write_one 5 | w: 37; wrote 1 messages (to seq 1) 6 | w: do_stat 7 | ring size: 37, bytes: 0, messages: 0 8 | cache size: 37, bytes: 37, messages: 1 9 | w: do_close 10 | r: do_stat 11 | ring size: 37, bytes: 37, messages: 1 12 | cache size: 0, bytes: 0, messages: 0 13 | r: do_read_one 14 | 0 15 | f: do_close 16 | r: do_close 17 | w: do_exit 18 | w: exiting 19 | f: do_exit 20 | f: exiting 21 | r: do_exit 22 | r: exiting 23 | end 24 | -------------------------------------------------------------------------------- /tests/test18.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | #define W 0 14 | #define R 1 15 | #define F 2 16 | 17 | char *ring = __FILE__ ".ring"; 18 | 19 | /* make an enum and a char*[] for the ops */ 20 | #define adim(x) (sizeof(x)/sizeof(*x)) 21 | #define OPS o(do_none) o(do_open) o(do_write_one) o(do_stat) o(do_read_one) \ 22 | o(do_close) o(do_exit) 23 | #define o(x) #x, 24 | char *op_s[] = { OPS }; 25 | #undef o 26 | #define o(x) x, 27 | typedef enum { OPS } ops; 28 | 29 | #define NMSG 1 30 | char msg[] = "000000000000000000000000000000000000"; 31 | const int ring_sz = (sizeof(msg)+0)*NMSG; 32 | struct iovec iov[NMSG]; 33 | char msg_all[sizeof(msg)*NMSG]; 34 | 35 | struct { 36 | char *prog; 37 | time_t start; 38 | int verbose; 39 | int speed; 40 | int unlink; 41 | } CF = { 42 | .speed = 1, 43 | .unlink = 1, 44 | }; 45 | 46 | /* the event sequence we want executed */ 47 | struct events { 48 | int who; 49 | ops op; 50 | } ev[] = { 51 | { W, do_open}, 52 | { F, do_open}, 53 | { R, do_open}, 54 | 55 | { W, do_write_one}, /* fills cache */ 56 | { W, do_stat}, /* confirms in cache */ 57 | { W, do_close}, /* shr_close will shr_flush. in this case, there is room */ 58 | 59 | { R, do_stat}, /* confirms in ring */ 60 | { R, do_read_one}, /* gets sequence 0 */ 61 | 62 | { F, do_close}, 63 | { R, do_close}, 64 | 65 | { W, do_exit}, 66 | { F, do_exit}, 67 | { R, do_exit}, 68 | }; 69 | 70 | /* sleep til X seconds since start */ 71 | void sleep_til( int el ) { 72 | time_t now; 73 | time(&now); 74 | 75 | if (now > CF.start + el) { 76 | fprintf(stderr, "sleep_til: already elapsed\n"); 77 | return; 78 | } 79 | 80 | sleep((CF.start + el) - now); 81 | } 82 | 83 | /* run the event sequence 84 | * runs in child process. never returns 85 | */ 86 | void execute(int me) { 87 | char msg_one[sizeof(msg)]; 88 | struct shr *s = NULL; 89 | unsigned i, seq = 0; 90 | struct shr_stat st; 91 | ssize_t nr; 92 | int sc; 93 | 94 | for(i=0; i < adim(ev); i++) { 95 | 96 | if ( ev[i].who != me ) continue; 97 | 98 | sleep_til( i * CF.speed ); 99 | if (me == R) printf("r: "); 100 | if (me == F) printf("f: "); 101 | if (me == W) printf("w: "); 102 | printf("%s\n", op_s[ ev[i].op ]); 103 | 104 | switch( ev[i].op ) { 105 | case do_open: 106 | s = shr_open(ring, ((me == R) || (me == F)) ? 107 | SHR_RDONLY : 108 | (SHR_WRONLY | SHR_BUFFERED | SHR_NONBLOCK) ); 109 | if (s == NULL) goto done; 110 | break; 111 | case do_close: 112 | shr_close(s); 113 | break; 114 | case do_exit: 115 | goto done; 116 | break; 117 | case do_read_one: 118 | nr = shr_read(s, msg_one, sizeof(msg_one)); 119 | if (nr != sizeof(msg)) { 120 | printf("shr_read: %d\n", (int)nr); 121 | break; 122 | } 123 | printf("%s\n", msg_one); 124 | break; 125 | case do_stat: 126 | memset(&st, 0, sizeof(st)); 127 | sc = shr_stat(s, &st, NULL); 128 | if (sc < 0) printf("shr_stat: error\n"); 129 | printf("ring size: %zu, bytes: %zu, messages: %zu\n", st.bn, st.bu, st.mu); 130 | printf("cache size: %zu, bytes: %zu, messages: %zu\n", st.cn, st.cb, st.cm); 131 | break; 132 | case do_write_one: 133 | snprintf(msg_one, sizeof(msg_one), "%u", seq++); 134 | nr = shr_write(s, msg_one, sizeof(msg_one)); 135 | printf("w: %zd; wrote 1 messages (to seq %u)\n", nr, seq); 136 | break; 137 | default: 138 | fprintf(stderr,"op not implemented\n"); 139 | assert(0); 140 | break; 141 | } 142 | } 143 | 144 | done: 145 | if (me == R) printf("r: "); 146 | if (me == F) printf("f: "); 147 | if (me == W) printf("w: "); 148 | printf("exiting\n"); 149 | exit(0); 150 | } 151 | 152 | void usage() { 153 | fprintf(stderr,"usage: %s [-v] [-s ]\n", CF.prog); 154 | fprintf(stderr,"-v verbose\n"); 155 | fprintf(stderr,"-s (factor to slow test [def: 1])\n"); 156 | fprintf(stderr,"-u (don't unlink ring after test)\n"); 157 | exit(-1); 158 | } 159 | 160 | int main(int argc, char *argv[]) { 161 | setlinebuf(stdout); 162 | int rc = -1, opt; 163 | pid_t rpid,wpid,fpid; 164 | 165 | while ( (opt = getopt(argc,argv,"vhs:u")) > 0) { 166 | switch(opt) { 167 | case 'v': CF.verbose++; break; 168 | case 's': CF.speed = atoi(optarg); break; 169 | case 'u': CF.unlink = 0; break; 170 | case 'h': default: usage(); break; 171 | } 172 | } 173 | 174 | time(&CF.start); 175 | unlink(ring); 176 | shr_init(ring, ring_sz, 0); 177 | 178 | rpid = fork(); 179 | if (rpid < 0) goto done; 180 | if (rpid == 0) execute(R); 181 | assert(rpid > 0); 182 | 183 | wpid = fork(); 184 | if (wpid < 0) goto done; 185 | if (wpid == 0) execute(W); 186 | assert(wpid > 0); 187 | 188 | fpid = fork(); 189 | if (fpid < 0) goto done; 190 | if (fpid == 0) execute(F); 191 | assert(fpid > 0); 192 | 193 | waitpid(wpid,NULL,0); 194 | waitpid(rpid,NULL,0); 195 | waitpid(fpid,NULL,0); 196 | 197 | done: 198 | if (CF.unlink) unlink(ring); 199 | printf("end\n"); 200 | return rc; 201 | } 202 | 203 | -------------------------------------------------------------------------------- /tests/test19.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | f: do_open 3 | r: do_open 4 | w: do_write_one 5 | w: 37; wrote 1 messages (to seq 1) 6 | w: do_stat 7 | ring size: 37, bytes: 0, messages: 0 8 | cache size: 37, bytes: 37, messages: 1 9 | w: do_write_one 10 | w: 37; wrote 1 messages (to seq 2) 11 | w: do_close 12 | r: do_stat 13 | ring size: 37, bytes: 37, messages: 1 14 | cache size: 0, bytes: 0, messages: 0 15 | r: do_read_one 16 | 0 17 | f: do_close 18 | r: do_close 19 | w: do_exit 20 | w: exiting 21 | f: do_exit 22 | f: exiting 23 | r: do_exit 24 | r: exiting 25 | end 26 | -------------------------------------------------------------------------------- /tests/test2.ans: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/troydhanson/shr/c77e2709dcc7f81f4e2985ac7522993e3cde63d1/tests/test2.ans -------------------------------------------------------------------------------- /tests/test2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "shr.h" 4 | 5 | char *ring = __FILE__ ".ring"; 6 | 7 | int main() { 8 | setlinebuf(stdout); 9 | struct shr *s=NULL; 10 | int rc = -1; 11 | 12 | unlink(ring); 13 | if (shr_init(ring, 1024, 0) < 0) goto done; 14 | 15 | s = shr_open(ring, SHR_RDONLY); 16 | if (s == NULL) goto done; 17 | 18 | rc = 0; 19 | 20 | done: 21 | if (s) shr_close(s); 22 | unlink(ring); 23 | return rc; 24 | } 25 | -------------------------------------------------------------------------------- /tests/test20.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | f: do_open 3 | r: do_open 4 | w: do_write_one 5 | w: 37; wrote 1 messages (to seq 1) 6 | w: do_write_one 7 | w: 37; wrote 1 messages (to seq 2) 8 | w: do_stat 9 | ring size: 37, bytes: 37, messages: 1 10 | cache size: 37, bytes: 37, messages: 1 11 | w: do_flush_wait 12 | r: do_read_one 13 | 0 14 | r: do_read_one 15 | 1 16 | w: do_close 17 | f: do_close 18 | r: do_close 19 | w: do_exit 20 | w: exiting 21 | f: do_exit 22 | f: exiting 23 | r: do_exit 24 | r: exiting 25 | end 26 | -------------------------------------------------------------------------------- /tests/test21.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | f: do_open 3 | r: do_open 4 | w: do_write_one 5 | w: 37; wrote 1 messages (to seq 1) 6 | w: do_write_one 7 | w: 37; wrote 1 messages (to seq 2) 8 | w: do_stat 9 | ring size: 37, bytes: 37, messages: 1 10 | cache size: 37, bytes: 37, messages: 1 11 | w: do_flush_nb 12 | shr_flush: 0 13 | r: do_read_one 14 | 0 15 | w: do_flush_nb 16 | r: do_read_one 17 | 1 18 | w: do_stat 19 | ring size: 37, bytes: 0, messages: 0 20 | cache size: 37, bytes: 0, messages: 0 21 | w: do_flush_wait 22 | w: do_stat 23 | ring size: 37, bytes: 0, messages: 0 24 | cache size: 37, bytes: 0, messages: 0 25 | w: do_close 26 | f: do_close 27 | r: do_close 28 | w: do_exit 29 | w: exiting 30 | f: do_exit 31 | f: exiting 32 | r: do_exit 33 | r: exiting 34 | end 35 | -------------------------------------------------------------------------------- /tests/test22.ans: -------------------------------------------------------------------------------- 1 | init 2 | re-init, overwrite 3 | re-init, keep existing 4 | ok 5 | -------------------------------------------------------------------------------- /tests/test22.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "shr.h" 4 | 5 | char *ring = __FILE__ ".ring"; 6 | 7 | int main() { 8 | setlinebuf(stdout); 9 | struct shr *s=NULL; 10 | int rc = -1; 11 | 12 | unlink(ring); 13 | 14 | printf("init\n"); 15 | if (shr_init(ring, 1024, 0) < 0) goto done; 16 | 17 | printf("re-init, overwrite\n"); 18 | if (shr_init(ring, 1024, 0) < 0) goto done; 19 | 20 | printf("re-init, keep existing\n"); 21 | if (shr_init(ring, 1024, SHR_KEEPEXIST) < 0) goto done; 22 | 23 | printf("ok\n"); 24 | 25 | rc = 0; 26 | 27 | done: 28 | if (s) shr_close(s); 29 | unlink(ring); 30 | return rc; 31 | } 32 | -------------------------------------------------------------------------------- /tests/test25.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | w: do_fill 3 | w: wrote 10 messages (to seq 10) 4 | w: do_fill 5 | w: wrote 10 messages (to seq 20) 6 | r: do_open 7 | r: do_read_one 8 | 10 9 | w: do_close 10 | r: do_close 11 | w: do_exit 12 | w: exiting 13 | f: do_exit 14 | f: exiting 15 | r: do_exit 16 | r: exiting 17 | end 18 | -------------------------------------------------------------------------------- /tests/test25.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | #define W 0 14 | #define R 1 15 | #define F 2 16 | 17 | char *ring = __FILE__ ".ring"; 18 | 19 | /* make an enum and a char*[] for the ops */ 20 | #define adim(x) (sizeof(x)/sizeof(*x)) 21 | #define OPS o(do_none) o(do_open) o(do_fill) o(do_read_half) o(do_read_one) o(do_close) o(do_exit) 22 | #define o(x) #x, 23 | char *op_s[] = { OPS }; 24 | #undef o 25 | #define o(x) x, 26 | typedef enum { OPS } ops; 27 | 28 | #define NMSG 10 29 | char msg[] = "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"; 30 | const int ring_sz = (sizeof(msg)+0)*NMSG + 7; /* wraparound in midst of len header */ 31 | struct iovec iov[NMSG]; 32 | char msg_all[sizeof(msg)*NMSG]; 33 | 34 | struct { 35 | char *prog; 36 | time_t start; 37 | int verbose; 38 | int speed; 39 | int unlink; 40 | } CF = { 41 | .speed = 1, 42 | .unlink = 1, 43 | }; 44 | 45 | /* the event sequence we want executed */ 46 | struct events { 47 | int who; 48 | ops op; 49 | } ev[] = { 50 | { W, do_open}, 51 | 52 | { W, do_fill}, /* seq 0-9 */ 53 | { W, do_fill}, /* seq 10-19, drops 0-9, 10's length prefix wraps */ 54 | 55 | { R, do_open}, 56 | { R, do_read_one}, /* seq 10 */ 57 | 58 | { W, do_close}, 59 | { R, do_close}, 60 | 61 | { W, do_exit}, 62 | { F, do_exit}, 63 | { R, do_exit}, 64 | }; 65 | 66 | /* sleep til X seconds since start */ 67 | void sleep_til( int el ) { 68 | time_t now; 69 | time(&now); 70 | 71 | if (now > CF.start + el) { 72 | fprintf(stderr, "sleep_til: already elapsed\n"); 73 | return; 74 | } 75 | 76 | sleep((CF.start + el) - now); 77 | } 78 | 79 | /* run the event sequence 80 | * runs in child process. never returns 81 | */ 82 | void execute(int me) { 83 | char msg_one[sizeof(msg)]; 84 | struct shr *s = NULL; 85 | unsigned i, n; 86 | ssize_t nr; 87 | unsigned seq = 0; 88 | 89 | for(i=0; i < adim(ev); i++) { 90 | 91 | if ( ev[i].who != me ) continue; 92 | 93 | sleep_til( i * CF.speed ); 94 | if (me == R) printf("r: "); 95 | if (me == F) printf("f: "); 96 | if (me == W) printf("w: "); 97 | printf("%s\n", op_s[ ev[i].op ]); 98 | 99 | switch( ev[i].op ) { 100 | case do_open: 101 | s = shr_open(ring, ((me == R) || (me == F)) ? SHR_RDONLY : SHR_WRONLY); 102 | if (s == NULL) goto done; 103 | break; 104 | case do_close: 105 | shr_close(s); 106 | break; 107 | case do_exit: 108 | goto done; 109 | break; 110 | case do_read_one: 111 | for(n=0; n < 1; n++) { 112 | nr = shr_read(s, msg_one, sizeof(msg_one)); 113 | if (nr != sizeof(msg)) { 114 | printf("shr_read: %d\n", (int)nr); 115 | break; 116 | } 117 | printf("%s\n", msg_one); 118 | } 119 | break; 120 | case do_read_half: 121 | for(n=0; n < NMSG/2; n++) { 122 | nr = shr_read(s, msg_one, sizeof(msg_one)); 123 | if (nr != sizeof(msg)) { 124 | printf("shr_read: %d\n", (int)nr); 125 | break; 126 | } 127 | printf("%s\n", msg_one); 128 | } 129 | break; 130 | case do_fill: 131 | for(n=0; n < NMSG; n++) { 132 | snprintf(msg_one, sizeof(msg_one), "%u", seq++); 133 | nr = shr_write(s, msg_one, sizeof(msg_one)); 134 | } 135 | printf("w: wrote %d messages (to seq %u)\n", NMSG, seq); 136 | break; 137 | default: 138 | fprintf(stderr,"op not implemented\n"); 139 | assert(0); 140 | break; 141 | } 142 | } 143 | 144 | done: 145 | if (me == R) printf("r: "); 146 | if (me == F) printf("f: "); 147 | if (me == W) printf("w: "); 148 | printf("exiting\n"); 149 | exit(0); 150 | } 151 | 152 | void usage() { 153 | fprintf(stderr,"usage: %s [-v] [-s ]\n", CF.prog); 154 | fprintf(stderr,"-v verbose\n"); 155 | fprintf(stderr,"-s (factor to slow test [def: 1])\n"); 156 | fprintf(stderr,"-u (don't unlink ring after test)\n"); 157 | exit(-1); 158 | } 159 | 160 | int main(int argc, char *argv[]) { 161 | setlinebuf(stdout); 162 | int rc = -1, opt; 163 | pid_t rpid,wpid,fpid; 164 | 165 | while ( (opt = getopt(argc,argv,"vhs:u")) > 0) { 166 | switch(opt) { 167 | case 'v': CF.verbose++; break; 168 | case 's': CF.speed = atoi(optarg); break; 169 | case 'u': CF.unlink = 0; break; 170 | case 'h': default: usage(); break; 171 | } 172 | } 173 | 174 | time(&CF.start); 175 | unlink(ring); 176 | shr_init(ring, ring_sz, SHR_FARM); 177 | 178 | rpid = fork(); 179 | if (rpid < 0) goto done; 180 | if (rpid == 0) execute(R); 181 | assert(rpid > 0); 182 | 183 | wpid = fork(); 184 | if (wpid < 0) goto done; 185 | if (wpid == 0) execute(W); 186 | assert(wpid > 0); 187 | 188 | fpid = fork(); 189 | if (fpid < 0) goto done; 190 | if (fpid == 0) execute(F); 191 | assert(fpid > 0); 192 | 193 | waitpid(wpid,NULL,0); 194 | waitpid(rpid,NULL,0); 195 | waitpid(fpid,NULL,0); 196 | 197 | done: 198 | if (CF.unlink) unlink(ring); 199 | printf("end\n"); 200 | return rc; 201 | } 202 | 203 | -------------------------------------------------------------------------------- /tests/test26.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | w: do_fill 3 | w: wrote 10 messages (to seq 10) 4 | w: do_fill 5 | w: wrote 10 messages (to seq 20) 6 | r: do_open 7 | r: do_read_one 8 | 10 9 | w: do_close 10 | r: do_close 11 | w: do_exit 12 | w: exiting 13 | f: do_exit 14 | f: exiting 15 | r: do_exit 16 | r: exiting 17 | end 18 | -------------------------------------------------------------------------------- /tests/test26.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | #define W 0 14 | #define R 1 15 | #define F 2 16 | 17 | char *ring = __FILE__ ".ring"; 18 | 19 | /* make an enum and a char*[] for the ops */ 20 | #define adim(x) (sizeof(x)/sizeof(*x)) 21 | #define OPS o(do_none) o(do_open) o(do_fill) o(do_read_half) o(do_read_one) o(do_close) o(do_exit) 22 | #define o(x) #x, 23 | char *op_s[] = { OPS }; 24 | #undef o 25 | #define o(x) x, 26 | typedef enum { OPS } ops; 27 | 28 | #define NMSG 10 29 | char msg[] = "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"; 30 | const int ring_sz = (sizeof(msg)+0)*NMSG + 8; /* wraparound after len header */ 31 | struct iovec iov[NMSG]; 32 | char msg_all[sizeof(msg)*NMSG]; 33 | 34 | struct { 35 | char *prog; 36 | time_t start; 37 | int verbose; 38 | int speed; 39 | int unlink; 40 | } CF = { 41 | .speed = 1, 42 | .unlink = 1, 43 | }; 44 | 45 | /* the event sequence we want executed */ 46 | struct events { 47 | int who; 48 | ops op; 49 | } ev[] = { 50 | { W, do_open}, 51 | 52 | { W, do_fill}, /* seq 0-9 */ 53 | { W, do_fill}, /* seq 10-19, drops 0-9, 10's length prefix wraps */ 54 | 55 | { R, do_open}, 56 | { R, do_read_one}, /* seq 10 */ 57 | 58 | { W, do_close}, 59 | { R, do_close}, 60 | 61 | { W, do_exit}, 62 | { F, do_exit}, 63 | { R, do_exit}, 64 | }; 65 | 66 | /* sleep til X seconds since start */ 67 | void sleep_til( int el ) { 68 | time_t now; 69 | time(&now); 70 | 71 | if (now > CF.start + el) { 72 | fprintf(stderr, "sleep_til: already elapsed\n"); 73 | return; 74 | } 75 | 76 | sleep((CF.start + el) - now); 77 | } 78 | 79 | /* run the event sequence 80 | * runs in child process. never returns 81 | */ 82 | void execute(int me) { 83 | char msg_one[sizeof(msg)]; 84 | struct shr *s = NULL; 85 | unsigned i, n; 86 | ssize_t nr; 87 | unsigned seq = 0; 88 | 89 | for(i=0; i < adim(ev); i++) { 90 | 91 | if ( ev[i].who != me ) continue; 92 | 93 | sleep_til( i * CF.speed ); 94 | if (me == R) printf("r: "); 95 | if (me == F) printf("f: "); 96 | if (me == W) printf("w: "); 97 | printf("%s\n", op_s[ ev[i].op ]); 98 | 99 | switch( ev[i].op ) { 100 | case do_open: 101 | s = shr_open(ring, ((me == R) || (me == F)) ? SHR_RDONLY : SHR_WRONLY); 102 | if (s == NULL) goto done; 103 | break; 104 | case do_close: 105 | shr_close(s); 106 | break; 107 | case do_exit: 108 | goto done; 109 | break; 110 | case do_read_one: 111 | for(n=0; n < 1; n++) { 112 | nr = shr_read(s, msg_one, sizeof(msg_one)); 113 | if (nr != sizeof(msg)) { 114 | printf("shr_read: %d\n", (int)nr); 115 | break; 116 | } 117 | printf("%s\n", msg_one); 118 | } 119 | break; 120 | case do_read_half: 121 | for(n=0; n < NMSG/2; n++) { 122 | nr = shr_read(s, msg_one, sizeof(msg_one)); 123 | if (nr != sizeof(msg)) { 124 | printf("shr_read: %d\n", (int)nr); 125 | break; 126 | } 127 | printf("%s\n", msg_one); 128 | } 129 | break; 130 | case do_fill: 131 | for(n=0; n < NMSG; n++) { 132 | snprintf(msg_one, sizeof(msg_one), "%u", seq++); 133 | nr = shr_write(s, msg_one, sizeof(msg_one)); 134 | } 135 | printf("w: wrote %d messages (to seq %u)\n", NMSG, seq); 136 | break; 137 | default: 138 | fprintf(stderr,"op not implemented\n"); 139 | assert(0); 140 | break; 141 | } 142 | } 143 | 144 | done: 145 | if (me == R) printf("r: "); 146 | if (me == F) printf("f: "); 147 | if (me == W) printf("w: "); 148 | printf("exiting\n"); 149 | exit(0); 150 | } 151 | 152 | void usage() { 153 | fprintf(stderr,"usage: %s [-v] [-s ]\n", CF.prog); 154 | fprintf(stderr,"-v verbose\n"); 155 | fprintf(stderr,"-s (factor to slow test [def: 1])\n"); 156 | fprintf(stderr,"-u (don't unlink ring after test)\n"); 157 | exit(-1); 158 | } 159 | 160 | int main(int argc, char *argv[]) { 161 | setlinebuf(stdout); 162 | int rc = -1, opt; 163 | pid_t rpid,wpid,fpid; 164 | 165 | while ( (opt = getopt(argc,argv,"vhs:u")) > 0) { 166 | switch(opt) { 167 | case 'v': CF.verbose++; break; 168 | case 's': CF.speed = atoi(optarg); break; 169 | case 'u': CF.unlink = 0; break; 170 | case 'h': default: usage(); break; 171 | } 172 | } 173 | 174 | time(&CF.start); 175 | unlink(ring); 176 | shr_init(ring, ring_sz, SHR_FARM); 177 | 178 | rpid = fork(); 179 | if (rpid < 0) goto done; 180 | if (rpid == 0) execute(R); 181 | assert(rpid > 0); 182 | 183 | wpid = fork(); 184 | if (wpid < 0) goto done; 185 | if (wpid == 0) execute(W); 186 | assert(wpid > 0); 187 | 188 | fpid = fork(); 189 | if (fpid < 0) goto done; 190 | if (fpid == 0) execute(F); 191 | assert(fpid > 0); 192 | 193 | waitpid(wpid,NULL,0); 194 | waitpid(rpid,NULL,0); 195 | waitpid(fpid,NULL,0); 196 | 197 | done: 198 | if (CF.unlink) unlink(ring); 199 | printf("end\n"); 200 | return rc; 201 | } 202 | 203 | -------------------------------------------------------------------------------- /tests/test27.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | r: do_open 3 | w: do_fill 4 | w: wrote 10 messages (to seq 10) 5 | r: do_read_one 6 | 0 7 | w: do_fill 8 | w: wrote 10 messages (to seq 20) 9 | r: do_read_one 10 | 10 11 | r: do_read_one 12 | 11 13 | f: do_open 14 | f: do_read_one 15 | 10 16 | f: do_read_one 17 | 11 18 | w: do_close 19 | r: do_close 20 | f: do_close 21 | w: do_exit 22 | w: exiting 23 | f: do_exit 24 | f: exiting 25 | r: do_exit 26 | r: exiting 27 | end 28 | -------------------------------------------------------------------------------- /tests/test27.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | #define W 0 14 | #define R 1 15 | #define F 2 16 | 17 | char *ring = __FILE__ ".ring"; 18 | 19 | /* make an enum and a char*[] for the ops */ 20 | #define adim(x) (sizeof(x)/sizeof(*x)) 21 | #define OPS o(do_none) o(do_open) o(do_fill) o(do_read_half) o(do_read_one) o(do_close) o(do_exit) 22 | #define o(x) #x, 23 | char *op_s[] = { OPS }; 24 | #undef o 25 | #define o(x) x, 26 | typedef enum { OPS } ops; 27 | 28 | #define NMSG 10 29 | char msg[] = "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"; 30 | const int ring_sz = (sizeof(msg)+0)*NMSG + 7; /* wraparound after len header */ 31 | struct iovec iov[NMSG]; 32 | char msg_all[sizeof(msg)*NMSG]; 33 | 34 | struct { 35 | char *prog; 36 | time_t start; 37 | int verbose; 38 | int speed; 39 | int unlink; 40 | } CF = { 41 | .speed = 1, 42 | .unlink = 1, 43 | }; 44 | 45 | /* the event sequence we want executed */ 46 | struct events { 47 | int who; 48 | ops op; 49 | } ev[] = { 50 | { W, do_open}, 51 | { R, do_open}, 52 | 53 | { W, do_fill}, /* seq 0-9 */ 54 | 55 | { R, do_read_one}, /* seq 0 */ 56 | 57 | { W, do_fill}, /* seq 10-19, drops 0-9, 10's length prefix wraps */ 58 | 59 | { R, do_read_one}, /* seq 10 */ 60 | { R, do_read_one}, /* seq 11 */ 61 | 62 | { F, do_open}, 63 | { F, do_read_one}, /* seq 10 */ 64 | { F, do_read_one}, /* seq 11 */ 65 | 66 | { W, do_close}, 67 | { R, do_close}, 68 | { F, do_close}, 69 | 70 | { W, do_exit}, 71 | { F, do_exit}, 72 | { R, do_exit}, 73 | }; 74 | 75 | /* sleep til X seconds since start */ 76 | void sleep_til( int el ) { 77 | time_t now; 78 | time(&now); 79 | 80 | if (now > CF.start + el) { 81 | fprintf(stderr, "sleep_til: already elapsed\n"); 82 | return; 83 | } 84 | 85 | sleep((CF.start + el) - now); 86 | } 87 | 88 | /* run the event sequence 89 | * runs in child process. never returns 90 | */ 91 | void execute(int me) { 92 | char msg_one[sizeof(msg)]; 93 | struct shr *s = NULL; 94 | unsigned i, n; 95 | ssize_t nr; 96 | unsigned seq = 0; 97 | 98 | for(i=0; i < adim(ev); i++) { 99 | 100 | if ( ev[i].who != me ) continue; 101 | 102 | sleep_til( i * CF.speed ); 103 | if (me == R) printf("r: "); 104 | if (me == F) printf("f: "); 105 | if (me == W) printf("w: "); 106 | printf("%s\n", op_s[ ev[i].op ]); 107 | 108 | switch( ev[i].op ) { 109 | case do_open: 110 | s = shr_open(ring, ((me == R) || (me == F)) ? SHR_RDONLY : SHR_WRONLY); 111 | if (s == NULL) goto done; 112 | break; 113 | case do_close: 114 | shr_close(s); 115 | break; 116 | case do_exit: 117 | goto done; 118 | break; 119 | case do_read_one: 120 | for(n=0; n < 1; n++) { 121 | nr = shr_read(s, msg_one, sizeof(msg_one)); 122 | if (nr != sizeof(msg)) { 123 | printf("shr_read: %d\n", (int)nr); 124 | break; 125 | } 126 | printf("%s\n", msg_one); 127 | } 128 | break; 129 | case do_read_half: 130 | for(n=0; n < NMSG/2; n++) { 131 | nr = shr_read(s, msg_one, sizeof(msg_one)); 132 | if (nr != sizeof(msg)) { 133 | printf("shr_read: %d\n", (int)nr); 134 | break; 135 | } 136 | printf("%s\n", msg_one); 137 | } 138 | break; 139 | case do_fill: 140 | for(n=0; n < NMSG; n++) { 141 | snprintf(msg_one, sizeof(msg_one), "%u", seq++); 142 | nr = shr_write(s, msg_one, sizeof(msg_one)); 143 | } 144 | printf("w: wrote %d messages (to seq %u)\n", NMSG, seq); 145 | break; 146 | default: 147 | fprintf(stderr,"op not implemented\n"); 148 | assert(0); 149 | break; 150 | } 151 | } 152 | 153 | done: 154 | if (me == R) printf("r: "); 155 | if (me == F) printf("f: "); 156 | if (me == W) printf("w: "); 157 | printf("exiting\n"); 158 | exit(0); 159 | } 160 | 161 | void usage() { 162 | fprintf(stderr,"usage: %s [-v] [-s ]\n", CF.prog); 163 | fprintf(stderr,"-v verbose\n"); 164 | fprintf(stderr,"-s (factor to slow test [def: 1])\n"); 165 | fprintf(stderr,"-u (don't unlink ring after test)\n"); 166 | exit(-1); 167 | } 168 | 169 | int main(int argc, char *argv[]) { 170 | setlinebuf(stdout); 171 | int rc = -1, opt; 172 | pid_t rpid,wpid,fpid; 173 | 174 | while ( (opt = getopt(argc,argv,"vhs:u")) > 0) { 175 | switch(opt) { 176 | case 'v': CF.verbose++; break; 177 | case 's': CF.speed = atoi(optarg); break; 178 | case 'u': CF.unlink = 0; break; 179 | case 'h': default: usage(); break; 180 | } 181 | } 182 | 183 | time(&CF.start); 184 | unlink(ring); 185 | shr_init(ring, ring_sz, SHR_FARM); 186 | 187 | rpid = fork(); 188 | if (rpid < 0) goto done; 189 | if (rpid == 0) execute(R); 190 | assert(rpid > 0); 191 | 192 | wpid = fork(); 193 | if (wpid < 0) goto done; 194 | if (wpid == 0) execute(W); 195 | assert(wpid > 0); 196 | 197 | fpid = fork(); 198 | if (fpid < 0) goto done; 199 | if (fpid == 0) execute(F); 200 | assert(fpid > 0); 201 | 202 | waitpid(wpid,NULL,0); 203 | waitpid(rpid,NULL,0); 204 | waitpid(fpid,NULL,0); 205 | 206 | done: 207 | if (CF.unlink) unlink(ring); 208 | printf("end\n"); 209 | return rc; 210 | } 211 | 212 | -------------------------------------------------------------------------------- /tests/test28.ans: -------------------------------------------------------------------------------- 1 | init 2 | shr_read: -3 3 | ok 4 | -------------------------------------------------------------------------------- /tests/test28.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "shr.h" 8 | 9 | char *ring = __FILE__ ".ring"; 10 | 11 | int main() { 12 | setlinebuf(stdout); 13 | int rc = -1, sc, signal_fd = -1; 14 | struct shr *s=NULL; 15 | unsigned int n; 16 | char buf[100]; 17 | ssize_t nr; 18 | 19 | unlink(ring); 20 | 21 | printf("init\n"); 22 | if (shr_init(ring, 1024, 0) < 0) goto done; 23 | 24 | s = shr_open(ring, SHR_RDONLY); 25 | if (s == NULL) goto done; 26 | 27 | /* signals that we'll accept via signalfd in epoll */ 28 | int sigs[] = {SIGHUP,SIGTERM,SIGINT,SIGQUIT,SIGALRM}; 29 | 30 | /* block all signals. we take signals synchronously via signalfd */ 31 | sigset_t all; 32 | sigfillset(&all); 33 | sigprocmask(SIG_SETMASK,&all,NULL); 34 | 35 | /* a few signals we'll accept via our signalfd */ 36 | sigset_t sw; 37 | sigemptyset(&sw); 38 | for(n=0; n < sizeof(sigs)/sizeof(*sigs); n++) sigaddset(&sw, sigs[n]); 39 | 40 | /* create the signalfd for receiving signals */ 41 | signal_fd = signalfd(-1, &sw, 0); 42 | if (signal_fd == -1) { 43 | fprintf(stderr,"signalfd: %s\n", strerror(errno)); 44 | goto done; 45 | } 46 | 47 | /* tell shr to monitor this fd while blocked */ 48 | sc = shr_ctl(s, SHR_POLLFD, signal_fd); 49 | if (sc < 0) goto done; 50 | 51 | /* schedule SIGARLM for 10s from now */ 52 | alarm(10); 53 | 54 | /* start a blocking read. signal should cause nr == -3 */ 55 | nr = shr_read(s, buf, sizeof(buf)); 56 | printf("shr_read: %zd\n", nr); 57 | 58 | printf("ok\n"); 59 | rc = 0; 60 | 61 | done: 62 | if (signal_fd) close(signal_fd); 63 | if (s) shr_close(s); 64 | unlink(ring); 65 | return rc; 66 | } 67 | -------------------------------------------------------------------------------- /tests/test29.ans: -------------------------------------------------------------------------------- 1 | init 2 | shr_write: 100 3 | shr_write: -3 4 | ok 5 | -------------------------------------------------------------------------------- /tests/test29.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "shr.h" 8 | 9 | char *ring = __FILE__ ".ring"; 10 | 11 | int main() { 12 | setlinebuf(stdout); 13 | int rc = -1, sc, signal_fd = -1; 14 | struct shr *s=NULL; 15 | unsigned int n; 16 | char buf[100]; 17 | ssize_t nr; 18 | 19 | unlink(ring); 20 | 21 | printf("init\n"); 22 | if (shr_init(ring, sizeof(buf)+0, 0) < 0) goto done; 23 | 24 | s = shr_open(ring, SHR_WRONLY); 25 | if (s == NULL) goto done; 26 | 27 | /* signals that we'll accept via signalfd in epoll */ 28 | int sigs[] = {SIGHUP,SIGTERM,SIGINT,SIGQUIT,SIGALRM}; 29 | 30 | /* block all signals. we take signals synchronously via signalfd */ 31 | sigset_t all; 32 | sigfillset(&all); 33 | sigprocmask(SIG_SETMASK,&all,NULL); 34 | 35 | /* a few signals we'll accept via our signalfd */ 36 | sigset_t sw; 37 | sigemptyset(&sw); 38 | for(n=0; n < sizeof(sigs)/sizeof(*sigs); n++) sigaddset(&sw, sigs[n]); 39 | 40 | /* create the signalfd for receiving signals */ 41 | signal_fd = signalfd(-1, &sw, 0); 42 | if (signal_fd == -1) { 43 | fprintf(stderr,"signalfd: %s\n", strerror(errno)); 44 | goto done; 45 | } 46 | 47 | /* tell shr to monitor this fd while blocked */ 48 | sc = shr_ctl(s, SHR_POLLFD, signal_fd); 49 | if (sc < 0) goto done; 50 | 51 | /* schedule SIGARLM for 10s from now */ 52 | alarm(10); 53 | 54 | /* initial write should succeed immediately */ 55 | memset(buf, 0, sizeof(buf)); 56 | nr = shr_write(s, buf, sizeof(buf)); 57 | printf("shr_write: %zd\n", nr); 58 | 59 | /* start a blocking write. signal should cause nr == -3 */ 60 | nr = shr_write(s, buf, sizeof(buf)); 61 | printf("shr_write: %zd\n", nr); 62 | 63 | printf("ok\n"); 64 | rc = 0; 65 | 66 | done: 67 | if (signal_fd) close(signal_fd); 68 | if (s) shr_close(s); 69 | unlink(ring); 70 | return rc; 71 | } 72 | -------------------------------------------------------------------------------- /tests/test3.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | w: do_fill 3 | w: wrote 370000 bytes / 10000 messages 4 | w: do_close 5 | w: do_exit 6 | w: exiting 7 | r: do_open 8 | r: do_read 9 | read 10000 messages 10 | r: do_close 11 | r: do_open 12 | r: do_read 13 | read 10000 messages 14 | r: do_close 15 | r: do_exit 16 | r: exiting 17 | end 18 | -------------------------------------------------------------------------------- /tests/test3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | #define W 0 14 | #define R 1 15 | 16 | char *ring = __FILE__ ".ring"; 17 | 18 | /* make an enum and a char*[] for the ops */ 19 | #define adim(x) (sizeof(x)/sizeof(*x)) 20 | #define OPS o(do_none) o(do_open) o(do_fill) o(do_read) o(do_close) o(do_exit) 21 | #define o(x) #x, 22 | char *op_s[] = { OPS }; 23 | #undef o 24 | #define o(x) x, 25 | typedef enum { OPS } ops; 26 | 27 | #define NMSG 10000 28 | char msg[] = "1234567890abcdefghijklmnopqrstuvwxyz"; 29 | const int ring_sz = sizeof(msg)*NMSG; 30 | struct iovec iov[NMSG]; 31 | char msg_all[sizeof(msg)*NMSG]; 32 | 33 | struct { 34 | char *prog; 35 | time_t start; 36 | int verbose; 37 | int speed; 38 | int unlink; 39 | } CF = { 40 | .speed = 1, 41 | .unlink = 1, 42 | }; 43 | 44 | /* the event sequence we want executed */ 45 | struct events { 46 | int when; 47 | int who; 48 | ops op; 49 | } ev[] = { 50 | {1, W, do_open}, 51 | {2, W, do_fill}, 52 | {3, W, do_close}, 53 | {4, W, do_exit}, 54 | 55 | {5, R, do_open}, 56 | {6, R, do_read}, 57 | {7, R, do_close}, 58 | 59 | {8, R, do_open}, 60 | {9, R, do_read}, 61 | {10, R, do_close}, 62 | 63 | {11, R, do_exit}, 64 | }; 65 | 66 | /* sleep til X seconds since start */ 67 | void sleep_til( int el ) { 68 | time_t now; 69 | time(&now); 70 | 71 | if (now > CF.start + el) { 72 | fprintf(stderr, "sleep_til: already elapsed\n"); 73 | return; 74 | } 75 | 76 | sleep((CF.start + el) - now); 77 | } 78 | 79 | /* run the event sequence 80 | * runs in child process. never returns 81 | */ 82 | void execute(int me) { 83 | char msg_one[sizeof(msg)]; 84 | struct shr *s = NULL; 85 | unsigned i, n; 86 | ssize_t nr; 87 | 88 | for(i=0; i < adim(ev); i++) { 89 | 90 | if ( ev[i].who != me ) continue; 91 | 92 | sleep_til( ev[i].when * CF.speed ); 93 | printf("%s: %s\n", (me == R) ? "r" : "w", op_s[ ev[i].op ]); 94 | 95 | switch( ev[i].op ) { 96 | case do_open: 97 | s = shr_open(ring, (me == R) ? SHR_RDONLY : SHR_WRONLY); 98 | if (s == NULL) goto done; 99 | break; 100 | case do_close: 101 | shr_close(s); 102 | break; 103 | case do_exit: 104 | goto done; 105 | break; 106 | case do_read: 107 | for(n=0; n < NMSG; n++) { 108 | nr = shr_read(s, msg_one, sizeof(msg_one)); 109 | if (nr != sizeof(msg)) { 110 | printf("shr_read: %d\n", (int)nr); 111 | break; 112 | } 113 | } 114 | printf("read %d messages\n", n); 115 | break; 116 | case do_fill: 117 | for(n=0; n < NMSG; n++) { 118 | iov[n].iov_len = sizeof(msg); 119 | iov[n].iov_base = msg; 120 | } 121 | nr = shr_writev(s, iov, NMSG); 122 | printf("w: wrote %d bytes / %d messages\n", (int)nr, NMSG); 123 | break; 124 | default: 125 | fprintf(stderr,"op not implemented\n"); 126 | assert(0); 127 | break; 128 | } 129 | } 130 | 131 | done: 132 | printf("%s: exiting\n", (me == R) ? "r" : "w"); 133 | exit(0); 134 | } 135 | 136 | void usage() { 137 | fprintf(stderr,"usage: %s [-v] [-s ]\n", CF.prog); 138 | fprintf(stderr,"-v verbose\n"); 139 | fprintf(stderr,"-s (factor to slow test [def: 1])\n"); 140 | fprintf(stderr,"-u (don't unlink ring after test)\n"); 141 | exit(-1); 142 | } 143 | 144 | int main(int argc, char *argv[]) { 145 | setlinebuf(stdout); 146 | int rc = -1, opt; 147 | pid_t rpid,wpid; 148 | 149 | while ( (opt = getopt(argc,argv,"vhs:u")) > 0) { 150 | switch(opt) { 151 | case 'v': CF.verbose++; break; 152 | case 's': CF.speed = atoi(optarg); break; 153 | case 'u': CF.unlink = 0; break; 154 | case 'h': default: usage(); break; 155 | } 156 | } 157 | 158 | time(&CF.start); 159 | unlink(ring); 160 | shr_init(ring, ring_sz, SHR_FARM|SHR_MAXMSGS_2, NMSG); 161 | 162 | rpid = fork(); 163 | if (rpid < 0) goto done; 164 | if (rpid == 0) execute(R); 165 | assert(rpid > 0); 166 | 167 | wpid = fork(); 168 | if (wpid < 0) goto done; 169 | if (wpid == 0) execute(W); 170 | assert(wpid > 0); 171 | 172 | waitpid(wpid,NULL,0); 173 | waitpid(rpid,NULL,0); 174 | 175 | done: 176 | if (CF.unlink) unlink(ring); 177 | printf("end\n"); 178 | return rc; 179 | } 180 | 181 | -------------------------------------------------------------------------------- /tests/test30.ans: -------------------------------------------------------------------------------- 1 | r: ready 2 | w: ready 3 | w: open 4 | r: open 5 | w: write 6 | r: undersized read 7 | r: -2 8 | r: read 9 | r: 361 10 | w: unlink 11 | w: close 12 | r: close 13 | w: eof 14 | r: eof 15 | end 16 | -------------------------------------------------------------------------------- /tests/test31.ans: -------------------------------------------------------------------------------- 1 | r: ready 2 | w: ready 3 | w: open 4 | r: open 5 | w: write 6 | r: read 7 | r: 361 8 | w: write 9 | r: read 10 | r: 361 11 | w: unlink 12 | w: close 13 | r: close 14 | w: eof 15 | r: eof 16 | end 17 | -------------------------------------------------------------------------------- /tests/test32.ans: -------------------------------------------------------------------------------- 1 | r: ready 2 | w: ready 3 | w: open 4 | r: open 5 | w: write 6 | r: read 7 | r: 361 8 | w: write 9 | r: read 10 | r: 361 11 | w: unlink 12 | w: close 13 | r: close 14 | w: eof 15 | r: eof 16 | end 17 | -------------------------------------------------------------------------------- /tests/test33.ans: -------------------------------------------------------------------------------- 1 | r: ready 2 | w: ready 3 | w: open 4 | r: open 5 | w: write 6 | r: read 7 | r: 361 8 | w: write 9 | r: read 10 | r: 361 11 | w: unlink 12 | w: close 13 | r: close 14 | w: eof 15 | r: eof 16 | end 17 | -------------------------------------------------------------------------------- /tests/test34.ans: -------------------------------------------------------------------------------- 1 | r: ready 2 | w: ready 3 | w: open 4 | r: open 5 | w: write 6 | r: read 7 | r: 361 8 | w: write 9 | r: read 10 | r: 361 11 | w: unlink 12 | w: close 13 | r: close 14 | w: eof 15 | r: eof 16 | end 17 | -------------------------------------------------------------------------------- /tests/test35.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | r: do_open 3 | w: do_fill 4 | w: wrote 370000 bytes / 10000 messages 5 | r: do_read 6 | read 10000 messages 7 | w: do_close 8 | r: do_close 9 | w: do_exit 10 | w: exiting 11 | r: do_exit 12 | r: exiting 13 | end 14 | -------------------------------------------------------------------------------- /tests/test35.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | #define W 0 14 | #define R 1 15 | 16 | char *ring = __FILE__ ".ring"; 17 | 18 | /* make an enum and a char*[] for the ops */ 19 | #define adim(x) (sizeof(x)/sizeof(*x)) 20 | #define OPS o(do_none) o(do_open) o(do_fill) o(do_read) o(do_close) o(do_exit) 21 | #define o(x) #x, 22 | char *op_s[] = { OPS }; 23 | #undef o 24 | #define o(x) x, 25 | typedef enum { OPS } ops; 26 | 27 | #define NMSG 10000 28 | char msg[] = "1234567890abcdefghijklmnopqrstuvwxyz"; 29 | const int ring_sz = (sizeof(msg)+0)*NMSG; 30 | struct iovec iov[NMSG]; 31 | 32 | struct { 33 | char *prog; 34 | time_t start; 35 | int verbose; 36 | int speed; 37 | struct iovec *io; 38 | } CF = { 39 | .speed = 1, 40 | .io = iov, 41 | }; 42 | 43 | /* the event sequence we want executed */ 44 | struct events { 45 | int when; 46 | int who; 47 | ops op; 48 | } ev[] = { 49 | {1, W, do_open}, 50 | {2, R, do_open}, 51 | 52 | {3, W, do_fill}, 53 | {4, R, do_read}, 54 | 55 | {5, W, do_close}, 56 | {6, R, do_close}, 57 | 58 | {7, W, do_exit}, 59 | {8, R, do_exit}, 60 | }; 61 | 62 | /* sleep til X seconds since start */ 63 | void sleep_til( int el ) { 64 | time_t now; 65 | time(&now); 66 | 67 | if (now > CF.start + el) { 68 | fprintf(stderr, "sleep_til: already elapsed\n"); 69 | return; 70 | } 71 | 72 | sleep((CF.start + el) - now); 73 | } 74 | 75 | /* run the event sequence 76 | * runs in child process. never returns 77 | */ 78 | void execute(int me) { 79 | char buf[sizeof(msg)]; 80 | struct shr *s = NULL; 81 | unsigned i, n; 82 | ssize_t nr; 83 | 84 | for(i=0; i < adim(ev); i++) { 85 | 86 | if ( ev[i].who != me ) continue; 87 | 88 | sleep_til( ev[i].when * CF.speed ); 89 | printf("%s: %s\n", (me == R) ? "r" : "w", op_s[ ev[i].op ]); 90 | 91 | switch( ev[i].op ) { 92 | case do_open: 93 | s = shr_open(ring, (me == R) ? SHR_RDONLY : SHR_WRONLY); 94 | if (s == NULL) goto done; 95 | break; 96 | case do_close: 97 | shr_close(s); 98 | break; 99 | case do_exit: 100 | goto done; 101 | break; 102 | case do_read: 103 | for(n=0; n < NMSG; n++) { 104 | nr = shr_read(s, buf, sizeof(buf)); 105 | if (nr != sizeof(msg)) { 106 | printf("shr_read: %d\n", (int)nr); 107 | break; 108 | } 109 | } 110 | printf("read %d messages\n", NMSG); 111 | break; 112 | case do_fill: 113 | for(n=0; n < NMSG; n++) { 114 | CF.io[n].iov_len = sizeof(msg); 115 | CF.io[n].iov_base = msg; 116 | } 117 | nr = shr_writev(s, CF.io, NMSG); 118 | printf("w: wrote %d bytes / %d messages\n", (int)nr, NMSG); 119 | break; 120 | default: 121 | fprintf(stderr,"op not implemented\n"); 122 | assert(0); 123 | break; 124 | } 125 | } 126 | 127 | done: 128 | printf("%s: exiting\n", (me == R) ? "r" : "w"); 129 | exit(0); 130 | } 131 | 132 | void usage() { 133 | fprintf(stderr,"usage: %s [-v] [-s ]\n", CF.prog); 134 | fprintf(stderr,"-s (factor to slow test [def: 1])\n"); 135 | fprintf(stderr,"-v verbose\n"); 136 | exit(-1); 137 | } 138 | 139 | int main(int argc, char *argv[]) { 140 | setlinebuf(stdout); 141 | int rc = -1, opt; 142 | pid_t rpid,wpid; 143 | 144 | while ( (opt = getopt(argc,argv,"vhs:")) > 0) { 145 | switch(opt) { 146 | case 'v': CF.verbose++; break; 147 | case 's': CF.speed = atoi(optarg); break; 148 | case 'h': default: usage(); break; 149 | } 150 | } 151 | 152 | time(&CF.start); 153 | unlink(ring); 154 | shr_init(ring, ring_sz, SHR_MAXMSGS_2, NMSG); 155 | 156 | rpid = fork(); 157 | if (rpid < 0) goto done; 158 | if (rpid == 0) execute(R); 159 | assert(rpid > 0); 160 | 161 | wpid = fork(); 162 | if (wpid < 0) goto done; 163 | if (wpid == 0) execute(W); 164 | assert(wpid > 0); 165 | 166 | waitpid(wpid,NULL,0); 167 | waitpid(rpid,NULL,0); 168 | 169 | done: 170 | unlink(ring); 171 | printf("end\n"); 172 | return rc; 173 | } 174 | 175 | -------------------------------------------------------------------------------- /tests/test36.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | r: do_open 3 | w: do_write_one_3b 4 | w: wrote seq aaa 5 | w: do_write_one 6 | w: wrote seq b 7 | w: do_write_one_3b 8 | w: wrote seq ccc 9 | w: do_write_one_4b 10 | w: wrote seq dddd 11 | w: do_write_one_4b 12 | w: wrote seq eeee 13 | w: do_write_one_4b 14 | w: wrote seq ffff 15 | w: do_write_one_4b 16 | w: wrote seq gggg 17 | w: do_write_one_4b 18 | w: wrote seq hhhh 19 | w: do_write_one_4b 20 | w: wrote seq iiii 21 | w: do_write_one_2b 22 | w: wrote seq jj 23 | r: do_stat 24 | w: stat: 0 25 | w: bw 33, br 0, mw 10, mr 0, md 0, bd 0, bn 34, bu 33, mu 10 26 | w: do_write_one_4b 27 | w: wrote seq kkkk 28 | r: do_stat 29 | w: stat: 0 30 | w: bw 37, br 0, mw 11, mr 0, md 1, bd 3, bn 34, bu 34, mu 10 31 | r: do_read_one 32 | b 33 | r: do_read_one 34 | ccc 35 | w: do_close 36 | f: do_close 37 | r: do_close 38 | w: do_exit 39 | w: exiting 40 | r: do_exit 41 | r: exiting 42 | end 43 | -------------------------------------------------------------------------------- /tests/test37.ans: -------------------------------------------------------------------------------- 1 | r: ready 2 | w: ready 3 | w: open 4 | r: open 5 | w: write 6 | w: write 7 | r: read 8 | r: rc = 7 9 | r: [abcdef] 10 | w: write 11 | r: read 12 | r: rc = 7 13 | r: [abcdef] 14 | w: close 15 | r: close 16 | w: eof 17 | r: eof 18 | end 19 | -------------------------------------------------------------------------------- /tests/test38.ans: -------------------------------------------------------------------------------- 1 | r: ready 2 | w: ready 3 | w: open 4 | r: open 5 | w: write 6 | w: write 7 | r: read 8 | r: rc = 7 9 | r: [abcdef] 10 | w: write 11 | r: read 12 | r: rc = 7 13 | r: [abcdef] 14 | r: read 15 | r: rc = 7 16 | r: [abcdef] 17 | w: close 18 | r: close 19 | w: eof 20 | r: eof 21 | end 22 | -------------------------------------------------------------------------------- /tests/test39.ans: -------------------------------------------------------------------------------- 1 | r: ready 2 | w: ready 3 | w: open 4 | r: open 5 | w: write 6 | w: write 7 | w: write 8 | r: read 9 | r: rc = 7 10 | r: [abcdef] 11 | r: read 12 | r: rc = 7 13 | r: [abcdef] 14 | r: read 15 | r: rc = 0 16 | r: wouldblock 17 | w: close 18 | r: close 19 | w: eof 20 | r: eof 21 | end 22 | -------------------------------------------------------------------------------- /tests/test4.ans: -------------------------------------------------------------------------------- 1 | writing ...ok 2 | reading ...read 3 bytes 3 | abc 4 | end 5 | -------------------------------------------------------------------------------- /tests/test4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "shr.h" 4 | 5 | char *data = "abcdefghi"; 6 | char *ring = __FILE__ ".ring"; 7 | 8 | char out[10]; 9 | 10 | int main() { 11 | setlinebuf(stdout); 12 | struct shr *s=NULL,*t=NULL; 13 | ssize_t nr; 14 | int rc = -1; 15 | 16 | unlink(ring); 17 | if (shr_init(ring, 14, 0) < 0) goto done; 18 | 19 | s = shr_open(ring, SHR_RDONLY); 20 | if (s == NULL) goto done; 21 | 22 | t = shr_open(ring, SHR_WRONLY); 23 | if (t == NULL) goto done; 24 | 25 | printf("writing ..."); 26 | nr = shr_write(t, &data[0], 3); 27 | if (nr < 0) goto done; 28 | printf("ok\n"); 29 | 30 | printf("reading ..."); 31 | nr = shr_read(s, out, sizeof(out)); 32 | if (nr < 0) goto done; 33 | printf("read %ld bytes\n", (long)nr); 34 | if (nr > 0) printf("%.*s\n", (int)nr, out); 35 | 36 | rc = 0; 37 | 38 | done: 39 | printf("end\n"); 40 | if (s) shr_close(s); 41 | if (t) shr_close(t); 42 | unlink(ring); 43 | return rc; 44 | } 45 | -------------------------------------------------------------------------------- /tests/test40.ans: -------------------------------------------------------------------------------- 1 | r: ready 2 | w: ready 3 | w: open 4 | r: open 5 | w: stat: 0 6 | w: bw 0, br 0, mw 0, mr 0, md 0, bd 0, bn 15, bu 0 mu 0 7 | w: write 8 | w: stat: 0 9 | w: bw 7, br 0, mw 1, mr 0, md 0, bd 0, bn 15, bu 7 mu 1 10 | w: write 11 | w: stat: 0 12 | w: bw 14, br 0, mw 2, mr 0, md 0, bd 0, bn 15, bu 14 mu 2 13 | w: write 14 | w: stat: 0 15 | w: bw 21, br 0, mw 3, mr 0, md 1, bd 7, bn 15, bu 14 mu 2 16 | r: read 17 | r: rc = 7 18 | r: [abcdef] 19 | w: stat: 0 20 | w: bw 21, br 7, mw 3, mr 1, md 1, bd 7, bn 15, bu 7 mu 1 21 | r: read 22 | r: rc = 7 23 | r: [abcdef] 24 | w: stat: 0 25 | w: bw 21, br 14, mw 3, mr 2, md 1, bd 7, bn 15, bu 0 mu 0 26 | r: read 27 | r: rc = 0 28 | r: wouldblock 29 | w: stat: 0 30 | w: bw 21, br 14, mw 3, mr 2, md 1, bd 7, bn 15, bu 0 mu 0 31 | w: close 32 | r: close 33 | w: eof 34 | r: eof 35 | end 36 | -------------------------------------------------------------------------------- /tests/test41.ans: -------------------------------------------------------------------------------- 1 | r: ready 2 | w: ready 3 | w: open 4 | r: open 5 | w: stat: 0 6 | w: start 0 7 | w: bw 0, br 0, mw 0, mr 0, md 0, bd 0, bn 15, bu 0, mu 0 8 | w: write 9 | w: stat: 0 10 | w: start 10 11 | w: bw 7, br 0, mw 1, mr 0, md 0, bd 0, bn 15, bu 7, mu 1 12 | w: write 13 | w: stat: 0 14 | w: start 20 15 | w: bw 7, br 0, mw 1, mr 0, md 0, bd 0, bn 15, bu 14, mu 2 16 | w: write 17 | w: stat: 0 18 | w: start 30 19 | w: bw 7, br 0, mw 1, mr 0, md 1, bd 7, bn 15, bu 14, mu 2 20 | r: read 21 | r: rc = 7 22 | r: [abcdef] 23 | w: stat: 0 24 | w: start 40 25 | w: bw 0, br 7, mw 0, mr 1, md 0, bd 0, bn 15, bu 7, mu 1 26 | r: read 27 | r: rc = 7 28 | r: [abcdef] 29 | w: stat: 0 30 | w: start 50 31 | w: bw 0, br 7, mw 0, mr 1, md 0, bd 0, bn 15, bu 0, mu 0 32 | r: read 33 | r: rc = 0 34 | r: wouldblock 35 | w: stat: 0 36 | w: start 60 37 | w: bw 0, br 0, mw 0, mr 0, md 0, bd 0, bn 15, bu 0, mu 0 38 | w: close 39 | r: close 40 | w: eof 41 | r: eof 42 | end 43 | -------------------------------------------------------------------------------- /tests/test42.ans: -------------------------------------------------------------------------------- 1 | writing 2 iovec...ok 2 | writing 1 iovec...non-blocking shr_write: would block 3 | end 4 | -------------------------------------------------------------------------------- /tests/test42.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "shr.h" 4 | 5 | char *ring = __FILE__ ".ring"; 6 | char *data = "abcdefghi"; 7 | 8 | int main() { 9 | setlinebuf(stdout); 10 | struct shr *s=NULL; 11 | int rc = -1, i; 12 | struct iovec io[3]; 13 | for(i = 0; i < 3; i++) { 14 | io[i].iov_base = data; 15 | io[i].iov_len = 3; 16 | } 17 | 18 | unlink(ring); 19 | if (shr_init(ring, 2*3, 0) < 0) goto done; 20 | 21 | s = shr_open(ring, SHR_WRONLY|SHR_NONBLOCK); 22 | if (s == NULL) goto done; 23 | 24 | printf("writing 2 iovec..."); 25 | if (shr_writev(s, io, 2) < 0) goto done; 26 | printf("ok\n"); 27 | 28 | /* this should fail */ 29 | printf("writing 1 iovec..."); 30 | int nr = shr_writev(s, io, 1); 31 | if (nr < 0) goto done; 32 | if (nr == 0) printf("non-blocking shr_write: would block\n"); 33 | else printf("ok\n"); 34 | 35 | rc = 0; 36 | 37 | done: 38 | printf("end\n"); 39 | if (s) shr_close(s); 40 | unlink(ring); 41 | return rc; 42 | } 43 | -------------------------------------------------------------------------------- /tests/test43.ans: -------------------------------------------------------------------------------- 1 | r: ready 2 | w: ready 3 | w: open 4 | r: open 5 | w: writev 6 | w: stat: 0 7 | w: bw 14, br 0, mw 2, mr 0, md 0, bd 0, bn 15, bu 14, mu 2 8 | w: stat: 0 9 | w: bw 0, br 14, mw 0, mr 2, md 0, bd 0, bn 15, bu 0, mu 0 10 | w: close 11 | r: close 12 | w: eof 13 | r: eof 14 | end 15 | -------------------------------------------------------------------------------- /tests/test44.ans: -------------------------------------------------------------------------------- 1 | r: ready 2 | w: ready 3 | w: open 4 | r: open 5 | w: write 6 | w: writev 7 | w: rc 0 8 | w: stat: 0 9 | w: bw 7, br 0, mw 1, mr 0, md 0, bd 0, bn 15, bu 7, mu 1 10 | w: close 11 | r: close 12 | w: eof 13 | r: eof 14 | end 15 | -------------------------------------------------------------------------------- /tests/test45.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | r: do_open 3 | w: do_write_one_3b 4 | w: wrote seq aaa 5 | w: do_write_one 6 | w: wrote seq b 7 | w: do_write_one_3b 8 | w: wrote seq ccc 9 | w: do_write_one_4b 10 | w: wrote seq dddd 11 | w: do_write_one_4b 12 | w: wrote seq eeee 13 | w: do_write_one_4b 14 | w: wrote seq ffff 15 | w: do_write_one_4b 16 | w: wrote seq gggg 17 | w: do_write_one_4b 18 | w: wrote seq hhhh 19 | w: do_write_one_4b 20 | w: wrote seq iiii 21 | w: do_write_one_2b 22 | w: wrote seq jj 23 | r: do_stat 24 | w: stat: 0 25 | w: bw 33, br 0, mw 10, mr 0, md 0, bd 0, bn 34, bu 33, mu 10 26 | w: do_write_one_4b 27 | w: wrote seq kkkk 28 | r: do_stat 29 | w: stat: 0 30 | w: bw 37, br 0, mw 11, mr 0, md 1, bd 3, bn 34, bu 34, mu 10 31 | r: do_read_one 32 | b 33 | r: do_read_one 34 | ccc 35 | f: do_open 36 | f: do_read_one 37 | b 38 | f: do_read_one 39 | ccc 40 | w: do_write_one_4b 41 | w: wrote seq llll 42 | w: do_write_one_4b 43 | w: wrote seq mmmm 44 | w: do_write_one_4b 45 | w: wrote seq nnnn 46 | w: do_write_one_4b 47 | w: wrote seq oooo 48 | w: do_write_one_4b 49 | w: wrote seq pppp 50 | w: do_write_one_4b 51 | w: wrote seq qqqq 52 | w: do_write_one_4b 53 | w: wrote seq rrrr 54 | w: do_write_one_4b 55 | w: wrote seq ssss 56 | w: do_write_one_4b 57 | w: wrote seq tttt 58 | w: do_write_one_4b 59 | w: wrote seq uuuu 60 | r: do_read_one 61 | nnnn 62 | f: do_read_one 63 | nnnn 64 | f: do_read_one 65 | oooo 66 | f: do_read_one 67 | pppp 68 | f: do_read_one 69 | qqqq 70 | f: do_read_one 71 | rrrr 72 | f: do_read_one 73 | ssss 74 | f: do_read_one 75 | tttt 76 | f: do_read_one 77 | uuuu 78 | f: do_read_one 79 | shr_read: no data 80 | w: do_close 81 | f: do_close 82 | r: do_close 83 | w: do_exit 84 | w: exiting 85 | f: do_exit 86 | f: exiting 87 | r: do_exit 88 | r: exiting 89 | end 90 | -------------------------------------------------------------------------------- /tests/test46.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | r: do_open 3 | w: do_write_one_5b 4 | w: wrote seq aaaaa 5 | w: do_write_one_3b 6 | w: wrote seq bbb 7 | w: do_write_one 8 | w: wrote seq c 9 | w: do_write_one_3b 10 | w: wrote seq ddd 11 | w: do_write_one 12 | w: wrote seq e 13 | w: do_write_one_5b 14 | w: wrote seq fffff 15 | w: do_write_one 16 | w: wrote seq g 17 | w: do_write_one 18 | w: wrote seq h 19 | r: do_stat 20 | stat: 0 21 | bw 20, br 0, mw 8, mr 0, md 0, bd 0, bn 20, bu 20, mu 8 22 | r: do_read_one 23 | aaaaa 24 | w: do_write_one_5b 25 | w: wrote seq iiiii 26 | r: do_read_one 27 | bbb 28 | r: do_read_one 29 | c 30 | f: do_open 31 | f: do_stat 32 | stat: 0 33 | bw 25, br 9, mw 9, mr 3, md 0, bd 0, bn 20, bu 16, mu 6 34 | f: do_read_one 35 | ddd 36 | f: do_read_one 37 | e 38 | w: do_write_one_5b 39 | w: wrote seq jjjjj 40 | r: do_read_one 41 | fffff 42 | f: do_read_one 43 | g 44 | w: do_close 45 | f: do_close 46 | r: do_close 47 | w: do_exit 48 | w: exiting 49 | f: do_exit 50 | f: exiting 51 | r: do_exit 52 | r: exiting 53 | end 54 | -------------------------------------------------------------------------------- /tests/test47.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | r: do_open 3 | w: do_write_one_5b 4 | w: wrote seq aaaaa 5 | w: do_write_one_3b 6 | w: wrote seq bbb 7 | w: do_write_one 8 | w: wrote seq c 9 | w: do_write_one_3b 10 | w: wrote seq ddd 11 | w: do_write_one 12 | w: wrote seq e 13 | w: do_write_one_5b 14 | w: wrote seq fffff 15 | w: do_write_one 16 | w: wrote seq g 17 | w: do_write_one 18 | w: wrote seq h 19 | r: do_stat 20 | stat: 0 21 | bw 20, br 0, mw 8, mr 0, md 0, bd 0, bn 20, bu 20, mu 8 22 | r: do_read_one 23 | aaaaa 24 | w: do_write_one_5b 25 | w: wrote seq iiiii 26 | r: do_read_one 27 | bbb 28 | r: do_read_one 29 | c 30 | f: do_open 31 | f: do_stat 32 | stat: 0 33 | bw 25, br 9, mw 9, mr 3, md 1, bd 5, bn 20, bu 20, mu 8 34 | f: do_read_one 35 | bbb 36 | f: do_read_one 37 | c 38 | w: do_write_one_5b 39 | w: wrote seq jjjjj 40 | r: do_read_one 41 | e 42 | f: do_read_one 43 | e 44 | r: do_read_one 45 | fffff 46 | w: do_write_one_5b 47 | w: wrote seq kkkkk 48 | r: do_read_one 49 | g 50 | f: do_read_one 51 | g 52 | r: do_read_one 53 | h 54 | r: do_read_one 55 | iiiii 56 | r: do_read_one 57 | jjjjj 58 | w: do_write_one_5b 59 | w: wrote seq lllll 60 | r: do_read_one 61 | kkkkk 62 | f: do_read_one 63 | iiiii 64 | w: do_close 65 | f: do_close 66 | r: do_close 67 | w: do_exit 68 | w: exiting 69 | f: do_exit 70 | f: exiting 71 | r: do_exit 72 | r: exiting 73 | end 74 | -------------------------------------------------------------------------------- /tests/test48.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | r: do_open 3 | w: do_write_one_5b 4 | w: wrote seq aaaaa 5 | w: do_write_one_3b 6 | w: wrote seq bbb 7 | w: do_write_one 8 | w: wrote seq c 9 | w: do_write_one_3b 10 | w: wrote seq ddd 11 | w: do_write_one 12 | w: wrote seq e 13 | w: do_write_one_5b 14 | w: wrote seq fffff 15 | w: do_write_one 16 | w: wrote seq g 17 | w: do_write_one 18 | w: wrote seq h 19 | r: do_stat 20 | stat: 0 21 | bw 20, br 0, mw 8, mr 0, md 7, bd 19, bn 20, bu 1, mu 1 22 | r: do_read_one 23 | h 24 | w: do_write_one_5b 25 | w: wrote seq iiiii 26 | r: do_read_one 27 | iiiii 28 | r: do_read_one 29 | shr_read: no data 30 | f: do_open 31 | f: do_stat 32 | stat: 0 33 | bw 25, br 6, mw 9, mr 2, md 8, bd 20, bn 20, bu 5, mu 1 34 | f: do_read_one 35 | iiiii 36 | f: do_read_one 37 | shr_read: no data 38 | w: do_write_one_5b 39 | w: wrote seq jjjjj 40 | r: do_read_one 41 | jjjjj 42 | f: do_read_one 43 | jjjjj 44 | w: do_write_one_3b 45 | w: wrote seq kkk 46 | r: do_read_one 47 | kkk 48 | f: do_read_one 49 | kkk 50 | w: do_write_one_2b 51 | w: wrote seq ll 52 | w: do_write_one 53 | w: wrote seq m 54 | r: do_read_one 55 | m 56 | f: do_read_one 57 | m 58 | w: do_close 59 | f: do_close 60 | r: do_close 61 | w: do_exit 62 | w: exiting 63 | f: do_exit 64 | f: exiting 65 | r: do_exit 66 | r: exiting 67 | end 68 | -------------------------------------------------------------------------------- /tests/test49.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | r: do_open 3 | w: do_write_one_5b 4 | w: wrote seq aaaaa 5 | w: do_write_one_3b 6 | w: wrote seq bbb 7 | w: do_write_one 8 | w: wrote seq c 9 | w: do_write_one_3b 10 | w: wrote seq ddd 11 | w: do_write_one 12 | w: wrote seq e 13 | w: do_write_one_5b 14 | w: wrote seq fffff 15 | w: do_write_one 16 | w: wrote seq g 17 | w: do_write_one 18 | w: wrote seq h 19 | r: do_stat 20 | stat: 0 21 | bw 20, br 0, mw 8, mr 0, md 6, bd 18, bn 20, bu 2, mu 2 22 | r: do_read_one 23 | g 24 | w: do_write_one_5b 25 | w: wrote seq iiiii 26 | r: do_read_one 27 | h 28 | r: do_read_one 29 | iiiii 30 | f: do_open 31 | f: do_stat 32 | stat: 0 33 | bw 25, br 7, mw 9, mr 3, md 7, bd 19, bn 20, bu 6, mu 2 34 | f: do_read_one 35 | h 36 | f: do_read_one 37 | iiiii 38 | w: do_write_one_5b 39 | w: wrote seq jjjjj 40 | r: do_read_one 41 | jjjjj 42 | f: do_read_one 43 | jjjjj 44 | w: do_write_one_3b 45 | w: wrote seq kkk 46 | r: do_read_one 47 | kkk 48 | f: do_read_one 49 | kkk 50 | w: do_write_one_2b 51 | w: wrote seq ll 52 | w: do_write_one 53 | w: wrote seq m 54 | r: do_read_one 55 | ll 56 | f: do_read_one 57 | ll 58 | r: do_read_one 59 | m 60 | f: do_read_one 61 | m 62 | f: do_close 63 | f: do_open 64 | f: do_read_one 65 | ll 66 | r: do_read_one 67 | shr_read: no data 68 | w: do_write_one_2b 69 | w: wrote seq nn 70 | f: do_read_one 71 | m 72 | r: do_read_one 73 | nn 74 | f: do_read_one 75 | nn 76 | r: do_read_one 77 | shr_read: no data 78 | f: do_read_one 79 | shr_read: no data 80 | w: do_close 81 | f: do_close 82 | r: do_close 83 | w: do_exit 84 | w: exiting 85 | f: do_exit 86 | f: exiting 87 | r: do_exit 88 | r: exiting 89 | end 90 | -------------------------------------------------------------------------------- /tests/test5.ans: -------------------------------------------------------------------------------- 1 | writing ...ok 2 | reading ...read 3 bytes 3 | abc 4 | reading ...read 0 bytes 5 | end 6 | -------------------------------------------------------------------------------- /tests/test5.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "shr.h" 4 | 5 | char *ring = __FILE__ ".ring"; 6 | char *data = "abcdefghi"; 7 | 8 | char out[10]; 9 | 10 | int main() { 11 | setlinebuf(stdout); 12 | struct shr *s=NULL,*t=NULL; 13 | int rc = -1; 14 | 15 | unlink(ring); 16 | if (shr_init(ring, 14, 0) < 0) goto done; 17 | 18 | s = shr_open(ring, SHR_RDONLY|SHR_NONBLOCK); 19 | if (s == NULL) goto done; 20 | 21 | t = shr_open(ring, SHR_WRONLY); 22 | if (t == NULL) goto done; 23 | 24 | printf("writing ..."); 25 | if (shr_write(t, &data[0], 3) < 0) goto done; 26 | printf("ok\n"); 27 | 28 | printf("reading ..."); 29 | ssize_t nr; 30 | nr = shr_read(s, out, sizeof(out)); 31 | if (nr < 0) goto done; 32 | printf("read %ld bytes\n", (long)nr); 33 | if (nr > 0) printf("%.*s\n", (int)nr, out); 34 | 35 | printf("reading ..."); 36 | nr = shr_read(s, out, sizeof(out)); 37 | if (nr < 0) goto done; 38 | printf("read %ld bytes\n", (long)nr); 39 | if (nr > 0) printf("%.*s\n", (int)nr, out); 40 | 41 | rc = 0; 42 | 43 | done: 44 | printf("end\n"); 45 | if (s) shr_close(s); 46 | if (t) shr_close(t); 47 | unlink(ring); 48 | return rc; 49 | } 50 | -------------------------------------------------------------------------------- /tests/test50.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | r: do_open 3 | w: do_write_one_5b 4 | w: wrote seq aaaaa 5 | w: do_write_one_3b 6 | w: wrote seq bbb 7 | w: do_write_one 8 | w: wrote seq c 9 | w: do_write_one_3b 10 | w: wrote seq ddd 11 | w: do_write_one 12 | w: wrote seq e 13 | w: do_write_one_5b 14 | w: wrote seq fffff 15 | w: do_write_one 16 | w: wrote seq g 17 | w: do_write_one 18 | w: wrote seq h 19 | r: do_stat 20 | stat: 0 21 | bw 20, br 0, mw 8, mr 0, md 5, bd 13, bn 20, bu 7, mu 3 22 | r: do_read_one 23 | fffff 24 | w: do_write_one_5b 25 | w: wrote seq iiiii 26 | r: do_read_one 27 | g 28 | r: do_read_one 29 | h 30 | f: do_open 31 | f: do_stat 32 | stat: 0 33 | bw 25, br 7, mw 9, mr 3, md 6, bd 18, bn 20, bu 7, mu 3 34 | f: do_read_one 35 | g 36 | f: do_read_one 37 | h 38 | f: do_read_one 39 | iiiii 40 | w: do_write_one_5b 41 | w: wrote seq jjjjj 42 | r: do_read_one 43 | iiiii 44 | f: do_read_one 45 | jjjjj 46 | w: do_write_one_3b 47 | w: wrote seq kkk 48 | r: do_read_one 49 | jjjjj 50 | f: do_read_one 51 | kkk 52 | w: do_write_one_2b 53 | w: wrote seq ll 54 | w: do_write_one 55 | w: wrote seq m 56 | r: do_read_one 57 | kkk 58 | f: do_read_one 59 | ll 60 | r: do_read_one 61 | ll 62 | f: do_read_one 63 | m 64 | f: do_close 65 | f: do_open 66 | f: do_read_one 67 | kkk 68 | r: do_read_one 69 | m 70 | w: do_write_one_2b 71 | w: wrote seq nn 72 | f: do_read_one 73 | ll 74 | r: do_read_one 75 | nn 76 | f: do_read_one 77 | m 78 | r: do_read_one 79 | shr_read: no data 80 | f: do_read_one 81 | nn 82 | w: do_close 83 | f: do_close 84 | r: do_close 85 | w: do_exit 86 | w: exiting 87 | f: do_exit 88 | f: exiting 89 | r: do_exit 90 | r: exiting 91 | end 92 | -------------------------------------------------------------------------------- /tests/test51.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | r: do_open 3 | f: do_open 4 | w: do_write_20b 5 | w: wrote abcdefghijklmnopqrst 6 | w: do_write_20b 7 | w: wrote bcdefghijklmnopqrstu 8 | w: do_write_20b 9 | w: wrote cdefghijklmnopqrstuv 10 | w: do_stat 11 | stat: 0 12 | bw 60, br 0, mw 3, mr 0, md 2, bd 40, bn 20, bu 20, mu 1 13 | r: do_read_one 14 | cdefghijklmnopqrstuv 15 | w: do_write_20b 16 | w: wrote defghijklmnopqrstuvw 17 | w: do_write_one 18 | w: wrote seq e 19 | w: do_stat 20 | stat: 0 21 | bw 81, br 20, mw 5, mr 1, md 3, bd 60, bn 20, bu 1, mu 1 22 | r: do_read_one 23 | e 24 | w: do_write_20b 25 | w: wrote fghijklmnopqrstuvwxy 26 | r: do_read_one 27 | fghijklmnopqrstuvwxy 28 | w: do_write_one 29 | w: wrote seq g 30 | r: do_read_one 31 | g 32 | w: do_close 33 | f: do_close 34 | r: do_close 35 | w: do_exit 36 | w: exiting 37 | f: do_exit 38 | f: exiting 39 | r: do_exit 40 | r: exiting 41 | end 42 | -------------------------------------------------------------------------------- /tests/test52.ans: -------------------------------------------------------------------------------- 1 | r: ready 2 | w: ready 3 | w: open 4 | r: open 5 | w: write 6 | w: write 7 | w: write 8 | r: readv 9 | r: rc 9 10 | r: niov 3 11 | [abc] 12 | [abc] 13 | [abc] 14 | w: close 15 | r: close 16 | w: eof 17 | r: eof 18 | end 19 | -------------------------------------------------------------------------------- /tests/test53.ans: -------------------------------------------------------------------------------- 1 | r: ready 2 | w: ready 3 | w: open 4 | r: open 5 | r: readv 6 | r: rc 0 7 | r: niov 0 8 | w: write 9 | w: write 10 | w: write 11 | w: close 12 | r: close 13 | w: eof 14 | r: eof 15 | end 16 | -------------------------------------------------------------------------------- /tests/test54.ans: -------------------------------------------------------------------------------- 1 | r: ready 2 | w: ready 3 | w: open 4 | r: open 5 | w: write 6 | w: write 7 | w: write 8 | r: readv 9 | r: rc 6 10 | r: niov 2 11 | [abc] 12 | [abc] 13 | w: close 14 | r: close 15 | w: eof 16 | r: eof 17 | end 18 | -------------------------------------------------------------------------------- /tests/test55.ans: -------------------------------------------------------------------------------- 1 | r: ready 2 | w: ready 3 | w: open 4 | r: open 5 | w: write 6 | w: write 7 | w: write 8 | r: readv 9 | r: rc 6 10 | r: niov 2 11 | [abc] 12 | [abc] 13 | w: close 14 | r: close 15 | w: eof 16 | r: eof 17 | end 18 | -------------------------------------------------------------------------------- /tests/test56.ans: -------------------------------------------------------------------------------- 1 | r: ready 2 | w: ready 3 | w: open 4 | r: open 5 | w: write 6 | w: write 7 | w: write 8 | r: readv 9 | r: rc -2 10 | r: niov 0 11 | w: close 12 | r: close 13 | w: eof 14 | r: eof 15 | end 16 | -------------------------------------------------------------------------------- /tests/test57.ans: -------------------------------------------------------------------------------- 1 | r: ready 2 | w: ready 3 | w: open 4 | r: open 5 | w: stat: 0 6 | w: bw 0, br 0, mw 0, mr 0, md 0, bd 0, bn 40, bu 0, mu 0 7 | w: write 8 | w: stat: 0 9 | w: bw 3, br 0, mw 1, mr 0, md 0, bd 0, bn 40, bu 3, mu 1 10 | w: write 11 | w: stat: 0 12 | w: bw 6, br 0, mw 2, mr 0, md 0, bd 0, bn 40, bu 6, mu 2 13 | w: write 14 | w: stat: 0 15 | w: bw 9, br 0, mw 3, mr 0, md 0, bd 0, bn 40, bu 9, mu 3 16 | r: readv 17 | r: rc 9 18 | r: niov 3 19 | [abc] 20 | [abc] 21 | [abc] 22 | w: stat: 0 23 | w: bw 9, br 9, mw 3, mr 3, md 0, bd 0, bn 40, bu 0, mu 0 24 | w: close 25 | r: close 26 | w: eof 27 | r: eof 28 | end 29 | -------------------------------------------------------------------------------- /tests/test58.ans: -------------------------------------------------------------------------------- 1 | r: ready 2 | w: ready 3 | w: open 4 | r: open 5 | w: stat: 0 6 | w: bw 0, br 0, mw 0, mr 0, md 0, bd 0, bn 40, bu 0, mu 0 7 | w: write 8 | w: stat: 0 9 | w: bw 3, br 0, mw 1, mr 0, md 0, bd 0, bn 40, bu 3, mu 1 10 | w: write 11 | w: stat: 0 12 | w: bw 6, br 0, mw 2, mr 0, md 0, bd 0, bn 40, bu 6, mu 2 13 | w: write 14 | w: stat: 0 15 | w: bw 9, br 0, mw 3, mr 0, md 0, bd 0, bn 40, bu 9, mu 3 16 | r: readv 17 | r: rc 6 18 | r: niov 2 19 | [abc] 20 | [abc] 21 | w: stat: 0 22 | w: bw 9, br 6, mw 3, mr 2, md 0, bd 0, bn 40, bu 3, mu 1 23 | w: close 24 | r: close 25 | w: eof 26 | r: eof 27 | end 28 | -------------------------------------------------------------------------------- /tests/test59.ans: -------------------------------------------------------------------------------- 1 | r: ready 2 | w: ready 3 | w: open 4 | r: open 5 | w: stat: 0 6 | w: bw 0, br 0, mw 0, mr 0, md 0, bd 0, bn 40, bu 0, mu 0 7 | w: writev 8 | w: rc 6 9 | w: stat: 0 10 | w: bw 6, br 0, mw 3, mr 0, md 0, bd 0, bn 40, bu 6, mu 3 11 | r: readv 12 | r: rc 6 13 | r: niov 3 14 | [a] 15 | [ab] 16 | [abc] 17 | w: stat: 0 18 | w: bw 6, br 6, mw 3, mr 3, md 0, bd 0, bn 40, bu 0, mu 0 19 | w: close 20 | r: close 21 | w: eof 22 | r: eof 23 | end 24 | -------------------------------------------------------------------------------- /tests/test6.ans: -------------------------------------------------------------------------------- 1 | writing ...ok 2 | reading ...read 3 bytes 3 | abc 4 | writing ...ok 5 | reading ...read 3 bytes 6 | def 7 | end 8 | -------------------------------------------------------------------------------- /tests/test6.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "shr.h" 4 | 5 | char *ring = __FILE__ ".ring"; 6 | char *data = "abcdefghi"; 7 | 8 | char out[10]; 9 | 10 | int main() { 11 | setlinebuf(stdout); 12 | struct shr *s=NULL,*t=NULL; 13 | int rc = -1; 14 | 15 | unlink(ring); 16 | if (shr_init(ring, 14, 0) < 0) goto done; 17 | 18 | s = shr_open(ring, SHR_RDONLY); 19 | if (s == NULL) goto done; 20 | 21 | t = shr_open(ring, SHR_WRONLY); 22 | if (t == NULL) goto done; 23 | 24 | printf("writing ..."); 25 | if (shr_write(t, &data[0], 3) < 0) goto done; 26 | printf("ok\n"); 27 | 28 | printf("reading ..."); 29 | ssize_t nr; 30 | nr = shr_read(s, out, sizeof(out)); 31 | if (nr < 0) goto done; 32 | printf("read %ld bytes\n", (long)nr); 33 | if (nr > 0) printf("%.*s\n", (int)nr, out); 34 | 35 | printf("writing ..."); 36 | if (shr_write(t, &data[3], 3) < 0) goto done; 37 | printf("ok\n"); 38 | 39 | printf("reading ..."); 40 | nr = shr_read(s, out, sizeof(out)); 41 | if (nr < 0) goto done; 42 | printf("read %ld bytes\n", (long)nr); 43 | if (nr > 0) printf("%.*s\n", (int)nr, out); 44 | 45 | rc = 0; 46 | 47 | done: 48 | printf("end\n"); 49 | if (s) shr_close(s); 50 | if (t) shr_close(t); 51 | unlink(ring); 52 | return rc; 53 | } 54 | -------------------------------------------------------------------------------- /tests/test60.ans: -------------------------------------------------------------------------------- 1 | write 3 2 | opening for reading 3 | getting selectable fd 4 | selecting... 5 | select: ready 6 | read 7 | r: [-2] (buf too small) 8 | select: ready 9 | -------------------------------------------------------------------------------- /tests/test60.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "shr.h" 9 | 10 | char *ring = __FILE__ ".ring"; 11 | 12 | int main() { 13 | setlinebuf(stdout); 14 | int rc = 0,fd; 15 | shr *s; 16 | ssize_t nr; 17 | char c; 18 | 19 | setbuf(stdout,NULL); 20 | unlink(ring); 21 | 22 | shr_init(ring, 14, 0); 23 | s = shr_open(ring, SHR_WRONLY); 24 | if (s == NULL) goto done; 25 | nr = shr_write(s, "abc", 3); 26 | printf("write %d\n", (int)nr); 27 | shr_close(s); 28 | 29 | printf("opening for reading\n"); 30 | s = shr_open(ring, SHR_RDONLY|SHR_NONBLOCK); 31 | if (s == NULL) goto done; 32 | printf("getting selectable fd\n"); 33 | fd = shr_get_selectable_fd(s); 34 | if (fd < 0) goto done; 35 | 36 | printf("selecting...\n"); 37 | fd_set fds; 38 | FD_ZERO(&fds); 39 | FD_SET(fd, &fds); 40 | struct timeval tv = {.tv_sec = 0, .tv_usec =10}; 41 | rc = select(fd+1, &fds, NULL, NULL, &tv); 42 | if (rc < 0) printf("select: %s\n", strerror(errno)); 43 | else if (rc == 0) printf("select: timeout\n"); 44 | else if (rc == 1) printf("select: ready\n"); 45 | 46 | do { 47 | printf("read\n"); 48 | nr = shr_read(s, &c, sizeof(c)); // byte read 49 | if (nr < 0) printf("r: [%zd] (buf too small)\n", nr); 50 | if (nr > 0) printf("r: [%c]\n", c); 51 | if (nr == 0) printf("r: wouldblock\n"); 52 | 53 | FD_ZERO(&fds); 54 | FD_SET(fd, &fds); 55 | struct timeval tv = {.tv_sec = 0, .tv_usec =10}; 56 | rc = select(fd+1, &fds, NULL, NULL, &tv); 57 | if (rc < 0) printf("select: %s\n", strerror(errno)); 58 | else if (rc == 0) printf("select: timeout\n"); 59 | else if (rc == 1) printf("select: ready\n"); 60 | 61 | } while (nr > 0); 62 | 63 | shr_close(s); 64 | rc = 0; 65 | 66 | done: 67 | unlink(ring); 68 | return rc; 69 | } 70 | -------------------------------------------------------------------------------- /tests/test61.ans: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/troydhanson/shr/c77e2709dcc7f81f4e2985ac7522993e3cde63d1/tests/test61.ans -------------------------------------------------------------------------------- /tests/test61.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "shr.h" 4 | 5 | char *ring = __FILE__ ".ring"; 6 | 7 | const char app[] = "abcdefghijklmnopqrstuvwxyz"; 8 | 9 | int main() { 10 | setlinebuf(stdout); 11 | int rc = -1; 12 | 13 | unlink(ring); 14 | if (shr_init(ring, 8, SHR_APPDATA, app, sizeof(app)) < 0) goto done; 15 | 16 | rc = 0; 17 | 18 | done: 19 | unlink(ring); 20 | return rc; 21 | } 22 | -------------------------------------------------------------------------------- /tests/test62.ans: -------------------------------------------------------------------------------- 1 | abcdefghijklmnopqrstuvwxyz 2 | -------------------------------------------------------------------------------- /tests/test62.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "shr.h" 4 | 5 | char *ring = __FILE__ ".ring"; 6 | 7 | const char app[] = "abcdefghijklmnopqrstuvwxyz"; 8 | 9 | int main() { 10 | setlinebuf(stdout); 11 | struct shr *s=NULL; 12 | int rc = -1, sc; 13 | 14 | unlink(ring); 15 | if (shr_init(ring, 8, SHR_APPDATA, app, sizeof(app)) < 0) goto done; 16 | 17 | char *buf=NULL; 18 | size_t len=0; 19 | 20 | s = shr_open(ring, SHR_RDONLY); 21 | if (s == NULL) goto done; 22 | 23 | sc = shr_appdata(s, (void**)&buf, NULL, &len); 24 | if (sc) goto done; 25 | if (buf) printf("%.*s\n", (int)len, buf); 26 | 27 | rc = 0; 28 | 29 | done: 30 | if (s) shr_close(s); 31 | unlink(ring); 32 | return rc; 33 | } 34 | -------------------------------------------------------------------------------- /tests/test63.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | w: do_close 3 | w: do_exit 4 | w: exiting 5 | r: do_exit 6 | r: exiting 7 | end 8 | -------------------------------------------------------------------------------- /tests/test63.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | #define W 0 14 | #define R 1 15 | 16 | char *ring = __FILE__ ".ring"; 17 | 18 | /* make an enum and a char*[] for the ops */ 19 | #define adim(x) (sizeof(x)/sizeof(*x)) 20 | #define OPS o(do_none) o(do_open) o(do_close) o(do_exit) 21 | #define o(x) #x, 22 | char *op_s[] = { OPS }; 23 | #undef o 24 | #define o(x) x, 25 | typedef enum { OPS } ops; 26 | 27 | const int ring_sz = 100000; 28 | 29 | struct { 30 | char *prog; 31 | time_t start; 32 | int verbose; 33 | int speed; 34 | } CF = { 35 | .speed = 1, 36 | }; 37 | 38 | /* the event sequence we want executed */ 39 | struct events { 40 | int when; 41 | int who; 42 | ops op; 43 | } ev[] = { 44 | {1, W, do_open}, 45 | {2, W, do_close}, 46 | {3, W, do_exit}, 47 | {4, R, do_exit}, 48 | }; 49 | 50 | /* sleep til X seconds since start */ 51 | void sleep_til( int el ) { 52 | time_t now; 53 | time(&now); 54 | 55 | if (now > CF.start + el) { 56 | fprintf(stderr, "sleep_til: already elapsed\n"); 57 | return; 58 | } 59 | 60 | sleep((CF.start + el) - now); 61 | } 62 | 63 | /* run the event sequence 64 | * runs in child process. never returns 65 | */ 66 | void execute(int me) { 67 | struct shr *s = NULL; 68 | unsigned i; 69 | 70 | for(i=0; i < adim(ev); i++) { 71 | 72 | if ( ev[i].who != me ) continue; 73 | 74 | sleep_til( ev[i].when * CF.speed ); 75 | printf("%s: %s\n", (me == R) ? "r" : "w", op_s[ ev[i].op ]); 76 | 77 | switch( ev[i].op ) { 78 | case do_open: 79 | s = shr_open(ring, (me == R) ? SHR_RDONLY : SHR_WRONLY); 80 | if (s == NULL) goto done; 81 | break; 82 | case do_close: 83 | shr_close(s); 84 | break; 85 | case do_exit: 86 | goto done; 87 | break; 88 | default: 89 | fprintf(stderr,"op not implemented\n"); 90 | assert(0); 91 | break; 92 | } 93 | } 94 | 95 | done: 96 | printf("%s: exiting\n", (me == R) ? "r" : "w"); 97 | exit(0); 98 | } 99 | 100 | void usage() { 101 | fprintf(stderr,"usage: %s [-v] [-s ]\n", CF.prog); 102 | fprintf(stderr,"-s (factor to slow test [def: 1])\n"); 103 | fprintf(stderr,"-v verbose\n"); 104 | exit(-1); 105 | } 106 | 107 | int main(int argc, char *argv[]) { 108 | setlinebuf(stdout); 109 | int rc = -1, opt; 110 | pid_t rpid,wpid; 111 | 112 | while ( (opt = getopt(argc,argv,"vhs:")) > 0) { 113 | switch(opt) { 114 | case 'v': CF.verbose++; break; 115 | case 's': CF.speed = atoi(optarg); break; 116 | case 'h': default: usage(); break; 117 | } 118 | } 119 | 120 | time(&CF.start); 121 | unlink(ring); 122 | shr_init(ring, ring_sz, 0); 123 | 124 | rpid = fork(); 125 | if (rpid < 0) goto done; 126 | if (rpid == 0) execute(R); 127 | assert(rpid > 0); 128 | 129 | wpid = fork(); 130 | if (wpid < 0) goto done; 131 | if (wpid == 0) execute(W); 132 | assert(wpid > 0); 133 | 134 | waitpid(wpid,NULL,0); 135 | waitpid(rpid,NULL,0); 136 | 137 | done: 138 | unlink(ring); 139 | printf("end\n"); 140 | return rc; 141 | } 142 | 143 | -------------------------------------------------------------------------------- /tests/test64.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | w: do_fill 3 | w: wrote 370000 bytes / 10000 messages 4 | w: do_close 5 | w: do_exit 6 | w: exiting 7 | r: do_exit 8 | r: exiting 9 | end 10 | -------------------------------------------------------------------------------- /tests/test64.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | #define W 0 14 | #define R 1 15 | 16 | char *ring = __FILE__ ".ring"; 17 | 18 | /* make an enum and a char*[] for the ops */ 19 | #define adim(x) (sizeof(x)/sizeof(*x)) 20 | #define OPS o(do_none) o(do_open) o(do_fill) o(do_close) o(do_exit) 21 | #define o(x) #x, 22 | char *op_s[] = { OPS }; 23 | #undef o 24 | #define o(x) x, 25 | typedef enum { OPS } ops; 26 | 27 | #define NMSG 10000 28 | char msg[] = "1234567890abcdefghijklmnopqrstuvwxyz"; 29 | const int ring_sz = (sizeof(msg)+0)*NMSG; 30 | struct iovec iov[NMSG]; 31 | 32 | struct { 33 | char *prog; 34 | time_t start; 35 | int verbose; 36 | int speed; 37 | struct iovec *io; 38 | } CF = { 39 | .speed = 1, 40 | .io = iov, 41 | }; 42 | 43 | /* the event sequence we want executed */ 44 | struct events { 45 | int when; 46 | int who; 47 | ops op; 48 | } ev[] = { 49 | {1, W, do_open}, 50 | {2, W, do_fill}, 51 | {3, W, do_close}, 52 | {4, W, do_exit}, 53 | {5, R, do_exit}, 54 | }; 55 | 56 | /* sleep til X seconds since start */ 57 | void sleep_til( int el ) { 58 | time_t now; 59 | time(&now); 60 | 61 | if (now > CF.start + el) { 62 | fprintf(stderr, "sleep_til: already elapsed\n"); 63 | return; 64 | } 65 | 66 | sleep((CF.start + el) - now); 67 | } 68 | 69 | /* run the event sequence 70 | * runs in child process. never returns 71 | */ 72 | void execute(int me) { 73 | struct shr *s = NULL; 74 | unsigned i, n; 75 | ssize_t nr; 76 | 77 | for(i=0; i < adim(ev); i++) { 78 | 79 | if ( ev[i].who != me ) continue; 80 | 81 | sleep_til( ev[i].when * CF.speed ); 82 | printf("%s: %s\n", (me == R) ? "r" : "w", op_s[ ev[i].op ]); 83 | 84 | switch( ev[i].op ) { 85 | case do_open: 86 | s = shr_open(ring, (me == R) ? SHR_RDONLY : SHR_WRONLY); 87 | if (s == NULL) goto done; 88 | break; 89 | case do_close: 90 | shr_close(s); 91 | break; 92 | case do_exit: 93 | goto done; 94 | break; 95 | case do_fill: 96 | for(n=0; n < NMSG; n++) { 97 | CF.io[n].iov_len = sizeof(msg); 98 | CF.io[n].iov_base = msg; 99 | } 100 | nr = shr_writev(s, CF.io, NMSG); 101 | printf("w: wrote %d bytes / %d messages\n", (int)nr, NMSG); 102 | break; 103 | default: 104 | fprintf(stderr,"op not implemented\n"); 105 | assert(0); 106 | break; 107 | } 108 | } 109 | 110 | done: 111 | printf("%s: exiting\n", (me == R) ? "r" : "w"); 112 | exit(0); 113 | } 114 | 115 | void usage() { 116 | fprintf(stderr,"usage: %s [-v] [-s ]\n", CF.prog); 117 | fprintf(stderr,"-s (factor to slow test [def: 1])\n"); 118 | fprintf(stderr,"-v verbose\n"); 119 | exit(-1); 120 | } 121 | 122 | int main(int argc, char *argv[]) { 123 | setlinebuf(stdout); 124 | int rc = -1, opt; 125 | pid_t rpid,wpid; 126 | 127 | while ( (opt = getopt(argc,argv,"vhs:")) > 0) { 128 | switch(opt) { 129 | case 'v': CF.verbose++; break; 130 | case 's': CF.speed = atoi(optarg); break; 131 | case 'h': default: usage(); break; 132 | } 133 | } 134 | 135 | time(&CF.start); 136 | unlink(ring); 137 | shr_init(ring, ring_sz, SHR_MAXMSGS_2, NMSG); 138 | 139 | rpid = fork(); 140 | if (rpid < 0) goto done; 141 | if (rpid == 0) execute(R); 142 | assert(rpid > 0); 143 | 144 | wpid = fork(); 145 | if (wpid < 0) goto done; 146 | if (wpid == 0) execute(W); 147 | assert(wpid > 0); 148 | 149 | waitpid(wpid,NULL,0); 150 | waitpid(rpid,NULL,0); 151 | 152 | done: 153 | unlink(ring); 154 | printf("end\n"); 155 | return rc; 156 | } 157 | 158 | -------------------------------------------------------------------------------- /tests/test65.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | w: do_fill 3 | w: wrote 370000 bytes / 10000 messages 4 | w: do_close 5 | w: do_exit 6 | w: exiting 7 | r: do_open 8 | r: do_read 9 | read 10000 messages 10 | r: do_close 11 | r: do_exit 12 | r: exiting 13 | end 14 | -------------------------------------------------------------------------------- /tests/test65.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | #define W 0 14 | #define R 1 15 | 16 | char *ring = __FILE__ ".ring"; 17 | 18 | /* make an enum and a char*[] for the ops */ 19 | #define adim(x) (sizeof(x)/sizeof(*x)) 20 | #define OPS o(do_none) o(do_open) o(do_fill) o(do_read) o(do_close) o(do_exit) 21 | #define o(x) #x, 22 | char *op_s[] = { OPS }; 23 | #undef o 24 | #define o(x) x, 25 | typedef enum { OPS } ops; 26 | 27 | #define NMSG 10000 28 | char msg[] = "1234567890abcdefghijklmnopqrstuvwxyz"; 29 | const int ring_sz = (sizeof(msg)+0)*NMSG; 30 | struct iovec iov[NMSG]; 31 | 32 | struct { 33 | char *prog; 34 | time_t start; 35 | int verbose; 36 | int speed; 37 | struct iovec *io; 38 | } CF = { 39 | .speed = 1, 40 | .io = iov, 41 | }; 42 | 43 | /* the event sequence we want executed */ 44 | struct events { 45 | int when; 46 | int who; 47 | ops op; 48 | } ev[] = { 49 | {1, W, do_open}, 50 | {2, W, do_fill}, 51 | {3, W, do_close}, 52 | {4, W, do_exit}, 53 | {5, R, do_open}, 54 | {6, R, do_read}, 55 | {7, R, do_close}, 56 | {8, R, do_exit}, 57 | }; 58 | 59 | /* sleep til X seconds since start */ 60 | void sleep_til( int el ) { 61 | time_t now; 62 | time(&now); 63 | 64 | if (now > CF.start + el) { 65 | fprintf(stderr, "sleep_til: already elapsed\n"); 66 | return; 67 | } 68 | 69 | sleep((CF.start + el) - now); 70 | } 71 | 72 | /* run the event sequence 73 | * runs in child process. never returns 74 | */ 75 | void execute(int me) { 76 | char buf[sizeof(msg)]; 77 | struct shr *s = NULL; 78 | unsigned i, n; 79 | ssize_t nr; 80 | 81 | for(i=0; i < adim(ev); i++) { 82 | 83 | if ( ev[i].who != me ) continue; 84 | 85 | sleep_til( ev[i].when * CF.speed ); 86 | printf("%s: %s\n", (me == R) ? "r" : "w", op_s[ ev[i].op ]); 87 | 88 | switch( ev[i].op ) { 89 | case do_open: 90 | s = shr_open(ring, (me == R) ? SHR_RDONLY : SHR_WRONLY); 91 | if (s == NULL) goto done; 92 | break; 93 | case do_close: 94 | shr_close(s); 95 | break; 96 | case do_exit: 97 | goto done; 98 | break; 99 | case do_read: 100 | for(n=0; n < NMSG; n++) { 101 | nr = shr_read(s, buf, sizeof(buf)); 102 | if (nr != sizeof(msg)) { 103 | printf("shr_read: %d\n", (int)nr); 104 | break; 105 | } 106 | } 107 | printf("read %d messages\n", NMSG); 108 | break; 109 | case do_fill: 110 | for(n=0; n < NMSG; n++) { 111 | CF.io[n].iov_len = sizeof(msg); 112 | CF.io[n].iov_base = msg; 113 | } 114 | nr = shr_writev(s, CF.io, NMSG); 115 | printf("w: wrote %d bytes / %d messages\n", (int)nr, NMSG); 116 | break; 117 | default: 118 | fprintf(stderr,"op not implemented\n"); 119 | assert(0); 120 | break; 121 | } 122 | } 123 | 124 | done: 125 | printf("%s: exiting\n", (me == R) ? "r" : "w"); 126 | exit(0); 127 | } 128 | 129 | void usage() { 130 | fprintf(stderr,"usage: %s [-v] [-s ]\n", CF.prog); 131 | fprintf(stderr,"-s (factor to slow test [def: 1])\n"); 132 | fprintf(stderr,"-v verbose\n"); 133 | exit(-1); 134 | } 135 | 136 | int main(int argc, char *argv[]) { 137 | setlinebuf(stdout); 138 | int rc = -1, opt; 139 | pid_t rpid,wpid; 140 | 141 | while ( (opt = getopt(argc,argv,"vhs:")) > 0) { 142 | switch(opt) { 143 | case 'v': CF.verbose++; break; 144 | case 's': CF.speed = atoi(optarg); break; 145 | case 'h': default: usage(); break; 146 | } 147 | } 148 | 149 | time(&CF.start); 150 | unlink(ring); 151 | shr_init(ring, ring_sz, SHR_MAXMSGS_2, NMSG); 152 | 153 | rpid = fork(); 154 | if (rpid < 0) goto done; 155 | if (rpid == 0) execute(R); 156 | assert(rpid > 0); 157 | 158 | wpid = fork(); 159 | if (wpid < 0) goto done; 160 | if (wpid == 0) execute(W); 161 | assert(wpid > 0); 162 | 163 | waitpid(wpid,NULL,0); 164 | waitpid(rpid,NULL,0); 165 | 166 | done: 167 | unlink(ring); 168 | printf("end\n"); 169 | return rc; 170 | } 171 | 172 | -------------------------------------------------------------------------------- /tests/test66.ans: -------------------------------------------------------------------------------- 1 | r: do_open 2 | w: do_open 3 | w: do_fill 4 | w: wrote 10 messages (to seq 10) 5 | r: do_read_half 6 | 0 7 | 1 8 | 2 9 | 3 10 | 4 11 | w: do_fill 12 | w: wrote 10 messages (to seq 20) 13 | r: do_read_half 14 | 10 15 | 11 16 | 12 17 | 13 18 | 14 19 | w: do_close 20 | r: do_close 21 | w: do_exit 22 | w: exiting 23 | r: do_exit 24 | r: exiting 25 | end 26 | -------------------------------------------------------------------------------- /tests/test66.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | #define W 0 14 | #define R 1 15 | 16 | char *ring = __FILE__ ".ring"; 17 | 18 | /* make an enum and a char*[] for the ops */ 19 | #define adim(x) (sizeof(x)/sizeof(*x)) 20 | #define OPS o(do_none) o(do_open) o(do_fill) o(do_read_half) o(do_close) o(do_exit) 21 | #define o(x) #x, 22 | char *op_s[] = { OPS }; 23 | #undef o 24 | #define o(x) x, 25 | typedef enum { OPS } ops; 26 | 27 | #define NMSG 10 28 | char msg[] = "000000000000000000000000000000000000"; 29 | const int ring_sz = (sizeof(msg)+0)*NMSG; 30 | struct iovec iov[NMSG]; 31 | char msg_all[sizeof(msg)*NMSG]; 32 | 33 | struct { 34 | char *prog; 35 | time_t start; 36 | int verbose; 37 | int speed; 38 | int unlink; 39 | } CF = { 40 | .speed = 1, 41 | .unlink = 1, 42 | }; 43 | 44 | /* the event sequence we want executed */ 45 | struct events { 46 | int when; 47 | int who; 48 | ops op; 49 | } ev[] = { 50 | {1, R, do_open}, 51 | {2, W, do_open}, 52 | 53 | {3, W, do_fill}, /* w 10 */ 54 | {4, R, do_read_half}, /* r 5 */ 55 | {5, W, do_fill}, /* w 10 (Drop 5) */ 56 | {6, R, do_read_half}, /* r 5 (skip lost) */ 57 | 58 | {7, W, do_close}, 59 | {8, R, do_close}, 60 | {9, W, do_exit}, 61 | {10, R, do_exit}, 62 | }; 63 | 64 | /* sleep til X seconds since start */ 65 | void sleep_til( int el ) { 66 | time_t now; 67 | time(&now); 68 | 69 | if (now > CF.start + el) { 70 | fprintf(stderr, "sleep_til: already elapsed\n"); 71 | return; 72 | } 73 | 74 | sleep((CF.start + el) - now); 75 | } 76 | 77 | /* run the event sequence 78 | * runs in child process. never returns 79 | */ 80 | void execute(int me) { 81 | char msg_one[sizeof(msg)]; 82 | struct shr *s = NULL; 83 | unsigned i, n; 84 | ssize_t nr; 85 | unsigned seq = 0; 86 | 87 | for(i=0; i < adim(ev); i++) { 88 | 89 | if ( ev[i].who != me ) continue; 90 | 91 | sleep_til( ev[i].when * CF.speed ); 92 | printf("%s: %s\n", (me == R) ? "r" : "w", op_s[ ev[i].op ]); 93 | 94 | switch( ev[i].op ) { 95 | case do_open: 96 | s = shr_open(ring, (me == R) ? SHR_RDONLY : SHR_WRONLY); 97 | if (s == NULL) goto done; 98 | break; 99 | case do_close: 100 | shr_close(s); 101 | break; 102 | case do_exit: 103 | goto done; 104 | break; 105 | case do_read_half: 106 | for(n=0; n < NMSG/2; n++) { 107 | nr = shr_read(s, msg_one, sizeof(msg_one)); 108 | if (nr != sizeof(msg)) { 109 | printf("shr_read: %d\n", (int)nr); 110 | break; 111 | } 112 | printf("%s\n", msg_one); 113 | } 114 | break; 115 | case do_fill: 116 | for(n=0; n < NMSG; n++) { 117 | snprintf(msg_one, sizeof(msg_one), "%u", seq++); 118 | nr = shr_write(s, msg_one, sizeof(msg_one)); 119 | } 120 | printf("w: wrote %d messages (to seq %u)\n", NMSG, seq); 121 | break; 122 | default: 123 | fprintf(stderr,"op not implemented\n"); 124 | assert(0); 125 | break; 126 | } 127 | } 128 | 129 | done: 130 | printf("%s: exiting\n", (me == R) ? "r" : "w"); 131 | exit(0); 132 | } 133 | 134 | void usage() { 135 | fprintf(stderr,"usage: %s [-v] [-s ]\n", CF.prog); 136 | fprintf(stderr,"-v verbose\n"); 137 | fprintf(stderr,"-s (factor to slow test [def: 1])\n"); 138 | fprintf(stderr,"-u (don't unlink ring after test)\n"); 139 | exit(-1); 140 | } 141 | 142 | int main(int argc, char *argv[]) { 143 | setlinebuf(stdout); 144 | int rc = -1, opt; 145 | pid_t rpid,wpid; 146 | 147 | while ( (opt = getopt(argc,argv,"vhs:u")) > 0) { 148 | switch(opt) { 149 | case 'v': CF.verbose++; break; 150 | case 's': CF.speed = atoi(optarg); break; 151 | case 'u': CF.unlink = 0; break; 152 | case 'h': default: usage(); break; 153 | } 154 | } 155 | 156 | time(&CF.start); 157 | unlink(ring); 158 | shr_init(ring, ring_sz, SHR_FARM | SHR_MAXMSGS_2, NMSG); 159 | 160 | rpid = fork(); 161 | if (rpid < 0) goto done; 162 | if (rpid == 0) execute(R); 163 | assert(rpid > 0); 164 | 165 | wpid = fork(); 166 | if (wpid < 0) goto done; 167 | if (wpid == 0) execute(W); 168 | assert(wpid > 0); 169 | 170 | waitpid(wpid,NULL,0); 171 | waitpid(rpid,NULL,0); 172 | 173 | done: 174 | if (CF.unlink) unlink(ring); 175 | printf("end\n"); 176 | return rc; 177 | } 178 | 179 | -------------------------------------------------------------------------------- /tests/test67.ans: -------------------------------------------------------------------------------- 1 | r: do_open 2 | w: do_open 3 | w: do_fill 4 | w: wrote 10 messages (to seq 10) 5 | r: do_read_half 6 | 0 7 | 1 8 | 2 9 | 3 10 | 4 11 | w: do_fill 12 | w: wrote 10 messages (to seq 20) 13 | r: do_read_half 14 | 10 15 | 11 16 | 12 17 | 13 18 | 14 19 | r: do_read_half 20 | 15 21 | 16 22 | 17 23 | 18 24 | 19 25 | w: do_close 26 | r: do_close 27 | w: do_exit 28 | w: exiting 29 | r: do_exit 30 | r: exiting 31 | end 32 | -------------------------------------------------------------------------------- /tests/test67.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | #define W 0 14 | #define R 1 15 | 16 | char *ring = __FILE__ ".ring"; 17 | 18 | /* make an enum and a char*[] for the ops */ 19 | #define adim(x) (sizeof(x)/sizeof(*x)) 20 | #define OPS o(do_none) o(do_open) o(do_fill) o(do_read_half) o(do_close) o(do_exit) 21 | #define o(x) #x, 22 | char *op_s[] = { OPS }; 23 | #undef o 24 | #define o(x) x, 25 | typedef enum { OPS } ops; 26 | 27 | #define NMSG 10 28 | char msg[] = "000000000000000000000000000000000000"; 29 | const int ring_sz = (sizeof(msg)+0)*NMSG; 30 | struct iovec iov[NMSG]; 31 | char msg_all[sizeof(msg)*NMSG]; 32 | 33 | struct { 34 | char *prog; 35 | time_t start; 36 | int verbose; 37 | int speed; 38 | int unlink; 39 | } CF = { 40 | .speed = 1, 41 | .unlink = 1, 42 | }; 43 | 44 | /* the event sequence we want executed */ 45 | struct events { 46 | int when; 47 | int who; 48 | ops op; 49 | } ev[] = { 50 | {1, R, do_open}, 51 | {2, W, do_open}, 52 | 53 | {3, W, do_fill}, /* w 10 */ 54 | {4, R, do_read_half}, /* r 5 */ 55 | {5, W, do_fill}, /* w 10 (Drop 5) */ 56 | {6, R, do_read_half}, /* r 5 (skip lost) */ 57 | {7, R, do_read_half}, /* r 5 (drain) */ 58 | 59 | {8, W, do_close}, 60 | {9, R, do_close}, 61 | {10, W, do_exit}, 62 | {11, R, do_exit}, 63 | }; 64 | 65 | /* sleep til X seconds since start */ 66 | void sleep_til( int el ) { 67 | time_t now; 68 | time(&now); 69 | 70 | if (now > CF.start + el) { 71 | fprintf(stderr, "sleep_til: already elapsed\n"); 72 | return; 73 | } 74 | 75 | sleep((CF.start + el) - now); 76 | } 77 | 78 | /* run the event sequence 79 | * runs in child process. never returns 80 | */ 81 | void execute(int me) { 82 | char msg_one[sizeof(msg)]; 83 | struct shr *s = NULL; 84 | unsigned i, n; 85 | ssize_t nr; 86 | unsigned seq = 0; 87 | 88 | for(i=0; i < adim(ev); i++) { 89 | 90 | if ( ev[i].who != me ) continue; 91 | 92 | sleep_til( ev[i].when * CF.speed ); 93 | printf("%s: %s\n", (me == R) ? "r" : "w", op_s[ ev[i].op ]); 94 | 95 | switch( ev[i].op ) { 96 | case do_open: 97 | s = shr_open(ring, (me == R) ? SHR_RDONLY : SHR_WRONLY); 98 | if (s == NULL) goto done; 99 | break; 100 | case do_close: 101 | shr_close(s); 102 | break; 103 | case do_exit: 104 | goto done; 105 | break; 106 | case do_read_half: 107 | for(n=0; n < NMSG/2; n++) { 108 | nr = shr_read(s, msg_one, sizeof(msg_one)); 109 | if (nr != sizeof(msg)) { 110 | printf("shr_read: %d\n", (int)nr); 111 | break; 112 | } 113 | printf("%s\n", msg_one); 114 | } 115 | break; 116 | case do_fill: 117 | for(n=0; n < NMSG; n++) { 118 | snprintf(msg_one, sizeof(msg_one), "%u", seq++); 119 | nr = shr_write(s, msg_one, sizeof(msg_one)); 120 | } 121 | printf("w: wrote %d messages (to seq %u)\n", NMSG, seq); 122 | break; 123 | default: 124 | fprintf(stderr,"op not implemented\n"); 125 | assert(0); 126 | break; 127 | } 128 | } 129 | 130 | done: 131 | printf("%s: exiting\n", (me == R) ? "r" : "w"); 132 | exit(0); 133 | } 134 | 135 | void usage() { 136 | fprintf(stderr,"usage: %s [-v] [-s ]\n", CF.prog); 137 | fprintf(stderr,"-v verbose\n"); 138 | fprintf(stderr,"-s (factor to slow test [def: 1])\n"); 139 | fprintf(stderr,"-u (don't unlink ring after test)\n"); 140 | exit(-1); 141 | } 142 | 143 | int main(int argc, char *argv[]) { 144 | setlinebuf(stdout); 145 | int rc = -1, opt; 146 | pid_t rpid,wpid; 147 | 148 | while ( (opt = getopt(argc,argv,"vhs:u")) > 0) { 149 | switch(opt) { 150 | case 'v': CF.verbose++; break; 151 | case 's': CF.speed = atoi(optarg); break; 152 | case 'u': CF.unlink = 0; break; 153 | case 'h': default: usage(); break; 154 | } 155 | } 156 | 157 | time(&CF.start); 158 | unlink(ring); 159 | shr_init(ring, ring_sz, SHR_FARM|SHR_MAXMSGS_2, NMSG); 160 | 161 | rpid = fork(); 162 | if (rpid < 0) goto done; 163 | if (rpid == 0) execute(R); 164 | assert(rpid > 0); 165 | 166 | wpid = fork(); 167 | if (wpid < 0) goto done; 168 | if (wpid == 0) execute(W); 169 | assert(wpid > 0); 170 | 171 | waitpid(wpid,NULL,0); 172 | waitpid(rpid,NULL,0); 173 | 174 | done: 175 | if (CF.unlink) unlink(ring); 176 | printf("end\n"); 177 | return rc; 178 | } 179 | 180 | -------------------------------------------------------------------------------- /tests/test68.ans: -------------------------------------------------------------------------------- 1 | r: do_open 2 | w: do_open 3 | w: do_fill 4 | w: wrote 10 messages (to seq 10) 5 | r: do_read_half 6 | 0 7 | 1 8 | 2 9 | 3 10 | 4 11 | w: do_fill 12 | w: wrote 10 messages (to seq 20) 13 | r: do_read_half 14 | 10 15 | 11 16 | 12 17 | 13 18 | 14 19 | r: do_read_half 20 | 15 21 | 16 22 | 17 23 | 18 24 | 19 25 | r: do_close 26 | r: do_open 27 | r: do_read_half 28 | 10 29 | 11 30 | 12 31 | 13 32 | 14 33 | r: do_read_half 34 | 15 35 | 16 36 | 17 37 | 18 38 | 19 39 | r: do_close 40 | w: do_close 41 | w: do_exit 42 | w: exiting 43 | r: do_exit 44 | r: exiting 45 | end 46 | -------------------------------------------------------------------------------- /tests/test68.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | #define W 0 14 | #define R 1 15 | 16 | char *ring = __FILE__ ".ring"; 17 | 18 | /* make an enum and a char*[] for the ops */ 19 | #define adim(x) (sizeof(x)/sizeof(*x)) 20 | #define OPS o(do_none) o(do_open) o(do_fill) o(do_read_half) o(do_close) o(do_exit) 21 | #define o(x) #x, 22 | char *op_s[] = { OPS }; 23 | #undef o 24 | #define o(x) x, 25 | typedef enum { OPS } ops; 26 | 27 | #define NMSG 10 28 | char msg[] = "000000000000000000000000000000000000"; 29 | const int ring_sz = (sizeof(msg)+0)*NMSG; 30 | struct iovec iov[NMSG]; 31 | char msg_all[sizeof(msg)*NMSG]; 32 | 33 | struct { 34 | char *prog; 35 | time_t start; 36 | int verbose; 37 | int speed; 38 | int unlink; 39 | } CF = { 40 | .speed = 1, 41 | .unlink = 1, 42 | }; 43 | 44 | /* the event sequence we want executed */ 45 | struct events { 46 | int when; 47 | int who; 48 | ops op; 49 | } ev[] = { 50 | {1, R, do_open}, 51 | {2, W, do_open}, 52 | 53 | {3, W, do_fill}, /* w 10 */ 54 | {4, R, do_read_half}, /* r 5 (seq 0-4) */ 55 | {5, W, do_fill}, /* w 10 (Drop 5) */ 56 | {6, R, do_read_half}, /* r 5 (seq 10-14) */ 57 | {7, R, do_read_half}, /* r 5 (seq 15-19) */ 58 | {8, R, do_close}, 59 | 60 | { 9, R, do_open}, /* start over again */ 61 | {10, R, do_read_half}, /* r 5 (seq (10-14) */ 62 | {11, R, do_read_half}, /* r 5 (seq (15-19) */ 63 | 64 | {12, R, do_close}, 65 | {13, W, do_close}, 66 | {14, W, do_exit}, 67 | {15, R, do_exit}, 68 | }; 69 | 70 | /* sleep til X seconds since start */ 71 | void sleep_til( int el ) { 72 | time_t now; 73 | time(&now); 74 | 75 | if (now > CF.start + el) { 76 | fprintf(stderr, "sleep_til: already elapsed\n"); 77 | return; 78 | } 79 | 80 | sleep((CF.start + el) - now); 81 | } 82 | 83 | /* run the event sequence 84 | * runs in child process. never returns 85 | */ 86 | void execute(int me) { 87 | char msg_one[sizeof(msg)]; 88 | struct shr *s = NULL; 89 | unsigned i, n; 90 | ssize_t nr; 91 | unsigned seq = 0; 92 | 93 | for(i=0; i < adim(ev); i++) { 94 | 95 | if ( ev[i].who != me ) continue; 96 | 97 | sleep_til( ev[i].when * CF.speed ); 98 | printf("%s: %s\n", (me == R) ? "r" : "w", op_s[ ev[i].op ]); 99 | 100 | switch( ev[i].op ) { 101 | case do_open: 102 | s = shr_open(ring, (me == R) ? SHR_RDONLY : SHR_WRONLY); 103 | if (s == NULL) goto done; 104 | break; 105 | case do_close: 106 | shr_close(s); 107 | break; 108 | case do_exit: 109 | goto done; 110 | break; 111 | case do_read_half: 112 | for(n=0; n < NMSG/2; n++) { 113 | nr = shr_read(s, msg_one, sizeof(msg_one)); 114 | if (nr != sizeof(msg)) { 115 | printf("shr_read: %d\n", (int)nr); 116 | break; 117 | } 118 | printf("%s\n", msg_one); 119 | } 120 | break; 121 | case do_fill: 122 | for(n=0; n < NMSG; n++) { 123 | snprintf(msg_one, sizeof(msg_one), "%u", seq++); 124 | nr = shr_write(s, msg_one, sizeof(msg_one)); 125 | } 126 | printf("w: wrote %d messages (to seq %u)\n", NMSG, seq); 127 | break; 128 | default: 129 | fprintf(stderr,"op not implemented\n"); 130 | assert(0); 131 | break; 132 | } 133 | } 134 | 135 | done: 136 | printf("%s: exiting\n", (me == R) ? "r" : "w"); 137 | exit(0); 138 | } 139 | 140 | void usage() { 141 | fprintf(stderr,"usage: %s [-v] [-s ]\n", CF.prog); 142 | fprintf(stderr,"-v verbose\n"); 143 | fprintf(stderr,"-s (factor to slow test [def: 1])\n"); 144 | fprintf(stderr,"-u (don't unlink ring after test)\n"); 145 | exit(-1); 146 | } 147 | 148 | int main(int argc, char *argv[]) { 149 | setlinebuf(stdout); 150 | int rc = -1, opt; 151 | pid_t rpid,wpid; 152 | 153 | while ( (opt = getopt(argc,argv,"vhs:u")) > 0) { 154 | switch(opt) { 155 | case 'v': CF.verbose++; break; 156 | case 's': CF.speed = atoi(optarg); break; 157 | case 'u': CF.unlink = 0; break; 158 | case 'h': default: usage(); break; 159 | } 160 | } 161 | 162 | time(&CF.start); 163 | unlink(ring); 164 | shr_init(ring, ring_sz, SHR_FARM|SHR_MAXMSGS_2, NMSG); 165 | 166 | rpid = fork(); 167 | if (rpid < 0) goto done; 168 | if (rpid == 0) execute(R); 169 | assert(rpid > 0); 170 | 171 | wpid = fork(); 172 | if (wpid < 0) goto done; 173 | if (wpid == 0) execute(W); 174 | assert(wpid > 0); 175 | 176 | waitpid(wpid,NULL,0); 177 | waitpid(rpid,NULL,0); 178 | 179 | done: 180 | if (CF.unlink) unlink(ring); 181 | printf("end\n"); 182 | return rc; 183 | } 184 | 185 | -------------------------------------------------------------------------------- /tests/test69.ans: -------------------------------------------------------------------------------- 1 | r: do_open 2 | w: do_open 3 | w: do_fill 4 | w: wrote 10 messages (to seq 10) 5 | r: do_read_half 6 | 0 7 | 1 8 | 2 9 | 3 10 | 4 11 | w: do_fill 12 | w: wrote 10 messages (to seq 20) 13 | r: do_read_half 14 | 10 15 | 11 16 | 12 17 | 13 18 | 14 19 | r: do_read_half 20 | 15 21 | 16 22 | 17 23 | 18 24 | 19 25 | r: do_close 26 | r: do_open 27 | r: do_read_half 28 | shr_read: 0 29 | r: do_read_half 30 | shr_read: 0 31 | r: do_close 32 | w: do_close 33 | w: do_exit 34 | w: exiting 35 | r: do_exit 36 | r: exiting 37 | end 38 | -------------------------------------------------------------------------------- /tests/test69.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | #define W 0 14 | #define R 1 15 | 16 | char *ring = __FILE__ ".ring"; 17 | 18 | /* make an enum and a char*[] for the ops */ 19 | #define adim(x) (sizeof(x)/sizeof(*x)) 20 | #define OPS o(do_none) o(do_open) o(do_fill) o(do_read_half) o(do_close) o(do_exit) 21 | #define o(x) #x, 22 | char *op_s[] = { OPS }; 23 | #undef o 24 | #define o(x) x, 25 | typedef enum { OPS } ops; 26 | 27 | #define NMSG 10 28 | char msg[] = "000000000000000000000000000000000000"; 29 | const int ring_sz = (sizeof(msg)+0)*NMSG; 30 | struct iovec iov[NMSG]; 31 | char msg_all[sizeof(msg)*NMSG]; 32 | 33 | struct { 34 | char *prog; 35 | time_t start; 36 | int verbose; 37 | int speed; 38 | int unlink; 39 | } CF = { 40 | .speed = 1, 41 | .unlink = 1, 42 | }; 43 | 44 | /* the event sequence we want executed */ 45 | struct events { 46 | int when; 47 | int who; 48 | ops op; 49 | } ev[] = { 50 | {1, R, do_open}, 51 | {2, W, do_open}, 52 | 53 | {3, W, do_fill}, /* w 10 */ 54 | {4, R, do_read_half}, /* r 5 (seq 0-4) */ 55 | {5, W, do_fill}, /* w 10 (Drop 5) */ 56 | {6, R, do_read_half}, /* r 5 (seq 10-14) */ 57 | {7, R, do_read_half}, /* r 5 (seq 15-19) */ 58 | {8, R, do_close}, 59 | 60 | { 9, R, do_open}, /* start over again */ 61 | {10, R, do_read_half}, /* r 0 (non block no data) */ 62 | {11, R, do_read_half}, /* r 0 (non block no data) */ 63 | 64 | {12, R, do_close}, 65 | {13, W, do_close}, 66 | {14, W, do_exit}, 67 | {15, R, do_exit}, 68 | }; 69 | 70 | /* sleep til X seconds since start */ 71 | void sleep_til( int el ) { 72 | time_t now; 73 | time(&now); 74 | 75 | if (now > CF.start + el) { 76 | fprintf(stderr, "sleep_til: already elapsed\n"); 77 | return; 78 | } 79 | 80 | sleep((CF.start + el) - now); 81 | } 82 | 83 | /* run the event sequence 84 | * runs in child process. never returns 85 | */ 86 | void execute(int me) { 87 | char msg_one[sizeof(msg)]; 88 | struct shr *s = NULL; 89 | unsigned i, n; 90 | ssize_t nr; 91 | unsigned seq = 0; 92 | 93 | for(i=0; i < adim(ev); i++) { 94 | 95 | if ( ev[i].who != me ) continue; 96 | 97 | sleep_til( ev[i].when * CF.speed ); 98 | printf("%s: %s\n", (me == R) ? "r" : "w", op_s[ ev[i].op ]); 99 | 100 | switch( ev[i].op ) { 101 | case do_open: 102 | s = shr_open(ring, (me == R) ? SHR_RDONLY|SHR_NONBLOCK : SHR_WRONLY); 103 | if (s == NULL) goto done; 104 | break; 105 | case do_close: 106 | shr_close(s); 107 | break; 108 | case do_exit: 109 | goto done; 110 | break; 111 | case do_read_half: 112 | for(n=0; n < NMSG/2; n++) { 113 | nr = shr_read(s, msg_one, sizeof(msg_one)); 114 | if (nr != sizeof(msg)) { 115 | printf("shr_read: %d\n", (int)nr); 116 | break; 117 | } 118 | printf("%s\n", msg_one); 119 | } 120 | break; 121 | case do_fill: 122 | for(n=0; n < NMSG; n++) { 123 | snprintf(msg_one, sizeof(msg_one), "%u", seq++); 124 | nr = shr_write(s, msg_one, sizeof(msg_one)); 125 | } 126 | printf("w: wrote %d messages (to seq %u)\n", NMSG, seq); 127 | break; 128 | default: 129 | fprintf(stderr,"op not implemented\n"); 130 | assert(0); 131 | break; 132 | } 133 | } 134 | 135 | done: 136 | printf("%s: exiting\n", (me == R) ? "r" : "w"); 137 | exit(0); 138 | } 139 | 140 | void usage() { 141 | fprintf(stderr,"usage: %s [-v] [-s ]\n", CF.prog); 142 | fprintf(stderr,"-v verbose\n"); 143 | fprintf(stderr,"-s (factor to slow test [def: 1])\n"); 144 | fprintf(stderr,"-u (don't unlink ring after test)\n"); 145 | exit(-1); 146 | } 147 | 148 | int main(int argc, char *argv[]) { 149 | setlinebuf(stdout); 150 | int rc = -1, opt; 151 | pid_t rpid,wpid; 152 | 153 | while ( (opt = getopt(argc,argv,"vhs:u")) > 0) { 154 | switch(opt) { 155 | case 'v': CF.verbose++; break; 156 | case 's': CF.speed = atoi(optarg); break; 157 | case 'u': CF.unlink = 0; break; 158 | case 'h': default: usage(); break; 159 | } 160 | } 161 | 162 | time(&CF.start); 163 | unlink(ring); 164 | shr_init(ring, ring_sz, SHR_DROP|SHR_MAXMSGS_2, NMSG); 165 | 166 | rpid = fork(); 167 | if (rpid < 0) goto done; 168 | if (rpid == 0) execute(R); 169 | assert(rpid > 0); 170 | 171 | wpid = fork(); 172 | if (wpid < 0) goto done; 173 | if (wpid == 0) execute(W); 174 | assert(wpid > 0); 175 | 176 | waitpid(wpid,NULL,0); 177 | waitpid(rpid,NULL,0); 178 | 179 | done: 180 | if (CF.unlink) unlink(ring); 181 | printf("end\n"); 182 | return rc; 183 | } 184 | 185 | -------------------------------------------------------------------------------- /tests/test7.ans: -------------------------------------------------------------------------------- 1 | writing ...ok 2 | reading ...read 3 bytes 3 | abc 4 | writing ...ok 5 | reading ...read 3 bytes 6 | def 7 | writing ...ok 8 | reading ...read 3 bytes 9 | ghi 10 | end 11 | -------------------------------------------------------------------------------- /tests/test7.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "shr.h" 4 | 5 | char *ring = __FILE__ ".ring"; 6 | char *data = "abcdefghi"; 7 | 8 | char out[10]; 9 | 10 | int main() { 11 | setlinebuf(stdout); 12 | struct shr *s=NULL,*t=NULL; 13 | int rc = -1; 14 | 15 | unlink(ring); 16 | if (shr_init(ring, 11, 0) < 0) goto done; 17 | 18 | s = shr_open(ring, SHR_RDONLY); 19 | if (s == NULL) goto done; 20 | 21 | t = shr_open(ring, SHR_WRONLY); 22 | if (t == NULL) goto done; 23 | 24 | printf("writing ..."); 25 | if (shr_write(t, &data[0], 3) < 0) goto done; 26 | printf("ok\n"); 27 | 28 | printf("reading ..."); 29 | ssize_t nr; 30 | nr = shr_read(s, out, sizeof(out)); 31 | if (nr < 0) goto done; 32 | printf("read %ld bytes\n", (long)nr); 33 | if (nr > 0) printf("%.*s\n", (int)nr, out); 34 | 35 | printf("writing ..."); 36 | if (shr_write(t, &data[3], 3) < 0) goto done; 37 | printf("ok\n"); 38 | 39 | printf("reading ..."); 40 | nr = shr_read(s, out, sizeof(out)); 41 | if (nr < 0) goto done; 42 | printf("read %ld bytes\n", (long)nr); 43 | if (nr > 0) printf("%.*s\n", (int)nr, out); 44 | 45 | printf("writing ..."); 46 | if (shr_write(t, &data[6], 3) < 0) goto done; 47 | printf("ok\n"); 48 | 49 | printf("reading ..."); 50 | nr = shr_read(s, out, sizeof(out)); 51 | if (nr < 0) goto done; 52 | printf("read %ld bytes\n", (long)nr); 53 | if (nr > 0) printf("%.*s\n", (int)nr, out); 54 | 55 | rc = 0; 56 | 57 | done: 58 | printf("end\n"); 59 | if (s) shr_close(s); 60 | if (t) shr_close(t); 61 | unlink(ring); 62 | return rc; 63 | } 64 | -------------------------------------------------------------------------------- /tests/test70.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | f: do_open 3 | r: do_open 4 | w: do_fill 5 | w: wrote 10 messages (to seq 10) 6 | w: do_fill 7 | w: wrote 10 messages (to seq 20) 8 | f: do_read_half 9 | 10 10 | 11 11 | 12 12 | 13 13 | 14 14 | r: do_read_half 15 | 10 16 | 11 17 | 12 18 | 13 19 | 14 20 | w: do_fill 21 | w: wrote 10 messages (to seq 30) 22 | f: do_read_half 23 | 20 24 | 21 25 | 22 26 | 23 27 | 24 28 | r: do_read_half 29 | 20 30 | 21 31 | 22 32 | 23 33 | 24 34 | w: do_close 35 | f: do_close 36 | r: do_close 37 | w: do_exit 38 | w: exiting 39 | f: do_exit 40 | f: exiting 41 | r: do_exit 42 | r: exiting 43 | end 44 | -------------------------------------------------------------------------------- /tests/test70.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | #define W 0 14 | #define R 1 15 | #define F 2 16 | 17 | char *ring = __FILE__ ".ring"; 18 | 19 | /* make an enum and a char*[] for the ops */ 20 | #define adim(x) (sizeof(x)/sizeof(*x)) 21 | #define OPS o(do_none) o(do_open) o(do_fill) o(do_read_half) o(do_close) o(do_exit) 22 | #define o(x) #x, 23 | char *op_s[] = { OPS }; 24 | #undef o 25 | #define o(x) x, 26 | typedef enum { OPS } ops; 27 | 28 | #define NMSG 10 29 | char msg[] = "000000000000000000000000000000000000"; 30 | const int ring_sz = (sizeof(msg)+0)*NMSG; 31 | struct iovec iov[NMSG]; 32 | char msg_all[sizeof(msg)*NMSG]; 33 | 34 | struct { 35 | char *prog; 36 | time_t start; 37 | int verbose; 38 | int speed; 39 | int unlink; 40 | } CF = { 41 | .speed = 1, 42 | .unlink = 1, 43 | }; 44 | 45 | /* the event sequence we want executed */ 46 | struct events { 47 | int when; 48 | int who; 49 | ops op; 50 | } ev[] = { 51 | {1, W, do_open}, 52 | {2, F, do_open}, 53 | {3, R, do_open}, 54 | 55 | {4, W, do_fill}, /* seq 0-9 */ 56 | {5, W, do_fill}, /* seq 10-19 */ 57 | 58 | {6, F, do_read_half}, /* seq 10-14 */ 59 | {7, R, do_read_half}, /* seq 10-14 */ 60 | 61 | {8, W, do_fill}, /* seq 20-29 */ 62 | 63 | {9, F, do_read_half}, /* seq 20-24 */ 64 | {10, R, do_read_half}, /* seq 20-24 */ 65 | 66 | {11, W, do_close}, 67 | {12, F, do_close}, 68 | {13, R, do_close}, 69 | 70 | {14, W, do_exit}, 71 | {15, F, do_exit}, 72 | {16, R, do_exit}, 73 | }; 74 | 75 | /* sleep til X seconds since start */ 76 | void sleep_til( int el ) { 77 | time_t now; 78 | time(&now); 79 | 80 | if (now > CF.start + el) { 81 | fprintf(stderr, "sleep_til: already elapsed\n"); 82 | return; 83 | } 84 | 85 | sleep((CF.start + el) - now); 86 | } 87 | 88 | /* run the event sequence 89 | * runs in child process. never returns 90 | */ 91 | void execute(int me) { 92 | char msg_one[sizeof(msg)]; 93 | struct shr *s = NULL; 94 | unsigned i, n; 95 | ssize_t nr; 96 | unsigned seq = 0; 97 | 98 | for(i=0; i < adim(ev); i++) { 99 | 100 | if ( ev[i].who != me ) continue; 101 | 102 | sleep_til( ev[i].when * CF.speed ); 103 | if (me == R) printf("r: "); 104 | if (me == F) printf("f: "); 105 | if (me == W) printf("w: "); 106 | printf("%s\n", op_s[ ev[i].op ]); 107 | 108 | switch( ev[i].op ) { 109 | case do_open: 110 | s = shr_open(ring, ((me == R) || (me == F)) ? SHR_RDONLY : SHR_WRONLY); 111 | if (s == NULL) goto done; 112 | break; 113 | case do_close: 114 | shr_close(s); 115 | break; 116 | case do_exit: 117 | goto done; 118 | break; 119 | case do_read_half: 120 | for(n=0; n < NMSG/2; n++) { 121 | nr = shr_read(s, msg_one, sizeof(msg_one)); 122 | if (nr != sizeof(msg)) { 123 | printf("shr_read: %d\n", (int)nr); 124 | break; 125 | } 126 | printf("%s\n", msg_one); 127 | } 128 | break; 129 | case do_fill: 130 | for(n=0; n < NMSG; n++) { 131 | snprintf(msg_one, sizeof(msg_one), "%u", seq++); 132 | nr = shr_write(s, msg_one, sizeof(msg_one)); 133 | } 134 | printf("w: wrote %d messages (to seq %u)\n", NMSG, seq); 135 | break; 136 | default: 137 | fprintf(stderr,"op not implemented\n"); 138 | assert(0); 139 | break; 140 | } 141 | } 142 | 143 | done: 144 | if (me == R) printf("r: "); 145 | if (me == F) printf("f: "); 146 | if (me == W) printf("w: "); 147 | printf("exiting\n"); 148 | exit(0); 149 | } 150 | 151 | void usage() { 152 | fprintf(stderr,"usage: %s [-v] [-s ]\n", CF.prog); 153 | fprintf(stderr,"-v verbose\n"); 154 | fprintf(stderr,"-s (factor to slow test [def: 1])\n"); 155 | fprintf(stderr,"-u (don't unlink ring after test)\n"); 156 | exit(-1); 157 | } 158 | 159 | int main(int argc, char *argv[]) { 160 | setlinebuf(stdout); 161 | int rc = -1, opt; 162 | pid_t rpid,wpid,fpid; 163 | 164 | while ( (opt = getopt(argc,argv,"vhs:u")) > 0) { 165 | switch(opt) { 166 | case 'v': CF.verbose++; break; 167 | case 's': CF.speed = atoi(optarg); break; 168 | case 'u': CF.unlink = 0; break; 169 | case 'h': default: usage(); break; 170 | } 171 | } 172 | 173 | time(&CF.start); 174 | unlink(ring); 175 | shr_init(ring, ring_sz, SHR_FARM|SHR_MAXMSGS_2, NMSG); 176 | 177 | rpid = fork(); 178 | if (rpid < 0) goto done; 179 | if (rpid == 0) execute(R); 180 | assert(rpid > 0); 181 | 182 | wpid = fork(); 183 | if (wpid < 0) goto done; 184 | if (wpid == 0) execute(W); 185 | assert(wpid > 0); 186 | 187 | fpid = fork(); 188 | if (fpid < 0) goto done; 189 | if (fpid == 0) execute(F); 190 | assert(fpid > 0); 191 | 192 | waitpid(wpid,NULL,0); 193 | waitpid(rpid,NULL,0); 194 | waitpid(fpid,NULL,0); 195 | 196 | done: 197 | if (CF.unlink) unlink(ring); 198 | printf("end\n"); 199 | return rc; 200 | } 201 | 202 | -------------------------------------------------------------------------------- /tests/test71.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | f: do_open 3 | r: do_open 4 | w: do_fill 5 | w: wrote 10 messages (to seq 10) 6 | w: do_fill 7 | w: wrote 10 messages (to seq 20) 8 | f: do_read_one 9 | 10 10 | r: do_read_one 11 | 10 12 | r: do_read_one 13 | 11 14 | r: do_read_one 15 | 12 16 | f: do_read_one 17 | 11 18 | w: do_fill 19 | w: wrote 10 messages (to seq 30) 20 | f: do_read_half 21 | 20 22 | 21 23 | 22 24 | 23 25 | 24 26 | r: do_read_half 27 | 20 28 | 21 29 | 22 30 | 23 31 | 24 32 | w: do_close 33 | f: do_close 34 | r: do_close 35 | w: do_exit 36 | w: exiting 37 | f: do_exit 38 | f: exiting 39 | r: do_exit 40 | r: exiting 41 | end 42 | -------------------------------------------------------------------------------- /tests/test72.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | r: do_open 3 | f: do_open 4 | w: do_write_20b 5 | w: wrote abcdefghijklmnopqrst 6 | w: do_write_20b 7 | w: wrote bcdefghijklmnopqrstu 8 | w: do_write_20b 9 | w: wrote cdefghijklmnopqrstuv 10 | w: do_stat 11 | stat: 0 12 | bw 60, br 0, mw 3, mr 0, md 2, bd 40, bn 20, bu 20, mu 1 13 | r: do_read_one 14 | cdefghijklmnopqrstuv 15 | w: do_write_20b 16 | w: wrote defghijklmnopqrstuvw 17 | w: do_write_one 18 | w: wrote seq e 19 | w: do_stat 20 | stat: 0 21 | bw 81, br 20, mw 5, mr 1, md 4, bd 80, bn 20, bu 1, mu 1 22 | r: do_read_one 23 | e 24 | w: do_write_20b 25 | w: wrote fghijklmnopqrstuvwxy 26 | r: do_read_one 27 | fghijklmnopqrstuvwxy 28 | w: do_write_one 29 | w: wrote seq g 30 | r: do_read_one 31 | g 32 | w: do_write_one 33 | w: wrote seq h 34 | f: do_read_one 35 | g 36 | w: do_write_20b 37 | w: wrote ijklmnopqrstuvwxyz{| 38 | f: do_read_one 39 | ijklmnopqrstuvwxyz{| 40 | w: do_close 41 | f: do_close 42 | r: do_close 43 | w: do_exit 44 | w: exiting 45 | f: do_exit 46 | f: exiting 47 | r: do_exit 48 | r: exiting 49 | end 50 | -------------------------------------------------------------------------------- /tests/test73.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | f: do_open 3 | r: do_open 4 | w: do_fill 5 | w: wrote 10 messages (to seq 10) 6 | f: do_read_half 7 | 0 8 | 1 9 | 2 10 | 3 11 | 4 12 | f: do_read_half 13 | 5 14 | 6 15 | 7 16 | 8 17 | 9 18 | f: do_read_half 19 | w: do_fill 20 | w: wrote 10 messages (to seq 20) 21 | 10 22 | 11 23 | 12 24 | 13 25 | 14 26 | w: do_close 27 | f: do_close 28 | r: do_close 29 | w: do_exit 30 | w: exiting 31 | f: do_exit 32 | f: exiting 33 | r: do_exit 34 | r: exiting 35 | end 36 | -------------------------------------------------------------------------------- /tests/test73.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | #define W 0 14 | #define R 1 15 | #define F 2 16 | 17 | char *ring = __FILE__ ".ring"; 18 | 19 | /* make an enum and a char*[] for the ops */ 20 | #define adim(x) (sizeof(x)/sizeof(*x)) 21 | #define OPS o(do_none) o(do_open) o(do_fill) o(do_read_half) o(do_read_one) o(do_close) o(do_exit) 22 | #define o(x) #x, 23 | char *op_s[] = { OPS }; 24 | #undef o 25 | #define o(x) x, 26 | typedef enum { OPS } ops; 27 | 28 | #define NMSG 10 29 | char msg[] = "000000000000000000000000000000000000"; 30 | const int ring_sz = (sizeof(msg)+0)*NMSG; 31 | struct iovec iov[NMSG]; 32 | char msg_all[sizeof(msg)*NMSG]; 33 | 34 | struct { 35 | char *prog; 36 | time_t start; 37 | int verbose; 38 | int speed; 39 | int unlink; 40 | } CF = { 41 | .speed = 1, 42 | .unlink = 1, 43 | }; 44 | 45 | /* the event sequence we want executed */ 46 | struct events { 47 | int when; 48 | int who; 49 | ops op; 50 | } ev[] = { 51 | {1, W, do_open}, 52 | {2, F, do_open}, 53 | {3, R, do_open}, 54 | 55 | {4, W, do_fill}, /* seq 0-9 */ 56 | 57 | {5, F, do_read_half}, /* seq 0-4 */ 58 | {6, F, do_read_half}, /* seq 5-9 */ 59 | {7, F, do_read_half}, /* block for seq 10-14 */ 60 | 61 | {8, W, do_fill}, /* seq 10-19 */ 62 | /* immediately unblocks F */ 63 | 64 | {9, W, do_close}, 65 | {10, F, do_close}, 66 | {11, R, do_close}, 67 | 68 | {12, W, do_exit}, 69 | {13, F, do_exit}, 70 | {14, R, do_exit}, 71 | }; 72 | 73 | /* sleep til X seconds since start */ 74 | void sleep_til( int el ) { 75 | time_t now; 76 | time(&now); 77 | 78 | if (now > CF.start + el) { 79 | fprintf(stderr, "sleep_til: already elapsed\n"); 80 | return; 81 | } 82 | 83 | sleep((CF.start + el) - now); 84 | } 85 | 86 | /* run the event sequence 87 | * runs in child process. never returns 88 | */ 89 | void execute(int me) { 90 | char msg_one[sizeof(msg)]; 91 | struct shr *s = NULL; 92 | unsigned i, n; 93 | ssize_t nr; 94 | unsigned seq = 0; 95 | 96 | for(i=0; i < adim(ev); i++) { 97 | 98 | if ( ev[i].who != me ) continue; 99 | 100 | sleep_til( ev[i].when * CF.speed ); 101 | if (me == R) printf("r: "); 102 | if (me == F) printf("f: "); 103 | if (me == W) printf("w: "); 104 | printf("%s\n", op_s[ ev[i].op ]); 105 | 106 | switch( ev[i].op ) { 107 | case do_open: 108 | s = shr_open(ring, ((me == R) || (me == F)) ? SHR_RDONLY : SHR_WRONLY); 109 | if (s == NULL) goto done; 110 | break; 111 | case do_close: 112 | shr_close(s); 113 | break; 114 | case do_exit: 115 | goto done; 116 | break; 117 | case do_read_one: 118 | for(n=0; n < 1; n++) { 119 | nr = shr_read(s, msg_one, sizeof(msg_one)); 120 | if (nr != sizeof(msg)) { 121 | printf("shr_read: %d\n", (int)nr); 122 | break; 123 | } 124 | printf("%s\n", msg_one); 125 | } 126 | break; 127 | case do_read_half: 128 | for(n=0; n < NMSG/2; n++) { 129 | nr = shr_read(s, msg_one, sizeof(msg_one)); 130 | if (nr != sizeof(msg)) { 131 | printf("shr_read: %d\n", (int)nr); 132 | break; 133 | } 134 | printf("%s\n", msg_one); 135 | } 136 | break; 137 | case do_fill: 138 | for(n=0; n < NMSG; n++) { 139 | snprintf(msg_one, sizeof(msg_one), "%u", seq++); 140 | nr = shr_write(s, msg_one, sizeof(msg_one)); 141 | } 142 | printf("w: wrote %d messages (to seq %u)\n", NMSG, seq); 143 | break; 144 | default: 145 | fprintf(stderr,"op not implemented\n"); 146 | assert(0); 147 | break; 148 | } 149 | } 150 | 151 | done: 152 | if (me == R) printf("r: "); 153 | if (me == F) printf("f: "); 154 | if (me == W) printf("w: "); 155 | printf("exiting\n"); 156 | exit(0); 157 | } 158 | 159 | void usage() { 160 | fprintf(stderr,"usage: %s [-v] [-s ]\n", CF.prog); 161 | fprintf(stderr,"-v verbose\n"); 162 | fprintf(stderr,"-s (factor to slow test [def: 1])\n"); 163 | fprintf(stderr,"-u (don't unlink ring after test)\n"); 164 | exit(-1); 165 | } 166 | 167 | int main(int argc, char *argv[]) { 168 | setlinebuf(stdout); 169 | int rc = -1, opt; 170 | pid_t rpid,wpid,fpid; 171 | 172 | while ( (opt = getopt(argc,argv,"vhs:u")) > 0) { 173 | switch(opt) { 174 | case 'v': CF.verbose++; break; 175 | case 's': CF.speed = atoi(optarg); break; 176 | case 'u': CF.unlink = 0; break; 177 | case 'h': default: usage(); break; 178 | } 179 | } 180 | 181 | time(&CF.start); 182 | unlink(ring); 183 | shr_init(ring, ring_sz, SHR_FARM|SHR_MAXMSGS_2, NMSG); 184 | 185 | rpid = fork(); 186 | if (rpid < 0) goto done; 187 | if (rpid == 0) execute(R); 188 | assert(rpid > 0); 189 | 190 | wpid = fork(); 191 | if (wpid < 0) goto done; 192 | if (wpid == 0) execute(W); 193 | assert(wpid > 0); 194 | 195 | fpid = fork(); 196 | if (fpid < 0) goto done; 197 | if (fpid == 0) execute(F); 198 | assert(fpid > 0); 199 | 200 | waitpid(wpid,NULL,0); 201 | waitpid(rpid,NULL,0); 202 | waitpid(fpid,NULL,0); 203 | 204 | done: 205 | if (CF.unlink) unlink(ring); 206 | printf("end\n"); 207 | return rc; 208 | } 209 | 210 | -------------------------------------------------------------------------------- /tests/test74.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | f: do_open 3 | r: do_open 4 | f: do_read_one 5 | r: do_read_one 6 | w: do_fill 7 | 0 8 | 0 9 | w: do_close 10 | f: do_close 11 | r: do_close 12 | w: do_exit 13 | w: exiting 14 | f: do_exit 15 | f: exiting 16 | r: do_exit 17 | r: exiting 18 | end 19 | -------------------------------------------------------------------------------- /tests/test74.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | #define W 0 14 | #define R 1 15 | #define F 2 16 | 17 | char *ring = __FILE__ ".ring"; 18 | 19 | /* make an enum and a char*[] for the ops */ 20 | #define adim(x) (sizeof(x)/sizeof(*x)) 21 | #define OPS o(do_none) o(do_open) o(do_fill) o(do_read_half) o(do_read_one) o(do_close) o(do_exit) 22 | #define o(x) #x, 23 | char *op_s[] = { OPS }; 24 | #undef o 25 | #define o(x) x, 26 | typedef enum { OPS } ops; 27 | 28 | #define NMSG 10 29 | char msg[] = "000000000000000000000000000000000000"; 30 | const int ring_sz = (sizeof(msg)+0)*NMSG; 31 | struct iovec iov[NMSG]; 32 | char msg_all[sizeof(msg)*NMSG]; 33 | 34 | struct { 35 | char *prog; 36 | time_t start; 37 | int verbose; 38 | int speed; 39 | int unlink; 40 | } CF = { 41 | .speed = 1, 42 | .unlink = 1, 43 | }; 44 | 45 | /* the event sequence we want executed */ 46 | struct events { 47 | int who; 48 | ops op; 49 | } ev[] = { 50 | { W, do_open}, 51 | { F, do_open}, 52 | { R, do_open}, 53 | 54 | { F, do_read_one}, /* block for seq 0 */ 55 | { R, do_read_one}, /* block for seq 0 */ 56 | 57 | { W, do_fill}, /* seq 0-9 */ 58 | 59 | /* unblocks F and R */ 60 | 61 | { W, do_close}, 62 | { F, do_close}, 63 | { R, do_close}, 64 | 65 | { W, do_exit}, 66 | { F, do_exit}, 67 | { R, do_exit}, 68 | }; 69 | 70 | /* sleep til X seconds since start */ 71 | void sleep_til( int el ) { 72 | time_t now; 73 | time(&now); 74 | 75 | if (now > CF.start + el) { 76 | fprintf(stderr, "sleep_til: already elapsed\n"); 77 | return; 78 | } 79 | 80 | sleep((CF.start + el) - now); 81 | } 82 | 83 | /* run the event sequence 84 | * runs in child process. never returns 85 | */ 86 | void execute(int me) { 87 | char msg_one[sizeof(msg)]; 88 | struct shr *s = NULL; 89 | unsigned i, n; 90 | ssize_t nr; 91 | unsigned seq = 0; 92 | 93 | for(i=0; i < adim(ev); i++) { 94 | 95 | if ( ev[i].who != me ) continue; 96 | 97 | sleep_til( i * CF.speed ); 98 | if (me == R) printf("r: "); 99 | if (me == F) printf("f: "); 100 | if (me == W) printf("w: "); 101 | printf("%s\n", op_s[ ev[i].op ]); 102 | 103 | switch( ev[i].op ) { 104 | case do_open: 105 | s = shr_open(ring, ((me == R) || (me == F)) ? SHR_RDONLY : SHR_WRONLY); 106 | if (s == NULL) goto done; 107 | break; 108 | case do_close: 109 | shr_close(s); 110 | break; 111 | case do_exit: 112 | goto done; 113 | break; 114 | case do_read_one: 115 | for(n=0; n < 1; n++) { 116 | nr = shr_read(s, msg_one, sizeof(msg_one)); 117 | if (nr != sizeof(msg)) { 118 | printf("shr_read: %d\n", (int)nr); 119 | break; 120 | } 121 | printf("%s\n", msg_one); 122 | } 123 | break; 124 | case do_read_half: 125 | for(n=0; n < NMSG/2; n++) { 126 | nr = shr_read(s, msg_one, sizeof(msg_one)); 127 | if (nr != sizeof(msg)) { 128 | printf("shr_read: %d\n", (int)nr); 129 | break; 130 | } 131 | printf("%s\n", msg_one); 132 | } 133 | break; 134 | case do_fill: 135 | for(n=0; n < NMSG; n++) { 136 | snprintf(msg_one, sizeof(msg_one), "%u", seq++); 137 | nr = shr_write(s, msg_one, sizeof(msg_one)); 138 | } 139 | //printf("w: wrote %d messages (to seq %u)\n", NMSG, seq); 140 | break; 141 | default: 142 | fprintf(stderr,"op not implemented\n"); 143 | assert(0); 144 | break; 145 | } 146 | } 147 | 148 | done: 149 | if (me == R) printf("r: "); 150 | if (me == F) printf("f: "); 151 | if (me == W) printf("w: "); 152 | printf("exiting\n"); 153 | exit(0); 154 | } 155 | 156 | void usage() { 157 | fprintf(stderr,"usage: %s [-v] [-s ]\n", CF.prog); 158 | fprintf(stderr,"-v verbose\n"); 159 | fprintf(stderr,"-s (factor to slow test [def: 1])\n"); 160 | fprintf(stderr,"-u (don't unlink ring after test)\n"); 161 | exit(-1); 162 | } 163 | 164 | int main(int argc, char *argv[]) { 165 | setlinebuf(stdout); 166 | int rc = -1, opt; 167 | pid_t rpid,wpid,fpid; 168 | 169 | while ( (opt = getopt(argc,argv,"vhs:u")) > 0) { 170 | switch(opt) { 171 | case 'v': CF.verbose++; break; 172 | case 's': CF.speed = atoi(optarg); break; 173 | case 'u': CF.unlink = 0; break; 174 | case 'h': default: usage(); break; 175 | } 176 | } 177 | 178 | time(&CF.start); 179 | unlink(ring); 180 | shr_init(ring, ring_sz, SHR_FARM|SHR_MAXMSGS_2, NMSG); 181 | 182 | rpid = fork(); 183 | if (rpid < 0) goto done; 184 | if (rpid == 0) execute(R); 185 | assert(rpid > 0); 186 | 187 | wpid = fork(); 188 | if (wpid < 0) goto done; 189 | if (wpid == 0) execute(W); 190 | assert(wpid > 0); 191 | 192 | fpid = fork(); 193 | if (fpid < 0) goto done; 194 | if (fpid == 0) execute(F); 195 | assert(fpid > 0); 196 | 197 | waitpid(wpid,NULL,0); 198 | waitpid(rpid,NULL,0); 199 | waitpid(fpid,NULL,0); 200 | 201 | done: 202 | if (CF.unlink) unlink(ring); 203 | printf("end\n"); 204 | return rc; 205 | } 206 | 207 | -------------------------------------------------------------------------------- /tests/test75.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | r: do_open 3 | w: do_fill 4 | w: wrote 10 messages (to seq 10) 5 | w: do_write_one 6 | w: wrote 1 message (to seq 11) 7 | w: do_write_one 8 | w: wrote 1 message (to seq 12) 9 | w: do_write_one 10 | w: wrote 1 message (to seq 13) 11 | w: do_write_one 12 | w: wrote 1 message (to seq 14) 13 | f: do_open 14 | f: do_read_one 15 | 4 16 | r: do_read_one 17 | 4 18 | f: do_farm_stat 19 | drops: 0 20 | r: do_farm_stat 21 | drops: 4 22 | f: do_read_half 23 | 5 24 | 6 25 | 7 26 | 8 27 | 9 28 | r: do_read_half 29 | 5 30 | 6 31 | 7 32 | 8 33 | 9 34 | f: do_read_half 35 | 10 36 | 11 37 | 12 38 | 13 39 | shr_read: 0 40 | r: do_read_half 41 | 10 42 | 11 43 | 12 44 | 13 45 | shr_read: 0 46 | w: do_close 47 | f: do_close 48 | r: do_close 49 | w: do_exit 50 | w: exiting 51 | f: do_exit 52 | f: exiting 53 | r: do_exit 54 | r: exiting 55 | end 56 | -------------------------------------------------------------------------------- /tests/test76.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | r: do_open 3 | w: do_write_one 4 | w: wrote seq a 5 | w: do_write_one_2b 6 | w: wrote seq bb 7 | w: do_write_one_3b 8 | w: wrote seq ccc 9 | w: do_write_one_4b 10 | w: wrote seq dddd 11 | r: do_stat 12 | w: stat: 0 13 | w: bw 10, br 0, mw 4, mr 0, md 0, bd 0, bn 370, bu 10, mu 4 14 | r: do_read_one 15 | a 16 | r: do_stat 17 | w: stat: 0 18 | w: bw 10, br 1, mw 4, mr 1, md 0, bd 0, bn 370, bu 9, mu 3 19 | r: do_read_one 20 | bb 21 | r: do_read_one 22 | ccc 23 | r: do_read_one 24 | dddd 25 | r: do_read_one 26 | shr_read: no data 27 | r: do_stat 28 | w: stat: 0 29 | w: bw 10, br 10, mw 4, mr 4, md 0, bd 0, bn 370, bu 0, mu 0 30 | w: do_close 31 | f: do_close 32 | r: do_close 33 | w: do_exit 34 | w: exiting 35 | r: do_exit 36 | r: exiting 37 | end 38 | -------------------------------------------------------------------------------- /tests/test77.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | r: do_open 3 | w: do_write_one 4 | w: wrote seq a 5 | w: do_write_one_2b 6 | w: wrote seq bb 7 | w: do_write_one_3b 8 | w: wrote seq ccc 9 | w: do_write_one_4b 10 | w: wrote seq dddd 11 | r: do_stat 12 | w: stat: 0 13 | w: bw 10, br 0, mw 4, mr 0, md 0, bd 0, bn 370, bu 10, mu 4 14 | r: do_read_one 15 | a 16 | r: do_stat 17 | w: stat: 0 18 | w: bw 10, br 1, mw 4, mr 1, md 0, bd 0, bn 370, bu 10, mu 4 19 | r: do_read_one 20 | bb 21 | r: do_read_one 22 | ccc 23 | r: do_read_one 24 | dddd 25 | r: do_read_one 26 | shr_read: no data 27 | w: do_close 28 | f: do_close 29 | r: do_close 30 | w: do_exit 31 | w: exiting 32 | r: do_exit 33 | r: exiting 34 | end 35 | -------------------------------------------------------------------------------- /tests/test78.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | r: do_open 3 | w: do_write_one 4 | w: wrote seq a 5 | w: do_write_one_2b 6 | w: wrote seq bb 7 | w: do_write_one_3b 8 | w: wrote seq ccc 9 | w: do_write_one_4b 10 | w: wrote seq dddd 11 | r: do_stat 12 | w: stat: 0 13 | w: bw 10, br 0, mw 4, mr 0, md 0, bd 0, bn 370, bu 10, mu 4 14 | r: do_read_one 15 | a 16 | r: do_stat 17 | w: stat: 0 18 | w: bw 10, br 1, mw 4, mr 1, md 0, bd 0, bn 370, bu 9, mu 3 19 | r: do_read_one 20 | bb 21 | r: do_read_one 22 | ccc 23 | r: do_read_one 24 | dddd 25 | r: do_read_one 26 | shr_read: no data 27 | r: do_stat 28 | w: stat: 0 29 | w: bw 10, br 10, mw 4, mr 4, md 0, bd 0, bn 370, bu 0, mu 0 30 | w: do_close 31 | f: do_close 32 | r: do_close 33 | w: do_exit 34 | w: exiting 35 | r: do_exit 36 | r: exiting 37 | end 38 | -------------------------------------------------------------------------------- /tests/test79.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | r: do_open 3 | w: do_write_one_4b 4 | w: wrote seq aaaa 5 | w: do_write_one 6 | w: wrote seq b 7 | w: do_write_one_3b 8 | w: wrote seq ccc 9 | w: do_write_one_4b 10 | w: wrote seq dddd 11 | w: do_write_one_4b 12 | w: wrote seq eeee 13 | w: do_write_one_4b 14 | w: wrote seq ffff 15 | w: do_write_one_4b 16 | w: wrote seq gggg 17 | w: do_write_one_4b 18 | w: wrote seq hhhh 19 | w: do_write_one_4b 20 | w: wrote seq iiii 21 | w: do_write_one_2b 22 | w: wrote seq jj 23 | r: do_stat 24 | w: stat: 0 25 | w: bw 34, br 0, mw 10, mr 0, md 0, bd 0, bn 370, bu 34, mu 10 26 | w: do_write_one_4b 27 | w: wrote seq kkkk 28 | r: do_stat 29 | w: stat: 0 30 | w: bw 38, br 0, mw 11, mr 0, md 1, bd 4, bn 370, bu 34, mu 10 31 | r: do_read_one 32 | b 33 | w: do_close 34 | f: do_close 35 | r: do_close 36 | w: do_exit 37 | w: exiting 38 | r: do_exit 39 | r: exiting 40 | end 41 | -------------------------------------------------------------------------------- /tests/test8.ans: -------------------------------------------------------------------------------- 1 | writing ...ok 2 | writing ...ok 3 | reading ...read 3 bytes 4 | abc 5 | reading ...read 3 bytes 6 | def 7 | end 8 | -------------------------------------------------------------------------------- /tests/test8.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "shr.h" 4 | 5 | char *ring = __FILE__ ".ring"; 6 | char *data = "abcdefghi"; 7 | 8 | char out[10]; 9 | 10 | int main() { 11 | setlinebuf(stdout); 12 | struct shr *s=NULL,*t=NULL; 13 | int rc = -1; 14 | ssize_t nr; 15 | 16 | unlink(ring); 17 | if (shr_init(ring, 3*2, 0) < 0) goto done; 18 | 19 | s = shr_open(ring, SHR_RDONLY|SHR_NONBLOCK); 20 | if (s == NULL) goto done; 21 | 22 | t = shr_open(ring, SHR_WRONLY); 23 | if (t == NULL) goto done; 24 | 25 | printf("writing ..."); 26 | if (shr_write(t, &data[0], 3) < 0) goto done; 27 | printf("ok\n"); 28 | 29 | printf("writing ..."); 30 | if (shr_write(t, &data[3], 3) < 0) goto done; 31 | printf("ok\n"); 32 | 33 | printf("reading ..."); 34 | nr = shr_read(s, out, sizeof(out)); 35 | if (nr < 0) goto done; 36 | printf("read %ld bytes\n", (long)nr); 37 | if (nr > 0) printf("%.*s\n", (int)nr, out); 38 | 39 | printf("reading ..."); 40 | nr = shr_read(s, out, sizeof(out)); 41 | if (nr < 0) goto done; 42 | printf("read %ld bytes\n", (long)nr); 43 | if (nr > 0) printf("%.*s\n", (int)nr, out); 44 | 45 | rc = 0; 46 | 47 | done: 48 | printf("end\n"); 49 | if (s) shr_close(s); 50 | if (t) shr_close(t); 51 | unlink(ring); 52 | return rc; 53 | } 54 | -------------------------------------------------------------------------------- /tests/test80.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | r: do_open 3 | w: do_write_one_4b 4 | w: wrote seq aaaa 5 | w: do_write_one 6 | w: wrote seq b 7 | w: do_write_one_3b 8 | w: wrote seq ccc 9 | w: do_write_one_4b 10 | w: wrote seq dddd 11 | w: do_write_one_4b 12 | w: wrote seq eeee 13 | w: do_write_one_4b 14 | w: wrote seq ffff 15 | w: do_write_one_4b 16 | w: wrote seq gggg 17 | w: do_write_one_4b 18 | w: wrote seq hhhh 19 | w: do_write_one_4b 20 | w: wrote seq iiii 21 | w: do_write_one_2b 22 | w: wrote seq jj 23 | r: do_stat 24 | w: stat: 0 25 | w: bw 34, br 0, mw 10, mr 0, md 0, bd 0, bn 34, bu 34, mu 10 26 | w: do_write_one_4b 27 | w: wrote seq kkkk 28 | r: do_stat 29 | w: stat: 0 30 | w: bw 38, br 0, mw 11, mr 0, md 1, bd 4, bn 34, bu 34, mu 10 31 | r: do_read_one 32 | b 33 | w: do_close 34 | f: do_close 35 | r: do_close 36 | w: do_exit 37 | w: exiting 38 | r: do_exit 39 | r: exiting 40 | end 41 | -------------------------------------------------------------------------------- /tests/test81.ans: -------------------------------------------------------------------------------- 1 | w: do_open 2 | r: do_open 3 | w: do_write_one_3b 4 | w: wrote seq aaa 5 | w: do_write_one 6 | w: wrote seq b 7 | w: do_write_one_3b 8 | w: wrote seq ccc 9 | w: do_write_one_4b 10 | w: wrote seq dddd 11 | w: do_write_one_4b 12 | w: wrote seq eeee 13 | w: do_write_one_4b 14 | w: wrote seq ffff 15 | w: do_write_one_4b 16 | w: wrote seq gggg 17 | w: do_write_one_4b 18 | w: wrote seq hhhh 19 | w: do_write_one_4b 20 | w: wrote seq iiii 21 | w: do_write_one_2b 22 | w: wrote seq jj 23 | w: do_write_one 24 | w: wrote seq k 25 | r: do_stat 26 | w: stat: 0 27 | w: bw 34, br 0, mw 11, mr 0, md 0, bd 0, bn 34, bu 34, mu 11 28 | w: do_write_one_4b 29 | w: wrote seq llll 30 | r: do_stat 31 | w: stat: 0 32 | w: bw 38, br 0, mw 12, mr 0, md 2, bd 4, bn 34, bu 34, mu 10 33 | r: do_read_one 34 | ccc 35 | w: do_close 36 | f: do_close 37 | r: do_close 38 | w: do_exit 39 | w: exiting 40 | r: do_exit 41 | r: exiting 42 | end 43 | -------------------------------------------------------------------------------- /tests/test82.ans: -------------------------------------------------------------------------------- 1 | bw 6 br 0 mw 3 mr 0 md 0 bd 0 bn 6 bu 6 mu 3 2 | bw 10 br 0 mw 4 mr 0 md 3 bd 6 bn 6 bu 4 mu 1 3 | -------------------------------------------------------------------------------- /tests/test82.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | char *ring = __FILE__ ".ring"; 14 | int ring_sz = 6; 15 | int nmsg = 100; 16 | 17 | void stats(struct shr *s) { 18 | struct shr_stat ss; 19 | int sc; 20 | 21 | sc = shr_stat(s, &ss, NULL); 22 | if (sc < 0) { 23 | fprintf(stderr, "shr_stat: error\n"); 24 | return; 25 | } 26 | 27 | printf("bw %ld br %ld mw %ld mr %ld md %ld bd %ld bn %ld bu %ld mu %ld\n", 28 | ss.bw, ss.br, ss.mw, ss.mr, ss.md, ss.bd, ss.bn, ss.bu, ss.mu); 29 | } 30 | 31 | int main() { 32 | struct shr *s=NULL; 33 | int rc = -1, sc; 34 | ssize_t nr; 35 | 36 | unlink(ring); 37 | sc = shr_init(ring, ring_sz, SHR_DROP|SHR_MAXMSGS_2, nmsg); 38 | if (sc < 0) { 39 | fprintf(stderr, "shr_init: error\n"); 40 | goto done; 41 | } 42 | 43 | s = shr_open(ring, SHR_WRONLY); 44 | 45 | nr = shr_write(s, "a", 1); 46 | assert(nr == 1); 47 | 48 | nr = shr_write(s, "b", 1); 49 | assert(nr == 1); 50 | 51 | nr = shr_write(s, "cccc", 4); 52 | assert(nr == 4); 53 | stats(s); 54 | 55 | nr = shr_write(s, "dddd", 4); 56 | assert(nr == 4); 57 | stats(s); 58 | 59 | done: 60 | if (s) shr_close(s); 61 | unlink(ring); 62 | return rc; 63 | } 64 | 65 | -------------------------------------------------------------------------------- /tests/test83.ans: -------------------------------------------------------------------------------- 1 | bw 6 br 0 mw 3 mr 0 md 0 bd 0 bn 7 bu 6 mu 3 2 | bw 10 br 0 mw 4 mr 0 md 3 bd 6 bn 7 bu 4 mu 1 3 | -------------------------------------------------------------------------------- /tests/test83.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | char *ring = __FILE__ ".ring"; 14 | int ring_sz = 7; 15 | int nmsg = 100; 16 | 17 | void stats(struct shr *s) { 18 | struct shr_stat ss; 19 | int sc; 20 | 21 | sc = shr_stat(s, &ss, NULL); 22 | if (sc < 0) { 23 | fprintf(stderr, "shr_stat: error\n"); 24 | return; 25 | } 26 | 27 | printf("bw %ld br %ld mw %ld mr %ld md %ld bd %ld bn %ld bu %ld mu %ld\n", 28 | ss.bw, ss.br, ss.mw, ss.mr, ss.md, ss.bd, ss.bn, ss.bu, ss.mu); 29 | } 30 | 31 | int main() { 32 | struct shr *s=NULL; 33 | int rc = -1, sc; 34 | ssize_t nr; 35 | 36 | unlink(ring); 37 | sc = shr_init(ring, ring_sz, SHR_DROP|SHR_MAXMSGS_2, nmsg); 38 | if (sc < 0) { 39 | fprintf(stderr, "shr_init: error\n"); 40 | goto done; 41 | } 42 | 43 | s = shr_open(ring, SHR_WRONLY); 44 | 45 | nr = shr_write(s, "a", 1); 46 | assert(nr == 1); 47 | 48 | nr = shr_write(s, "b", 1); 49 | assert(nr == 1); 50 | 51 | nr = shr_write(s, "cccc", 4); 52 | assert(nr == 4); 53 | stats(s); 54 | 55 | nr = shr_write(s, "dddd", 4); 56 | assert(nr == 4); 57 | stats(s); 58 | 59 | done: 60 | if (s) shr_close(s); 61 | unlink(ring); 62 | return rc; 63 | } 64 | 65 | -------------------------------------------------------------------------------- /tests/test84.ans: -------------------------------------------------------------------------------- 1 | bw 6 br 0 mw 3 mr 0 md 0 bd 0 bn 6 bu 6 mu 3 2 | read a 3 | bw 7 br 1 mw 4 mr 1 md 0 bd 0 bn 6 bu 6 mu 3 4 | bw 8 br 1 mw 5 mr 1 md 1 bd 1 bn 6 bu 6 mu 3 5 | -------------------------------------------------------------------------------- /tests/test84.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | char *ring = __FILE__ ".ring"; 14 | int ring_sz = 6; 15 | int nmsg = 100; 16 | 17 | void stats(struct shr *s) { 18 | struct shr_stat ss; 19 | int sc; 20 | 21 | sc = shr_stat(s, &ss, NULL); 22 | if (sc < 0) { 23 | fprintf(stderr, "shr_stat: error\n"); 24 | return; 25 | } 26 | 27 | printf("bw %ld br %ld mw %ld mr %ld md %ld bd %ld bn %ld bu %ld mu %ld\n", 28 | ss.bw, ss.br, ss.mw, ss.mr, ss.md, ss.bd, ss.bn, ss.bu, ss.mu); 29 | } 30 | 31 | int main() { 32 | struct shr *s=NULL; 33 | struct shr *r=NULL; 34 | int rc = -1, sc; 35 | char buf[4]; 36 | ssize_t nr; 37 | 38 | unlink(ring); 39 | sc = shr_init(ring, ring_sz, SHR_DROP|SHR_MAXMSGS_2, nmsg); 40 | if (sc < 0) { 41 | fprintf(stderr, "shr_init: error\n"); 42 | goto done; 43 | } 44 | 45 | s = shr_open(ring, SHR_WRONLY); 46 | r = shr_open(ring, SHR_RDONLY); 47 | 48 | nr = shr_write(s, "a", 1); 49 | assert(nr == 1); 50 | 51 | nr = shr_write(s, "b", 1); 52 | assert(nr == 1); 53 | 54 | nr = shr_write(s, "cccc", 4); 55 | assert(nr == 4); 56 | stats(s); 57 | 58 | nr = shr_read(r, buf, sizeof(buf)); 59 | assert(nr == 1); 60 | printf("read %.*s\n", (int)nr, buf); 61 | 62 | nr = shr_write(s, "d", 1); /* space exists; replaces consumed a */ 63 | assert(nr == 1); 64 | stats(s); 65 | 66 | nr = shr_write(s, "e", 1); /* causes drop of unread b */ 67 | assert(nr == 1); 68 | stats(s); 69 | 70 | done: 71 | if (s) shr_close(s); 72 | if (r) shr_close(r); 73 | unlink(ring); 74 | return rc; 75 | } 76 | 77 | -------------------------------------------------------------------------------- /tests/test85.ans: -------------------------------------------------------------------------------- 1 | bw 6 br 0 mw 3 mr 0 md 0 bd 0 bn 6 bu 6 mu 3 2 | read a 3 | bw 7 br 1 mw 4 mr 1 md 0 bd 0 bn 6 bu 6 mu 3 4 | bw 9 br 1 mw 5 mr 1 md 2 bd 5 bn 6 bu 3 mu 2 5 | -------------------------------------------------------------------------------- /tests/test85.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | char *ring = __FILE__ ".ring"; 14 | int ring_sz = 6; 15 | int nmsg = 100; 16 | 17 | void stats(struct shr *s) { 18 | struct shr_stat ss; 19 | int sc; 20 | 21 | sc = shr_stat(s, &ss, NULL); 22 | if (sc < 0) { 23 | fprintf(stderr, "shr_stat: error\n"); 24 | return; 25 | } 26 | 27 | printf("bw %ld br %ld mw %ld mr %ld md %ld bd %ld bn %ld bu %ld mu %ld\n", 28 | ss.bw, ss.br, ss.mw, ss.mr, ss.md, ss.bd, ss.bn, ss.bu, ss.mu); 29 | } 30 | 31 | int main() { 32 | struct shr *s=NULL; 33 | struct shr *r=NULL; 34 | int rc = -1, sc; 35 | char buf[4]; 36 | ssize_t nr; 37 | 38 | unlink(ring); 39 | sc = shr_init(ring, ring_sz, SHR_DROP|SHR_MAXMSGS_2, nmsg); 40 | if (sc < 0) { 41 | fprintf(stderr, "shr_init: error\n"); 42 | goto done; 43 | } 44 | 45 | s = shr_open(ring, SHR_WRONLY); 46 | r = shr_open(ring, SHR_RDONLY); 47 | 48 | nr = shr_write(s, "a", 1); 49 | assert(nr == 1); 50 | 51 | nr = shr_write(s, "b", 1); 52 | assert(nr == 1); 53 | 54 | nr = shr_write(s, "cccc", 4); 55 | assert(nr == 4); 56 | stats(s); 57 | 58 | nr = shr_read(r, buf, sizeof(buf)); 59 | assert(nr == 1); 60 | printf("read %.*s\n", (int)nr, buf); 61 | 62 | nr = shr_write(s, "d", 1); /* space exists; replaces consumed a */ 63 | assert(nr == 1); 64 | stats(s); 65 | 66 | nr = shr_write(s, "ee", 2); /* causes drop of unread b and c */ 67 | assert(nr == 2); 68 | stats(s); 69 | 70 | done: 71 | if (s) shr_close(s); 72 | if (r) shr_close(r); 73 | unlink(ring); 74 | return rc; 75 | } 76 | 77 | -------------------------------------------------------------------------------- /tests/test86.ans: -------------------------------------------------------------------------------- 1 | bw 6 br 0 mw 3 mr 0 md 0 bd 0 bn 6 bu 6 mu 3 2 | read a 3 | bw 8 br 1 mw 4 mr 1 md 1 bd 1 bn 6 bu 6 mu 2 4 | -------------------------------------------------------------------------------- /tests/test86.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | char *ring = __FILE__ ".ring"; 14 | int ring_sz = 6; 15 | int nmsg = 100; 16 | 17 | void stats(struct shr *s) { 18 | struct shr_stat ss; 19 | int sc; 20 | 21 | sc = shr_stat(s, &ss, NULL); 22 | if (sc < 0) { 23 | fprintf(stderr, "shr_stat: error\n"); 24 | return; 25 | } 26 | 27 | printf("bw %ld br %ld mw %ld mr %ld md %ld bd %ld bn %ld bu %ld mu %ld\n", 28 | ss.bw, ss.br, ss.mw, ss.mr, ss.md, ss.bd, ss.bn, ss.bu, ss.mu); 29 | } 30 | 31 | int main() { 32 | struct shr *s=NULL; 33 | struct shr *r=NULL; 34 | int rc = -1, sc; 35 | char buf[4]; 36 | ssize_t nr; 37 | 38 | unlink(ring); 39 | sc = shr_init(ring, ring_sz, SHR_DROP|SHR_MAXMSGS_2, nmsg); 40 | if (sc < 0) { 41 | fprintf(stderr, "shr_init: error\n"); 42 | goto done; 43 | } 44 | 45 | s = shr_open(ring, SHR_WRONLY); 46 | r = shr_open(ring, SHR_RDONLY); 47 | 48 | nr = shr_write(s, "a", 1); 49 | assert(nr == 1); 50 | 51 | nr = shr_write(s, "b", 1); 52 | assert(nr == 1); 53 | 54 | nr = shr_write(s, "cccc", 4); 55 | assert(nr == 4); 56 | stats(s); 57 | 58 | nr = shr_read(r, buf, sizeof(buf)); 59 | assert(nr == 1); 60 | printf("read %.*s\n", (int)nr, buf); 61 | 62 | nr = shr_write(s, "dd", 2); /* replaces consumed a, and unconsumed b */ 63 | assert(nr == 2); 64 | stats(s); 65 | 66 | done: 67 | if (s) shr_close(s); 68 | if (r) shr_close(r); 69 | unlink(ring); 70 | return rc; 71 | } 72 | 73 | -------------------------------------------------------------------------------- /tests/test87.ans: -------------------------------------------------------------------------------- 1 | bw 6 br 0 mw 3 mr 0 md 0 bd 0 bn 6 bu 6 mu 3 2 | read a 3 | bw 7 br 1 mw 4 mr 1 md 0 bd 0 bn 6 bu 6 mu 3 4 | bw 9 br 1 mw 5 mr 1 md 2 bd 5 bn 6 bu 3 mu 2 5 | read d 6 | -------------------------------------------------------------------------------- /tests/test87.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | char *ring = __FILE__ ".ring"; 14 | int ring_sz = 6; 15 | int nmsg = 100; 16 | 17 | void stats(struct shr *s) { 18 | struct shr_stat ss; 19 | int sc; 20 | 21 | sc = shr_stat(s, &ss, NULL); 22 | if (sc < 0) { 23 | fprintf(stderr, "shr_stat: error\n"); 24 | return; 25 | } 26 | 27 | printf("bw %ld br %ld mw %ld mr %ld md %ld bd %ld bn %ld bu %ld mu %ld\n", 28 | ss.bw, ss.br, ss.mw, ss.mr, ss.md, ss.bd, ss.bn, ss.bu, ss.mu); 29 | } 30 | 31 | int main() { 32 | struct shr *s=NULL; 33 | struct shr *r=NULL; 34 | int rc = -1, sc; 35 | char buf[4]; 36 | ssize_t nr; 37 | 38 | unlink(ring); 39 | sc = shr_init(ring, ring_sz, SHR_DROP|SHR_MAXMSGS_2, nmsg); 40 | if (sc < 0) { 41 | fprintf(stderr, "shr_init: error\n"); 42 | goto done; 43 | } 44 | 45 | s = shr_open(ring, SHR_WRONLY); 46 | r = shr_open(ring, SHR_RDONLY); 47 | 48 | nr = shr_write(s, "a", 1); 49 | assert(nr == 1); 50 | 51 | nr = shr_write(s, "b", 1); 52 | assert(nr == 1); 53 | 54 | nr = shr_write(s, "cccc", 4); 55 | assert(nr == 4); 56 | stats(s); 57 | 58 | nr = shr_read(r, buf, sizeof(buf)); 59 | assert(nr == 1); 60 | printf("read %.*s\n", (int)nr, buf); 61 | 62 | nr = shr_write(s, "d", 1); /* space exists; replaces consumed a */ 63 | assert(nr == 1); 64 | stats(s); 65 | 66 | nr = shr_write(s, "ee", 2); /* causes drop of unread b and c */ 67 | assert(nr == 2); 68 | stats(s); 69 | 70 | nr = shr_read(r, buf, sizeof(buf)); /* read d */ 71 | assert(nr == 1); 72 | printf("read %.*s\n", (int)nr, buf); 73 | 74 | done: 75 | if (s) shr_close(s); 76 | if (r) shr_close(r); 77 | unlink(ring); 78 | return rc; 79 | } 80 | 81 | -------------------------------------------------------------------------------- /tests/test88.ans: -------------------------------------------------------------------------------- 1 | bw 6 br 0 mw 3 mr 0 md 0 bd 0 bn 7 bu 6 mu 3 2 | read a 3 | bw 7 br 1 mw 4 mr 1 md 0 bd 0 bn 7 bu 6 mu 3 4 | bw 8 br 1 mw 5 mr 1 md 0 bd 0 bn 7 bu 7 mu 4 5 | -------------------------------------------------------------------------------- /tests/test88.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | char *ring = __FILE__ ".ring"; 14 | int ring_sz = 7; 15 | int nmsg = 100; 16 | 17 | void stats(struct shr *s) { 18 | struct shr_stat ss; 19 | int sc; 20 | 21 | sc = shr_stat(s, &ss, NULL); 22 | if (sc < 0) { 23 | fprintf(stderr, "shr_stat: error\n"); 24 | return; 25 | } 26 | 27 | printf("bw %ld br %ld mw %ld mr %ld md %ld bd %ld bn %ld bu %ld mu %ld\n", 28 | ss.bw, ss.br, ss.mw, ss.mr, ss.md, ss.bd, ss.bn, ss.bu, ss.mu); 29 | } 30 | 31 | int main() { 32 | struct shr *s=NULL; 33 | struct shr *r=NULL; 34 | int rc = -1, sc; 35 | char buf[4]; 36 | ssize_t nr; 37 | 38 | unlink(ring); 39 | sc = shr_init(ring, ring_sz, SHR_DROP|SHR_MAXMSGS_2, nmsg); 40 | if (sc < 0) { 41 | fprintf(stderr, "shr_init: error\n"); 42 | goto done; 43 | } 44 | 45 | s = shr_open(ring, SHR_WRONLY); 46 | r = shr_open(ring, SHR_RDONLY); 47 | 48 | nr = shr_write(s, "a", 1); 49 | assert(nr == 1); 50 | 51 | nr = shr_write(s, "b", 1); 52 | assert(nr == 1); 53 | 54 | nr = shr_write(s, "cccc", 4); 55 | assert(nr == 4); 56 | stats(s); 57 | 58 | nr = shr_read(r, buf, sizeof(buf)); 59 | assert(nr == 1); 60 | printf("read %.*s\n", (int)nr, buf); 61 | 62 | nr = shr_write(s, "d", 1); /* space exists */ 63 | assert(nr == 1); 64 | stats(s); 65 | 66 | nr = shr_write(s, "e", 1); /* space exists; overwrites read a */ 67 | assert(nr == 1); 68 | stats(s); 69 | 70 | done: 71 | if (s) shr_close(s); 72 | if (r) shr_close(r); 73 | unlink(ring); 74 | return rc; 75 | } 76 | 77 | -------------------------------------------------------------------------------- /tests/test89.ans: -------------------------------------------------------------------------------- 1 | bw 6 br 0 mw 3 mr 0 md 0 bd 0 bn 7 bu 6 mu 3 2 | read a 3 | bw 7 br 1 mw 4 mr 1 md 0 bd 0 bn 7 bu 6 mu 3 4 | bw 9 br 1 mw 5 mr 1 md 1 bd 1 bn 7 bu 7 mu 3 5 | -------------------------------------------------------------------------------- /tests/test89.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | char *ring = __FILE__ ".ring"; 14 | int ring_sz = 7; 15 | int nmsg = 100; 16 | 17 | void stats(struct shr *s) { 18 | struct shr_stat ss; 19 | int sc; 20 | 21 | sc = shr_stat(s, &ss, NULL); 22 | if (sc < 0) { 23 | fprintf(stderr, "shr_stat: error\n"); 24 | return; 25 | } 26 | 27 | printf("bw %ld br %ld mw %ld mr %ld md %ld bd %ld bn %ld bu %ld mu %ld\n", 28 | ss.bw, ss.br, ss.mw, ss.mr, ss.md, ss.bd, ss.bn, ss.bu, ss.mu); 29 | } 30 | 31 | int main() { 32 | struct shr *s=NULL; 33 | struct shr *r=NULL; 34 | int rc = -1, sc; 35 | char buf[4]; 36 | ssize_t nr; 37 | 38 | unlink(ring); 39 | sc = shr_init(ring, ring_sz, SHR_DROP|SHR_MAXMSGS_2, nmsg); 40 | if (sc < 0) { 41 | fprintf(stderr, "shr_init: error\n"); 42 | goto done; 43 | } 44 | 45 | s = shr_open(ring, SHR_WRONLY); 46 | r = shr_open(ring, SHR_RDONLY); 47 | 48 | nr = shr_write(s, "a", 1); 49 | assert(nr == 1); 50 | 51 | nr = shr_write(s, "b", 1); 52 | assert(nr == 1); 53 | 54 | nr = shr_write(s, "cccc", 4); 55 | assert(nr == 4); 56 | stats(s); 57 | 58 | nr = shr_read(r, buf, sizeof(buf)); 59 | assert(nr == 1); 60 | printf("read %.*s\n", (int)nr, buf); 61 | 62 | nr = shr_write(s, "d", 1); /* space exists */ 63 | assert(nr == 1); 64 | stats(s); 65 | 66 | nr = shr_write(s, "ee", 2); /* overwrites read a and unread b */ 67 | assert(nr == 2); 68 | stats(s); 69 | 70 | done: 71 | if (s) shr_close(s); 72 | if (r) shr_close(r); 73 | unlink(ring); 74 | return rc; 75 | } 76 | 77 | -------------------------------------------------------------------------------- /tests/test9.ans: -------------------------------------------------------------------------------- 1 | app_data: was 0 2 | app_data: now 1 3 | app_data: was 1 4 | app_data: now 2 5 | -------------------------------------------------------------------------------- /tests/test9.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "shr.h" 4 | 5 | char *ring = __FILE__ ".ring"; 6 | 7 | struct app_data { 8 | int counter; 9 | } ad, od; 10 | 11 | int main() { 12 | setlinebuf(stdout); 13 | struct shr *s = NULL; 14 | int rc = -1, sc; 15 | void *p; 16 | size_t sz = sizeof(ad); 17 | 18 | unlink(ring); 19 | 20 | sc = shr_init(ring, 8, SHR_APPDATA, &ad, sizeof(ad)); 21 | if (sc < 0) goto done; 22 | 23 | s = shr_open(ring, SHR_RDONLY); 24 | if (s == NULL) goto done; 25 | 26 | p = &od; 27 | ad.counter = 1; 28 | sc = shr_appdata(s, &p, &ad, &sz); 29 | if (sc < 0) goto done; 30 | printf("app_data: was %d\n", od.counter); 31 | printf("app_data: now %d\n", ad.counter); 32 | 33 | ad.counter = 2; 34 | sc = shr_appdata(s, &p, &ad, &sz); 35 | if (sc < 0) goto done; 36 | printf("app_data: was %d\n", od.counter); 37 | printf("app_data: now %d\n", ad.counter); 38 | 39 | rc = 0; 40 | 41 | done: 42 | if (s) shr_close(s); 43 | unlink(ring); 44 | return rc; 45 | } 46 | -------------------------------------------------------------------------------- /tests/test90.ans: -------------------------------------------------------------------------------- 1 | bw 6 br 0 mw 3 mr 0 md 0 bd 0 bn 7 bu 6 mu 3 2 | read a 3 | bw 8 br 1 mw 4 mr 1 md 0 bd 0 bn 7 bu 7 mu 3 4 | -------------------------------------------------------------------------------- /tests/test90.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | char *ring = __FILE__ ".ring"; 14 | int ring_sz = 7; 15 | int nmsg = 100; 16 | 17 | void stats(struct shr *s) { 18 | struct shr_stat ss; 19 | int sc; 20 | 21 | sc = shr_stat(s, &ss, NULL); 22 | if (sc < 0) { 23 | fprintf(stderr, "shr_stat: error\n"); 24 | return; 25 | } 26 | 27 | printf("bw %ld br %ld mw %ld mr %ld md %ld bd %ld bn %ld bu %ld mu %ld\n", 28 | ss.bw, ss.br, ss.mw, ss.mr, ss.md, ss.bd, ss.bn, ss.bu, ss.mu); 29 | } 30 | 31 | int main() { 32 | struct shr *s=NULL; 33 | struct shr *r=NULL; 34 | int rc = -1, sc; 35 | char buf[4]; 36 | ssize_t nr; 37 | 38 | unlink(ring); 39 | sc = shr_init(ring, ring_sz, SHR_DROP|SHR_MAXMSGS_2, nmsg); 40 | if (sc < 0) { 41 | fprintf(stderr, "shr_init: error\n"); 42 | goto done; 43 | } 44 | 45 | s = shr_open(ring, SHR_WRONLY); 46 | r = shr_open(ring, SHR_RDONLY); 47 | 48 | nr = shr_write(s, "a", 1); 49 | assert(nr == 1); 50 | 51 | nr = shr_write(s, "b", 1); 52 | assert(nr == 1); 53 | 54 | nr = shr_write(s, "cccc", 4); 55 | assert(nr == 4); 56 | stats(s); 57 | 58 | nr = shr_read(r, buf, sizeof(buf)); 59 | assert(nr == 1); 60 | printf("read %.*s\n", (int)nr, buf); 61 | 62 | nr = shr_write(s, "dd", 2); /* space exists; free byte plus consumed a */ 63 | assert(nr == 2); 64 | stats(s); 65 | 66 | done: 67 | if (s) shr_close(s); 68 | if (r) shr_close(r); 69 | unlink(ring); 70 | return rc; 71 | } 72 | 73 | -------------------------------------------------------------------------------- /tests/test91.ans: -------------------------------------------------------------------------------- 1 | bw 6 br 0 mw 3 mr 0 md 0 bd 0 bn 7 bu 6 mu 3 2 | read a 3 | bw 9 br 1 mw 4 mr 1 md 1 bd 1 bn 7 bu 7 mu 2 4 | read cccc 5 | -------------------------------------------------------------------------------- /tests/test91.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | char *ring = __FILE__ ".ring"; 14 | int ring_sz = 7; 15 | int nmsg = 100; 16 | 17 | void stats(struct shr *s) { 18 | struct shr_stat ss; 19 | int sc; 20 | 21 | sc = shr_stat(s, &ss, NULL); 22 | if (sc < 0) { 23 | fprintf(stderr, "shr_stat: error\n"); 24 | return; 25 | } 26 | 27 | printf("bw %ld br %ld mw %ld mr %ld md %ld bd %ld bn %ld bu %ld mu %ld\n", 28 | ss.bw, ss.br, ss.mw, ss.mr, ss.md, ss.bd, ss.bn, ss.bu, ss.mu); 29 | } 30 | 31 | int main() { 32 | struct shr *s=NULL; 33 | struct shr *r=NULL; 34 | int rc = -1, sc; 35 | char buf[4]; 36 | ssize_t nr; 37 | 38 | unlink(ring); 39 | sc = shr_init(ring, ring_sz, SHR_DROP|SHR_MAXMSGS_2, nmsg); 40 | if (sc < 0) { 41 | fprintf(stderr, "shr_init: error\n"); 42 | goto done; 43 | } 44 | 45 | s = shr_open(ring, SHR_WRONLY); 46 | r = shr_open(ring, SHR_RDONLY); 47 | 48 | nr = shr_write(s, "a", 1); 49 | assert(nr == 1); 50 | 51 | nr = shr_write(s, "b", 1); 52 | assert(nr == 1); 53 | 54 | nr = shr_write(s, "cccc", 4); 55 | assert(nr == 4); 56 | stats(s); 57 | 58 | nr = shr_read(r, buf, sizeof(buf)); 59 | assert(nr == 1); 60 | printf("read %.*s\n", (int)nr, buf); 61 | 62 | nr = shr_write(s, "ddd", 3); /* free byte plus consumed a, drops b */ 63 | assert(nr == 3); 64 | stats(s); 65 | 66 | nr = shr_read(r, buf, sizeof(buf)); 67 | assert(nr == 4); 68 | printf("read %.*s\n", (int)nr, buf); 69 | 70 | done: 71 | if (s) shr_close(s); 72 | if (r) shr_close(r); 73 | unlink(ring); 74 | return rc; 75 | } 76 | 77 | -------------------------------------------------------------------------------- /tests/test92.ans: -------------------------------------------------------------------------------- 1 | bw 6 br 0 mw 3 mr 0 md 0 bd 0 bn 7 bu 6 mu 3 2 | read a 3 | bw 10 br 1 mw 4 mr 1 md 2 bd 5 bn 7 bu 4 mu 1 4 | read dddd 5 | -------------------------------------------------------------------------------- /tests/test92.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | char *ring = __FILE__ ".ring"; 14 | int ring_sz = 7; 15 | int nmsg = 100; 16 | 17 | void stats(struct shr *s) { 18 | struct shr_stat ss; 19 | int sc; 20 | 21 | sc = shr_stat(s, &ss, NULL); 22 | if (sc < 0) { 23 | fprintf(stderr, "shr_stat: error\n"); 24 | return; 25 | } 26 | 27 | printf("bw %ld br %ld mw %ld mr %ld md %ld bd %ld bn %ld bu %ld mu %ld\n", 28 | ss.bw, ss.br, ss.mw, ss.mr, ss.md, ss.bd, ss.bn, ss.bu, ss.mu); 29 | } 30 | 31 | int main() { 32 | struct shr *s=NULL; 33 | struct shr *r=NULL; 34 | int rc = -1, sc; 35 | char buf[4]; 36 | ssize_t nr; 37 | 38 | unlink(ring); 39 | sc = shr_init(ring, ring_sz, SHR_DROP|SHR_MAXMSGS_2, nmsg); 40 | if (sc < 0) { 41 | fprintf(stderr, "shr_init: error\n"); 42 | goto done; 43 | } 44 | 45 | s = shr_open(ring, SHR_WRONLY); 46 | r = shr_open(ring, SHR_RDONLY); 47 | 48 | nr = shr_write(s, "a", 1); 49 | assert(nr == 1); 50 | 51 | nr = shr_write(s, "b", 1); 52 | assert(nr == 1); 53 | 54 | nr = shr_write(s, "cccc", 4); 55 | assert(nr == 4); 56 | stats(s); 57 | 58 | nr = shr_read(r, buf, sizeof(buf)); 59 | assert(nr == 1); 60 | printf("read %.*s\n", (int)nr, buf); 61 | 62 | nr = shr_write(s, "dddd", 4); /* free byte plus consumed a, drops b, cccc */ 63 | assert(nr == 4); 64 | stats(s); 65 | 66 | nr = shr_read(r, buf, sizeof(buf)); 67 | assert(nr == 4); 68 | printf("read %.*s\n", (int)nr, buf); 69 | 70 | done: 71 | if (s) shr_close(s); 72 | if (r) shr_close(r); 73 | unlink(ring); 74 | return rc; 75 | } 76 | 77 | -------------------------------------------------------------------------------- /tests/test93.ans: -------------------------------------------------------------------------------- 1 | bw 6 br 0 mw 3 mr 0 md 0 bd 0 bn 7 bu 6 mu 3 2 | read a 3 | bw 10 br 1 mw 4 mr 1 md 2 bd 5 bn 7 bu 4 mu 1 4 | read dddd 5 | bw 17 br 5 mw 5 mr 2 md 2 bd 5 bn 7 bu 7 mu 1 6 | read eeeeeee 7 | bw 17 br 12 mw 5 mr 3 md 2 bd 5 bn 7 bu 0 mu 0 8 | -------------------------------------------------------------------------------- /tests/test93.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | char *ring = __FILE__ ".ring"; 14 | int ring_sz = 7; 15 | int nmsg = 100; 16 | 17 | void stats(struct shr *s) { 18 | struct shr_stat ss; 19 | int sc; 20 | 21 | sc = shr_stat(s, &ss, NULL); 22 | if (sc < 0) { 23 | fprintf(stderr, "shr_stat: error\n"); 24 | return; 25 | } 26 | 27 | printf("bw %ld br %ld mw %ld mr %ld md %ld bd %ld bn %ld bu %ld mu %ld\n", 28 | ss.bw, ss.br, ss.mw, ss.mr, ss.md, ss.bd, ss.bn, ss.bu, ss.mu); 29 | } 30 | 31 | int main() { 32 | struct shr *s=NULL; 33 | struct shr *r=NULL; 34 | int rc = -1, sc; 35 | char buf[7]; 36 | ssize_t nr; 37 | 38 | unlink(ring); 39 | sc = shr_init(ring, ring_sz, SHR_DROP|SHR_MAXMSGS_2, nmsg); 40 | if (sc < 0) { 41 | fprintf(stderr, "shr_init: error\n"); 42 | goto done; 43 | } 44 | 45 | s = shr_open(ring, SHR_WRONLY); 46 | r = shr_open(ring, SHR_RDONLY); 47 | 48 | nr = shr_write(s, "a", 1); 49 | assert(nr == 1); 50 | 51 | nr = shr_write(s, "b", 1); 52 | assert(nr == 1); 53 | 54 | nr = shr_write(s, "cccc", 4); 55 | assert(nr == 4); 56 | stats(s); 57 | 58 | nr = shr_read(r, buf, sizeof(buf)); 59 | assert(nr == 1); 60 | printf("read %.*s\n", (int)nr, buf); 61 | 62 | nr = shr_write(s, "dddd", 4); /* free byte plus consumed a, drops b, [c]ccc */ 63 | assert(nr == 4); 64 | stats(s); 65 | 66 | nr = shr_read(r, buf, sizeof(buf)); 67 | assert(nr == 4); 68 | printf("read %.*s\n", (int)nr, buf); 69 | 70 | nr = shr_write(s, "eeeeeee", 7); /* fills buffer, no drop */ 71 | assert(nr == 7); 72 | stats(s); 73 | 74 | nr = shr_read(r, buf, sizeof(buf)); 75 | assert(nr == 7); 76 | printf("read %.*s\n", (int)nr, buf); 77 | stats(s); 78 | 79 | done: 80 | if (s) shr_close(s); 81 | if (r) shr_close(r); 82 | unlink(ring); 83 | return rc; 84 | } 85 | 86 | -------------------------------------------------------------------------------- /tests/test94.ans: -------------------------------------------------------------------------------- 1 | bw 6 br 0 mw 3 mr 0 md 0 bd 0 bn 8 bu 6 mu 3 2 | read a 3 | bw 10 br 1 mw 4 mr 1 md 1 bd 1 bn 8 bu 8 mu 2 4 | read cccc 5 | -------------------------------------------------------------------------------- /tests/test94.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | char *ring = __FILE__ ".ring"; 14 | int ring_sz = 8; 15 | int nmsg = 100; 16 | 17 | void stats(struct shr *s) { 18 | struct shr_stat ss; 19 | int sc; 20 | 21 | sc = shr_stat(s, &ss, NULL); 22 | if (sc < 0) { 23 | fprintf(stderr, "shr_stat: error\n"); 24 | return; 25 | } 26 | 27 | printf("bw %ld br %ld mw %ld mr %ld md %ld bd %ld bn %ld bu %ld mu %ld\n", 28 | ss.bw, ss.br, ss.mw, ss.mr, ss.md, ss.bd, ss.bn, ss.bu, ss.mu); 29 | } 30 | 31 | int main() { 32 | struct shr *s=NULL; 33 | struct shr *r=NULL; 34 | int rc = -1, sc; 35 | char buf[4]; 36 | ssize_t nr; 37 | 38 | unlink(ring); 39 | sc = shr_init(ring, ring_sz, SHR_DROP|SHR_MAXMSGS_2, nmsg); 40 | if (sc < 0) { 41 | fprintf(stderr, "shr_init: error\n"); 42 | goto done; 43 | } 44 | 45 | s = shr_open(ring, SHR_WRONLY); 46 | r = shr_open(ring, SHR_RDONLY); 47 | 48 | nr = shr_write(s, "a", 1); 49 | assert(nr == 1); 50 | 51 | nr = shr_write(s, "b", 1); 52 | assert(nr == 1); 53 | 54 | nr = shr_write(s, "cccc", 4); 55 | assert(nr == 4); 56 | stats(s); 57 | 58 | nr = shr_read(r, buf, sizeof(buf)); 59 | assert(nr == 1); 60 | printf("read %.*s\n", (int)nr, buf); 61 | 62 | nr = shr_write(s, "dddd", 4); /* two free bytes, plus consumed a, drops b */ 63 | assert(nr == 4); 64 | stats(s); 65 | 66 | nr = shr_read(r, buf, sizeof(buf)); 67 | assert(nr == 4); 68 | printf("read %.*s\n", (int)nr, buf); 69 | 70 | done: 71 | if (s) shr_close(s); 72 | if (r) shr_close(r); 73 | unlink(ring); 74 | return rc; 75 | } 76 | 77 | -------------------------------------------------------------------------------- /tests/test95.ans: -------------------------------------------------------------------------------- 1 | bw 6 br 0 mw 3 mr 0 md 0 bd 0 bn 8 bu 6 mu 3 2 | read a 3 | bw 11 br 1 mw 4 mr 1 md 2 bd 5 bn 8 bu 5 mu 1 4 | read ddddd 5 | -------------------------------------------------------------------------------- /tests/test95.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | char *ring = __FILE__ ".ring"; 14 | int ring_sz = 8; 15 | int nmsg = 100; 16 | 17 | void stats(struct shr *s) { 18 | struct shr_stat ss; 19 | int sc; 20 | 21 | sc = shr_stat(s, &ss, NULL); 22 | if (sc < 0) { 23 | fprintf(stderr, "shr_stat: error\n"); 24 | return; 25 | } 26 | 27 | printf("bw %ld br %ld mw %ld mr %ld md %ld bd %ld bn %ld bu %ld mu %ld\n", 28 | ss.bw, ss.br, ss.mw, ss.mr, ss.md, ss.bd, ss.bn, ss.bu, ss.mu); 29 | } 30 | 31 | int main() { 32 | struct shr *s=NULL; 33 | struct shr *r=NULL; 34 | int rc = -1, sc; 35 | char buf[5]; 36 | ssize_t nr; 37 | 38 | unlink(ring); 39 | sc = shr_init(ring, ring_sz, SHR_DROP|SHR_MAXMSGS_2, nmsg); 40 | if (sc < 0) { 41 | fprintf(stderr, "shr_init: error\n"); 42 | goto done; 43 | } 44 | 45 | s = shr_open(ring, SHR_WRONLY); 46 | r = shr_open(ring, SHR_RDONLY); 47 | 48 | nr = shr_write(s, "a", 1); 49 | assert(nr == 1); 50 | 51 | nr = shr_write(s, "b", 1); 52 | assert(nr == 1); 53 | 54 | nr = shr_write(s, "cccc", 4); 55 | assert(nr == 4); 56 | stats(s); 57 | 58 | nr = shr_read(r, buf, sizeof(buf)); 59 | assert(nr == 1); 60 | printf("read %.*s\n", (int)nr, buf); 61 | 62 | nr = shr_write(s, "ddddd", 5); /* two free bytes, plus consumed a, 63 | drops b, drops ccccc */ 64 | assert(nr == 5); 65 | stats(s); 66 | 67 | nr = shr_read(r, buf, sizeof(buf)); 68 | assert(nr == 5); 69 | printf("read %.*s\n", (int)nr, buf); 70 | 71 | done: 72 | if (s) shr_close(s); 73 | if (r) shr_close(r); 74 | unlink(ring); 75 | return rc; 76 | } 77 | 78 | -------------------------------------------------------------------------------- /tests/test96.ans: -------------------------------------------------------------------------------- 1 | bw 6 br 0 mw 3 mr 0 md 0 bd 0 bn 8 bu 6 mu 3 2 | read a 3 | bw 11 br 1 mw 4 mr 1 md 2 bd 5 bn 8 bu 5 mu 1 4 | read ddddd 5 | bw 16 br 6 mw 5 mr 2 md 2 bd 5 bn 8 bu 5 mu 1 6 | bw 18 br 6 mw 6 mr 2 md 2 bd 5 bn 8 bu 7 mu 2 7 | -------------------------------------------------------------------------------- /tests/test96.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | char *ring = __FILE__ ".ring"; 14 | int ring_sz = 8; 15 | int nmsg = 100; 16 | 17 | void stats(struct shr *s) { 18 | struct shr_stat ss; 19 | int sc; 20 | 21 | sc = shr_stat(s, &ss, NULL); 22 | if (sc < 0) { 23 | fprintf(stderr, "shr_stat: error\n"); 24 | return; 25 | } 26 | 27 | printf("bw %ld br %ld mw %ld mr %ld md %ld bd %ld bn %ld bu %ld mu %ld\n", 28 | ss.bw, ss.br, ss.mw, ss.mr, ss.md, ss.bd, ss.bn, ss.bu, ss.mu); 29 | } 30 | 31 | int main() { 32 | struct shr *s=NULL; 33 | struct shr *r=NULL; 34 | int rc = -1, sc; 35 | char buf[5]; 36 | ssize_t nr; 37 | 38 | unlink(ring); 39 | sc = shr_init(ring, ring_sz, SHR_DROP|SHR_MAXMSGS_2, nmsg); 40 | if (sc < 0) { 41 | fprintf(stderr, "shr_init: error\n"); 42 | goto done; 43 | } 44 | 45 | s = shr_open(ring, SHR_WRONLY); 46 | r = shr_open(ring, SHR_RDONLY); 47 | 48 | nr = shr_write(s, "a", 1); 49 | assert(nr == 1); 50 | 51 | nr = shr_write(s, "b", 1); 52 | assert(nr == 1); 53 | 54 | nr = shr_write(s, "cccc", 4); 55 | assert(nr == 4); 56 | stats(s); 57 | 58 | nr = shr_read(r, buf, sizeof(buf)); 59 | assert(nr == 1); 60 | printf("read %.*s\n", (int)nr, buf); 61 | 62 | nr = shr_write(s, "ddddd", 5); /* two free bytes, plus consumed a, 63 | drops b, drops ccccc */ 64 | assert(nr == 5); 65 | stats(s); 66 | 67 | nr = shr_read(r, buf, sizeof(buf)); 68 | assert(nr == 5); 69 | printf("read %.*s\n", (int)nr, buf); 70 | 71 | nr = shr_write(s, "eeeee", 5); 72 | assert(nr == 5); 73 | stats(s); 74 | 75 | nr = shr_write(s, "ff", 2); 76 | assert(nr == 2); 77 | stats(s); 78 | 79 | done: 80 | if (s) shr_close(s); 81 | if (r) shr_close(r); 82 | unlink(ring); 83 | return rc; 84 | } 85 | 86 | -------------------------------------------------------------------------------- /tests/test97.ans: -------------------------------------------------------------------------------- 1 | bw 6 br 0 mw 3 mr 0 md 0 bd 0 bn 8 bu 6 mu 3 2 | read a 3 | bw 11 br 1 mw 4 mr 1 md 2 bd 5 bn 8 bu 5 mu 1 4 | read ddddd 5 | bw 16 br 6 mw 5 mr 2 md 2 bd 5 bn 8 bu 5 mu 1 6 | bw 18 br 6 mw 6 mr 2 md 2 bd 5 bn 8 bu 7 mu 2 7 | bw 19 br 6 mw 7 mr 2 md 2 bd 5 bn 8 bu 8 mu 3 8 | read eeeee 9 | read ff 10 | read g 11 | -------------------------------------------------------------------------------- /tests/test97.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | char *ring = __FILE__ ".ring"; 14 | int ring_sz = 8; 15 | int nmsg = 100; 16 | 17 | void stats(struct shr *s) { 18 | struct shr_stat ss; 19 | int sc; 20 | 21 | sc = shr_stat(s, &ss, NULL); 22 | if (sc < 0) { 23 | fprintf(stderr, "shr_stat: error\n"); 24 | return; 25 | } 26 | 27 | printf("bw %ld br %ld mw %ld mr %ld md %ld bd %ld bn %ld bu %ld mu %ld\n", 28 | ss.bw, ss.br, ss.mw, ss.mr, ss.md, ss.bd, ss.bn, ss.bu, ss.mu); 29 | } 30 | 31 | int main() { 32 | struct shr *s=NULL; 33 | struct shr *r=NULL; 34 | int rc = -1, sc; 35 | char buf[5]; 36 | ssize_t nr; 37 | 38 | unlink(ring); 39 | sc = shr_init(ring, ring_sz, SHR_DROP|SHR_MAXMSGS_2, nmsg); 40 | if (sc < 0) { 41 | fprintf(stderr, "shr_init: error\n"); 42 | goto done; 43 | } 44 | 45 | s = shr_open(ring, SHR_WRONLY); 46 | r = shr_open(ring, SHR_RDONLY); 47 | 48 | nr = shr_write(s, "a", 1); 49 | assert(nr == 1); 50 | 51 | nr = shr_write(s, "b", 1); 52 | assert(nr == 1); 53 | 54 | nr = shr_write(s, "cccc", 4); 55 | assert(nr == 4); 56 | stats(s); 57 | 58 | nr = shr_read(r, buf, sizeof(buf)); 59 | assert(nr == 1); 60 | printf("read %.*s\n", (int)nr, buf); 61 | 62 | nr = shr_write(s, "ddddd", 5); /* two free bytes, plus consumed a, 63 | drops b, drops ccccc */ 64 | assert(nr == 5); 65 | stats(s); 66 | 67 | nr = shr_read(r, buf, sizeof(buf)); 68 | assert(nr == 5); 69 | printf("read %.*s\n", (int)nr, buf); 70 | 71 | nr = shr_write(s, "eeeee", 5); 72 | assert(nr == 5); 73 | stats(s); 74 | 75 | nr = shr_write(s, "ff", 2); 76 | assert(nr == 2); 77 | stats(s); 78 | 79 | nr = shr_write(s, "g", 1); 80 | assert(nr == 1); 81 | stats(s); 82 | 83 | nr = shr_read(r, buf, sizeof(buf)); 84 | assert(nr == 5); 85 | printf("read %.*s\n", (int)nr, buf); 86 | 87 | nr = shr_read(r, buf, sizeof(buf)); 88 | assert(nr == 2); 89 | printf("read %.*s\n", (int)nr, buf); 90 | 91 | nr = shr_read(r, buf, sizeof(buf)); 92 | assert(nr == 1); 93 | printf("read %.*s\n", (int)nr, buf); 94 | 95 | done: 96 | if (s) shr_close(s); 97 | if (r) shr_close(r); 98 | unlink(ring); 99 | return rc; 100 | } 101 | 102 | -------------------------------------------------------------------------------- /tests/test98.ans: -------------------------------------------------------------------------------- 1 | bw 6 br 0 mw 3 mr 0 md 0 bd 0 bn 7 bu 6 mu 3 2 | read a 3 | bw 11 br 1 mw 4 mr 1 md 2 bd 5 bn 7 bu 5 mu 1 4 | read ddddd 5 | bw 16 br 6 mw 5 mr 2 md 2 bd 5 bn 7 bu 5 mu 1 6 | bw 18 br 6 mw 6 mr 2 md 2 bd 5 bn 7 bu 7 mu 2 7 | bw 19 br 6 mw 7 mr 2 md 3 bd 10 bn 7 bu 3 mu 2 8 | read ff 9 | read g 10 | -------------------------------------------------------------------------------- /tests/test98.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | char *ring = __FILE__ ".ring"; 14 | int ring_sz = 7; 15 | int nmsg = 100; 16 | 17 | void stats(struct shr *s) { 18 | struct shr_stat ss; 19 | int sc; 20 | 21 | sc = shr_stat(s, &ss, NULL); 22 | if (sc < 0) { 23 | fprintf(stderr, "shr_stat: error\n"); 24 | return; 25 | } 26 | 27 | printf("bw %ld br %ld mw %ld mr %ld md %ld bd %ld bn %ld bu %ld mu %ld\n", 28 | ss.bw, ss.br, ss.mw, ss.mr, ss.md, ss.bd, ss.bn, ss.bu, ss.mu); 29 | } 30 | 31 | int main() { 32 | struct shr *s=NULL; 33 | struct shr *r=NULL; 34 | int rc = -1, sc; 35 | char buf[5]; 36 | ssize_t nr; 37 | 38 | unlink(ring); 39 | sc = shr_init(ring, ring_sz, SHR_DROP|SHR_MAXMSGS_2, nmsg); 40 | if (sc < 0) { 41 | fprintf(stderr, "shr_init: error\n"); 42 | goto done; 43 | } 44 | 45 | s = shr_open(ring, SHR_WRONLY); 46 | r = shr_open(ring, SHR_RDONLY); 47 | 48 | nr = shr_write(s, "a", 1); 49 | assert(nr == 1); 50 | 51 | nr = shr_write(s, "b", 1); 52 | assert(nr == 1); 53 | 54 | nr = shr_write(s, "cccc", 4); 55 | assert(nr == 4); 56 | stats(s); 57 | 58 | nr = shr_read(r, buf, sizeof(buf)); 59 | assert(nr == 1); 60 | printf("read %.*s\n", (int)nr, buf); 61 | 62 | nr = shr_write(s, "ddddd", 5); /* two free bytes, plus consumed a, 63 | drops b, drops ccccc */ 64 | assert(nr == 5); 65 | stats(s); 66 | 67 | nr = shr_read(r, buf, sizeof(buf)); 68 | assert(nr == 5); 69 | printf("read %.*s\n", (int)nr, buf); 70 | 71 | nr = shr_write(s, "eeeee", 5); 72 | assert(nr == 5); 73 | stats(s); 74 | 75 | nr = shr_write(s, "ff", 2); 76 | assert(nr == 2); 77 | stats(s); 78 | 79 | nr = shr_write(s, "g", 1); /* drops eeeee */ 80 | assert(nr == 1); 81 | stats(s); 82 | 83 | nr = shr_read(r, buf, sizeof(buf)); 84 | assert(nr == 2); 85 | printf("read %.*s\n", (int)nr, buf); 86 | 87 | nr = shr_read(r, buf, sizeof(buf)); 88 | assert(nr == 1); 89 | printf("read %.*s\n", (int)nr, buf); 90 | 91 | done: 92 | if (s) shr_close(s); 93 | if (r) shr_close(r); 94 | unlink(ring); 95 | return rc; 96 | } 97 | 98 | -------------------------------------------------------------------------------- /tests/test99.ans: -------------------------------------------------------------------------------- 1 | bw 6 br 0 mw 6 mr 0 md 0 bd 0 bn 6 bu 6 mu 6 2 | bw 12 br 0 mw 12 mr 0 md 6 bd 6 bn 6 bu 6 mu 6 3 | read g 4 | read h 5 | read i 6 | read j 7 | read k 8 | read l 9 | -------------------------------------------------------------------------------- /tests/test99.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "shr.h" 12 | 13 | char *ring = __FILE__ ".ring"; 14 | int ring_sz = 6; 15 | int nmsg = 100; 16 | 17 | void stats(struct shr *s) { 18 | struct shr_stat ss; 19 | int sc; 20 | 21 | sc = shr_stat(s, &ss, NULL); 22 | if (sc < 0) { 23 | fprintf(stderr, "shr_stat: error\n"); 24 | return; 25 | } 26 | 27 | printf("bw %ld br %ld mw %ld mr %ld md %ld bd %ld bn %ld bu %ld mu %ld\n", 28 | ss.bw, ss.br, ss.mw, ss.mr, ss.md, ss.bd, ss.bn, ss.bu, ss.mu); 29 | } 30 | 31 | int main() { 32 | struct shr *s=NULL; 33 | struct shr *r=NULL; 34 | int rc = -1, sc; 35 | char buf[5]; 36 | ssize_t nr; 37 | 38 | unlink(ring); 39 | sc = shr_init(ring, ring_sz, SHR_DROP|SHR_MAXMSGS_2, nmsg); 40 | if (sc < 0) { 41 | fprintf(stderr, "shr_init: error\n"); 42 | goto done; 43 | } 44 | 45 | s = shr_open(ring, SHR_WRONLY); 46 | r = shr_open(ring, SHR_RDONLY); 47 | 48 | nr = shr_write(s, "a", 1); 49 | assert(nr == 1); 50 | nr = shr_write(s, "b", 1); 51 | assert(nr == 1); 52 | nr = shr_write(s, "c", 1); 53 | assert(nr == 1); 54 | nr = shr_write(s, "d", 1); 55 | assert(nr == 1); 56 | nr = shr_write(s, "e", 1); 57 | assert(nr == 1); 58 | nr = shr_write(s, "f", 1); 59 | assert(nr == 1); 60 | stats(s); 61 | 62 | nr = shr_write(s, "g", 1); 63 | assert(nr == 1); 64 | nr = shr_write(s, "h", 1); 65 | assert(nr == 1); 66 | nr = shr_write(s, "i", 1); 67 | assert(nr == 1); 68 | nr = shr_write(s, "j", 1); 69 | assert(nr == 1); 70 | nr = shr_write(s, "k", 1); 71 | assert(nr == 1); 72 | nr = shr_write(s, "l", 1); 73 | assert(nr == 1); 74 | stats(s); 75 | 76 | nr = shr_read(r, buf, sizeof(buf)); 77 | assert(nr == 1); 78 | printf("read %.*s\n", (int)nr, buf); 79 | 80 | nr = shr_read(r, buf, sizeof(buf)); 81 | assert(nr == 1); 82 | printf("read %.*s\n", (int)nr, buf); 83 | 84 | nr = shr_read(r, buf, sizeof(buf)); 85 | assert(nr == 1); 86 | printf("read %.*s\n", (int)nr, buf); 87 | 88 | nr = shr_read(r, buf, sizeof(buf)); 89 | assert(nr == 1); 90 | printf("read %.*s\n", (int)nr, buf); 91 | 92 | nr = shr_read(r, buf, sizeof(buf)); 93 | assert(nr == 1); 94 | printf("read %.*s\n", (int)nr, buf); 95 | 96 | nr = shr_read(r, buf, sizeof(buf)); 97 | assert(nr == 1); 98 | printf("read %.*s\n", (int)nr, buf); 99 | 100 | 101 | done: 102 | if (s) shr_close(s); 103 | if (r) shr_close(r); 104 | unlink(ring); 105 | return rc; 106 | } 107 | 108 | -------------------------------------------------------------------------------- /util/.gitignore: -------------------------------------------------------------------------------- 1 | shr-tool 2 | -------------------------------------------------------------------------------- /util/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.11.4) 2 | set(CMAKE_CXX_STANDARD 11) 3 | 4 | # shr-tool utility 5 | add_executable(shr-tool shr-tool.c) 6 | target_link_libraries(shr-tool shr) 7 | 8 | # install utility 9 | install(TARGETS shr-tool) 10 | -------------------------------------------------------------------------------- /util/README.md: -------------------------------------------------------------------------------- 1 | Utilities for shr buffers 2 | 3 | * shr-tool: create, read/write data, view ring metrics 4 | --------------------------------------------------------------------------------