KineticStatus KineticAdminClient_UpdateFirmware(KineticSession * const session,
    char const * const fw_path)
{
    KINETIC_ASSERT(session != NULL);

    KineticOperation* operation = KineticAllocator_NewOperation(session);
    if (operation == NULL) {return KINETIC_STATUS_MEMORY_ERROR;}
    
    KineticStatus status = KineticBuilder_BuildUpdateFirmware(operation, fw_path);
    if (status != KINETIC_STATUS_SUCCESS) {
        return status;
    }
    
    return KineticController_ExecuteOperation(operation, NULL);
}
void test_KineticBuilder_BuildSetACL_should_build_a_SECURITY_operation(void)
{
    struct ACL ACLs = {
        .ACL_count = 1,
        .ACL_ceil = 1,
        .ACLs = NULL,
    };

    KineticOperation_ValidateOperation_Expect(&Operation);

    KineticBuilder_BuildSetACL(&Operation, &ACLs);

    TEST_ASSERT_EQUAL(COM__SEAGATE__KINETIC__PROTO__COMMAND__MESSAGE_TYPE__SECURITY,
        Request.message.command.header->messagetype);
    TEST_ASSERT_TRUE(Request.message.command.header->has_messagetype);
    TEST_ASSERT_EQUAL_PTR(&Request.message.body, Request.command->body);
    
    TEST_ASSERT_FALSE(Request.command->body->security->has_oldlockpin);
    TEST_ASSERT_FALSE(Request.command->body->security->has_newlockpin);
    TEST_ASSERT_FALSE(Request.command->body->security->has_olderasepin);
    TEST_ASSERT_FALSE(Request.command->body->security->has_newerasepin);

    TEST_ASSERT_EQUAL_PTR(Request.command->body->security->acl, ACLs.ACLs);

    TEST_ASSERT_EQUAL_PTR(&KineticCallbacks_SetACL, Operation.opCallback);
    TEST_ASSERT_NULL(Operation.response);
    TEST_ASSERT_EQUAL(KineticOperation_TimeoutSetACL, Operation.timeoutSeconds);
}

void test_KineticBuilder_BuildUpdateFirmware_should_build_a_FIRMWARE_DOWNLOAD_operation(void)
{
    const char* path = "test/support/data/dummy_fw.slod";
    const char* fwBytes = "firmware\nupdate\ncontents\n";
    int fwLen = strlen(fwBytes);

    KineticOperation_ValidateOperation_Expect(&Operation);

    KineticStatus status = KineticBuilder_BuildUpdateFirmware(&Operation, path);

    TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status);

    TEST_ASSERT_FALSE(Request.pinAuth);
    TEST_ASSERT_NOT_NULL(Operation.value.data);
    TEST_ASSERT_EQUAL(fwLen, Operation.value.len);
    TEST_ASSERT_NULL(Operation.response);
    TEST_ASSERT_EQUAL(0, Operation.timeoutSeconds);
    TEST_ASSERT_TRUE(Request.message.command.header->has_messagetype);
    TEST_ASSERT_EQUAL(COM__SEAGATE__KINETIC__PROTO__COMMAND__MESSAGE_TYPE__SETUP,
        Request.message.command.header->messagetype);
    TEST_ASSERT_EQUAL_PTR(&Request.message.body, Request.command->body);

    TEST_ASSERT_EQUAL_PTR(&Request.message.setup, Request.command->body->setup);
    TEST_ASSERT_TRUE(Request.message.setup.firmwaredownload);
    TEST_ASSERT_TRUE(Request.message.setup.has_firmwaredownload);
    TEST_ASSERT_EQUAL_PTR(&KineticCallbacks_UpdateFirmware, Operation.opCallback);

    TEST_ASSERT_NOT_NULL(Operation.value.data);
    TEST_ASSERT_EQUAL(fwLen, Operation.value.len);
    TEST_ASSERT_EQUAL_STRING(fwBytes, (char*)Operation.value.data);
}

void test_KineticBuilder_BuildUpdateFirmware_should_return_INVALID_FILE_if_does_not_exist(void)
{
    const char* path = "test/support/data/none.slod";

    KineticOperation_ValidateOperation_Expect(&Operation);

    KineticStatus status = KineticBuilder_BuildUpdateFirmware(&Operation, path);

    TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_INVALID_FILE, status);
}