int init_iothread(/*out*/iothread_t* iothr) { int err; thread_t* old_thread = iothr->thread; thread_t* thread; // DESIGN-TASK::: // TODO: implement thread pool / one thread per io device ! // - move thread into thread pool // - remove old_thread and iothr->thread = 0 assignment ! after thread pool creation // - use iothread pool iothr->thread = 0; if (! PROCESS_testerrortimer(&s_iothread_errtimer, &err)) { err = newgeneric_thread(&thread, &ioop_worker_thread, iothr); } if (err) goto ONERR; // set out iothr->request_stop = 0; init_iolist(&iothr->iolist); write_atomicint(&iothr->thread, thread); // start worker resume_thread(thread); return 0; ONERR: iothr->thread = old_thread; TRACEEXIT_ERRLOG(err); return err; }
static int test_update(void) { logbuffer_t logbuf = logbuffer_FREE; thread_t * thread = 0; pipe_t pipe = pipe_FREE; uint8_t buffer[1024]; uint8_t readbuffer[1024+1]; // prepare TEST(0 == init_pipe(&pipe)); logbuf = (logbuffer_t) logbuffer_INIT(sizeof(buffer), buffer, pipe.write); // TEST truncate_logbuffer for (unsigned i = 0; i < 32; ++i) { logbuf.logsize = 32; logbuf.addr[i] = 'a'; truncate_logbuffer(&logbuf, i); TEST(logbuf.addr == buffer); TEST(logbuf.size == sizeof(buffer)); TEST(logbuf.io == pipe.write); TEST(logbuf.addr[i] == 0); TEST(logbuf.logsize == i); } // TEST truncate_logbuffer: parameter with bigger or equal size are ignored for (unsigned i = 0; i < 32; ++i) { logbuf.logsize = i; logbuf.addr[i] = 'a'; logbuf.addr[i+1] = 'a'; truncate_logbuffer(&logbuf, i+1); truncate_logbuffer(&logbuf, i); TEST(logbuf.addr == buffer); TEST(logbuf.size == sizeof(buffer)); TEST(logbuf.io == pipe.write); TEST(logbuf.addr[i] == 'a'); TEST(logbuf.addr[i+1] == 'a'); TEST(logbuf.logsize == i); } // TEST write_logbuffer memset(readbuffer, 0, sizeof(readbuffer)); for (unsigned i = 0; i < sizeof(buffer); ++i) { buffer[i] = (uint8_t)i; } logbuf.logsize = logbuf.size; // test TEST( 0 == write_logbuffer(&logbuf)); // check logbuf TEST( logbuf.addr == buffer); TEST( logbuf.size == sizeof(buffer)); TEST( logbuf.logsize == sizeof(buffer)); TEST( logbuf.io == pipe.write); // check content of pipe static_assert(sizeof(readbuffer) > sizeof(buffer), "check that only sizeof(buffer) are written"); TEST(sizeof(buffer) == read(pipe.read, readbuffer, sizeof(readbuffer))); for (unsigned i = 0; i < sizeof(buffer); ++i) { TEST(buffer[i] == readbuffer[i]); } // TEST printheader_logbuffer logbuf.logsize = 0; log_header_t header = log_header_INIT("test_update", "file", 123456); printheader_logbuffer(&logbuf, &header); TEST(0 == compare_header(logbuf.logsize, logbuf.addr, "test_update", "file", 123456)); for (size_t len = logbuf.logsize, i = 1; i < 10; ++i) { printheader_logbuffer(&logbuf, &header); TEST((i+1)*len == logbuf.logsize); TEST(0 == compare_header(len, logbuf.addr + i*len, "test_update", "file", 123456)); } // TEST printheader_logbuffer: other thread TEST(0 == newgeneric_thread(&thread, &thread_printheader, &logbuf)); TEST(0 == join_thread(thread)); TEST(0 == returncode_thread(thread)); TEST(0 == delete_thread(&thread)); // TEST printheader_logbuffer: adds " ..." at end in case of truncated message logbuf.logsize = logbuf.size - 10; logbuf.addr[logbuf.logsize] = 0; printheader_logbuffer(&logbuf, &header); TEST(logbuf.logsize == logbuf.size - 1) TEST(0 == memcmp(logbuf.addr + logbuf.size - 10, "[", 1)); TEST(0 == memcmp(logbuf.addr + logbuf.size - 5, " ...", 5)); // TEST vprintf_logbuffer: append on already stored content for (unsigned i = 0; i < sizeof(buffer)-100; ++i) { memset(buffer, 0, sizeof(buffer)); memset(readbuffer, 0, sizeof(readbuffer)); logbuf.logsize = i; printf_logbuffer(&logbuf, "%d : %s : %c;;", i, "OK!", '0'); snprintf((char*)readbuffer + i, 100, "%d : %s : %c;;", i, "OK!", '0'); TEST(0 == memcmp(buffer, readbuffer, sizeof(buffer))); } // TEST vprintf_logbuffer: different formats logbuf.logsize = 0; printf_logbuffer(&logbuf, "%%%s%%", "str" ); printf_logbuffer(&logbuf, "%"PRIi8";", (int8_t)-1); printf_logbuffer(&logbuf, "%"PRIu8";", (uint8_t)1); printf_logbuffer(&logbuf, "%"PRIi16";", (int16_t)-256); printf_logbuffer(&logbuf, "%"PRIu16";", (uint16_t)256); printf_logbuffer(&logbuf, "%"PRIi32";", (int32_t)-65536); printf_logbuffer(&logbuf, "%"PRIu32";", (uint32_t)65536); printf_logbuffer(&logbuf, "%zd;", (ssize_t)-65536); printf_logbuffer(&logbuf, "%zu;", (size_t)65536); printf_logbuffer(&logbuf, "%g;", 2e100); printf_logbuffer(&logbuf, "%.0f;", (double)1234567); const char * result = "%str%-1;1;-256;256;-65536;65536;-65536;65536;2e+100;1234567;"; TEST(strlen(result) == logbuf.logsize); TEST(0 == memcmp(logbuf.addr, result, logbuf.logsize)); // TEST vprintf_logwriter: adds " ..." at end in case of truncated message char strtoobig[100]; memset(strtoobig, '1', sizeof(strtoobig)); logbuf.logsize = logbuf.size - sizeof(strtoobig); logbuf.addr[logbuf.logsize] = 0; printf_logbuffer(&logbuf, "%.100s", strtoobig); TEST(logbuf.logsize == logbuf.size - 1) TEST(0 == memcmp(logbuf.addr + logbuf.size - sizeof(strtoobig), strtoobig, sizeof(strtoobig)-5)); TEST(0 == memcmp(logbuf.addr + logbuf.size - 5, " ...", 5)); // TEST vprintf_logbuffer: format == 0 logbuf.logsize = 0; printf_logbuffer(&logbuf, 0); // nothing printed TEST(0 == logbuf.logsize); // TEST vprintf_logbuffer: sizefree_logbuffer() == 0 logbuf.logsize = logbuf.size; memset(logbuf.addr, 255, logbuf.size); printf_logbuffer(&logbuf, "%d", 12345); // check logbuf not changed TEST(buffer == logbuf.addr); TEST(sizeof(buffer) == logbuf.size); TEST(sizeof(buffer) == logbuf.logsize); TEST(pipe.write == logbuf.io); // check content of logbuf not changed except for " ..." for (size_t i = 0; i < logbuf.logsize - 5; ++i) { TEST(255 == logbuf.addr[i]); } TEST(0 == memcmp(logbuf.addr + logbuf.logsize - 5, " ...", 4)); TEST(255 == logbuf.addr[logbuf.logsize-1]); // TEST vprintf_logbuffer: logbuffer_t.size <= 5 for (size_t s = 5; s <= 5; --s) { TEST(sizeof(buffer) == logbuf.size); logbuf.size = s; logbuf.logsize = 0; memset(logbuf.addr, 255, s); printf_logbuffer(&logbuf, "%d", 12345); // check logbuf TEST(buffer == logbuf.addr); TEST(s == logbuf.size); TEST((s?s-1:0) == logbuf.logsize); TEST(pipe.write == logbuf.io); // check content of logbuf if (s == 5) { // " ..." TEST(0 == memcmp(logbuf.addr, " ...", 5)); } else { // truncated 12345 for (size_t i = 0; i < logbuf.logsize; ++i) { TEST(i+'1' == logbuf.addr[i]); } TEST(0 == (logbuf.size ? logbuf.addr[logbuf.size-1] : 0)); } // reset logbuf.size = sizeof(buffer); } // unprepare TEST(-1 == read(pipe.read, readbuffer, sizeof(readbuffer))); TEST(0 == free_pipe(&pipe)); return 0; ONERR: delete_thread(&thread); free_pipe(&pipe); return EINVAL; }