blob: 992b706cb58a45e7fe7154b249fa9c1b38169cbe [file] [log] [blame]
#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include "cmockery.h"
#include "c.h"
#include "postgres.h"
#include "utils/memutils.h"
#include "../syslogger.c"
#define MOCK_PIPE_CHUNK_PAYLOAD_SIZE 16
static char alphabets[26] = "abcdefghijklmnopqrstuvwxyz";
static char mock_content[MOCK_PIPE_CHUNK_PAYLOAD_SIZE];
extern void __wrap_syslogger_log_chunk_data(PipeProtoHeader* p, char *data, int len);
void __wrap_syslogger_log_chunk_data(PipeProtoHeader* p, char *data, int len)
{
check_expected(data);
mock();
}
static void mock_chunk(PipeProtoChunk* p, int dest)
{
p->hdr.zero = 0;
p->hdr.thid = mythread();
p->hdr.main_thid = mainthread();
p->hdr.chunk_no = 0;
p->hdr.log_format = (dest == LOG_DESTINATION_CSVLOG ? 'c' : 't');
p->hdr.is_segv_msg = 'f';
p->hdr.next = -1;
p->hdr.is_last = 'f';
p->hdr.len = MOCK_PIPE_CHUNK_PAYLOAD_SIZE;
p->hdr.pid = 10000;
}
static int
interleave_chunks_to_buffer(char* logbuffer, int pids, int chunks, int dest)
{
Assert(chunks > 0);
int total = 0;
PipeProtoChunk p;
mock_chunk(&p, LOG_DESTINATION_CSVLOG);
/* interleaved write non-last chunks */
for (int c = 0; c < chunks - 1; c++)
{
for (int i = 0; i < pids; i++)
{
p.hdr.pid = i + 10000;
memset(&mock_content, alphabets[i], MOCK_PIPE_CHUNK_PAYLOAD_SIZE);
memcpy(p.data, mock_content, MOCK_PIPE_CHUNK_PAYLOAD_SIZE);
memcpy(logbuffer, &p, PIPE_HEADER_UNALIGNED_SIZE + MOCK_PIPE_CHUNK_PAYLOAD_SIZE);
logbuffer += PIPE_HEADER_UNALIGNED_SIZE + MOCK_PIPE_CHUNK_PAYLOAD_SIZE;
total += PIPE_HEADER_UNALIGNED_SIZE + MOCK_PIPE_CHUNK_PAYLOAD_SIZE;
++p.hdr.chunk_no;
}
}
/* interleaved write last chunks */
p.hdr.is_last = 't';
for (int i = 0; i < pids; i++)
{
p.hdr.pid = i + 10000;
memset(&mock_content, alphabets[i], MOCK_PIPE_CHUNK_PAYLOAD_SIZE);
memcpy(p.data, mock_content, MOCK_PIPE_CHUNK_PAYLOAD_SIZE);
memcpy(logbuffer, &p, PIPE_HEADER_UNALIGNED_SIZE + MOCK_PIPE_CHUNK_PAYLOAD_SIZE);
logbuffer += PIPE_HEADER_UNALIGNED_SIZE + MOCK_PIPE_CHUNK_PAYLOAD_SIZE;
total += PIPE_HEADER_UNALIGNED_SIZE + MOCK_PIPE_CHUNK_PAYLOAD_SIZE;
}
return total;
}
static int
thirdparty_chunks_to_buffer(char* logbuffer, int dest)
{
int total = 0;
/* mock 3rd party message before protocol chunk */
char tmp1[100] = "testing_3rd_log_before_protocol_chunk";
strcpy(logbuffer, tmp1);
logbuffer += strlen(tmp1);
total += strlen(tmp1);
/* mock protocol chunk */
PipeProtoChunk p;
mock_chunk(&p, LOG_DESTINATION_CSVLOG);
p.hdr.is_last = 't';
memset(&mock_content, 'a', MOCK_PIPE_CHUNK_PAYLOAD_SIZE);
memcpy(p.data, mock_content, MOCK_PIPE_CHUNK_PAYLOAD_SIZE);
memcpy(logbuffer, &p, PIPE_HEADER_UNALIGNED_SIZE + MOCK_PIPE_CHUNK_PAYLOAD_SIZE);
logbuffer += PIPE_HEADER_UNALIGNED_SIZE + MOCK_PIPE_CHUNK_PAYLOAD_SIZE;
total += PIPE_HEADER_UNALIGNED_SIZE + MOCK_PIPE_CHUNK_PAYLOAD_SIZE;
/* actually '\0' is not needed. just helps us to mark string end and check the expect value. */
*(logbuffer++) = '\0';
total++;
/* mock 3rd party message after protocol chunk */
char tmp2[100] = "testing_3rd_log_after_protocol_chunk";
strcpy(logbuffer, tmp2);
logbuffer += strlen(tmp2);
total += strlen(tmp2);
/* another protocol chunk to force the third party message be flushed */
memset(&mock_content, 'b', MOCK_PIPE_CHUNK_PAYLOAD_SIZE);
memcpy(p.data, mock_content, MOCK_PIPE_CHUNK_PAYLOAD_SIZE);
memcpy(logbuffer, &p, PIPE_HEADER_UNALIGNED_SIZE + MOCK_PIPE_CHUNK_PAYLOAD_SIZE);
logbuffer += PIPE_HEADER_UNALIGNED_SIZE + MOCK_PIPE_CHUNK_PAYLOAD_SIZE;
total += PIPE_HEADER_UNALIGNED_SIZE + MOCK_PIPE_CHUNK_PAYLOAD_SIZE;
return total;
}
static void
test__process_pipe_input_third_party__ProcessPipeInputThirdParty(void **state)
{
char logbuffer[READ_BUF_SIZE];
memset(logbuffer, '\0', READ_BUF_SIZE);
int bytes_in_logbuffer = thirdparty_chunks_to_buffer(logbuffer, LOG_DESTINATION_CSVLOG);
expect_string(__wrap_syslogger_log_chunk_data, data, "aaaaaaaaaaaaaaaa");
will_be_called(__wrap_syslogger_log_chunk_data);
expect_string(__wrap_syslogger_log_chunk_data, data, "bbbbbbbbbbbbbbbb");
will_be_called(__wrap_syslogger_log_chunk_data);
process_pipe_input(logbuffer, &bytes_in_logbuffer);
}
static void
test__process_pipe_input_interleave__ProcessPipeInputInterleave(void **state)
{
char logbuffer[READ_BUF_SIZE];
memset(logbuffer, '\0', READ_BUF_SIZE);
#define PIDS 3
#define CHUNKS 5
int bytes_in_logbuffer = interleave_chunks_to_buffer(logbuffer, PIDS, CHUNKS, LOG_DESTINATION_CSVLOG);
char tmp[PIDS][CHUNKS * MOCK_PIPE_CHUNK_PAYLOAD_SIZE + 3];
memset(tmp, '\0', PIDS * (CHUNKS * MOCK_PIPE_CHUNK_PAYLOAD_SIZE + 3));
for (int i = 0; i < PIDS; i++)
{
memset(&tmp[i], alphabets[i], CHUNKS * MOCK_PIPE_CHUNK_PAYLOAD_SIZE);
expect_string(__wrap_syslogger_log_chunk_data, data, tmp[i]);
will_be_called(__wrap_syslogger_log_chunk_data);
}
process_pipe_input(logbuffer, &bytes_in_logbuffer);
}
int
main(int argc, char* argv[]) {
cmockery_parse_arguments(argc, argv);
const UnitTest tests[] = {
unit_test(test__process_pipe_input_third_party__ProcessPipeInputThirdParty),
unit_test(test__process_pipe_input_interleave__ProcessPipeInputInterleave)
};
MemoryContextInit();
return run_tests(tests);
}