diff --git a/src/fsm.c b/src/fsm.c index ae13ca10b..6b2164637 100644 --- a/src/fsm.c +++ b/src/fsm.c @@ -315,7 +315,7 @@ static int fsm__apply(struct raft_fsm *fsm, int rc; rc = command__decode(buf, &type, &command); if (rc != 0) { - // errorf(f->logger, "fsm: decode command: %d", rc); + tracef("fsm: decode command: %d", rc); goto err; } @@ -334,17 +334,12 @@ static int fsm__apply(struct raft_fsm *fsm, break; default: rc = RAFT_MALFORMED; - goto err_after_command_decode; + break; } - raft_free(command); - - *result = NULL; - return 0; - -err_after_command_decode: raft_free(command); err: + *result = NULL; return rc; } diff --git a/test/integration/test_fsm.c b/test/integration/test_fsm.c index 85c2a3514..c088ffb21 100644 --- a/test/integration/test_fsm.c +++ b/test/integration/test_fsm.c @@ -1,4 +1,5 @@ #include "../../src/client.h" +#include "../../src/command.h" #include "../../src/server.h" #include "../lib/client.h" #include "../lib/heap.h" @@ -527,3 +528,68 @@ TEST(fsm, snapshotRestoreMultipleDBs, setUp, tearDown, 0, snapshot_params) return MUNIT_OK; } + +/****************************************************************************** + * + * apply + * + ******************************************************************************/ + +TEST(fsm, applyFail, setUp, tearDown, 0, NULL) +{ + int rv; + struct command_frames c; + struct raft_buffer buf; + struct fixture *f = data; + struct raft_fsm *fsm = &f->servers[0].dqlite->raft_fsm; + void* result = (void*)(uintptr_t)0xDEADBEEF; + + /* Create a frames command without data. */ + c.filename = "test"; + c.tx_id = 0; + c.truncate = 0; + c.is_commit = 0; + c.frames.n_pages = 0; + c.frames.page_size = 4096; + c.frames.data = NULL; + rv = command__encode(COMMAND_FRAMES, &c, &buf); + + /* Apply the command and expect it to fail. */ + rv = fsm->apply(fsm, &buf, &result); + munit_assert_int(rv, !=, 0); + munit_assert_ptr_null(result); + + raft_free(buf.base); + return MUNIT_OK; +} + +TEST(fsm, applyUnknownTypeFail, setUp, tearDown, 0, NULL) +{ + int rv; + struct command_frames c; + struct raft_buffer buf; + struct fixture *f = data; + struct raft_fsm *fsm = &f->servers[0].dqlite->raft_fsm; + void* result = (void*)(uintptr_t)0xDEADBEEF; + + /* Create a frames command without data. */ + c.filename = "test"; + c.tx_id = 0; + c.truncate = 0; + c.is_commit = 0; + c.frames.n_pages = 0; + c.frames.page_size = 4096; + c.frames.data = NULL; + rv = command__encode(COMMAND_FRAMES, &c, &buf); + + /* Command type does not exist. */ + ((uint8_t*)(buf.base))[1] = COMMAND_CHECKPOINT + 8; + + /* Apply the command and expect it to fail. */ + rv = fsm->apply(fsm, &buf, &result); + munit_assert_int(rv, ==, DQLITE_PROTO); + munit_assert_ptr_null(result); + + raft_free(buf.base); + return MUNIT_OK; +}