void test_KineticBuilder_BuildPut_should_build_and_execute_a_PUT_operation_to_create_a_new_object(void) { ByteArray value = ByteArray_CreateWithCString("Luke, I am your father"); ByteArray key = ByteArray_CreateWithCString("foobar"); ByteArray newVersion = ByteArray_CreateWithCString("v1.0"); ByteArray tag = ByteArray_CreateWithCString("some_tag"); KineticEntry entry = { .key = ByteBuffer_CreateWithArray(key), .newVersion = ByteBuffer_CreateWithArray(newVersion), .tag = ByteBuffer_CreateWithArray(tag), .algorithm = KINETIC_ALGORITHM_SHA1, .value = ByteBuffer_CreateWithArray(value), }; KineticOperation_ValidateOperation_Expect(&Operation); KineticMessage_ConfigureKeyValue_Expect(&Operation.request->message, &entry); // Build the operation KineticBuilder_BuildPut(&Operation, &entry); TEST_ASSERT_FALSE(Request.pinAuth); TEST_ASSERT_EQUAL_PTR(entry.value.array.data, Operation.value.data); TEST_ASSERT_EQUAL(entry.value.bytesUsed, Operation.value.len); TEST_ASSERT_TRUE(Request.message.command.header->has_messagetype); TEST_ASSERT_EQUAL(COM__SEAGATE__KINETIC__PROTO__COMMAND__MESSAGE_TYPE__PUT, Request.message.command.header->messagetype); TEST_ASSERT_EQUAL_ByteArray(value, Operation.entry->value.array); TEST_ASSERT_EQUAL(0, Operation.entry->value.bytesUsed); TEST_ASSERT_FALSE(Request.pinAuth); TEST_ASSERT_EQUAL(0, Operation.timeoutSeconds); TEST_ASSERT_NULL(Operation.response); }
void test_KineticClient_Delete_should_execute_DELETE_operation(void) { ByteArray key = ByteArray_CreateWithCString("some_key"); ByteArray tag = ByteArray_CreateWithCString("SomeTagValue"); KineticEntry entry = { .key = ByteBuffer_CreateWithArray(key), .tag = ByteBuffer_CreateWithArray(tag), }; KineticConnection_FromHandle_ExpectAndReturn(DummyHandle, &Connection); KineticAllocator_NewPDU_ExpectAndReturn(&Connection.pdus, &Request); KineticAllocator_NewPDU_ExpectAndReturn(&Connection.pdus, &Response); KineticPDU_Init_Expect(&Request, &Connection); KineticPDU_Init_Expect(&Response, &Connection); KineticConnection_IncrementSequence_Expect(&Connection); KineticMessage_ConfigureKeyValue_Expect(&Request.protoData.message, &entry); KineticPDU_Send_ExpectAndReturn(&Request, KINETIC_STATUS_SUCCESS); KineticPDU_Receive_ExpectAndReturn(&Response, KINETIC_STATUS_SUCCESS); KineticPDU_GetStatus_ExpectAndReturn(&Response, KINETIC_STATUS_SUCCESS); KineticAllocator_FreePDU_Expect(&Connection.pdus, &Request); KineticAllocator_FreePDU_Expect(&Connection.pdus, &Response); KineticStatus status = KineticClient_Delete(DummyHandle, &entry); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); }
int main(int argc, char** argv) { (void)argc; (void)argv; // Initialize kinetic-c and configure sessions KineticSession* session; KineticClientConfig clientConfig = { .logFile = "stdout", .logLevel = 1, }; KineticClient * client = KineticClient_Init(&clientConfig); if (client == NULL) { return 1; } const char HmacKeyString[] = "asdfasdf"; KineticSessionConfig sessionConfig = { .host = "localhost", .port = KINETIC_PORT, .clusterVersion = 0, .identity = 1, .hmacKey = ByteArray_CreateWithCString(HmacKeyString), }; KineticStatus status = KineticClient_CreateSession(&sessionConfig, client, &session); if (status != KINETIC_STATUS_SUCCESS) { fprintf(stderr, "Failed connecting to the Kinetic device w/status: %s\n", Kinetic_GetStatusDescription(status)); exit(1); } do_put_and_get(session); // Shutdown client connection and cleanup KineticClient_DestroySession(session); KineticClient_Shutdown(client); return 0; }
void test_KineticHMAC_Validate_should_return_false_if_the_HMAC_presence_is_false_for_the_supplied_message_and_key_is_incorrect(void) { KineticHMAC actual; Com__Seagate__Kinetic__Proto__Command__Status status = COM__SEAGATE__KINETIC__PROTO__COMMAND__STATUS__INIT; Com__Seagate__Kinetic__Proto__Command command = COM__SEAGATE__KINETIC__PROTO__COMMAND__INIT; status.code = COM__SEAGATE__KINETIC__PROTO__COMMAND__STATUS__STATUS_CODE__NO_SPACE; status.has_code = true; command.status = &status; Com__Seagate__Kinetic__Proto__Message proto = COM__SEAGATE__KINETIC__PROTO__MESSAGE__INIT; Com__Seagate__Kinetic__Proto__Message__HMACauth hmacAuth = COM__SEAGATE__KINETIC__PROTO__MESSAGE__HMACAUTH__INIT; uint8_t data[KINETIC_HMAC_MAX_LEN]; ProtobufCBinaryData hmac = {.len = KINETIC_HMAC_MAX_LEN, .data = data}; const ByteArray key = ByteArray_CreateWithCString("1234567890ABCDEFGHIJK"); proto.has_commandbytes = true; uint8_t packedCmd[128]; size_t packedLen = com__seagate__kinetic__proto__command__pack(&command, packedCmd); proto.commandbytes = (ProtobufCBinaryData){.data = packedCmd, .len = packedLen}; hmacAuth.identity = 7; hmacAuth.has_identity = true; hmacAuth.hmac = hmac; hmacAuth.has_hmac = true; proto.hmacauth = &hmacAuth; proto.authtype = COM__SEAGATE__KINETIC__PROTO__MESSAGE__AUTH_TYPE__HMACAUTH; proto.has_authtype = true; KineticHMAC_Init(&actual, COM__SEAGATE__KINETIC__PROTO__COMMAND__SECURITY__ACL__HMACALGORITHM__HmacSHA1); KineticHMAC_Populate(&actual, &proto, key); TEST_ASSERT_TRUE(KineticHMAC_Validate(&proto, key)); // Bork the HMAC hmacAuth.has_hmac = false; TEST_ASSERT_FALSE(KineticHMAC_Validate(&proto, key)); }
void test_ByteArray_CreateWithCString_should_create_ByteArray_using_C_string(void) { char* str = "some string"; size_t len = strlen(str); ByteArray array = ByteArray_CreateWithCString(str); TEST_ASSERT_EQUAL_PTR(str, array.data); TEST_ASSERT_EQUAL(len, array.len); TEST_ASSERT_EQUAL_HEX8_ARRAY(str, array.data, len); }
void setUp(void) { HMACKey = ByteArray_CreateWithCString("some_hmac_key"); KINETIC_CONNECTION_INIT(&Connection); Connection.connectionID = ConnectionID; KINETIC_PDU_INIT_WITH_MESSAGE(&Request, &Connection); KINETIC_PDU_INIT_WITH_MESSAGE(&Response, &Connection); KINETIC_OPERATION_INIT(&Operation, &Connection); Operation.request = &Request; Operation.response = &Response; }
void test_KineticBuilder_BuildPut_should_return_BUFFER_OVERRUN_if_object_value_too_long(void) { ByteArray value = ByteArray_CreateWithCString("Luke, I am your father"); ByteArray key = ByteArray_CreateWithCString("foobar"); ByteArray newVersion = ByteArray_CreateWithCString("v1.0"); ByteArray tag = ByteArray_CreateWithCString("some_tag"); KineticEntry entry = { .key = ByteBuffer_CreateWithArray(key), .newVersion = ByteBuffer_CreateWithArray(newVersion), .tag = ByteBuffer_CreateWithArray(tag), .algorithm = KINETIC_ALGORITHM_SHA1, .value = ByteBuffer_CreateWithArray(value), }; entry.value.bytesUsed = KINETIC_OBJ_SIZE + 1; KineticOperation_ValidateOperation_Expect(&Operation); // Build the operation KineticStatus status = KineticBuilder_BuildPut(&Operation, &entry); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_BUFFER_OVERRUN, status); }
void setUp(void) { KINETIC_CONNECTION_INIT(&Connection); Connection.connected = false; // Ensure gets set appropriately by internal connect call HmacKey = ByteArray_CreateWithCString("some hmac key"); KINETIC_SESSION_INIT(&Session, "somehost.com", ClusterVersion, Identity, HmacKey); KineticConnection_NewConnection_ExpectAndReturn(&Session, DummyHandle); KineticConnection_FromHandle_ExpectAndReturn(DummyHandle, &Connection); KineticConnection_Connect_ExpectAndReturn(&Connection, KINETIC_STATUS_SUCCESS); KineticStatus status = KineticClient_Connect(&Session, &SessionHandle); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); TEST_ASSERT_EQUAL(DummyHandle, SessionHandle); }
void test_KineticAdminClient_GetDeviceSpecificLog_should_request_the_specified_device_specific_log_data_from_the_device(void) { const char* nameData = "com.Seagate"; ByteArray name = ByteArray_CreateWithCString(nameData); KineticLogInfo* info; KineticOperation operation; KineticAllocator_NewOperation_ExpectAndReturn(&Session, &operation); KineticBuilder_BuildGetLog_ExpectAndReturn(&operation, COM__SEAGATE__KINETIC__PROTO__COMMAND__GET_LOG__TYPE__DEVICE, name, &info, KINETIC_STATUS_SUCCESS); KineticController_ExecuteOperation_ExpectAndReturn(&operation, NULL, KINETIC_STATUS_SUCCESS); KineticStatus status = KineticAdminClient_GetDeviceSpecificLog(&Session, name, &info, NULL); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); }
void test_KineticClient_Put_should_execute_PUT_operation(void) { ByteArray value = ByteArray_CreateWithCString("Four score, and seven years ago"); KineticEntry entry = {.value = ByteBuffer_CreateWithArray(value)}; KineticOperation operation; operation.session = &Session; KineticAllocator_NewOperation_ExpectAndReturn(&Session, &operation); KineticBuilder_BuildPut_ExpectAndReturn(&operation, &entry, KINETIC_STATUS_SUCCESS); KineticController_ExecuteOperation_ExpectAndReturn(&operation, NULL, KINETIC_STATUS_VERSION_MISMATCH); KineticStatus status = KineticClient_Put(&Session, &entry, NULL); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_VERSION_MISMATCH, status); }
static void ConnectSession(void) { KINETIC_CONNECTION_INIT(&Connection); Connection.connected = false; // Ensure gets set appropriately by internal connect call Connection.connectionID = 12374626536; // Fake connection ID to allow connection to complete for these tests HmacKey = ByteArray_CreateWithCString("some hmac key"); KINETIC_SESSION_INIT(&Session, "somehost.com", ClusterVersion, Identity, HmacKey); KineticConnection_NewConnection_ExpectAndReturn(&Session, DummyHandle); KineticConnection_FromHandle_ExpectAndReturn(DummyHandle, &Connection); KineticConnection_Connect_ExpectAndReturn(&Connection, KINETIC_STATUS_SUCCESS); // KineticConnection_ReceiveDeviceStatusMessage_ExpectAndReturn(&Connection, KINETIC_STATUS_SUCCESS); KineticStatus status = KineticClient_Connect(&Session, &SessionHandle); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); TEST_ASSERT_EQUAL(DummyHandle, SessionHandle); }
void setUp(void) { KineticLogger_Init("stdout", 3); // Create and configure a new Kinetic protocol instance ; Session = (KineticSession) { .connected = true, .socket = 456, .config = (KineticSessionConfig) { .port = 1234, .host = "valid-host.com", .hmacKey = ByteArray_CreateWithCString("some valid HMAC key..."), .clusterVersion = ClusterVersion, } }; ByteArray_FillWithDummyData(Value); }
void setUp(void) { KineticLogger_Init("stdout", 3); Session = (KineticSession) { .connected = true, .socket = 456, .config = (KineticSessionConfig) { .port = 1234, .host = "valid-host.com", .hmacKey = ByteArray_CreateWithCString("some valid HMAC key..."), .clusterVersion = ClusterVersion, } }; KineticRequest_Init(&Request, &Session); ByteArray_FillWithDummyData(Value); memset(si_buf, 0, SI_BUF_SIZE); }
void setUp(void) { // Create and configure a new Kinetic protocol instance Key = ByteArray_CreateWithCString("some valid HMAC key..."); Session = (KineticSession) { .nonBlocking = false, .port = 1234, .host = "valid-host.com", .hmacKey = (ByteArray) {.data = &Session.keyData[0], .len = Key.len}, }; memcpy(Session.hmacKey.data, Key.data, Key.len); KINETIC_CONNECTION_INIT(&Connection); Connection.connected = true; Connection.socket = 456; Connection.session = Session; KINETIC_PDU_INIT(&PDU, &Connection); ByteArray_FillWithDummyData(Value); KineticLogger_Init(NULL); }
void test_KineticHMAC_Populate_should_compute_and_populate_the_SHA1_HMAC_for_the_supplied_message_and_key(void) { KineticHMAC actual; Com__Seagate__Kinetic__Proto__Message msg = COM__SEAGATE__KINETIC__PROTO__MESSAGE__INIT; Com__Seagate__Kinetic__Proto__Message__HMACauth hmacAuth = COM__SEAGATE__KINETIC__PROTO__MESSAGE__HMACAUTH__INIT; uint8_t data[KINETIC_HMAC_MAX_LEN]; ProtobufCBinaryData hmac = {.len = KINETIC_HMAC_MAX_LEN, .data = data}; const ByteArray key = ByteArray_CreateWithCString("1234567890ABCDEFGHIJK"); uint8_t commandBytes[123]; ByteArray commandArray = ByteArray_Create(commandBytes, sizeof(commandBytes)); ByteArray_FillWithDummyData(commandArray); ProtobufCBinaryData dummyCommandData = {.data = commandArray.data, .len = commandArray.len}; msg.commandbytes = dummyCommandData; msg.has_commandbytes = true; msg.authtype = COM__SEAGATE__KINETIC__PROTO__MESSAGE__AUTH_TYPE__HMACAUTH; msg.has_authtype = true; hmacAuth.has_hmac = true; hmacAuth.hmac = hmac; msg.hmacauth = &hmacAuth; KineticHMAC_Init(&actual, COM__SEAGATE__KINETIC__PROTO__COMMAND__SECURITY__ACL__HMACALGORITHM__HmacSHA1); KineticHMAC_Populate(&actual, &msg, key); TEST_ASSERT_TRUE(msg.hmacauth->has_hmac); TEST_ASSERT_EQUAL_PTR(hmac.data, msg.hmacauth->hmac.data); TEST_ASSERT_EQUAL(KINETIC_HMAC_MAX_LEN, msg.hmacauth->hmac.len); LOG0("Computed HMAC: "); LOGF0(" %02hhX%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX", actual.data[0], actual.data[1], actual.data[2], actual.data[3], actual.data[4], actual.data[5], actual.data[6], actual.data[7]); LOGF0(" %02hhX%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX", actual.data[8], actual.data[9], actual.data[10], actual.data[11], actual.data[12], actual.data[13], actual.data[14], actual.data[15]); LOGF0(" %02hhX%02hhX%02hhX%02hhX", actual.data[16], actual.data[17], actual.data[18], actual.data[19]); } void test_KineticHMAC_Validate_should_return_true_if_the_HMAC_for_the_supplied_message_and_key_is_correct(void) { KineticHMAC actual; Com__Seagate__Kinetic__Proto__Command__Status status = COM__SEAGATE__KINETIC__PROTO__COMMAND__STATUS__INIT; Com__Seagate__Kinetic__Proto__Command command = COM__SEAGATE__KINETIC__PROTO__COMMAND__INIT; status.code = COM__SEAGATE__KINETIC__PROTO__COMMAND__STATUS__STATUS_CODE__NO_SPACE; status.has_code = true; command.status = &status; Com__Seagate__Kinetic__Proto__Message proto = COM__SEAGATE__KINETIC__PROTO__MESSAGE__INIT; Com__Seagate__Kinetic__Proto__Message__HMACauth hmacAuth = COM__SEAGATE__KINETIC__PROTO__MESSAGE__HMACAUTH__INIT; uint8_t data[KINETIC_HMAC_MAX_LEN]; ProtobufCBinaryData hmac = {.len = KINETIC_HMAC_MAX_LEN, .data = data}; const ByteArray key = ByteArray_CreateWithCString("1234567890ABCDEFGHIJK"); proto.has_commandbytes = true; uint8_t packedCmd[128]; size_t packedLen = com__seagate__kinetic__proto__command__pack(&command, packedCmd); proto.commandbytes = (ProtobufCBinaryData){.data = packedCmd, .len = packedLen}; hmacAuth.identity = 7; hmacAuth.has_identity = true; hmacAuth.hmac = hmac; hmacAuth.has_hmac = true; proto.hmacauth = &hmacAuth; proto.authtype = COM__SEAGATE__KINETIC__PROTO__MESSAGE__AUTH_TYPE__HMACAUTH; proto.has_authtype = true; KineticHMAC_Init(&actual, COM__SEAGATE__KINETIC__PROTO__COMMAND__SECURITY__ACL__HMACALGORITHM__HmacSHA1); KineticHMAC_Populate(&actual, &proto, key); TEST_ASSERT_TRUE(KineticHMAC_Validate(&proto, key)); }
int main(int argc, char** argv) { (void)argc; (void)argv; // Initialize kinetic-c and configure sessions KineticSession* session; KineticClientConfig clientConfig = { .logFile = "stdout", .logLevel = 1, }; KineticClient * client = KineticClient_Init(&clientConfig); if (client == NULL) { return 1; } const char HmacKeyString[] = "asdfasdf"; KineticSessionConfig sessionConfig = { .host = "localhost", .port = KINETIC_PORT, .clusterVersion = 0, .identity = 1, .hmacKey = ByteArray_CreateWithCString(HmacKeyString), }; KineticStatus status = KineticClient_CreateSession(&sessionConfig, client, &session); if (status != KINETIC_STATUS_SUCCESS) { fprintf(stderr, "Failed connecting to the Kinetic device w/status: %s\n", Kinetic_GetStatusDescription(status)); return -1; } // Read in file contents to store const char* dataFile = "test/support/data/test.data"; struct stat st; stat(dataFile, &st); char* buf = malloc(st.st_size); int fd = open(dataFile, O_RDONLY); long dataLen = read(fd, buf, st.st_size); close(fd); if (dataLen <= 0) { fprintf(stderr, "Failed reading data file to store: %s\n", dataFile); exit(-1); } write_args* writeArgs = calloc(NUM_FILES, sizeof(write_args)); if (writeArgs == NULL) { fprintf(stderr, "Failed allocating overlapped thread arguments!\n"); } // Kick off a thread for each file to store for (int i = 0; i < NUM_FILES; i++) { // Establish connection status = KineticClient_CreateSession(&sessionConfig, client, &writeArgs[i].session); if (status != KINETIC_STATUS_SUCCESS) { fprintf(stderr, "Failed connecting to the Kinetic device w/status: %s\n", Kinetic_GetStatusDescription(status)); return -1; } strcpy(writeArgs[i].ip, sessionConfig.host); // Create a ByteBuffer for consuming chunks of data out of for overlapped PUTs writeArgs[i].data = ByteBuffer_Create(buf, dataLen, 0); // Configure common entry attributes struct timeval now; gettimeofday(&now, NULL); snprintf(writeArgs[i].keyPrefix, sizeof(writeArgs[i].keyPrefix), "%010llu_%02d_", (unsigned long long)now.tv_sec, i); ByteBuffer valBuf = ByteBuffer_Create(writeArgs[i].value, sizeof(writeArgs[i].value), 0); writeArgs[i].entry = (KineticEntry) { .key = ByteBuffer_CreateAndAppendCString( writeArgs[i].key, sizeof(writeArgs[i].key), writeArgs[i].keyPrefix), .tag = ByteBuffer_CreateAndAppendCString( writeArgs[i].tag, sizeof(writeArgs[i].tag), "some_value_tag..."), .algorithm = KINETIC_ALGORITHM_SHA1, .value = valBuf, }; // Store the entry int threadCreateStatus = pthread_create(&writeArgs[i].threadID, NULL, store_data, &writeArgs[i]); REPORT_ERRNO(threadCreateStatus, "pthread_create"); if (threadCreateStatus != 0) { fprintf(stderr, "pthread create failed!\n"); exit(-2); } } // Wait for all PUT operations to complete and cleanup for (int i = 0; i < NUM_FILES; i++) { int joinStatus = pthread_join(writeArgs[i].threadID, NULL); if (joinStatus != 0) { fprintf(stderr, "pthread join failed!\n"); } KineticClient_DestroySession(writeArgs[i].session); } // Shutdown client connection and cleanup KineticClient_Shutdown(client); free(writeArgs); free(buf); return 0; }
int main(int argc, char** argv) { (void)argc; (void)argv; // Initialize kinetic-c and configure sessions KineticSession* session; KineticClientConfig clientConfig = { .logFile = "stdout", .logLevel = 1, }; KineticClient * client = KineticClient_Init(&clientConfig); if (client == NULL) { return 1; } const char HmacKeyString[] = "asdfasdf"; KineticSessionConfig sessionConfig = { .host = "localhost", .port = KINETIC_PORT, .clusterVersion = 0, .identity = 1, .hmacKey = ByteArray_CreateWithCString(HmacKeyString), }; KineticStatus status = KineticClient_CreateSession(&sessionConfig, client, &session); if (status != KINETIC_STATUS_SUCCESS) { fprintf(stderr, "Failed connecting to the Kinetic device w/status: %s\n", Kinetic_GetStatusDescription(status)); exit(1); } // Read in file contents to store const char* dataFile = "test/support/data/test.data"; struct stat st; stat(dataFile, &st); char* buf = malloc(st.st_size); int fd = open(dataFile, O_RDONLY); long dataLen = read(fd, buf, st.st_size); close(fd); if (dataLen <= 0) { fprintf(stderr, "Failed reading data file to store: %s\n", dataFile); exit(-1); } write_args* writeArgs = calloc(1, sizeof(write_args)); writeArgs->session = session; // Create a ByteBuffer for consuming chunks of data out of for overlapped PUTs writeArgs->data = ByteBuffer_Create(buf, dataLen, 0); // Configure common meta-data for the entries struct timeval now; gettimeofday(&now, NULL); snprintf(writeArgs->keyPrefix, sizeof(writeArgs->keyPrefix), "%010ld_", now.tv_sec); ByteBuffer verBuf = ByteBuffer_Create(writeArgs->version, sizeof(writeArgs->version), 0); ByteBuffer_AppendCString(&verBuf, "v1.0"); ByteBuffer tagBuf = ByteBuffer_Create(writeArgs->tag, sizeof(writeArgs->tag), 0); ByteBuffer_AppendCString(&tagBuf, "some_value_tag..."); writeArgs->entry = (KineticEntry) { .key = ByteBuffer_Create(writeArgs->key, sizeof(writeArgs->key), 0), // .newVersion = verBuf, .tag = tagBuf, .algorithm = KINETIC_ALGORITHM_SHA1, .value = ByteBuffer_Create(writeArgs->value, sizeof(writeArgs->value), 0), .synchronization = KINETIC_SYNCHRONIZATION_WRITEBACK, }; strcpy(writeArgs->ip, sessionConfig.host); // Store the data printf("\nWriting data file to the Kinetic device...\n"); store_data(writeArgs); // Shutdown client connection and cleanup KineticClient_DestroySession(writeArgs->session); KineticClient_Shutdown(client); free(writeArgs); free(buf); return 0; }
void test_KineticOperation_BuildPut_should_build_and_execute_a_PUT_operation_to_create_a_new_object(void) { LOG_LOCATION; ByteArray value = ByteArray_CreateWithCString("Luke, I am your father"); ByteArray key = ByteArray_CreateWithCString("foobar"); ByteArray newVersion = ByteArray_CreateWithCString("v1.0"); ByteArray tag = ByteArray_CreateWithCString("some_tag"); KineticConnection_IncrementSequence_Expect(&Connection); // PUT // The PUT operation sets the value and metadata for a given key. If a value // already exists in the store for the given key, the client must pass a // value for dbVersion which matches the stored version for this key to // overwrite the value metadata. This behavior can be overridden (so that // the version is ignored and the value and metadata are always written) by // setting forced to true in the KeyValue option. // // Request Message: // // command { // // See top level cross cutting concerns for header details // header { // clusterVersion: ... // identity: ... // connectionID: ... // sequence: ... // messageType: PUT // } // body: { // keyValue { // // Required bytes // // The key for the value being set // key: "..." // // // Required bytes // // Versions are set on objects to support optimistic locking. // // For operations that modify data, if the dbVersion sent in the // // request message does not match the version stored in the db, the // // request will fail. // dbVersion: "..." // // // Required bytes // // Specifies what the next version of the data will be if this // // operation is successful. // newVersion: "..." // // // Optional bool, default false // // Setting force to true ignores potential version mismatches // // and carries out the operation. // force: true // // // Optional bytes // // The integrity value for the data. This value should be computed // // by the client application by applying the hash algorithm // // specified below to the value (and only to the value). // // The algorithm used should be specified in the algorithm field. // // The Kinetic Device will not do any processing on this value. // tag: "..." // // // Optional enum // // The algorithm used by the client to compute the tag. // // The allowed values are: SHA1, SHA2, SHA3, CRC32, CRC64 // algorithm: ... // // // Optional Synchronization enum value, defaults to WRITETHROUGH // // Allows client to specify if the data must be written to disk // // immediately, or can be written in the future. // // // // WRITETHROUGH: This request is made persistent before returning. // // This does not effect any other pending operations. // // WRITEBACK: They can be made persistent when the drive chooses, // // or when a subsequent FLUSH is give to the drive. // // FLUSH: All pending information that has not been written is // // pushed to the disk and the command that specifies // // FLUSH is written last and then returned. All WRITEBACK writes // // that have received ending status will be guaranteed to be // // written before the FLUSH operation is returned completed. // synchronization: ... // } KineticEntry entry = { .key = ByteBuffer_CreateWithArray(key), .newVersion = ByteBuffer_CreateWithArray(newVersion), // .dbVersion = ByteBuffer_CreateWithArray(BYTE_ARRAY_NONE), .tag = ByteBuffer_CreateWithArray(tag), .algorithm = KINETIC_ALGORITHM_SHA1, .value = ByteBuffer_CreateWithArray(value), }; KineticMessage_ConfigureKeyValue_Expect(&Operation.request->protoData.message, &entry); // } // } // hmac: "..." // // Build the operation KineticOperation_BuildPut(&Operation, &entry); // Ensure proper message type TEST_ASSERT_TRUE(Request.proto->command->header->has_messageType); TEST_ASSERT_EQUAL(KINETIC_PROTO_MESSAGE_TYPE_PUT, Request.proto->command->header->messageType); TEST_ASSERT_EQUAL_ByteArray(value, Operation.request->entry.value.array); TEST_ASSERT_EQUAL(0, Operation.request->entry.value.bytesUsed); TEST_ASSERT_ByteBuffer_NULL(Response.entry.value); }
void test_KineticBuilder_BuildPut_should_build_and_execute_a_PUT_operation_to_create_a_new_object_with_calculated_tag(void) { ByteArray value = ByteArray_CreateWithCString("Luke, I am your father"); ByteArray key = ByteArray_CreateWithCString("foobar"); ByteArray newVersion = ByteArray_CreateWithCString("v1.0"); ByteArray tag = ByteArray_CreateWithCString("some_tag"); KineticEntry entry = { .key = ByteBuffer_CreateWithArray(key), .newVersion = ByteBuffer_CreateWithArray(newVersion), .tag = ByteBuffer_CreateWithArray(tag), .algorithm = KINETIC_ALGORITHM_SHA1, .value = ByteBuffer_CreateWithArray(value), .computeTag = true, }; KineticOperation_ValidateOperation_Expect(&Operation); KineticMessage_ConfigureKeyValue_Expect(&Operation.request->message, &entry); // Build the operation KineticBuilder_BuildPut(&Operation, &entry); TEST_ASSERT_FALSE(Request.pinAuth); TEST_ASSERT_EQUAL_PTR(entry.value.array.data, Operation.value.data); TEST_ASSERT_EQUAL(entry.value.bytesUsed, Operation.value.len); TEST_ASSERT_TRUE(Request.message.command.header->has_messagetype); TEST_ASSERT_EQUAL(COM__SEAGATE__KINETIC__PROTO__COMMAND__MESSAGE_TYPE__PUT, Request.message.command.header->messagetype); TEST_ASSERT_EQUAL_ByteArray(value, Operation.entry->value.array); TEST_ASSERT_EQUAL(0, Operation.entry->value.bytesUsed); TEST_ASSERT_FALSE(Request.pinAuth); TEST_ASSERT_EQUAL(0, Operation.timeoutSeconds); TEST_ASSERT_NULL(Operation.response); } uint8_t ValueData[KINETIC_OBJ_SIZE]; void test_KineticBuilder_BuildGet_should_build_a_GET_operation(void) { const ByteArray key = ByteArray_CreateWithCString("foobar"); ByteArray value = {.data = ValueData, .len = sizeof(ValueData)}; KineticEntry entry = { .key = ByteBuffer_CreateWithArray(key), .value = ByteBuffer_CreateWithArray(value), }; entry.value.bytesUsed = 123; // Set to non-empty state, since it should be reset to 0 KineticOperation_ValidateOperation_Expect(&Operation); KineticMessage_ConfigureKeyValue_Expect(&Request.message, &entry); KineticBuilder_BuildGet(&Operation, &entry); TEST_ASSERT_TRUE(Request.message.command.header->has_messagetype); TEST_ASSERT_EQUAL(COM__SEAGATE__KINETIC__PROTO__COMMAND__MESSAGE_TYPE__GET, Request.message.command.header->messagetype); TEST_ASSERT_EQUAL_PTR(KineticCallbacks_Get, Operation.opCallback); TEST_ASSERT_EQUAL_PTR(value.data, Operation.entry->value.array.data); TEST_ASSERT_EQUAL(value.len, Operation.entry->value.array.len); TEST_ASSERT_EQUAL(0, Operation.entry->value.bytesUsed); TEST_ASSERT_FALSE(Request.pinAuth); TEST_ASSERT_EQUAL(0, Operation.timeoutSeconds); TEST_ASSERT_NULL(Operation.response); TEST_ASSERT_FALSE(Operation.entry->metadataOnly); } void test_KineticBuilder_BuildGet_should_build_a_GET_operation_requesting_metadata_only(void) { const ByteArray key = ByteArray_CreateWithCString("foobar"); ByteArray value = ByteArray_Create(ValueData, sizeof(ValueData)); KineticEntry entry = { .key = ByteBuffer_CreateWithArray(key), .metadataOnly = true, .value = ByteBuffer_CreateWithArray(value), }; entry.value.bytesUsed = 123; // Set to non-empty state, since it should be reset to 0 for a metadata-only request KineticOperation_ValidateOperation_Expect(&Operation); KineticMessage_ConfigureKeyValue_Expect(&Request.message, &entry); KineticBuilder_BuildGet(&Operation, &entry); TEST_ASSERT_TRUE(Request.message.command.header->has_messagetype); TEST_ASSERT_EQUAL(COM__SEAGATE__KINETIC__PROTO__COMMAND__MESSAGE_TYPE__GET, Request.message.command.header->messagetype); TEST_ASSERT_EQUAL_PTR(KineticCallbacks_Get, Operation.opCallback); TEST_ASSERT_EQUAL_PTR(value.data, Operation.entry->value.array.data); TEST_ASSERT_EQUAL_PTR(value.len, Operation.entry->value.array.len); TEST_ASSERT_EQUAL(0, Operation.entry->value.bytesUsed); TEST_ASSERT_FALSE(Request.pinAuth); TEST_ASSERT_EQUAL(0, Operation.timeoutSeconds); TEST_ASSERT_NULL(Operation.response); TEST_ASSERT_TRUE(Operation.entry->metadataOnly); } void test_KineticBuilder_BuildGetNext_should_build_a_GETNEXT_operation(void) { const ByteArray key = ByteArray_CreateWithCString("foobar"); ByteArray value = {.data = ValueData, .len = sizeof(ValueData)}; KineticEntry entry = { .key = ByteBuffer_CreateWithArray(key), .value = ByteBuffer_CreateWithArray(value), }; entry.value.bytesUsed = 123; // Set to non-empty state, since it should be reset to 0 KineticOperation_ValidateOperation_Expect(&Operation); KineticMessage_ConfigureKeyValue_Expect(&Request.message, &entry); KineticBuilder_BuildGetNext(&Operation, &entry); TEST_ASSERT_TRUE(Request.message.command.header->has_messagetype); TEST_ASSERT_EQUAL(COM__SEAGATE__KINETIC__PROTO__COMMAND__MESSAGE_TYPE__GETNEXT, Request.message.command.header->messagetype); TEST_ASSERT_EQUAL_PTR(KineticCallbacks_Get, Operation.opCallback); TEST_ASSERT_EQUAL_PTR(value.data, Operation.entry->value.array.data); TEST_ASSERT_EQUAL(value.len, Operation.entry->value.array.len); TEST_ASSERT_EQUAL(0, Operation.entry->value.bytesUsed); TEST_ASSERT_FALSE(Request.pinAuth); TEST_ASSERT_EQUAL(0, Operation.timeoutSeconds); TEST_ASSERT_NULL(Operation.response); TEST_ASSERT_FALSE(Operation.entry->metadataOnly); } void test_KineticBuilder_BuildGetNext_should_build_a_GETNEXT_operation_with_metadata_only(void) { const ByteArray key = ByteArray_CreateWithCString("foobar"); ByteArray value = ByteArray_Create(ValueData, sizeof(ValueData)); KineticEntry entry = { .key = ByteBuffer_CreateWithArray(key), .metadataOnly = true, .value = ByteBuffer_CreateWithArray(value), }; entry.value.bytesUsed = 123; // Set to non-empty state, since it should be reset to 0 for a metadata-only request KineticOperation_ValidateOperation_Expect(&Operation); KineticMessage_ConfigureKeyValue_Expect(&Request.message, &entry); KineticBuilder_BuildGetNext(&Operation, &entry); TEST_ASSERT_TRUE(Request.message.command.header->has_messagetype); TEST_ASSERT_EQUAL(COM__SEAGATE__KINETIC__PROTO__COMMAND__MESSAGE_TYPE__GETNEXT, Request.message.command.header->messagetype); TEST_ASSERT_EQUAL_PTR(KineticCallbacks_Get, Operation.opCallback); TEST_ASSERT_EQUAL_PTR(value.data, Operation.entry->value.array.data); TEST_ASSERT_EQUAL_PTR(value.len, Operation.entry->value.array.len); TEST_ASSERT_EQUAL(0, Operation.entry->value.bytesUsed); TEST_ASSERT_FALSE(Request.pinAuth); TEST_ASSERT_EQUAL(0, Operation.timeoutSeconds); TEST_ASSERT_NULL(Operation.response); TEST_ASSERT_TRUE(Operation.entry->metadataOnly); } void test_KineticBuilder_BuildGetPrevious_should_build_a_GETPREVIOUS_operation(void) { const ByteArray key = ByteArray_CreateWithCString("foobar"); ByteArray value = {.data = ValueData, .len = sizeof(ValueData)}; KineticEntry entry = { .key = ByteBuffer_CreateWithArray(key), .value = ByteBuffer_CreateWithArray(value), }; entry.value.bytesUsed = 123; // Set to non-empty state, since it should be reset to 0 KineticOperation_ValidateOperation_Expect(&Operation); KineticMessage_ConfigureKeyValue_Expect(&Request.message, &entry); KineticBuilder_BuildGetPrevious(&Operation, &entry); TEST_ASSERT_TRUE(Request.message.command.header->has_messagetype); TEST_ASSERT_EQUAL(COM__SEAGATE__KINETIC__PROTO__COMMAND__MESSAGE_TYPE__GETPREVIOUS, Request.message.command.header->messagetype); TEST_ASSERT_EQUAL_PTR(KineticCallbacks_Get, Operation.opCallback); TEST_ASSERT_EQUAL_PTR(value.data, Operation.entry->value.array.data); TEST_ASSERT_EQUAL(value.len, Operation.entry->value.array.len); TEST_ASSERT_EQUAL(0, Operation.entry->value.bytesUsed); TEST_ASSERT_FALSE(Request.pinAuth); TEST_ASSERT_EQUAL(0, Operation.timeoutSeconds); TEST_ASSERT_NULL(Operation.response); TEST_ASSERT_FALSE(Operation.entry->metadataOnly); } void test_KineticBuilder_BuildGetPrevious_should_build_a_GETPREVIOUS_operation_with_metadata_only(void) { const ByteArray key = ByteArray_CreateWithCString("foobar"); ByteArray value = ByteArray_Create(ValueData, sizeof(ValueData)); KineticEntry entry = { .key = ByteBuffer_CreateWithArray(key), .metadataOnly = true, .value = ByteBuffer_CreateWithArray(value), }; entry.value.bytesUsed = 123; // Set to non-empty state, since it should be reset to 0 for a metadata-only request KineticOperation_ValidateOperation_Expect(&Operation); KineticMessage_ConfigureKeyValue_Expect(&Request.message, &entry); KineticBuilder_BuildGetPrevious(&Operation, &entry); TEST_ASSERT_TRUE(Request.message.command.header->has_messagetype); TEST_ASSERT_EQUAL(COM__SEAGATE__KINETIC__PROTO__COMMAND__MESSAGE_TYPE__GETPREVIOUS, Request.message.command.header->messagetype); TEST_ASSERT_EQUAL_PTR(KineticCallbacks_Get, Operation.opCallback); TEST_ASSERT_EQUAL_PTR(value.data, Operation.entry->value.array.data); TEST_ASSERT_EQUAL_PTR(value.len, Operation.entry->value.array.len); TEST_ASSERT_EQUAL(0, Operation.entry->value.bytesUsed); TEST_ASSERT_FALSE(Request.pinAuth); TEST_ASSERT_EQUAL(0, Operation.timeoutSeconds); TEST_ASSERT_NULL(Operation.response); TEST_ASSERT_TRUE(Operation.entry->metadataOnly); } void test_KineticBuilder_BuildFlush_should_build_a_FLUSHALLDATA_operation(void) { KineticOperation_ValidateOperation_Expect(&Operation); KineticBuilder_BuildFlush(&Operation); TEST_ASSERT_TRUE(Request.message.command.header->has_messagetype); TEST_ASSERT_EQUAL(COM__SEAGATE__KINETIC__PROTO__COMMAND__MESSAGE_TYPE__FLUSHALLDATA, Request.message.command.header->messagetype); TEST_ASSERT_EQUAL_PTR(KineticCallbacks_Basic, Operation.opCallback); TEST_ASSERT_FALSE(Request.pinAuth); TEST_ASSERT_EQUAL(0, Operation.timeoutSeconds); TEST_ASSERT_NULL(Operation.response); } void test_KineticBuilder_BuildDelete_should_build_a_DELETE_operation(void) { const ByteArray key = ByteArray_CreateWithCString("foobar"); ByteArray value = ByteArray_Create(ValueData, sizeof(ValueData)); KineticEntry entry = {.key = ByteBuffer_CreateWithArray(key), .value = ByteBuffer_CreateWithArray(value)}; KineticOperation_ValidateOperation_Expect(&Operation); KineticMessage_ConfigureKeyValue_Expect(&Request.message, &entry); KineticBuilder_BuildDelete(&Operation, &entry); TEST_ASSERT_TRUE(Request.message.command.header->has_messagetype); TEST_ASSERT_EQUAL(COM__SEAGATE__KINETIC__PROTO__COMMAND__MESSAGE_TYPE__DELETE, Request.message.command.header->messagetype); TEST_ASSERT_EQUAL_PTR(KineticCallbacks_Delete, Operation.opCallback); TEST_ASSERT_EQUAL_PTR(value.data, Operation.entry->value.array.data); TEST_ASSERT_EQUAL_PTR(value.len, Operation.entry->value.array.len); TEST_ASSERT_EQUAL(0, Operation.entry->value.bytesUsed); TEST_ASSERT_FALSE(Request.pinAuth); TEST_ASSERT_EQUAL(0, Operation.timeoutSeconds); TEST_ASSERT_NULL(Operation.response); } void test_KineticBuilder_BuildGetKeyRange_should_build_a_GetKeyRange_request(void) { const int maxKeyLen = 32; // arbitrary key length for test uint8_t startKeyData[maxKeyLen]; uint8_t endKeyData[maxKeyLen]; ByteBuffer startKey, endKey; startKey = ByteBuffer_Create(startKeyData, sizeof(startKeyData), 0); ByteBuffer_AppendCString(&startKey, "key_range_00_00"); endKey = ByteBuffer_Create(endKeyData, sizeof(endKeyData), 0); ByteBuffer_AppendCString(&endKey, "key_range_00_03"); const int numKeysInRange = 4; KineticKeyRange range = { .startKey = startKey, .endKey = endKey, .startKeyInclusive = true, .endKeyInclusive = true, .maxReturned = numKeysInRange, .reverse = false, }; uint8_t keysData[numKeysInRange][maxKeyLen]; ByteBuffer keyBuffers[numKeysInRange]; for (int i = 0; i < numKeysInRange; i++) { keyBuffers[i] = ByteBuffer_Create(keysData[i], maxKeyLen, 0); } ByteBufferArray keys = {.buffers = keyBuffers, .count = numKeysInRange}; KineticOperation_ValidateOperation_Expect(&Operation); KineticMessage_ConfigureKeyRange_Expect(&Request.message, &range); KineticBuilder_BuildGetKeyRange(&Operation, &range, &keys); TEST_ASSERT_TRUE(Request.command->header->has_messagetype); TEST_ASSERT_EQUAL(COM__SEAGATE__KINETIC__PROTO__COMMAND__MESSAGE_TYPE__GETKEYRANGE, Request.command->header->messagetype); TEST_ASSERT_EQUAL_PTR(KineticCallbacks_GetKeyRange, Operation.opCallback); TEST_ASSERT_NULL(Operation.entry); TEST_ASSERT_EQUAL_PTR(&Request, Operation.request); TEST_ASSERT_FALSE(Request.pinAuth); TEST_ASSERT_EQUAL(0, Operation.timeoutSeconds); TEST_ASSERT_NULL(Operation.response); TEST_ASSERT_EQUAL_PTR(&Request.message.command, Request.command); } void test_KineticBuilder_BuildP2POperation_should_build_a_P2POperation_request(void) { ByteBuffer oldKey1 = ByteBuffer_Create((void*)0x1234, 10, 10); ByteBuffer newKey1 = ByteBuffer_Create((void*)0x4321, 33, 33); ByteBuffer version1 = ByteBuffer_Create((void*)0xABC, 6, 6); ByteBuffer oldKey2 = ByteBuffer_Create((void*)0x5678, 12, 12); ByteBuffer newKey2 = ByteBuffer_Create((void*)0x8765, 200, 200); KineticP2P_OperationData ops2[] ={ { .key = oldKey2, .newKey = newKey2, } }; KineticP2P_Operation chained_p2pOp = { .peer = { .hostname = "hostname1", .port = 4321, }, .numOperations = 1, .operations = ops2 }; KineticP2P_OperationData ops[] ={ { .key = oldKey1, .version = version1, .newKey = newKey1, .chainedOperation = &chained_p2pOp, }, { .key = oldKey2, .newKey = newKey2, } }; KineticP2P_Operation p2pOp = { .peer = { .hostname = "hostname", .port = 1234, .tls = true, }, .numOperations = 2, .operations = ops }; KineticOperation_ValidateOperation_Expect(&Operation); KineticBuilder_BuildP2POperation(&Operation, &p2pOp); TEST_ASSERT_FALSE(Request.pinAuth); TEST_ASSERT_TRUE(Request.message.command.header->has_messagetype); TEST_ASSERT_EQUAL(COM__SEAGATE__KINETIC__PROTO__COMMAND__MESSAGE_TYPE__PEER2PEERPUSH, Request.message.command.header->messagetype); TEST_ASSERT_EQUAL_PTR(&Request.message.body, Request.command->body); TEST_ASSERT_NOT_NULL(Request.command->body->p2poperation); TEST_ASSERT_EQUAL("hostname", Request.command->body->p2poperation->peer->hostname); TEST_ASSERT_TRUE(Request.command->body->p2poperation->peer->has_port); TEST_ASSERT_EQUAL(1234, Request.command->body->p2poperation->peer->port); TEST_ASSERT_TRUE(Request.command->body->p2poperation->peer->has_tls); TEST_ASSERT_TRUE(Request.command->body->p2poperation->peer->tls); TEST_ASSERT_FALSE(Request.command->body->p2poperation->allchildoperationssucceeded); TEST_ASSERT_FALSE(Request.command->body->p2poperation->has_allchildoperationssucceeded); TEST_ASSERT_EQUAL(2, Request.command->body->p2poperation->n_operation); TEST_ASSERT_TRUE(Request.command->body->p2poperation->operation[0]->has_key); TEST_ASSERT_EQUAL(oldKey1.array.data, Request.command->body->p2poperation->operation[0]->key.data); TEST_ASSERT_EQUAL(oldKey1.bytesUsed, Request.command->body->p2poperation->operation[0]->key.len); TEST_ASSERT_TRUE(Request.command->body->p2poperation->operation[0]->has_newkey); TEST_ASSERT_EQUAL(newKey1.array.data, Request.command->body->p2poperation->operation[0]->newkey.data); TEST_ASSERT_EQUAL(newKey1.bytesUsed, Request.command->body->p2poperation->operation[0]->newkey.len); TEST_ASSERT_TRUE(Request.command->body->p2poperation->operation[0]->has_version); TEST_ASSERT_EQUAL(version1.array.data, Request.command->body->p2poperation->operation[0]->version.data); TEST_ASSERT_EQUAL(version1.bytesUsed, Request.command->body->p2poperation->operation[0]->version.len); TEST_ASSERT_FALSE(Request.command->body->p2poperation->operation[0]->has_force); TEST_ASSERT_FALSE(Request.command->body->p2poperation->operation[0]->force); TEST_ASSERT_NOT_NULL(Request.command->body->p2poperation->operation[0]->p2pop); TEST_ASSERT_TRUE(Request.command->body->p2poperation->operation[0]->p2pop->peer->has_port); TEST_ASSERT_EQUAL(4321, Request.command->body->p2poperation->operation[0]->p2pop->peer->port); TEST_ASSERT_TRUE(Request.command->body->p2poperation->operation[0]->p2pop->peer->has_tls); TEST_ASSERT_FALSE(Request.command->body->p2poperation->operation[0]->p2pop->peer->tls); TEST_ASSERT_EQUAL(1, Request.command->body->p2poperation->operation[0]->p2pop->n_operation); TEST_ASSERT_TRUE(Request.command->body->p2poperation->operation[0]->p2pop->operation[0]->has_key); TEST_ASSERT_EQUAL(oldKey2.array.data, Request.command->body->p2poperation->operation[0]->p2pop->operation[0]->key.data); TEST_ASSERT_EQUAL(oldKey2.bytesUsed, Request.command->body->p2poperation->operation[0]->p2pop->operation[0]->key.len); TEST_ASSERT_TRUE(Request.command->body->p2poperation->operation[0]->p2pop->operation[0]->has_newkey); TEST_ASSERT_EQUAL(newKey2.array.data, Request.command->body->p2poperation->operation[0]->p2pop->operation[0]->newkey.data); TEST_ASSERT_EQUAL(newKey2.bytesUsed, Request.command->body->p2poperation->operation[0]->p2pop->operation[0]->newkey.len); TEST_ASSERT_FALSE(Request.command->body->p2poperation->operation[0]->p2pop->operation[0]->has_version); TEST_ASSERT_TRUE(Request.command->body->p2poperation->operation[0]->p2pop->operation[0]->has_force); TEST_ASSERT_TRUE(Request.command->body->p2poperation->operation[0]->p2pop->operation[0]->force); TEST_ASSERT_NULL(Request.command->body->p2poperation->operation[0]->status); TEST_ASSERT_TRUE(Request.command->body->p2poperation->operation[1]->has_key); TEST_ASSERT_EQUAL(oldKey2.array.data, Request.command->body->p2poperation->operation[1]->key.data); TEST_ASSERT_EQUAL(oldKey2.bytesUsed, Request.command->body->p2poperation->operation[1]->key.len); TEST_ASSERT_TRUE(Request.command->body->p2poperation->operation[1]->has_newkey); TEST_ASSERT_EQUAL(newKey2.array.data, Request.command->body->p2poperation->operation[1]->newkey.data); TEST_ASSERT_EQUAL(newKey2.bytesUsed, Request.command->body->p2poperation->operation[1]->newkey.len); TEST_ASSERT_FALSE(Request.command->body->p2poperation->operation[1]->has_version); TEST_ASSERT_TRUE(Request.command->body->p2poperation->operation[1]->has_force); TEST_ASSERT_TRUE(Request.command->body->p2poperation->operation[1]->force); TEST_ASSERT_NULL(Request.command->body->p2poperation->operation[1]->p2pop); TEST_ASSERT_NULL(Request.command->body->p2poperation->operation[1]->status); TEST_ASSERT_EQUAL_PTR(&p2pOp, Operation.p2pOp); TEST_ASSERT_EQUAL(0, Operation.timeoutSeconds); TEST_ASSERT_NULL(Operation.response); // This just free's the malloc'd memory and sets statuses to "invalid" (since no operation was actually performed) KineticAllocator_FreeP2PProtobuf(Request.command->body->p2poperation); } /******************************************************************************* * Admin Client Operations *******************************************************************************/ void test_KineticBuilder_BuildGetLog_should_build_a_GetLog_request(void) { KineticLogInfo* pInfo; KineticOperation_ValidateOperation_Expect(&Operation); KineticStatus status = KineticBuilder_BuildGetLog(&Operation, KINETIC_DEVICE_INFO_TYPE_STATISTICS, BYTE_ARRAY_NONE, &pInfo); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); TEST_ASSERT_TRUE(Request.message.command.header->has_messagetype); TEST_ASSERT_EQUAL(COM__SEAGATE__KINETIC__PROTO__COMMAND__MESSAGE_TYPE__GETLOG, Request.message.command.header->messagetype); TEST_ASSERT_EQUAL_PTR(&Request.message.body, Request.command->body); TEST_ASSERT_EQUAL_PTR(&Request.message.getLog, Request.command->body->getlog); TEST_ASSERT_NOT_NULL(Request.command->body->getlog->types); TEST_ASSERT_EQUAL(1, Request.command->body->getlog->n_types); TEST_ASSERT_EQUAL(COM__SEAGATE__KINETIC__PROTO__COMMAND__GET_LOG__TYPE__STATISTICS, Request.command->body->getlog->types[0]); TEST_ASSERT_EQUAL_PTR(&pInfo, Operation.deviceInfo); TEST_ASSERT_FALSE(Request.pinAuth); TEST_ASSERT_EQUAL(0, Operation.timeoutSeconds); TEST_ASSERT_NULL(Operation.response); } void test_KineticBuilder_BuildGetLog_should_build_a_GetLog_request_to_retrieve_device_specific_log_info(void) { KineticLogInfo* pInfo; const char nameData[] = "com.WD"; ByteArray name = ByteArray_CreateWithCString(nameData); KineticOperation_ValidateOperation_Expect(&Operation); KineticStatus status = KineticBuilder_BuildGetLog(&Operation, COM__SEAGATE__KINETIC__PROTO__COMMAND__GET_LOG__TYPE__DEVICE, name, &pInfo); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); TEST_ASSERT_TRUE(Request.message.command.header->has_messagetype); TEST_ASSERT_EQUAL(COM__SEAGATE__KINETIC__PROTO__COMMAND__MESSAGE_TYPE__GETLOG, Request.message.command.header->messagetype); TEST_ASSERT_EQUAL_PTR(&Request.message.body, Request.command->body); TEST_ASSERT_EQUAL_PTR(&Request.message.getLog, Request.command->body->getlog); TEST_ASSERT_NOT_NULL(Request.command->body->getlog->types); TEST_ASSERT_EQUAL(1, Request.command->body->getlog->n_types); TEST_ASSERT_EQUAL(COM__SEAGATE__KINETIC__PROTO__COMMAND__GET_LOG__TYPE__DEVICE, Request.command->body->getlog->types[0]); TEST_ASSERT_EQUAL_PTR(&Request.message.getLogDevice, Request.command->body->getlog->device); TEST_ASSERT_TRUE(Request.command->body->getlog->device->has_name); TEST_ASSERT_EQUAL_PTR(nameData, Request.command->body->getlog->device->name.data); TEST_ASSERT_EQUAL(strlen(nameData), Request.command->body->getlog->device->name.len); TEST_ASSERT_EQUAL_PTR(&pInfo, Operation.deviceInfo); TEST_ASSERT_FALSE(Request.pinAuth); TEST_ASSERT_EQUAL(0, Operation.timeoutSeconds); TEST_ASSERT_NULL(Operation.response); } void test_KineticBuilder_BuildGetLog_should_return_KINETIC_STATUS_DEVICE_NAME_REQUIRED_if_name_not_specified_correctly(void) { KineticLogInfo* pInfo; char nameData[] = "com.WD"; ByteArray name; KineticStatus status; // Length is zero name.data = (uint8_t*)nameData; name.len = 0; KineticOperation_ValidateOperation_Expect(&Operation); status = KineticBuilder_BuildGetLog(&Operation, COM__SEAGATE__KINETIC__PROTO__COMMAND__GET_LOG__TYPE__DEVICE, name, &pInfo); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_DEVICE_NAME_REQUIRED, status); // Data is NULL name.data = NULL; name.len = strlen(nameData); KineticOperation_ValidateOperation_Expect(&Operation); status = KineticBuilder_BuildGetLog(&Operation, COM__SEAGATE__KINETIC__PROTO__COMMAND__GET_LOG__TYPE__DEVICE, name, &pInfo); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_DEVICE_NAME_REQUIRED, status); // Length is zero and data is NULL name.data = NULL; name.len = 0; KineticOperation_ValidateOperation_Expect(&Operation); status = KineticBuilder_BuildGetLog(&Operation, COM__SEAGATE__KINETIC__PROTO__COMMAND__GET_LOG__TYPE__DEVICE, name, &pInfo); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_DEVICE_NAME_REQUIRED, status); }
void setUp(void) { SystemTestSetup(0, true); KeyBuffer = ByteBuffer_CreateAndAppendCString(KeyData, sizeof(KeyData), strKey); ExpectedKeyBuffer = ByteBuffer_CreateAndAppendCString(ExpectedKeyData, sizeof(ExpectedKeyData), strKey); TagBuffer = ByteBuffer_CreateAndAppendCString(TagData, sizeof(TagData), "SomeTagValue"); ExpectedTagBuffer = ByteBuffer_CreateAndAppendCString(ExpectedTagData, sizeof(ExpectedTagData), "SomeTagValue"); TestValue = ByteArray_CreateWithCString("lorem ipsum... blah blah blah... etc."); ValueBuffer = ByteBuffer_CreateAndAppendArray(ValueData, sizeof(ValueData), TestValue); // Setup to write some test data KineticEntry putEntry = { .key = KeyBuffer, .tag = TagBuffer, .algorithm = KINETIC_ALGORITHM_SHA1, .value = ValueBuffer, .force = true, .synchronization = KINETIC_SYNCHRONIZATION_FLUSH, }; KineticStatus status = KineticClient_Put(Fixture.session, &putEntry, NULL); if (status != KINETIC_STATUS_SUCCESS) { failing = true; TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); } // Validate the object exists initially KineticEntry getEntry = { .key = KeyBuffer, .tag = TagBuffer, .algorithm = KINETIC_ALGORITHM_SHA1, .value = ValueBuffer, .force = true, .synchronization = KINETIC_SYNCHRONIZATION_WRITETHROUGH, }; status = KineticClient_Get(Fixture.session, &getEntry, NULL); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); TEST_ASSERT_EQUAL_ByteArray(putEntry.key.array, getEntry.key.array); TEST_ASSERT_EQUAL_ByteArray(putEntry.tag.array, getEntry.tag.array); TEST_ASSERT_EQUAL(putEntry.algorithm, getEntry.algorithm); TEST_ASSERT_EQUAL_ByteBuffer(putEntry.value, getEntry.value); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); // Set the erase PIN to something non-empty strcpy(NewPinData, SESSION_PIN); OldPin = ByteArray_Create(OldPinData, 0); NewPin = ByteArray_Create(NewPinData, strlen(NewPinData)); status = KineticAdminClient_SetErasePin(Fixture.adminSession, OldPin, NewPin); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); } void tearDown(void) { KineticStatus status = KINETIC_STATUS_INVALID; if (failing) { return; } // Validate the object no longer exists KineticEntry regetEntryMetadata = { .key = KeyBuffer, .tag = TagBuffer, .metadataOnly = true, }; status = KineticClient_Get(Fixture.session, ®etEntryMetadata, NULL); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_NOT_FOUND, status); TEST_ASSERT_ByteArray_EMPTY(regetEntryMetadata.value.array); SystemTestShutDown(); } void test_SecureErase_should_erase_device_contents(void) { KineticStatus status = KineticAdminClient_SecureErase(Fixture.adminSession, NewPin); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); } void test_InstantErase_should_erase_device_contents(void) { KineticStatus status = KineticAdminClient_InstantErase(Fixture.adminSession, NewPin); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); }
void test_KineticClient_Connect_should_return_KINETIC_STATUS_HOST_EMPTY_upon_NULL_host(void) { ByteArray key = ByteArray_CreateWithCString("some_key"); KineticSession config = { .host = "", .hmacKey = key, }; SessionHandle = 17; KineticStatus status = KineticClient_Connect(&config, &SessionHandle); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_HOST_EMPTY, status); TEST_ASSERT_EQUAL(KINETIC_HANDLE_INVALID, SessionHandle); } void test_KineticClient_Connect_should_return_KINETIC_STATUS_HMAC_EMPTY_upon_NULL_HMAC_key(void) { ByteArray key = {.len = 4, .data = NULL}; KineticSession config = { .host = "somehost.com", .hmacKey = key, }; SessionHandle = 17; KineticStatus status = KineticClient_Connect(&config, &SessionHandle); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_HMAC_EMPTY, status); TEST_ASSERT_EQUAL(KINETIC_HANDLE_INVALID, SessionHandle); } void test_KineticClient_Connect_should_return_false_upon_empty_HMAC_key(void) { uint8_t keyData[] = {0, 1, 2, 3}; ByteArray key = {.len = 0, .data = keyData}; KineticSession config = { .host = "somehost.com", .hmacKey = key, }; SessionHandle = 17; KineticStatus status = KineticClient_Connect(&config, &SessionHandle); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_HMAC_EMPTY, status); TEST_ASSERT_EQUAL(KINETIC_HANDLE_INVALID, SessionHandle); } void test_KineticClient_Connect_should_return_KINETIC_STATUS_SESSION_EMPTY_upon_NULL_handle(void) { KineticSession config = { .host = "somehost.com", .hmacKey = ByteArray_CreateWithCString("some_key"), }; SessionHandle = 17; KineticStatus status = KineticClient_Connect(&config, NULL); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SESSION_EMPTY, status); } void test_KineticClient_Connect_should_return_KINETIC_STATUS_SESSION_INVALID_if_connection_for_handle_is_NULL(void) { KineticSession config = { .host = "somehost.com", .hmacKey = ByteArray_CreateWithCString("some_key"), }; SessionHandle = 17; KineticConnection_NewConnection_ExpectAndReturn(&config, DummyHandle); KineticConnection_FromHandle_ExpectAndReturn(DummyHandle, NULL); KineticStatus status = KineticClient_Connect(&config, &SessionHandle); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_CONNECTION_ERROR, status); } void test_KineticClient_Connect_should_return_status_from_a_failed_connection(void) { KineticSession config = { .host = "somehost.com", .hmacKey = ByteArray_CreateWithCString("some_key"), }; SessionHandle = 17; KineticConnection_NewConnection_ExpectAndReturn(&config, DummyHandle); KineticConnection_FromHandle_ExpectAndReturn(DummyHandle, &Connection); KineticConnection_Connect_ExpectAndReturn(&Connection, KINETIC_STATUS_HMAC_EMPTY); KineticConnection_FreeConnection_Expect(&SessionHandle); KineticStatus status = KineticClient_Connect(&config, &SessionHandle); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_HMAC_EMPTY, status); TEST_ASSERT_EQUAL(KINETIC_HANDLE_INVALID, SessionHandle); } void test_KineticClient_Disconnect_should_return_KINETIC_STATUS_CONNECTION_ERROR_upon_failure_to_get_connection_from_handle(void) { SessionHandle = DummyHandle; KineticConnection_FromHandle_ExpectAndReturn(DummyHandle, NULL); KineticStatus status = KineticClient_Disconnect(&SessionHandle); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_CONNECTION_ERROR, status); } void test_KineticClient_Disconnect_should_disconnect_and_free_the_connection_associated_with_handle(void) { SessionHandle = DummyHandle; KineticConnection_FromHandle_ExpectAndReturn(DummyHandle, &Connection); KineticConnection_Disconnect_ExpectAndReturn(&Connection, KINETIC_STATUS_SUCCESS); KineticConnection_FreeConnection_Expect(&SessionHandle); KineticStatus status = KineticClient_Disconnect(&SessionHandle); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); TEST_ASSERT_EQUAL(KINETIC_HANDLE_INVALID, SessionHandle); } void test_KineticClient_Disconnect_should_return_status_from_KineticConnection_upon_faileure(void) { SessionHandle = DummyHandle; KineticConnection_FromHandle_ExpectAndReturn(DummyHandle, &Connection); KineticConnection_Disconnect_ExpectAndReturn(&Connection, KINETIC_STATUS_SESSION_INVALID); KineticConnection_FreeConnection_Expect(&SessionHandle); KineticStatus status = KineticClient_Disconnect(&SessionHandle); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SESSION_INVALID, status); TEST_ASSERT_EQUAL(KINETIC_HANDLE_INVALID, SessionHandle); }
void test_KineticOperation_BuildGet_should_build_a_GET_operation(void) { LOG_LOCATION; const ByteArray key = ByteArray_CreateWithCString("foobar"); ByteArray value = {.data = ValueData, .len = sizeof(ValueData)}; KineticEntry entry = { .key = ByteBuffer_CreateWithArray(key), .value = ByteBuffer_CreateWithArray(value), }; KineticConnection_IncrementSequence_Expect(&Connection); KineticMessage_ConfigureKeyValue_Expect(&Request.protoData.message, &entry); KineticOperation_BuildGet(&Operation, &entry); // GET // The GET operation is used to retrieve the value and metadata for a given key. // // Request Message: // command { // header { // // See above for descriptions of these fields // clusterVersion: ... // identity: ... // connectionID: ... // sequence: ... // // // The mesageType should be GET // messageType: GET TEST_ASSERT_TRUE(Request.proto->command->header->has_messageType); TEST_ASSERT_EQUAL(KINETIC_PROTO_MESSAGE_TYPE_GET, Request.proto->command->header->messageType); // } // body { // keyValue { // // See above // key: "..." // } // } // } // // See above // hmac: "..." TEST_ASSERT_ByteBuffer_NULL(Request.entry.value); TEST_ASSERT_EQUAL_ByteArray(value, Operation.response->entry.value.array); TEST_ASSERT_EQUAL(0, Operation.response->entry.value.bytesUsed); } void test_KineticOperation_BuildGet_should_build_a_GET_operation_requesting_metadata_only(void) { LOG_LOCATION; const ByteArray key = ByteArray_CreateWithCString("foobar"); ByteArray value = ByteArray_Create(ValueData, sizeof(ValueData)); KineticEntry entry = { .key = ByteBuffer_CreateWithArray(key), .metadataOnly = true, .value = ByteBuffer_CreateWithArray(value), }; KineticConnection_IncrementSequence_Expect(&Connection); KineticMessage_ConfigureKeyValue_Expect(&Request.protoData.message, &entry); KineticOperation_BuildGet(&Operation, &entry); // GET // The GET operation is used to retrieve the value and metadata for a given key. // // Request Message: // command { // header { // // See above for descriptions of these fields // clusterVersion: ... // identity: ... // connectionID: ... // sequence: ... // // // The mesageType should be GET // messageType: GET TEST_ASSERT_TRUE(Request.proto->command->header->has_messageType); TEST_ASSERT_EQUAL(KINETIC_PROTO_MESSAGE_TYPE_GET, Request.proto->command->header->messageType); // } // body { // keyValue { // // See above // key: "..." // } // } // } // // See above // hmac: "..." TEST_ASSERT_ByteBuffer_NULL(Request.entry.value); TEST_ASSERT_ByteBuffer_NULL(Response.entry.value); } void test_KineticOperation_BuildDelete_should_build_a_DELETE_operation(void) { LOG_LOCATION; const ByteArray key = ByteArray_CreateWithCString("foobar"); KineticEntry entry = {.key = ByteBuffer_CreateWithArray(key)}; KineticConnection_IncrementSequence_Expect(&Connection); KineticMessage_ConfigureKeyValue_Expect(&Request.protoData.message, &entry); KineticOperation_BuildDelete(&Operation, &entry); // The `DELETE` operation removes the entry for a given key. It respects the // same locking behavior around `dbVersion` and `force` as described in the previous sections. // The following request will remove a key value pair to the store. // // ``` // command { // // See top level cross cutting concerns for header details // header { // clusterVersion: ... // identity: ... // connectionID: ... // sequence: ... // // messageType should be DELETE // messageType: DELETE TEST_ASSERT_TRUE(Request.proto->command->header->has_messageType); TEST_ASSERT_EQUAL(KINETIC_PROTO_MESSAGE_TYPE_DELETE, Request.proto->command->header->messageType); // } // body { // keyValue { // key: "..." // // See write operation cross cutting concerns // synchronization: ... // } // } // } // hmac: "..." TEST_ASSERT_ByteBuffer_NULL(Request.entry.value); TEST_ASSERT_ByteBuffer_NULL(Response.entry.value); }
void setUp(void) { NewPinSet = false; Locked = false; SystemTestSetup(1, true); KeyBuffer = ByteBuffer_CreateAndAppendCString(KeyData, sizeof(KeyData), strKey); ExpectedKeyBuffer = ByteBuffer_CreateAndAppendCString(ExpectedKeyData, sizeof(ExpectedKeyData), strKey); TagBuffer = ByteBuffer_CreateAndAppendCString(TagData, sizeof(TagData), "SomeTagValue"); ExpectedTagBuffer = ByteBuffer_CreateAndAppendCString(ExpectedTagData, sizeof(ExpectedTagData), "SomeTagValue"); TestValue = ByteArray_CreateWithCString("lorem ipsum... blah blah blah... etc."); ValueBuffer = ByteBuffer_CreateAndAppendArray(ValueData, sizeof(ValueData), TestValue); // Setup to write some test data KineticEntry putEntry = { .key = KeyBuffer, .tag = TagBuffer, .algorithm = KINETIC_ALGORITHM_SHA1, .value = ValueBuffer, .force = true, .synchronization = KINETIC_SYNCHRONIZATION_FLUSH, }; KineticStatus status = KineticClient_Put(Fixture.session, &putEntry, NULL); // Validate the object exists initially KineticEntry getEntry = { .key = KeyBuffer, .tag = TagBuffer, .algorithm = KINETIC_ALGORITHM_SHA1, .value = ValueBuffer, .force = true, .synchronization = KINETIC_SYNCHRONIZATION_WRITETHROUGH, }; status = KineticClient_Get(Fixture.session, &getEntry, NULL); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); TEST_ASSERT_EQUAL_ByteArray(putEntry.key.array, getEntry.key.array); TEST_ASSERT_EQUAL_ByteArray(putEntry.tag.array, getEntry.tag.array); TEST_ASSERT_EQUAL(putEntry.algorithm, getEntry.algorithm); TEST_ASSERT_EQUAL_ByteBuffer(putEntry.value, getEntry.value); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); // Set the erase PIN to something non-empty strcpy(NewPinData, SESSION_PIN); OldPin = ByteArray_Create(OldPinData, 0); NewPin = ByteArray_Create(NewPinData, strlen(NewPinData)); status = KineticAdminClient_SetLockPin(Fixture.adminSession, OldPin, NewPin); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); NewPinSet = true; } void tearDown(void) { KineticStatus status; // Unlock if for some reason we are still locked in order to // prevent the device from staying in a locked/unusable state if (Locked) { status = KineticAdminClient_UnlockDevice(Fixture.adminSession, NewPin); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); Locked = false; } // Set the lock PIN back to empty if (NewPinSet) { status = KineticAdminClient_SetLockPin(Fixture.adminSession, NewPin, OldPin); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); NewPinSet = false; } SystemTestShutDown(); } void test_KineticAdmin_should_lock_and_unlock_a_device(void) { KineticStatus status; status = KineticAdminClient_LockDevice(Fixture.adminSession, NewPin); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); Locked = true; /* Currently, the device appears to just hang up on us rather than * returning DEVICE_LOCKED (unlike the simulator). Some sort of * command here to confirm that the device lock succeeded would * be a better test. We need to check if the drive has another * interface that exposes this. */ if (SystemTestIsUnderSimulator()) { // Validate the object cannot being accessed while locked KineticEntry getEntry = { .key = KeyBuffer, .tag = TagBuffer, .value = ValueBuffer, .force = true, }; status = KineticClient_Get(Fixture.session, &getEntry, NULL); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_DEVICE_LOCKED, status); } status = KineticAdminClient_UnlockDevice(Fixture.adminSession, NewPin); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); Locked = false; }
static const char HmacKeyString[] = "asdfasdf"; void setUp(void) { KineticClientConfig clientConfig = { .logFile = "stdout", .logLevel = 1, }; client = KineticClient_Init(&clientConfig); // Create sessions with primary device KineticSessionConfig sessionConfig = { .clusterVersion = 0, .identity = 1, .hmacKey = ByteArray_CreateWithCString(HmacKeyString), }; strncpy(sessionConfig.host, GetSystemTestHost1(), sizeof(sessionConfig.host)-1); sessionConfig.port = GetSystemTestPort1(); KineticStatus status = KineticClient_CreateSession(&sessionConfig, client, &session); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); KineticSessionConfig adminSessionConfig = { .clusterVersion = 0, .identity = 1, .hmacKey = ByteArray_CreateWithCString(HmacKeyString), .useSsl = true, }; strncpy(adminSessionConfig.host, GetSystemTestHost1(), sizeof(adminSessionConfig.host)-1); adminSessionConfig.port = GetSystemTestTlsPort1(); status = KineticAdminClient_CreateSession(&adminSessionConfig, client, &adminSession); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status);
void run_throughput_tests(KineticClient * client, size_t num_ops, size_t value_size) { LOGF0("STRESS THREAD: object_size: %zu bytes, count: %zu entries", value_size, num_ops); // Configure and establish a session with the specified device KineticSession* session; const char HmacKeyString[] = "asdfasdf"; KineticSessionConfig config = { .clusterVersion = 0, .identity = 1, .hmacKey = ByteArray_CreateWithCString(HmacKeyString), }; strncpy(config.host, GetSystemTestHost1(), sizeof(config.host)-1); config.port = GetSystemTestPort1(); KineticStatus status = KineticClient_CreateSession(&config, client, &session); if (status != KINETIC_STATUS_SUCCESS) { char msg[128]; sprintf(msg, "Failed connecting to the Kinetic device w/status: %s", Kinetic_GetStatusDescription(status)); TEST_FAIL_MESSAGE(msg); } // Generate test entry data ByteBuffer test_data = ByteBuffer_Malloc(value_size); ByteBuffer_AppendDummyData(&test_data, test_data.array.len); uint8_t tag_data[] = {0x00, 0x01, 0x02, 0x03}; ByteBuffer tag = ByteBuffer_Create(tag_data, sizeof(tag_data), sizeof(tag_data)); uint64_t r = rand(); uint64_t keys[num_ops]; KineticEntry entries[num_ops]; for (uint32_t put = 0; put < num_ops; put++) { keys[put] = put | (r << 16); } // Measure PUT performance { OpStatus put_statuses[num_ops]; for (size_t i = 0; i < num_ops; i++) { put_statuses[i] = (OpStatus){ .sem = KineticSemaphore_Create(), .status = KINETIC_STATUS_INVALID, }; }; struct timeval start_time; gettimeofday(&start_time, NULL); for (uint32_t put = 0; put < num_ops; put++) { ByteBuffer key = ByteBuffer_Create(&keys[put], sizeof(keys[put]), sizeof(keys[put])); KineticSynchronization sync = (put == num_ops - 1) ? KINETIC_SYNCHRONIZATION_FLUSH : KINETIC_SYNCHRONIZATION_WRITEBACK; entries[put] = (KineticEntry) { .key = key, .tag = tag, .algorithm = KINETIC_ALGORITHM_SHA1, .value = test_data, .synchronization = sync, }; KineticStatus status = KineticClient_Put( session, &entries[put], &(KineticCompletionClosure) { .callback = op_finished, .clientData = &put_statuses[put], } ); if (status != KINETIC_STATUS_SUCCESS) { char msg[128]; sprintf(msg, "PUT failed w/status: %s", Kinetic_GetStatusDescription(status)); TEST_FAIL_MESSAGE(msg); } } for (size_t i = 0; i < num_ops; i++) { KineticSemaphore_WaitForSignalAndDestroy(put_statuses[i].sem); if (put_statuses[i].status != KINETIC_STATUS_SUCCESS) { char msg[128]; sprintf(msg, "PUT failed w/status: %s", Kinetic_GetStatusDescription(put_statuses[i].status)); TEST_FAIL_MESSAGE(msg); } } struct timeval stop_time; gettimeofday(&stop_time, NULL); size_t bytes_written = num_ops * test_data.array.len; int64_t elapsed_us = ((stop_time.tv_sec - start_time.tv_sec) * 1000000) + (stop_time.tv_usec - start_time.tv_usec); float elapsed_ms = elapsed_us / 1000.0f; float bandwidth = (bytes_written * 1000.0f) / (elapsed_ms * 1024 * 1024); LOGF0("PUT Performance: wrote: %.1f kB, duration: %.3f sec, throughput: %.2f MB/sec", bytes_written / 1024.0f, elapsed_ms / 1000.0f, bandwidth); } // Measure GET performance { OpStatus get_statuses[num_ops]; for (size_t i = 0; i < num_ops; i++) { get_statuses[i] = (OpStatus){ .sem = KineticSemaphore_Create(), .status = KINETIC_STATUS_INVALID, }; }; ByteBuffer test_get_datas[num_ops]; for (size_t i = 0; i < num_ops; i++) { test_get_datas[i] = ByteBuffer_Malloc(value_size); } struct timeval start_time; gettimeofday(&start_time, NULL); for (uint32_t get = 0; get < num_ops; get++) { ByteBuffer key = ByteBuffer_Create(&keys[get], sizeof(keys[get]), sizeof(keys[get])); entries[get] = (KineticEntry) { .key = key, .tag = tag, .value = test_get_datas[get], }; KineticStatus status = KineticClient_Get( session, &entries[get], &(KineticCompletionClosure) { .callback = op_finished, .clientData = &get_statuses[get], } ); if (status != KINETIC_STATUS_SUCCESS) { char msg[128]; sprintf(msg, "GET failed w/status: %s", Kinetic_GetStatusDescription(status)); TEST_FAIL_MESSAGE(msg); } } size_t bytes_read = 0; for (size_t i = 0; i < num_ops; i++) { KineticSemaphore_WaitForSignalAndDestroy(get_statuses[i].sem); if (get_statuses[i].status != KINETIC_STATUS_SUCCESS) { char msg[128]; sprintf(msg, "GET failed w/status: %s", Kinetic_GetStatusDescription(get_statuses[i].status)); TEST_FAIL_MESSAGE(msg); } else { bytes_read += entries[i].value.bytesUsed; } } // Check data for integrity size_t numFailures = 0; for (size_t i = 0; i < num_ops; i++) { int res = memcmp(test_data.array.data, test_get_datas[i].array.data, test_data.array.len); if (res != 0) { LOGF0("Failed validating data in object %zu of %zu!", i+1, num_ops); numFailures++; } } TEST_ASSERT_EQUAL_MESSAGE(0, numFailures, "DATA INTEGRITY CHECK FAILED UPON READBACK!"); // Calculate and report performance struct timeval stop_time; gettimeofday(&stop_time, NULL); int64_t elapsed_us = ((stop_time.tv_sec - start_time.tv_sec) * 1000000) + (stop_time.tv_usec - start_time.tv_usec); float elapsed_ms = elapsed_us / 1000.0f; float bandwidth = (bytes_read * 1000.0f) / (elapsed_ms * 1024 * 1024); LOGF0("GET Performance: read: %.1f kB, duration: %.3f sec, throughput: %.2f MB/sec", bytes_read / 1024.0f, elapsed_ms / 1000.0f, bandwidth); for (size_t i = 0; i < num_ops; i++) { ByteBuffer_Free(test_get_datas[i]); } }
void test_KineticClient_CreateSession_should_return_KINETIC_STATUS_HOST_EMPTY_upon_NULL_host(void) { KineticClient client; ByteArray key = ByteArray_CreateWithCString("some_key"); KineticSessionConfig config = { .host = "", .hmacKey = key, }; KineticSession* session = NULL; KineticStatus status = KineticClient_CreateSession(&config, &client, &session); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_HOST_EMPTY, status); } void test_KineticClient_CreateSession_should_return_KINETIC_STATUS_HMAC_REQUIRED_upon_NULL_HMAC_key(void) { KineticClient client; ByteArray key = {.len = 4, .data = NULL}; KineticSessionConfig config = { .host = "somehost.com", .hmacKey = key, }; KineticSession* session; KineticStatus status = KineticClient_CreateSession(&config, &client, &session); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_HMAC_REQUIRED, status); } void test_KineticClient_CreateSession_should_return_false_upon_empty_HMAC_key(void) { KineticClient client; uint8_t keyData[] = {0, 1, 2, 3}; ByteArray key = {.len = 0, .data = keyData}; KineticSessionConfig config = { .host = "somehost.com", .hmacKey = key, }; KineticSession* session; KineticStatus status = KineticClient_CreateSession(&config, &client, &session); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_HMAC_REQUIRED, status); } void test_KineticClient_CreateSession_should_return_MEMORY_ERROR_if_unable_to_allocate_a_session(void) { KineticClient client; client.bus = &MessageBus; KineticSessionConfig config = { .host = "somehost.com", .hmacKey = ByteArray_CreateWithCString("some_key"), }; KineticSession* session = NULL; KineticAllocator_NewSession_ExpectAndReturn(&MessageBus, &config, NULL); KineticStatus status = KineticClient_CreateSession(&config, &client, &session); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_MEMORY_ERROR, status); } void test_KineticClient_CreateSession_should_return_KINETIC_STATUS_MEMORY_ERROR_upon_NULL_connection(void) { KineticClient client = { .bus = &MessageBus, }; KineticSessionConfig config = { .host = "somehost.com", .hmacKey = ByteArray_CreateWithCString("some_key"), }; KineticSession* session = NULL; KineticAllocator_NewSession_ExpectAndReturn(&MessageBus, &config, NULL); KineticStatus status = KineticClient_CreateSession(&config, &client, &session); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_MEMORY_ERROR, status); TEST_ASSERT_NULL(session); } void test_KineticClient_CreateSession_should_return_status_from_a_failed_connection(void) { KineticClient client; client.bus = &MessageBus; KineticSessionConfig config = { .host = "somehost.com", .hmacKey = ByteArray_CreateWithCString("some_key"), }; KineticSession* session; KineticAllocator_NewSession_ExpectAndReturn(&MessageBus, &config, &Session); KineticSession_Create_ExpectAndReturn(&Session, &client, KINETIC_STATUS_SUCCESS); KineticSession_Connect_ExpectAndReturn(&Session, KINETIC_STATUS_HMAC_REQUIRED); KineticAllocator_FreeSession_Expect(&Session); KineticStatus status = KineticClient_CreateSession(&config, &client, &session); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_HMAC_REQUIRED, status); } void test_KineticClient_DestroySession_should_disconnect_and_free_the_connection_associated_with_handle(void) { KineticSession_Disconnect_ExpectAndReturn(&Session, KINETIC_STATUS_SUCCESS); KineticSession_Destroy_ExpectAndReturn(&Session, KINETIC_STATUS_SUCCESS); KineticStatus status = KineticClient_DestroySession(&Session); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); } void test_KineticClient_DestroySession_should_return_status_from_KineticSession_upon_faileure(void) { KineticSession_Disconnect_ExpectAndReturn(&Session, KINETIC_STATUS_SESSION_INVALID); KineticSession_Destroy_ExpectAndReturn(&Session, KINETIC_STATUS_SUCCESS); KineticStatus status = KineticClient_DestroySession(&Session); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SESSION_INVALID, status); } void test_KineticClient_GetTerminationStatus_should_delegate_to_session(void) { KineticSession_GetTerminationStatus_ExpectAndReturn(&Session, KINETIC_STATUS_DATA_ERROR); KineticStatus status = KineticClient_GetTerminationStatus(&Session); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_DATA_ERROR, status); }
int main(int argc, char** argv) { (void)argc; (void)argv; // Initialize kinetic-c and configure sessions KineticSession* session; KineticClientConfig clientConfig = { .logFile = "stdout", .logLevel = 1, }; KineticClient * client = KineticClient_Init(&clientConfig); if (client == NULL) { return 1; } const char HmacKeyString[] = "asdfasdf"; KineticSessionConfig sessionConfig = { .host = "localhost", .port = KINETIC_PORT, .clusterVersion = 0, .identity = 1, .hmacKey = ByteArray_CreateWithCString(HmacKeyString), }; KineticStatus status = KineticClient_CreateSession(&sessionConfig, client, &session); if (status != KINETIC_STATUS_SUCCESS) { fprintf(stderr, "Failed connecting to the Kinetic device w/status: %s\n", Kinetic_GetStatusDescription(status)); exit(1); } // some dummy data to PUT uint8_t value_data[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; ByteBuffer value = ByteBuffer_MallocAndAppend(value_data, sizeof(value_data)); // a dummy key uint8_t key_data[] = {0x00, 0x01, 0x02, 0x03, 0x04}; ByteBuffer key = ByteBuffer_MallocAndAppend(key_data, sizeof(key_data)); // Populate tag with SHA1 ByteBuffer tag = ByteBuffer_Malloc(20); uint8_t sha1[20]; SHA1(value.array.data, value.bytesUsed, &sha1[0]); ByteBuffer_Append(&tag, sha1, sizeof(sha1)); KineticEntry entry = { .key = key, .tag = tag, .algorithm = KINETIC_ALGORITHM_SHA1, .value = value, .synchronization = KINETIC_SYNCHRONIZATION_WRITETHROUGH, }; // Do a blocking put to make sure there is something there to read back KineticStatus put_status = KineticClient_Put(session, &entry, NULL); if (put_status != KINETIC_STATUS_SUCCESS) { fprintf(stderr, "Put failed w/status: %s\n", Kinetic_GetStatusDescription(put_status)); return 1; } // Create structure to populate with GET status in callback // a semaphore is used to notify the main thread that it's // safe to proceed. GetStatus get_status = { .sem = KineticSemaphore_Create(), .status = KINETIC_STATUS_INVALID, }; ByteBuffer getTag = ByteBuffer_Malloc(tag.bytesUsed); ByteBuffer getValue = ByteBuffer_Malloc(value.bytesUsed); // Because I'm passing a pointer to this entry to KineticClient_Put(), this entry must not // go out of scope until the GET completes KineticEntry get_entry = { .key = key, .tag = getTag, .algorithm = KINETIC_ALGORITHM_SHA1, .value = getValue, .force = true, }; status = KineticClient_Get( session, &get_entry, &(KineticCompletionClosure) { .callback = get_finished, .clientData = &get_status, } ); if (status != KINETIC_STATUS_SUCCESS) { fprintf(stderr, "Get failed w/status: %s\n", Kinetic_GetStatusDescription(status)); return 1; } // Wait for GET to finish KineticSemaphore_WaitForSignalAndDestroy(get_status.sem); if (get_status.status != KINETIC_STATUS_SUCCESS) { fprintf(stderr, "GET failed w/status: %s\n", Kinetic_GetStatusDescription(get_status.status)); return 1; } if ((value.bytesUsed == getValue.bytesUsed) && (memcmp(value.array.data, getValue.array.data, getValue.bytesUsed) != 0)) { fprintf(stderr, "GET completed but returned unexpected value"); return 1; } printf("GET completed successfully!\n"); // Free malloc'd buffers ByteBuffer_Free(value); ByteBuffer_Free(key); ByteBuffer_Free(tag); ByteBuffer_Free(getValue); ByteBuffer_Free(getTag); // Shutdown client connection and cleanup KineticClient_DestroySession(session); KineticClient_Shutdown(client); return 0; } static void get_finished(KineticCompletionData* kinetic_data, void* clientData) { GetStatus * get_status = clientData; // Save GET result status get_status->status = kinetic_data->status; // Signal that we're done KineticSemaphore_Signal(get_status->sem); }
void test_kinetic_client_should_be_able_to_store_an_arbitrarily_large_binary_object_and_split_across_entries_via_ovelapped_IO_operations(void) { const int maxIterations = 4; const int numCopiesToStore = 4; const KineticSession sessionConfig = { .host = "localhost", .port = KINETIC_PORT, .nonBlocking = false, .clusterVersion = 0, .identity = 1, .hmacKey = ByteArray_CreateWithCString("asdfasdf"), }; for (int iteration = 0; iteration < maxIterations; iteration++) { printf("Overlapped PUT operation (iteration %d of %d)\n", iteration + 1, maxIterations); char* buf = malloc(sizeof(char) * BUFSIZE); int fd = open("test/support/data/test.data", O_RDONLY); int dataLen = read(fd, buf, BUFSIZE); close(fd); TEST_ASSERT_MESSAGE(dataLen > 0, "read error"); /* thread structure */ struct kinetic_thread_arg* kt_arg; pthread_t thread_id[KINETIC_MAX_THREADS]; kinetic_client = malloc(sizeof(KineticSessionHandle) * numCopiesToStore); TEST_ASSERT_NOT_NULL_MESSAGE(kinetic_client, "kinetic_client malloc failed"); kt_arg = malloc(sizeof(struct kinetic_thread_arg) * numCopiesToStore); TEST_ASSERT_NOT_NULL_MESSAGE(kt_arg, "kinetic_thread_arg malloc failed"); for (int i = 0; i < numCopiesToStore; i++) { printf(" Overlapped PUT operations (writing copy %d of %d) on IP (iteration %d of %d):%s\n", i + 1, numCopiesToStore, iteration + 1, maxIterations, sessionConfig.host); // Establish connection TEST_ASSERT_EQUAL_KineticStatus( KINETIC_STATUS_SUCCESS, KineticClient_Connect(&sessionConfig, &kinetic_client[i])); strcpy(kt_arg[i].ip, sessionConfig.host); // Configure the KineticEntry char keyPrefix[128]; snprintf(keyPrefix, sizeof(keyPrefix), "pre_%02d%02d", iteration, i); LOGF("NEW HUNK PREFIX: %s", keyPrefix); ByteBuffer keyBuf = ByteBuffer_Create(kt_arg[i].key, sizeof(kt_arg[i].key)); ByteBuffer_AppendCString(&keyBuf, keyPrefix); kt_arg[i].keyPrefixLength = keyBuf.bytesUsed; ByteBuffer verBuf = ByteBuffer_Create(kt_arg[i].version, sizeof(kt_arg[i].version)); ByteBuffer_AppendCString(&verBuf, "v1.0"); ByteBuffer tagBuf = ByteBuffer_Create(kt_arg[i].tag, sizeof(kt_arg[i].tag)); ByteBuffer_AppendCString(&tagBuf, "some_value_tag..."); ByteBuffer valBuf = ByteBuffer_Create(kt_arg[i].value, sizeof(kt_arg[i].value)); kt_arg[i].entry = (KineticEntry) { .key = keyBuf, .newVersion = verBuf, .tag = tagBuf, .metadataOnly = false, .algorithm = KINETIC_ALGORITHM_SHA1, .value = valBuf, }; // Create a ByteBuffer for consuming chunks of data out of for overlapped PUTs kt_arg[i].data = ByteBuffer_Create(buf, dataLen); // Spawn the worker thread kt_arg[i].sessionHandle = kinetic_client[i]; int create_status = pthread_create(&thread_id[i], NULL, kinetic_put, &kt_arg[i]); TEST_ASSERT_EQUAL_MESSAGE(0, create_status, "pthread create failed"); } // Wait for each overlapped PUT operations to complete and cleanup printf(" Waiting for PUT threads to exit...\n"); for (int i = 0; i < numCopiesToStore; i++) { int join_status = pthread_join(thread_id[i], NULL); TEST_ASSERT_EQUAL_MESSAGE(0, join_status, "pthread join failed"); KineticClient_Disconnect(&kinetic_client[i]); } // Cleanup the rest of the reources free(kinetic_client); free(kt_arg); free(buf); printf(" Iteration complete!\n"); } printf("Overlapped PUT operation test complete!\n"); }
void test_KineticClient_Init_should_initialize_the_message_bus_and_return_a_new_client(void) { KineticClient client; KineticClientConfig config = { .logFile = "stdout", .logLevel = 3, }; KineticCalloc_ExpectAndReturn(1, sizeof(KineticClient), &client); KineticBus_Init_ExpectAndReturn(&client, &config, true); KineticClient * result = KineticClient_Init(&config); TEST_ASSERT_EQUAL(&client, result); } void test_KineticClient_Init_should_return_null_if_calloc_returns_null(void) { KineticClientConfig config = { .logFile = "stdout", .logLevel = 3, }; KineticCalloc_ExpectAndReturn(1, sizeof(KineticClient), NULL); KineticClient * result = KineticClient_Init(&config); TEST_ASSERT_NULL(result); } void test_KineticClient_Init_should_free_client_if_bus_init_fails(void) { KineticClient client; KineticClientConfig config = { .logFile = "stdout", .logLevel = 3, }; KineticCalloc_ExpectAndReturn(1, sizeof(KineticClient), &client); KineticBus_Init_ExpectAndReturn(&client, &config, false); KineticFree_Expect(&client); KineticClient * result = KineticClient_Init(&config); TEST_ASSERT_NULL(result); } static void ConnectSession(void) { KineticClient client; client.bus = &MessageBus; HmacKey = ByteArray_CreateWithCString("some hmac key"); KineticSessionConfig config = { .host = "localhost", .port = KINETIC_PORT, .clusterVersion = ClusterVersion, .identity = Identity, .hmacKey = HmacKey, }; Session.connected = false; // Ensure gets set appropriately by internal connect call Session.config = config; KineticSession* session; KineticAllocator_NewSession_ExpectAndReturn(&MessageBus, &config, &Session); KineticSession_Create_ExpectAndReturn(&Session, &client, KINETIC_STATUS_SUCCESS); KineticSession_Connect_ExpectAndReturn(&Session, KINETIC_STATUS_SUCCESS); KineticStatus status = KineticClient_CreateSession(&config, &client, &session); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); } void test_KineticClient_CreateSession_should_configure_a_session_and_connect_to_specified_host(void) { ConnectSession(); } void test_KineticClient_CreateSession_should_return_KINETIC_STATUS_SESSION_EMPTY_upon_NULL_session_config(void) { KineticStatus status = KineticClient_CreateSession(NULL, NULL, NULL); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SESSION_INVALID, status); }
static void do_put_and_getkeyrange(KineticSession * const session) { for (int i = 0; i < 5; i++) { char key[] = "keyX"; key[3] = '0' + i; ByteBuffer put_key_buf = ByteBuffer_MallocAndAppend(key, strlen(key)); uint8_t value[] = "valueX"; value[5] = '0' + i; ByteBuffer put_value_buf = ByteBuffer_MallocAndAppend(value, sizeof(value)); /* Populate tag with SHA1 of value */ ByteBuffer put_tag_buf = ByteBuffer_Malloc(20); uint8_t sha1[20]; SHA1(put_value_buf.array.data, put_value_buf.bytesUsed, &sha1[0]); ByteBuffer_Append(&put_tag_buf, sha1, sizeof(sha1)); KineticEntry put_entry = { .key = put_key_buf, .value = put_value_buf, .tag = put_tag_buf, .algorithm = KINETIC_ALGORITHM_SHA1, /* Set sync to WRITETHROUGH, which will wait to complete * until the drive has persistend the write. (WRITEBACK * returns as soon as the drive has buffered the write.) */ .synchronization = KINETIC_SYNCHRONIZATION_WRITETHROUGH, }; /* Put "keyX" => "valueX", where 'X' is 0..4. * This will block, because the callback field (arg 3) is NULL. */ KineticStatus status = KineticClient_Put(session, &put_entry, NULL); printf("Put status: %s\n", Kinetic_GetStatusDescription(status)); ByteBuffer_Free(put_key_buf); ByteBuffer_Free(put_value_buf); ByteBuffer_Free(put_tag_buf); } const size_t max_key_count = 5; const size_t max_key_length = 64; uint8_t first_key[max_key_length]; uint8_t last_key[max_key_length]; KineticKeyRange range = { .startKey = ByteBuffer_CreateAndAppendCString(first_key, sizeof(first_key), "key"), .endKey = ByteBuffer_CreateAndAppendCString(last_key, sizeof(last_key), "key\xFF"), .startKeyInclusive = true, .endKeyInclusive = true, .maxReturned = max_key_count, }; uint8_t key_mem[max_key_count][max_key_length]; memset(key_mem, 0, sizeof(key_mem)); ByteBuffer key_buffers[max_key_count]; for (size_t i = 0; i < max_key_count; i++) { key_buffers[i] = ByteBuffer_Create(&key_buffers[i], max_key_length, 0); } ByteBufferArray keys = { .buffers = key_buffers, .count = max_key_count, }; /* Request the key range as specified in &range, populating the keys in &keys. */ KineticStatus status = KineticClient_GetKeyRange(session, &range, &keys, NULL); printf("GetKeyRange status: %s\n", Kinetic_GetStatusDescription(status)); if (status == KINETIC_STATUS_SUCCESS) { for (size_t i = 0; i < max_key_count; i++) { printf("%zd: %s\n", i, key_buffers[i].array.data); } } /* No cleanup necessary */ } int main(int argc, char** argv) { (void)argc; (void)argv; // Initialize kinetic-c and configure sessions KineticSession* session; KineticClientConfig clientConfig = { .logFile = "stdout", .logLevel = 1, }; KineticClient * client = KineticClient_Init(&clientConfig); if (client == NULL) { return 1; } const char HmacKeyString[] = "asdfasdf"; KineticSessionConfig sessionConfig = { .host = "localhost", .port = KINETIC_PORT, .clusterVersion = 0, .identity = 1, .hmacKey = ByteArray_CreateWithCString(HmacKeyString), }; KineticStatus status = KineticClient_CreateSession(&sessionConfig, client, &session); if (status != KINETIC_STATUS_SUCCESS) { fprintf(stderr, "Failed connecting to the Kinetic device w/status: %s\n", Kinetic_GetStatusDescription(status)); exit(1); } do_put_and_getkeyrange(session); // Shutdown client connection and cleanup KineticClient_DestroySession(session); KineticClient_Shutdown(client); return 0; }