3 #include <sys/socket.h>
8 #include "../logger/logger_internal.h"
9 #include "../logger/logger_privileges.h"
10 #include "../logger/log_storage.h"
11 #include "../logger/reader_pipe.h"
13 int bind_fd_create(const char *path, int type);
14 int listen_fd_create(const char *path, int permissions);
15 int systemd_sock_get(const char *path, int type);
16 int dev_log_sock_get(void);
17 int dev_log_sock_create(void);
18 int create_kmsg_writer(struct writer **writer, struct log_buffer *log_buffer);
19 int service_writer_kmsg(struct logger *server, struct writer *wr, struct epoll_event *event);
20 int create_syslog_writer(struct writer **writer, struct log_buffer *log_buffer);
21 int service_writer_syslog(struct logger *server, struct writer *wr, struct epoll_event *event);
22 int service_socket_dummy(struct logger *server, struct writer *wr, struct dlog_control_msg *msg);
23 int socket_initialize(struct sock_data *sock, struct log_buffer *buffer, service_socket_t service_socket, struct socket_config_data *data);
24 void dispatch_event_sock(struct logger *server, struct epoll_event *event, void *userdata);
25 void socket_close(struct sock_data *sock);
26 void reader_pipe_free(struct reader_pipe *reader);
27 int buffer_append(const dlogutil_entry_s *entry, struct log_buffer *b);
28 int print_out_logs(struct reader_pipe *reader, struct now_t time);
29 int service_reader_file(struct reader_logger *reader, struct now_t time);
30 void writer_close_fd(struct logger *server, struct writer *wr);
31 int add_buffer_reader(struct log_buffer *buffer, struct reader_pipe *reader);
32 void reader_notify_losing_log(const dlogutil_entry_s *le, void *reader_);
34 bool fail_dlog_group_server = false;
35 int __wrap_getgrnam_r(const char *name, struct group *grp,
36 char *buf, size_t buflen, struct group **result)
42 if (!strcmp(name, "root"))
45 if (!strcmp(name, "mmajewski2"))
48 if (!strcmp(name, DLOG_SERVER_GROUP) && !fail_dlog_group_server)
51 if (!strcmp(name, "lvoldemort")) {
52 errno = EIO; // TODO: Are we sure the function does this?
60 // Note: we don't fill in the entire struct for simplicity.
61 // This means we can completely ignore buf{,len}
67 int __wrap_getpwnam_r(const char *name, struct passwd *pwd,
68 char *buf, size_t buflen, struct passwd **result)
74 if (!strcmp(name, "root"))
77 if (!strcmp(name, "mmajewski2"))
80 if (!strcmp(name, DLOG_SERVER_USER) && !fail_dlog_group_server)
83 if (!strcmp(name, "lvoldemort")) {
84 errno = EIO; // TODO: Are we sure the function does this?
98 gid_t getegid_return = 0;
99 gid_t __wrap_getegid(void)
101 return getegid_return;
104 uid_t geteuid_return = 0;
105 uid_t __wrap_geteuid(void)
107 return geteuid_return;
110 gid_t setgid_correct = 0;
111 int setgid_errno = 0;
112 bool setgid_called = false;
113 int __wrap_setgid(gid_t gid)
115 assert(gid == setgid_correct);
117 if (setgid_errno != 0) {
118 errno = setgid_errno;
121 setgid_called = true;
125 uid_t setuid_correct = 0;
126 int setuid_errno = 0;
127 bool setuid_called = false;
128 int __wrap_setuid(uid_t uid)
130 assert(uid == setuid_correct);
132 if (setuid_errno != 0) {
133 errno = setuid_errno;
136 setuid_called = true;
140 int socket_type_correct = 0;
141 int socket_errno = 0;
142 int socket_last_sock = 0;
143 int __wrap_socket(int domain, int type, int protocol)
145 assert(domain == AF_UNIX);
146 assert(type == socket_type_correct);
147 assert(protocol == 0);
149 if (socket_errno != 0) {
150 errno = socket_errno;
153 return ++socket_last_sock;
156 bool unlink_called_correct = false;
157 bool unlink_called_dev_link = false;
158 int __wrap_unlink(const char *pathname)
160 if (!strcmp("/sbin/init", pathname))
161 unlink_called_correct = true;
162 else if (!strcmp("/dev/log", pathname))
163 unlink_called_dev_link = true;
164 else if (!strcmp("/run/dlog/dev-log", pathname))
165 ; // TODO: Maybe we should check for that?
168 return 0; // None of the tested functions actually care what is returned here
172 bool bind_called_correct = false;
173 bool bind_called_dev = false;
174 int __wrap_bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
176 assert(sockfd == socket_last_sock);
177 assert(addrlen == sizeof(struct sockaddr_un));
179 const struct sockaddr_un *addr_un = (const struct sockaddr_un *)addr;
180 assert(addr_un->sun_family == AF_UNIX);
183 if (!strcmp("/sbin/init", addr_un->sun_path))
184 called = &bind_called_correct;
185 else if (!strcmp("/run/dlog/dev-log", addr_un->sun_path))
186 called = &bind_called_dev;
190 if (bind_errno != 0) {
200 int __wrap_close(int fd)
202 if (fd <= 0 || fd > MAX_FD || closed[fd - 1])
204 closed[fd - 1] = true;
208 mode_t chmod_correct_mode = 0;
210 bool chmod_called = false;
211 int __wrap_chmod(const char *pathname, mode_t mode)
214 assert(!strcmp(pathname, "/sbin/init"));
215 assert(mode == chmod_correct_mode);
217 if (chmod_errno != 0) {
225 int listen_correct_sockfd = 0;
226 int listen_errno = 0;
227 bool listen_called = false;
228 int __wrap_listen(int sockfd, int backlog)
230 assert(sockfd == listen_correct_sockfd);
232 if (listen_errno != 0) {
233 errno = listen_errno;
236 listen_called = true;
240 long __wrap_sysconf(int name)
245 bool sd_fail = false;
246 int __wrap_sd_listen_fds(int unset_environment)
248 return sd_fail ? -EIO : 2;
250 int __wrap_sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length)
252 assert(listening < 0);
256 return type == SOCK_STREAM && !strcmp(path, "/boot/vmlinuz");
258 return type == SOCK_DGRAM && !strcmp(path, "/run/dlog/dev-log");
264 int symlink_errno = 0;
265 bool symlink_called = false;
266 int __wrap_symlink(const char *target, const char *linkpath)
268 assert(!strcmp(target, "/run/dlog/dev-log"));
269 assert(!strcmp(linkpath, "/dev/log"));
271 if (symlink_errno != 0) {
272 errno = symlink_errno;
275 symlink_called = true;
279 bool calloc_fail = false;
280 void *__real_calloc(size_t nmemb, size_t size);
281 void *__wrap_calloc(size_t nmemb, size_t size)
283 return calloc_fail ? NULL : __real_calloc(nmemb, size);
287 int __real_open(const char *pathname, int flags, mode_t mode);
288 int __wrap_open(const char *pathname, int flags, mode_t mode)
290 // This is needed, because one day, we might want to open
291 // /home/abuild/rpmbuild/BUILD/dlog-5.5.1/src/shared/src_tests_logger-log_file.gcda...
292 if (strcmp(pathname, "/dev/kmsg"))
293 return __real_open(pathname, flags, mode);
295 assert(flags == (O_RDONLY | O_NONBLOCK));
297 if (open_errno != 0) {
304 int __wrap_open64(const char *pathname, int flags, mode_t mode)
306 return __wrap_open(pathname, flags, mode);
309 int fcntl_correct = 0;
311 int __real_fcntl(int fd, int cmd, ...);
312 int __wrap_fcntl(int fd, int cmd, ...)
314 // We allow fcntl_correct == 0 for the same reason as in __wrap_open
315 if (fcntl_correct == 0 && (cmd == F_SETLKW || cmd == F_SETLKW64)) {
318 struct flock *flock = va_arg(args, struct flock *);
320 return __real_fcntl(fd, cmd, flock);
323 assert(fd == fcntl_correct);
325 if (fcntl_errno != 0) {
332 return O_APPEND | O_NOATIME;
336 assert(va_arg(args, int) == (O_APPEND | O_NOATIME | O_NONBLOCK));
344 int __wrap_fcntl64(int fd, int cmd, ...)
346 if (cmd == F_SETFL) {
349 assert(va_arg(args, int) == (O_APPEND | O_NOATIME | O_NONBLOCK));
352 } else if ((cmd == F_SETLKW || cmd == F_SETLKW64) && fcntl_correct != 0) {
355 struct flock *flock = va_arg(args, struct flock *);
357 return __real_fcntl(fd, cmd, flock);
359 return __wrap_fcntl(fd, cmd);
363 uint64_t __wrap_log_storage_reader_get_ready_bytes(const log_storage_reader *reader)
365 return (intptr_t)reader; // We can't cast to uint64_t directly -- it fails on 32-bit
368 void *last_free = NULL;
369 void __real_free(void *ptr);
370 void __wrap_free(void *ptr)
376 int last_logfile_free_fd = 0;
377 void __wrap_logfile_free(struct log_file *l_file)
379 last_logfile_free_fd = l_file->fd;
382 bool add_new_entry_result = true;
383 bool __wrap_log_storage_add_new_entry(log_storage *storage, const dlogutil_entry_s *le)
385 assert(storage == (log_storage *)570);
386 assert(le == (dlogutil_entry_s *)0xE);
387 return add_new_entry_result;
390 bool reader_released = false;
391 void __wrap_log_storage_release_reader(log_storage_reader *reader)
393 assert(reader == (log_storage_reader *)13);
394 reader_released = true;
397 int epoll_ctl_epfd_correct_common = 0;
398 int epoll_ctl_epfd_correct_socket = 0;
399 int epoll_ctl_op_correct = 0;
400 int epoll_ctl_fd_correct = 0;
401 uint32_t epoll_ctl_events_correct = 0;
402 void *epoll_ctl_data_correct = NULL;
403 int epoll_ctl_errno = 0;
404 int __wrap_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
407 assert(epfd == epoll_ctl_epfd_correct_common || epoll_ctl_epfd_correct_socket == epfd);
408 assert(op == epoll_ctl_op_correct);
409 assert(fd == epoll_ctl_fd_correct);
410 if (op == EPOLL_CTL_DEL)
413 assert(event->events == epoll_ctl_events_correct);
414 assert(event->data.ptr == epoll_ctl_data_correct);
417 if (epoll_ctl_errno != 0) {
418 errno = epoll_ctl_errno;
424 struct log_storage *new_reader_storage_correct = NULL;
425 struct reader_pipe *new_reader_reader_correct = NULL;
426 bool new_reader_fail = false;
427 log_storage_reader *__wrap_log_storage_new_reader(log_storage *storage,
428 bool dumping, bool monitor, log_storage_reader_callback callback, void *user_data)
430 assert(storage == new_reader_storage_correct);
431 assert(user_data == new_reader_reader_correct);
432 assert(dumping == new_reader_reader_correct->is_dumping);
433 assert(callback == reader_notify_losing_log);
435 return new_reader_fail ? NULL : (log_storage_reader *)0x600D;
440 assert(parse_permissions(NULL) == (S_IWUSR | S_IWGRP | S_IWOTH));
441 assert(parse_permissions("All the permissions") == 0);
442 assert(parse_permissions("6789") == 0);
443 assert(parse_permissions("0001o") == 0);
445 assert(parse_permissions("0000") == 0);
446 assert(parse_permissions("0001") == S_IXOTH);
447 assert(parse_permissions("0002") == S_IWOTH);
448 assert(parse_permissions("0004") == S_IROTH);
449 assert(parse_permissions("0010") == S_IXGRP);
450 assert(parse_permissions("0020") == S_IWGRP);
451 assert(parse_permissions("0040") == S_IRGRP);
452 assert(parse_permissions("0100") == S_IXUSR);
453 assert(parse_permissions("0200") == S_IWUSR);
454 assert(parse_permissions("0400") == S_IRUSR);
455 assert(parse_permissions("1000") == S_ISVTX);
456 assert(parse_permissions("2000") == S_ISGID);
457 assert(parse_permissions("4000") == S_ISUID);
459 assert(parse_permissions("1234") == (S_ISVTX | S_IWUSR | S_IXGRP | S_IWGRP | S_IROTH));
460 assert(parse_permissions("1") == S_IXOTH);
461 assert(parse_permissions("70001") == S_IXOTH);
466 assert(usergr2id("root", "root", &uid, &gid) == 0);
470 assert(usergr2id("mmajewski2", "mmajewski2", &uid, &gid) == 0);
474 assert(usergr2id("mmajewski2", "root", &uid, &gid) == 0);
478 assert(usergr2id("root", "mmajewski2", &uid, &gid) == 0);
482 assert(usergr2id(DLOG_SERVER_USER, DLOG_SERVER_GROUP, &uid, &gid) == 0);
486 assert(usergr2id("mmajewski2", "lvoldemort", &uid, &gid) == -EIO);
487 assert(usergr2id("lvoldemort", "mmajewski2", &uid, &gid) == -EIO);
489 assert(usergr2id("root", "unexistent", &uid, &gid) == -ENOENT);
490 assert(usergr2id("unexistent", "root", &uid, &gid) == -ENOENT);
492 fail_dlog_group_server = true;
493 assert(reset_self_privileges() == -ENOENT);
494 fail_dlog_group_server = false;
498 assert(reset_self_privileges() == 0);
500 getegid_return = geteuid_return = 0;
502 setgid_errno = EINVAL;
503 assert(reset_self_privileges() == -EINVAL);
506 setgid_called = false;
508 setuid_errno = EINVAL;
509 assert(reset_self_privileges() == -EINVAL);
510 assert(setgid_called);
513 setgid_called = setuid_called = false;
514 assert(reset_self_privileges() == 0);
515 assert(setgid_called);
516 assert(setuid_called);
518 socket_type_correct = SOCK_STREAM;
519 socket_errno = ENFILE;
520 assert(bind_fd_create("/sbin/init", SOCK_STREAM) == -ENFILE);
522 socket_type_correct = SOCK_DGRAM;
523 assert(bind_fd_create("/sbin/init", SOCK_DGRAM) == -ENFILE);
527 unlink_called_correct = false;
528 assert(bind_fd_create("/sbin/init", SOCK_DGRAM) == -EINVAL);
529 assert(unlink_called_correct);
533 unlink_called_correct = bind_called_correct = false;
534 assert(bind_fd_create("/sbin/init", SOCK_DGRAM) == 2);
535 assert(unlink_called_correct);
536 assert(bind_called_correct);
539 socket_type_correct = SOCK_STREAM;
540 socket_errno = EACCES;
541 assert(listen_fd_create("/sbin/init", 0) == -EACCES);
544 chmod_correct_mode = S_IWOTH;
546 assert(listen_fd_create("/sbin/init", chmod_correct_mode) == -EIO);
549 listen_correct_sockfd = 4;
550 listen_errno = EADDRINUSE;
551 assert(listen_fd_create("/sbin/init", 0) == -EADDRINUSE);
555 listen_correct_sockfd = 5;
556 listen_called = false;
557 assert(listen_fd_create("/sbin/init", 0) == 5);
558 assert(listen_called);
561 listen_correct_sockfd = 6;
562 listen_called = chmod_called = false;
564 assert(listen_fd_create("/sbin/init", chmod_correct_mode) == 6);
565 assert(listen_called);
566 assert(chmod_called);
570 assert(systemd_sock_get("/root", SOCK_DGRAM) == -1);
571 assert(systemd_sock_get("/boot/vmlinuz", SOCK_STREAM) == -1);
572 assert(systemd_sock_get("/run/dlog/dev-log", SOCK_DGRAM) == -1);
573 assert(dev_log_sock_get() == -1);
576 assert(systemd_sock_get("/root", SOCK_DGRAM) == -1);
577 assert(systemd_sock_get("/boot/vmlinuz", SOCK_DGRAM) == -1);
578 assert(systemd_sock_get("/boot/vmlinuz", SOCK_STREAM) == 3);
579 assert(systemd_sock_get("/run/dlog/dev-log", SOCK_DGRAM) == 4);
580 assert(systemd_sock_get("/run/dlog/dev-log", SOCK_STREAM) == -1);
581 assert(dev_log_sock_get() == 4);
583 socket_type_correct = SOCK_DGRAM;
585 unlink_called_dev_link = false;
586 assert(dev_log_sock_create() == -EIO);
587 assert(!unlink_called_dev_link);
591 symlink_errno = ENOSPC;
592 unlink_called_dev_link = false;
593 assert(dev_log_sock_create() == -ENOSPC);
594 assert(unlink_called_dev_link);
598 unlink_called_dev_link = false;
599 assert(dev_log_sock_create() == 9);
600 assert(unlink_called_dev_link);
603 struct fd_entity ent;
604 init_fd_entity(&ent, (dispatch_event_t)0xD159A7C8, (void *)0xDA7A);
605 assert(ent.dispatch_event == (dispatch_event_t)0xD159A7C8);
606 assert(ent.dispatch_data == (void *)0xDA7A);
607 assert(ent.event.data.ptr == &ent);
608 assert(ent.event.events == 0);
609 assert(ent.fd == -1);
611 set_read_fd_entity(&ent, 1);
612 assert(ent.event.events == EPOLLIN);
615 set_write_fd_entity(&ent, 2);
616 assert(ent.event.events == EPOLLHUP);
619 struct logger logger = {
630 epoll_ctl_epfd_correct_common = 102;
631 epoll_ctl_op_correct = EPOLL_CTL_ADD;
632 epoll_ctl_fd_correct = 2;
633 epoll_ctl_events_correct = EPOLLHUP;
634 epoll_ctl_data_correct = &ent;
635 epoll_ctl_errno = ELOOP;
636 assert(add_fd_entity(&logger.epoll_common, &ent) == -ELOOP);
637 assert(logger.epoll_common.cnt == 0);
640 assert(add_fd_entity(&logger.epoll_common, &ent) == 0);
641 assert(logger.epoll_common.cnt == 1);
643 // TODO: I have no idea why this is checked here, but let's roll with it.
645 assert(modify_fd_entity(&logger.epoll_common, &ent, EPOLLMSG) == -EINVAL);
646 assert(ent.event.events == EPOLLHUP);
649 epoll_ctl_op_correct = EPOLL_CTL_MOD;
650 epoll_ctl_events_correct = EPOLLMSG;
651 epoll_ctl_errno = ENOENT;
652 assert(modify_fd_entity(&logger.epoll_common, &ent, EPOLLMSG) == -ENOENT);
653 assert(ent.event.events == EPOLLHUP);
656 assert(modify_fd_entity(&logger.epoll_common, &ent, EPOLLMSG) == 0);
657 assert(ent.event.events == EPOLLMSG);
659 epoll_ctl_errno = EBADF;
660 assert(modify_fd_entity(&logger.epoll_common, &ent, EPOLLMSG) == 0);
661 assert(ent.event.events == EPOLLMSG);
663 epoll_ctl_op_correct = EPOLL_CTL_DEL;
664 epoll_ctl_errno = EPERM;
665 assert(remove_fd_entity(&logger.epoll_common, &ent) == -EPERM);
666 assert(logger.epoll_common.cnt == 1);
669 assert(remove_fd_entity(&logger.epoll_common, &ent) == 0);
670 assert(logger.epoll_common.cnt == 0);
672 epoll_ctl_epfd_correct_socket = 201;
674 struct writer *writer;
676 assert(writer_create(&writer, 3, (struct log_buffer *)0xBU, (service_writer_t)17, (service_socket_t)18) == -ENOMEM);
680 assert(writer_create(&writer, 3, (struct log_buffer *)0xBU, (service_writer_t)17, (service_socket_t)18) == 0);
681 assert(writer->fd_entity.dispatch_event == dispatch_event_writer);
682 assert(writer->fd_entity.dispatch_data == writer);
683 assert(writer->fd_entity.event.data.ptr == &writer->fd_entity);
684 assert(writer->fd_entity.event.events == EPOLLIN);
685 assert(writer->fd_entity.fd == 3);
686 assert(writer->buf_ptr == (struct log_buffer *)0xBU);
687 assert(writer->readed == 0);
688 assert(writer->service_writer == (service_writer_t)17);
689 assert(writer->service_socket == (service_socket_t)18);
692 logger.epoll_common.cnt = 1;
693 logger.epoll_socket.cnt = 1;
694 epoll_ctl_op_correct = EPOLL_CTL_DEL;
695 epoll_ctl_fd_correct = 3;
696 writer_close_fd(&logger, writer);
698 assert(logger.epoll_common.cnt == 0);
699 // TODO: Check if epoll_ctl called
702 assert(create_kmsg_writer(&writer, (struct log_buffer *)0x2BU) == -ENOENT);
706 assert(create_kmsg_writer(&writer, (struct log_buffer *)0x2BU) == -ENOMEM);
711 assert(create_kmsg_writer(&writer, (struct log_buffer *)0x2BU) == 0);
712 assert(writer->fd_entity.dispatch_event == dispatch_event_writer);
713 assert(writer->fd_entity.dispatch_data == writer);
714 assert(writer->fd_entity.event.data.ptr == &writer->fd_entity);
715 assert(writer->fd_entity.event.events == EPOLLIN);
716 assert(writer->fd_entity.fd == 37);
717 assert(writer->buf_ptr == (struct log_buffer *)0x2BU);
718 assert(writer->readed == 0);
719 assert(writer->service_writer == service_writer_kmsg);
720 assert(writer->service_socket == service_socket_dummy);
726 assert(create_syslog_writer(&writer, (struct log_buffer *)0x3BU) == -EFAULT);
732 assert(create_syslog_writer(&writer, (struct log_buffer *)0x3BU) == -EIO);
739 assert(create_syslog_writer(&writer, (struct log_buffer *)0x3BU) == -EIO);
745 assert(create_syslog_writer(&writer, (struct log_buffer *)0x3BU) == -ENOMEM);
750 assert(create_syslog_writer(&writer, (struct log_buffer *)0x3BU) == 0);
751 assert(writer->fd_entity.dispatch_event == dispatch_event_writer);
752 assert(writer->fd_entity.dispatch_data == writer);
753 assert(writer->fd_entity.event.data.ptr == &writer->fd_entity);
754 assert(writer->fd_entity.event.events == EPOLLIN);
755 assert(writer->fd_entity.fd == 4);
756 assert(writer->buf_ptr == (struct log_buffer *)0x3BU);
757 assert(writer->readed == 0);
758 assert(writer->service_writer == service_writer_syslog);
759 assert(writer->service_socket == service_socket_dummy);
764 struct sock_data sock;
765 struct socket_config_data data;
766 memcpy(data.path, "/sbin/init", sizeof "/sbin/init");
767 data.permissions = S_IWUSR;
768 socket_type_correct = SOCK_STREAM;
769 socket_errno = ENOBUFS;
770 assert(socket_initialize(&sock, (struct log_buffer *)0x4BU, (service_socket_t)0x5E, &data) == -ENOBUFS);
773 listen_correct_sockfd = 12;
774 chmod_correct_mode = S_IWUSR;
776 assert(socket_initialize(&sock, (struct log_buffer *)0x4BU, (service_socket_t)0x5E, &data) == 0);
778 assert(sock.fd_entity.dispatch_event == dispatch_event_sock);
779 assert(sock.fd_entity.dispatch_data == &sock);
780 assert(sock.fd_entity.event.data.ptr == &sock.fd_entity);
781 assert(sock.fd_entity.event.events == EPOLLIN);
782 assert(sock.fd_entity.fd == 12);
783 assert(sock.buf_ptr == (struct log_buffer *)0x4BU);
784 assert(sock.service_socket == (service_socket_t)0x5E);
789 sock.fd_entity.fd = 0;
792 struct reader_pipe *reader = calloc(1, sizeof(*reader));
795 reader_pipe_free(reader);
796 assert(last_free == reader && last_logfile_free_fd == 1);
798 reader = calloc(1, sizeof(*reader));
801 reader->common.fd_entity_sink = ent;
802 assert(reader->common.fd_entity_sink.fd == 2);
803 reader->common.fd_entity_source.fd = 1;
804 reader->log_storage_reader_ptr = (log_storage_reader *)13;
805 closed[0] = closed[1] = false;
806 reader_pipe_free(reader);
807 assert(last_free == reader && last_logfile_free_fd == 3);
808 assert(closed[0] && closed[1]);
809 assert(reader_released);
811 struct log_buffer adder = {
812 .log_storage_ptr = (log_storage *)570,
815 add_new_entry_result = false;
816 assert(buffer_append((dlogutil_entry_s *)0xE, &adder) == -ENOMEM);
818 add_new_entry_result = true;
819 assert(buffer_append((dlogutil_entry_s *)0xE, &adder) == 0);
821 struct log_buffer buffer = {
822 .log_storage_ptr = (struct log_storage *)570,
824 struct reader_pipe reader4;
826 new_reader_storage_correct = buffer.log_storage_ptr;
827 new_reader_reader_correct = &reader4;
828 new_reader_fail = true;
829 assert(add_buffer_reader(&buffer, &reader4) == -ENOMEM);
831 new_reader_fail = false;
832 assert(add_buffer_reader(&buffer, &reader4) == 0);
833 assert(reader4.log_storage_reader_ptr == (struct log_storage_reader *)0x600D);
834 assert(list_at(buffer.readers_pipe) == &reader4);