diff --git a/Makefile b/Makefile index 3062634f..90f25ebb 100644 --- a/Makefile +++ b/Makefile @@ -6,8 +6,11 @@ build: test: @$(MAKE) -C test/unit test --no-print-directory -integration_test: - @$(MAKE) -C test/integration test --no-print-directory +build_test: + @$(MAKE) -C test/integration build --no-print-directory + +functionality_test: + @$(MAKE) -C test/integration functionality_test --no-print-directory clean: @$(MAKE) -C src/ clean --no-print-directory diff --git a/scripts/install.sh b/scripts/install.sh index e89f47d6..e27d0168 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -214,6 +214,8 @@ printf "%s%s\n\n" "$pad" '/____/ |__/|__/\____/_/ /_/|_|\___/_/ /_/_/ /_/__ verbose INFO "Version -----------------$newversion-------------------" +disown -r + # check previous crust-sworker checkOldCrustTee diff --git a/scripts/install_deps.sh b/scripts/install_deps.sh index 908779d2..b99a5b8f 100755 --- a/scripts/install_deps.sh +++ b/scripts/install_deps.sh @@ -362,6 +362,8 @@ crust_env_file=$realsworkerdir/etc/environment sgx_env_file=/opt/intel/sgxsdk/environment +disown -r + . $scriptdir/utils.sh #trap "success_exit" INT diff --git a/src/app/ecalls/ECalls.cpp b/src/app/ecalls/ECalls.cpp index 153932ba..76f66bcf 100644 --- a/src/app/ecalls/ECalls.cpp +++ b/src/app/ecalls/ECalls.cpp @@ -22,6 +22,7 @@ std::unordered_map g_task_priority_um = { {"Ecall_get_signed_order_report", 0}, {"Ecall_confirm_file", 0}, {"Ecall_delete_file", 0}, + {"Ecall_handle_report_result", 0}, {"Ecall_seal_file", 1}, {"Ecall_unseal_file", 1}, {"Ecall_srd_decrease", 1}, @@ -582,6 +583,25 @@ sgx_status_t Ecall_delete_file(sgx_enclave_id_t eid, crust_status_t *status, con return ret; } +/** + * @description: Delete file + * @param flag -> Report result + */ +sgx_status_t Ecall_handle_report_result(sgx_enclave_id_t eid) +{ + sgx_status_t ret = SGX_SUCCESS; + if (SGX_SUCCESS != (ret = try_get_enclave(__FUNCTION__))) + { + return ret; + } + + ret = ecall_handle_report_result(eid); + + free_enclave(__FUNCTION__); + + return ret; +} + /** * @description: Get enclave id information */ diff --git a/src/app/ecalls/ECalls.h b/src/app/ecalls/ECalls.h index 3719e9df..6cc16a8b 100644 --- a/src/app/ecalls/ECalls.h +++ b/src/app/ecalls/ECalls.h @@ -62,6 +62,8 @@ sgx_status_t Ecall_confirm_file(sgx_enclave_id_t eid, crust_status_t *status, co sgx_status_t Ecall_delete_file(sgx_enclave_id_t eid, crust_status_t *status, const char *hash); +sgx_status_t Ecall_handle_report_result(sgx_enclave_id_t eid); + sgx_status_t Ecall_get_signed_order_report(sgx_enclave_id_t eid, crust_status_t *status); sgx_status_t Ecall_id_get_info(sgx_enclave_id_t eid); diff --git a/src/app/process/Storage.cpp b/src/app/process/Storage.cpp index b6d4b05e..d93375bd 100644 --- a/src/app/process/Storage.cpp +++ b/src/app/process/Storage.cpp @@ -37,3 +37,19 @@ void storage_add_delete(std::string hash) } }); } + +/** + * @description: Add delete meaningful file task + * @param hash -> Meaningful file root hash + */ +void report_add_callback() +{ + sgx_enclave_id_t eid = global_eid; + std::async(std::launch::async, [eid](){ + sgx_status_t sgx_status = SGX_SUCCESS; + if (SGX_SUCCESS != (sgx_status = Ecall_handle_report_result(eid))) + { + p_log->err("Report result failed!Invoke SGX API failed!Error code:%lx\n", sgx_status); + } + }); +} diff --git a/src/app/process/Storage.h b/src/app/process/Storage.h index 9c13eef0..095273ff 100644 --- a/src/app/process/Storage.h +++ b/src/app/process/Storage.h @@ -14,6 +14,7 @@ extern "C" void storage_add_confirm(std::string hash); void storage_add_delete(std::string hash); +void report_add_callback(); #if defined(__cplusplus) } diff --git a/src/app/process/WorkReport.cpp b/src/app/process/WorkReport.cpp index f3ac9954..188eaf99 100644 --- a/src/app/process/WorkReport.cpp +++ b/src/app/process/WorkReport.cpp @@ -97,6 +97,7 @@ void work_report_loop(void) else { p_log->info("Send work report to crust chain successfully!\n"); + report_add_callback(); } } else if (crust_status == CRUST_BLOCK_HEIGHT_EXPIRED) diff --git a/src/app/process/WorkReport.h b/src/app/process/WorkReport.h index ecd21dc0..b03c777b 100644 --- a/src/app/process/WorkReport.h +++ b/src/app/process/WorkReport.h @@ -14,6 +14,7 @@ #include "CrustStatus.h" #include "FormatUtils.h" #include "Data.h" +#include "Storage.h" #define REPORT_BLOCK_HEIGHT_BASE 300 #define BLOCK_INTERVAL 6 diff --git a/src/enclave/Enclave.cpp b/src/enclave/Enclave.cpp index 8769a618..41908b77 100644 --- a/src/enclave/Enclave.cpp +++ b/src/enclave/Enclave.cpp @@ -243,6 +243,15 @@ crust_status_t ecall_delete_file(const char *hash) return ret; } +/** + * @description: Set work report result + * @param flag -> Report result + */ +void ecall_handle_report_result() +{ + Workload::get_instance()->handle_report_result(); +} + /** * @description: Get enclave id information */ diff --git a/src/enclave/Enclave.edl b/src/enclave/Enclave.edl index 5de0ab71..ccad93cf 100644 --- a/src/enclave/Enclave.edl +++ b/src/enclave/Enclave.edl @@ -33,6 +33,7 @@ enclave { public crust_status_t ecall_unseal_file([in, count=files_num] char **files, size_t files_num, [in, string] const char *p_dir, [out, size=path_len] char *p_new_path, uint32_t path_len); public crust_status_t ecall_confirm_file([in, string] const char *hash); public crust_status_t ecall_delete_file([in, string] const char *hash); + public void ecall_handle_report_result(); public void ecall_id_get_info(); public void ecall_get_workload(); diff --git a/src/enclave/identity/Identity.cpp b/src/enclave/identity/Identity.cpp index 02a6bd98..f83a3908 100644 --- a/src/enclave/identity/Identity.cpp +++ b/src/enclave/identity/Identity.cpp @@ -588,7 +588,7 @@ crust_status_t id_verify_iasreport(char **IASReport, size_t size) status = CRUST_SIGN_PUBKEY_FAILED; goto cleanup; } - + // Get tee identity and store it outside of tee id_json[IAS_CERT] = certchain_1; id_json[IAS_SIG] = ias_sig; @@ -924,16 +924,16 @@ crust_status_t id_store_metadata() meta_len += wl->srd_path2hashs_m.size() * (128 + 4); meta_len += strlen(TEE_PRIVATE_TAG) + 5 + strlen(ID_WORKLOAD) + 5 - + strlen(ID_KEY_PAIR) + 5 - + strlen(ID_REPORT_SLOT) + 5 - + strlen(ID_CHAIN_ACCOUNT_ID) + 5 - + strlen(ID_FILE) + 5; - size_t file_item_len = strlen(FILE_HASH) + 3 + 64 + 3 - + strlen(FILE_OLD_HASH) + 3 + 64 + 3 - + strlen(FILE_SIZE) + 3 + 14 + 1 - + strlen(FILE_OLD_SIZE) + 3 + 14 + 1 - + strlen(FILE_BLOCK_NUM) + 3 + 14 + 4 - + strlen(FILE_STATUS) + 16 + 4 + + strlen(ID_KEY_PAIR) + 3 + 256 + 3 + + strlen(ID_REPORT_SLOT) + 3 + 20 + 1 + + strlen(ID_CHAIN_ACCOUNT_ID) + 3 + 64 + 3 + + strlen(ID_FILE) + 3; + size_t file_item_len = strlen(FILE_HASH) + 3 + strlen(HASH_TAG) + 64 + 3 + + strlen(FILE_OLD_HASH) + 3 + strlen(HASH_TAG) + 64 + 3 + + strlen(FILE_SIZE) + 3 + 12 + 1 + + strlen(FILE_OLD_SIZE) + 3 + 12 + 1 + + strlen(FILE_BLOCK_NUM) + 3 + 6 + 1 + + strlen(FILE_STATUS) + 3 + 3 + 3 + 2; meta_len += wl->checked_files.size() * file_item_len; uint8_t *meta_buf = (uint8_t *)enc_malloc(meta_len); @@ -1094,14 +1094,6 @@ crust_status_t id_restore_metadata() g_is_set_account_id = true; just_after_restart = true; - // Show workload - json::JSON wl_json = json::JSON::Load(wl->get_workload()); - std::string wl_str = wl_json.dump(); - replace(wl_str, "\"{", "{"); - replace(wl_str, "}\"", " }"); - remove_char(wl_str, '\\'); - log_info("Workload:\n%s\n", wl_str.c_str()); - return CRUST_SUCCESS; } diff --git a/src/enclave/include/Parameter.h b/src/enclave/include/Parameter.h index d42dc61f..dd775beb 100644 --- a/src/enclave/include/Parameter.h +++ b/src/enclave/include/Parameter.h @@ -23,9 +23,16 @@ #define FILE_OLD_HASH "old_hash" #define FILE_BLOCK_NUM "block_num" #define FILE_STATUS "status" -#define FILE_STATUS_LOST "lost" -#define FILE_STATUS_VALID "valid" -#define FILE_STATUS_UNCONFIRMED "unconfirmed" +#define FILE_STATUS_UNCONFIRMED '0' +#define FILE_STATUS_VALID '1' +#define FILE_STATUS_LOST '2' +#define FILE_STATUS_DELETED '3' +// Current status +#define CURRENT_STATUS 0 +// Wait to sync status +#define WAITING_STATUS 1 +// Old status +#define ORIGIN_STATUS 2 // For DB data #define DB_SRD_INFO "srd_info" @@ -46,11 +53,17 @@ // For work report #define WORKREPORT_PUB_KEY "pub_key" +#define WORKREPORT_PRE_PUB_KEY "pre_pub_key" #define WORKREPORT_BLOCK_HEIGHT "block_height" #define WORKREPORT_BLOCK_HASH "block_hash" #define WORKREPORT_RESERVED "reserved" -#define WORKREPORT_FILES "files" +#define WORKREPORT_FILES_SIZE "files_size" +#define WORKREPORT_RESERVED_ROOT "reserved_root" +#define WORKREPORT_FILES_ROOT "files_root" +#define WORKREPORT_FILES_ADDED "added_files" +#define WORKREPORT_FILES_DELETED "deleted_files" #define WORKREPORT_SIG "sig" +#define WORKREPORT_FILE_LIMIT 1000 // For order report #define ORDERREPORT_FILES "files" diff --git a/src/enclave/report/Report.cpp b/src/enclave/report/Report.cpp index 5a14e7d7..d06b82eb 100644 --- a/src/enclave/report/Report.cpp +++ b/src/enclave/report/Report.cpp @@ -94,47 +94,165 @@ crust_status_t get_signed_work_report(const char *block_hash, size_t block_heigh sgx_status_t sgx_status; // ----- Get srd info ----- // sgx_thread_mutex_lock(&g_srd_mutex); - size_t srd_workload = 0; + size_t srd_workload; + sgx_sha256_hash_t srd_root; + // Get hashs for hashing + size_t g_hashs_num = 0; for (auto it : wl->srd_path2hashs_m) { - srd_workload += it.second.size() * 1024 * 1024 * 1024; + g_hashs_num += it.second.size(); } + uint8_t *hashs = (uint8_t *)enc_malloc(g_hashs_num * HASH_LENGTH); + if (hashs == NULL) + { + log_err("Malloc memory failed!\n"); + return CRUST_MALLOC_FAILED; + } + size_t hashs_len = 0; + for (auto it : wl->srd_path2hashs_m) + { + for (auto g_hash : it.second) + { + memcpy(hashs + hashs_len, g_hash, HASH_LENGTH); + hashs_len += HASH_LENGTH; + } + } + // Generate srd information + if (hashs_len == 0) + { + srd_workload = 0; + memset(srd_root, 0, HASH_LENGTH); + } + else + { + srd_workload = (hashs_len / HASH_LENGTH) * 1024 * 1024 * 1024; + sgx_sha256_msg(hashs, (uint32_t)hashs_len, &srd_root); + } + free(hashs); sgx_thread_mutex_unlock(&g_srd_mutex); // ----- Get files info ----- // - std::string old_files = "["; sgx_thread_mutex_lock(&g_checked_files_mutex); + // Deleted invalid file item + size_t files_buffer_len = 0; + for (auto it = wl->checked_files.begin(); it != wl->checked_files.end();) + { + std::string status = (*it)[FILE_STATUS].ToString(); + if (status[CURRENT_STATUS] == FILE_STATUS_VALID) + { + files_buffer_len += HASH_LENGTH; + } + if ((status[CURRENT_STATUS] == FILE_STATUS_DELETED && status[ORIGIN_STATUS] == FILE_STATUS_LOST) + || (status[CURRENT_STATUS] == FILE_STATUS_DELETED && status[ORIGIN_STATUS] == FILE_STATUS_DELETED) + || (status[CURRENT_STATUS] == FILE_STATUS_DELETED && status[ORIGIN_STATUS] == FILE_STATUS_UNCONFIRMED)) + { + it = wl->checked_files.erase(it); + } + else + { + it++; + } + } + // Clear reported_files_idx + wl->reported_files_idx.clear(); + // Generate files information + sgx_sha256_hash_t files_root; + long long files_size = 0; + size_t files_offset = 0; + uint8_t *files_buffer = (uint8_t *)enc_malloc(files_buffer_len); + if (files_buffer == NULL) + { + return CRUST_MALLOC_FAILED; + } + memset(files_buffer, 0, files_buffer_len); + std::string added_files = "["; + std::string deleted_files = "["; + size_t files_acc = 0; for (uint32_t i = 0; i < wl->checked_files.size(); i++) { - if (wl->checked_files[i][FILE_STATUS].ToString().compare(FILE_STATUS_VALID) != 0) + auto status = &wl->checked_files[i][FILE_STATUS]; + // Write current status to waiting status + status->set_char(WAITING_STATUS, status->get_char(CURRENT_STATUS)); + // Calculate old files size + if (status->get_char(ORIGIN_STATUS) == FILE_STATUS_VALID) { - continue; + files_size += wl->checked_files[i][FILE_OLD_SIZE].ToInt(); } - - if (old_files.size() != 1) + // Calculate files(valid) root hash + if (status->get_char(CURRENT_STATUS) == FILE_STATUS_VALID) + { + memcpy(files_buffer + files_offset, wl->checked_files[i][FILE_HASH].ToBytes(), HASH_LENGTH); + files_offset += HASH_LENGTH; + } + // Generate report files queue + if (files_acc < WORKREPORT_FILE_LIMIT) { - old_files.append(","); + if ((status->get_char(CURRENT_STATUS) == FILE_STATUS_VALID && status->get_char(ORIGIN_STATUS) == FILE_STATUS_UNCONFIRMED) + || (status->get_char(CURRENT_STATUS) == FILE_STATUS_VALID && status->get_char(ORIGIN_STATUS) == FILE_STATUS_LOST) + || (status->get_char(CURRENT_STATUS) == FILE_STATUS_LOST && status->get_char(ORIGIN_STATUS) == FILE_STATUS_VALID) + || (status->get_char(CURRENT_STATUS) == FILE_STATUS_DELETED && status->get_char(ORIGIN_STATUS) == FILE_STATUS_VALID)) + { + std::string file_str; + file_str.append("{\"").append(FILE_HASH).append("\":") + .append("\"").append(wl->checked_files[i][FILE_OLD_HASH].ToString()).append("\","); + file_str.append("\"").append(FILE_SIZE).append("\":") + .append(std::to_string(wl->checked_files[i][FILE_OLD_SIZE].ToInt())).append("}"); + if (status->get_char(CURRENT_STATUS) == FILE_STATUS_LOST || status->get_char(CURRENT_STATUS) == FILE_STATUS_DELETED) + { + if (deleted_files.size() != 1) + { + deleted_files.append(","); + } + deleted_files.append(file_str); + // Update new files size + files_size -= wl->checked_files[i][FILE_OLD_SIZE].ToInt(); + } + else if (status->get_char(CURRENT_STATUS) == FILE_STATUS_VALID) + { + if (added_files.size() != 1) + { + added_files.append(","); + } + added_files.append(file_str); + // Update new files size + files_size += wl->checked_files[i][FILE_OLD_SIZE].ToInt(); + } + wl->reported_files_idx.insert(i); + files_acc++; + } } - old_files.append("{\"").append(FILE_HASH).append("\":") - .append("\"").append(wl->checked_files[i][FILE_OLD_HASH].ToString()).append("\","); - old_files.append("\"").append(FILE_SIZE).append("\":") - .append(std::to_string(wl->checked_files[i][FILE_OLD_SIZE].ToInt())).append("}"); } + added_files.append("]"); + deleted_files.append("]"); sgx_thread_mutex_unlock(&g_checked_files_mutex); - old_files.append("]"); + sgx_sha256_msg(files_buffer, (uint32_t)files_offset, &files_root); + free(files_buffer); // ----- Create signature data ----- // sgx_ecc_state_handle_t ecc_state = NULL; sgx_ec256_signature_t sgx_sig; std::string wr_str; uint8_t *block_hash_u = NULL; + std::string pre_pub_key = ""; + size_t pre_pub_key_size = 0; + if (wl->is_upgrade()) + { + pre_pub_key_size = sizeof(wl->pre_pub_key); + pre_pub_key = hexstring_safe(&wl->pre_pub_key, sizeof(wl->pre_pub_key)); + } std::string block_height_str = std::to_string(block_height); std::string reserved_str = std::to_string(srd_workload); + std::string files_size_str = std::to_string(files_size); size_t sigbuf_len = sizeof(id_key_pair.pub_key) - + block_height_str.size() - + HASH_LENGTH - + reserved_str.size() - + old_files.size(); + + pre_pub_key_size + + block_height_str.size() + + HASH_LENGTH + + reserved_str.size() + + files_size_str.size() + + sizeof(sgx_sha256_hash_t) + + sizeof(sgx_sha256_hash_t) + + added_files.size() + + deleted_files.size(); uint8_t *sigbuf = (uint8_t *)enc_malloc(sigbuf_len); if (sigbuf == NULL) { @@ -143,9 +261,15 @@ crust_status_t get_signed_work_report(const char *block_hash, size_t block_heigh } memset(sigbuf, 0, sigbuf_len); uint8_t *p_sigbuf = sigbuf; - // Public key + // Current public key memcpy(sigbuf, &id_key_pair.pub_key, sizeof(id_key_pair.pub_key)); sigbuf += sizeof(id_key_pair.pub_key); + // Previous public key + if (wl->is_upgrade()) + { + memcpy(sigbuf, &wl->pre_pub_key, pre_pub_key_size); + sigbuf += pre_pub_key_size; + } // Block height memcpy(sigbuf, block_height_str.c_str(), block_height_str.size()); sigbuf += block_height_str.size(); @@ -159,11 +283,24 @@ crust_status_t get_signed_work_report(const char *block_hash, size_t block_heigh memcpy(sigbuf, block_hash_u, HASH_LENGTH); sigbuf += HASH_LENGTH; free(block_hash_u); - // Reserve + // Reserved memcpy(sigbuf, reserved_str.c_str(), reserved_str.size()); sigbuf += reserved_str.size(); - // Files - memcpy(sigbuf, old_files.c_str(), old_files.size()); + // Files size + memcpy(sigbuf, files_size_str.c_str(), files_size_str.size()); + sigbuf += files_size_str.size(); + // Reserved root + memcpy(sigbuf, srd_root, sizeof(sgx_sha256_hash_t)); + sigbuf += sizeof(sgx_sha256_hash_t); + // Files root + memcpy(sigbuf, files_root, sizeof(sgx_sha256_hash_t)); + sigbuf += sizeof(sgx_sha256_hash_t); + // Added files + memcpy(sigbuf, added_files.c_str(), added_files.size()); + sigbuf += added_files.size(); + // Deleted files + memcpy(sigbuf, deleted_files.c_str(), deleted_files.size()); + sigbuf += deleted_files.size(); // Sign work report sgx_status = sgx_ecc256_open_context(&ecc_state); @@ -183,14 +320,24 @@ crust_status_t get_signed_work_report(const char *block_hash, size_t block_heigh wr_str.append("{"); wr_str.append("\"").append(WORKREPORT_PUB_KEY).append("\":") .append("\"").append(hexstring_safe(&id_key_pair.pub_key, sizeof(id_key_pair.pub_key))).append("\","); + wr_str.append("\"").append(WORKREPORT_PRE_PUB_KEY).append("\":") + .append("\"").append(pre_pub_key).append("\","); wr_str.append("\"").append(WORKREPORT_BLOCK_HEIGHT).append("\":") .append("\"").append(block_height_str).append("\","); wr_str.append("\"").append(WORKREPORT_BLOCK_HASH).append("\":") .append("\"").append(block_hash, HASH_LENGTH * 2).append("\","); wr_str.append("\"").append(WORKREPORT_RESERVED).append("\":") .append(std::to_string(srd_workload)).append(","); - wr_str.append("\"").append(WORKREPORT_FILES).append("\":") - .append(old_files).append(","); + wr_str.append("\"").append(WORKREPORT_FILES_SIZE).append("\":") + .append(std::to_string(files_size)).append(","); + wr_str.append("\"").append(WORKREPORT_RESERVED_ROOT).append("\":") + .append("\"").append(hexstring_safe(srd_root, HASH_LENGTH)).append("\","); + wr_str.append("\"").append(WORKREPORT_FILES_ROOT).append("\":") + .append("\"").append(hexstring_safe(files_root, HASH_LENGTH)).append("\","); + wr_str.append("\"").append(WORKREPORT_FILES_ADDED).append("\":") + .append(added_files).append(","); + wr_str.append("\"").append(WORKREPORT_FILES_DELETED).append("\":") + .append(deleted_files).append(","); wr_str.append("\"").append(WORKREPORT_SIG).append("\":") .append("\"").append(hexstring_safe(&sgx_sig, sizeof(sgx_ec256_signature_t))).append("\""); wr_str.append("}"); diff --git a/src/enclave/storage/Storage.cpp b/src/enclave/storage/Storage.cpp index 9d45a3cc..78d892b6 100644 --- a/src/enclave/storage/Storage.cpp +++ b/src/enclave/storage/Storage.cpp @@ -86,7 +86,7 @@ crust_status_t storage_seal_file(const char *p_tree, size_t tree_len, const char file_entry_json[FILE_OLD_SIZE] = org_node_size; file_entry_json[FILE_BLOCK_NUM] = block_num; // Status indicates current new file's status, which must be one of valid, lost and unconfirmed - file_entry_json[FILE_STATUS] = FILE_STATUS_UNCONFIRMED; + file_entry_json[FILE_STATUS] = "000"; free(new_root_hash_u); free(org_root_hash_u); @@ -109,10 +109,9 @@ crust_status_t storage_seal_file(const char *p_tree, size_t tree_len, const char } // Print sealed file information - log_info("Seal complete, file info; hash: %s -> size: %ld, status: %s\n", + log_info("Seal complete, file info; hash: %s -> size: %ld, status: unconfirmed\n", file_entry_json[FILE_HASH].ToString().c_str(), - file_entry_json[FILE_SIZE].ToInt(), - file_entry_json[FILE_STATUS].ToString().c_str()); + file_entry_json[FILE_SIZE].ToInt()); // Add new file to buffer Workload::get_instance()->add_new_file(file_entry_json); @@ -435,9 +434,10 @@ crust_status_t storage_confirm_file(const char *hash) { if ((*it)[FILE_HASH].ToString().compare(hash) == 0) { - if ((*it)[FILE_STATUS].ToString().compare(FILE_STATUS_UNCONFIRMED) == 0) + auto status = &(*it)[FILE_STATUS]; + if (status->get_char(CURRENT_STATUS) == FILE_STATUS_UNCONFIRMED) { - (*it)[FILE_STATUS] = FILE_STATUS_VALID; + status->set_char(CURRENT_STATUS, FILE_STATUS_VALID); } is_confirmed = true; confirmed_file = *it; @@ -452,9 +452,10 @@ crust_status_t storage_confirm_file(const char *hash) { if ((*it)[FILE_HASH].ToString().compare(hash) == 0) { - if ((*it)[FILE_STATUS].ToString().compare(FILE_STATUS_UNCONFIRMED) == 0) + auto status = &(*it)[FILE_STATUS]; + if (status->get_char(CURRENT_STATUS) == FILE_STATUS_UNCONFIRMED) { - (*it)[FILE_STATUS] = FILE_STATUS_VALID; + status->set_char(CURRENT_STATUS, FILE_STATUS_VALID); is_confirmed = true; confirmed_file = *it; break; @@ -498,13 +499,13 @@ crust_status_t storage_delete_file(const char *hash) sgx_thread_mutex_lock(&g_checked_files_mutex); Workload *wl = Workload::get_instance(); bool is_deleted = false; - for (auto it = wl->checked_files.rbegin(); it != wl->checked_files.rend(); it++) + for (size_t i = 0; i < wl->checked_files.size(); i++) { - std::string hash_str = (*it)[FILE_HASH].ToString(); + std::string hash_str = wl->checked_files[i][FILE_HASH].ToString(); if (hash_str.compare(hash) == 0) { + wl->checked_files[i][FILE_STATUS].set_char(CURRENT_STATUS, FILE_STATUS_DELETED); deleted_file = hash_str; - wl->checked_files.erase((++it).base()); is_deleted = true; break; } diff --git a/src/enclave/utils/EJson.h b/src/enclave/utils/EJson.h index b6c77d1f..109952f7 100644 --- a/src/enclave/utils/EJson.h +++ b/src/enclave/utils/EJson.h @@ -13,6 +13,8 @@ #include #include "EUtils.h" +#define HASH_TAG "$&JT&$" + namespace json { @@ -350,6 +352,25 @@ class JSON return Internal.List->operator[](index); } + char get_char(size_t index) + { + if (Type != Class::String || index >= Internal.String->size()) + return '\0'; + + return Internal.String->operator[](index); + } + + void set_char(size_t index, char c) + { + if (Type != Class::String || index > Internal.String->size()) + return; + + if (index == Internal.String->size()) + Internal.String->push_back(c); + else + Internal.String->operator[](index) = c; + } + JSON &at(const string &key) { return operator[](key); @@ -420,6 +441,17 @@ class JSON return string(""); } + uint8_t *ToBytes() + { + bool b; + return ToBytes(b); + } + uint8_t *ToBytes(bool &ok) + { + ok = (Type == Class::Hash); + return ok ? Internal.HashList : NULL; + } + double ToFloat() const { bool b; @@ -521,7 +553,7 @@ class JSON } case Class::Hash: { - return "\"" + _hexstring(Internal.HashList, _hash_length) + "\""; + return "\"" HASH_TAG + _hexstring(Internal.HashList, _hash_length) + "\""; } case Class::String: return "\"" + json_escape(*Internal.String) + "\""; @@ -827,7 +859,7 @@ JSON parse_array(const uint8_t *p_data, size_t &offset) JSON parse_string(const string &str, size_t &offset) { - JSON String; + JSON ans; string val; for (char c = str[++offset]; c != '\"'; c = str[++offset]) { @@ -886,13 +918,24 @@ JSON parse_string(const string &str, size_t &offset) val += c; } ++offset; - String = val; - return std::move(String); + if (memcmp(val.c_str(), HASH_TAG, strlen(HASH_TAG)) == 0) + { + val = val.substr(strlen(HASH_TAG), val.size()); + uint8_t *p_hash = hex_string_to_bytes(val.c_str(), val.size()); + if (p_hash != NULL) + { + ans = p_hash; + free(p_hash); + return std::move(ans); + } + } + ans = val; + return std::move(ans); } JSON parse_string(const uint8_t *p_data, size_t &offset) { - JSON String; + JSON ans; string val; for (char c = p_data[++offset]; c != '\"'; c = p_data[++offset]) { @@ -951,8 +994,19 @@ JSON parse_string(const uint8_t *p_data, size_t &offset) val += c; } ++offset; - String = val; - return std::move(String); + if (memcmp(val.c_str(), HASH_TAG, strlen(HASH_TAG)) == 0) + { + val = val.substr(strlen(HASH_TAG), val.size()); + uint8_t *p_hash = hex_string_to_bytes(val.c_str(), val.size()); + if (p_hash != NULL) + { + ans = p_hash; + free(p_hash); + return std::move(ans); + } + } + ans = val; + return std::move(ans); } JSON parse_number(const string &str, size_t &offset) diff --git a/src/enclave/validator/Validator.cpp b/src/enclave/validator/Validator.cpp index 3a3357ea..c065bf84 100644 --- a/src/enclave/validator/Validator.cpp +++ b/src/enclave/validator/Validator.cpp @@ -243,8 +243,8 @@ void validate_meaningful_file() { wl->set_report_flag(false); } - ocall_validate_close(); sgx_thread_mutex_unlock(&g_checked_files_mutex); + ocall_validate_close(); return; } @@ -279,7 +279,9 @@ void validate_meaningful_file() } // If new file hasn't been confirmed, skip this validation - if (wl->checked_files[file_idx][FILE_STATUS].ToString().compare(FILE_STATUS_UNCONFIRMED) == 0) + auto status = &wl->checked_files[file_idx][FILE_STATUS]; + if (status->get_char(CURRENT_STATUS) == FILE_STATUS_UNCONFIRMED + || status->get_char(CURRENT_STATUS) == FILE_STATUS_DELETED) { continue; } @@ -291,9 +293,9 @@ void validate_meaningful_file() if (CRUST_SUCCESS != crust_status || p_data == NULL) { log_err("Validate meaningful data failed! Get tree:%s failed!\n", root_hash.c_str()); - if (wl->checked_files[file_idx][FILE_STATUS].ToString().compare(FILE_STATUS_VALID) == 0) + if (status->get_char(CURRENT_STATUS) == FILE_STATUS_VALID) { - wl->checked_files[file_idx][FILE_STATUS] = FILE_STATUS_LOST; + status->set_char(CURRENT_STATUS, FILE_STATUS_LOST); changed_idx2lost_um[file_idx] = true; } continue; @@ -309,9 +311,9 @@ void validate_meaningful_file() if (root_hash.compare(tree_json[FILE_HASH].ToString()) != 0 || CRUST_SUCCESS != validate_merkletree_json(tree_json)) { log_err("File:%s merkle tree is not valid!\n", root_hash.c_str()); - if (wl->checked_files[file_idx][FILE_STATUS].ToString().compare(FILE_STATUS_VALID) == 0) + if (status->get_char(CURRENT_STATUS) == FILE_STATUS_VALID) { - wl->checked_files[file_idx][FILE_STATUS] = FILE_STATUS_LOST; + status->set_char(CURRENT_STATUS, FILE_STATUS_LOST); changed_idx2lost_um[file_idx] = true; } continue; @@ -354,9 +356,9 @@ void validate_meaningful_file() if (spos == tree_str.npos || (epos = tree_str.find(etag, spos)) == tree_str.npos) { log_err("Find leaf node failed!node index:%ld\n", check_block_idx); - if (wl->checked_files[file_idx][FILE_STATUS].ToString().compare(FILE_STATUS_VALID) == 0) + if (status->get_char(CURRENT_STATUS) == FILE_STATUS_VALID) { - wl->checked_files[file_idx][FILE_STATUS] = FILE_STATUS_LOST; + status->set_char(CURRENT_STATUS, FILE_STATUS_LOST); changed_idx2lost_um[file_idx] = true; } checked_ret = false; @@ -375,13 +377,13 @@ void validate_meaningful_file() { log_err("Get file block:%ld failed!\n", check_block_idx); wl->set_report_flag(false); - ocall_validate_close(); sgx_thread_mutex_unlock(&g_checked_files_mutex); + ocall_validate_close(); return; } - if (wl->checked_files[file_idx][FILE_STATUS].ToString().compare(FILE_STATUS_VALID) == 0) + if (status->get_char(CURRENT_STATUS) == FILE_STATUS_VALID) { - wl->checked_files[file_idx][FILE_STATUS] = FILE_STATUS_LOST; + status->set_char(CURRENT_STATUS, FILE_STATUS_LOST); changed_idx2lost_um[file_idx] = true; } checked_ret = false; @@ -398,12 +400,12 @@ void validate_meaningful_file() } if (memcmp(leaf_hash_u, got_hash, HASH_LENGTH) != 0) { - log_err("Index:%ld block hash is not expected!\n", check_block_idx); - //log_err("Get hash : %s\n", hexstring(got_hash, HASH_LENGTH)); - //log_err("Org hash : %s\n", leaf_hash.c_str()); - if (wl->checked_files[file_idx][FILE_STATUS].ToString().compare(FILE_STATUS_VALID) == 0) + if (status->get_char(CURRENT_STATUS) == FILE_STATUS_VALID) { - wl->checked_files[file_idx][FILE_STATUS] = FILE_STATUS_LOST; + log_err("Index:%ld block hash is not expected!\n", check_block_idx); + //log_err("Get hash : %s\n", hexstring(got_hash, HASH_LENGTH)); + //log_err("Org hash : %s\n", leaf_hash.c_str()); + status->set_char(CURRENT_STATUS, FILE_STATUS_LOST); changed_idx2lost_um[file_idx] = true; } checked_ret = false; @@ -414,9 +416,9 @@ void validate_meaningful_file() spos = epos; } // Set lost file back - if (wl->checked_files[file_idx][FILE_STATUS].ToString().compare(FILE_STATUS_LOST) == 0 && checked_ret) + if (status->get_char(CURRENT_STATUS) == FILE_STATUS_LOST && checked_ret) { - wl->checked_files[file_idx][FILE_STATUS] = FILE_STATUS_VALID; + status->set_char(CURRENT_STATUS, FILE_STATUS_VALID); changed_idx2lost_um[file_idx] = false; } } @@ -428,8 +430,8 @@ void validate_meaningful_file() { log_info("File status changed, hash: %s status: %s -> %s\n", wl->checked_files[it.first][FILE_HASH].ToString().c_str(), - it.second ? FILE_STATUS_LOST : FILE_STATUS_VALID, - wl->checked_files[it.first][FILE_STATUS].ToString().c_str()); + (it.second ? g_file_status[FILE_STATUS_VALID] : g_file_status[FILE_STATUS_LOST]).c_str(), + g_file_status[wl->checked_files[it.first][FILE_STATUS].get_char(CURRENT_STATUS)].c_str()); } } diff --git a/src/enclave/workload/Workload.cpp b/src/enclave/workload/Workload.cpp index c46f066b..d87d4ab6 100644 --- a/src/enclave/workload/Workload.cpp +++ b/src/enclave/workload/Workload.cpp @@ -71,13 +71,14 @@ std::string Workload::get_workload(void) wl_str.append("\"").append(WL_FILES).append("\":{"); if (md_json.hasKey(ID_FILE) && md_json[ID_FILE].size() > 0) { - for (int i = 0; i < md_json[ID_FILE].size(); i++) + for (long i = 0; i < md_json[ID_FILE].size(); i++) { + std::string status = md_json[ID_FILE][i][FILE_STATUS].ToString(); std::string tmp_str = "{"; tmp_str.append("\"").append(WL_FILE_SEALED_SIZE).append("\":") .append(std::to_string(md_json[ID_FILE][i][FILE_SIZE].ToInt())).append(","); tmp_str.append("\"").append(WL_FILE_STATUS).append("\":") - .append("\"").append(md_json[ID_FILE][i][FILE_STATUS].ToString()).append("\"}"); + .append("\"").append(g_file_status[status[CURRENT_STATUS]]).append("\"}"); wl_str.append("\"").append(md_json[ID_FILE][i][FILE_HASH].ToString()).append("\":").append(tmp_str); if (i != md_json[ID_FILE].size() - 1) { @@ -366,3 +367,41 @@ json::JSON Workload::get_srd_info() return srd_info; } + +/** + * @description: Set upgrade flag + * @param flag -> Upgrade flag + */ +void Workload::set_upgrade(bool flag) +{ + this->upgrade = flag; +} + +/** + * @description: Get upgrade flag + * @return: Upgrade flag + */ +bool Workload::is_upgrade() +{ + return this->upgrade; +} + +/** + * @description: Handle workreport result + * @param report_res -> Workreport result + */ +void Workload::handle_report_result() +{ + // Set file status by report result + sgx_thread_mutex_lock(&g_checked_files_mutex); + for (auto i : this->reported_files_idx) + { + if (i < this->checked_files.size()) + { + auto status = &this->checked_files[i][FILE_STATUS]; + status->set_char(ORIGIN_STATUS, status->get_char(WAITING_STATUS)); + } + } + this->reported_files_idx.clear(); + sgx_thread_mutex_unlock(&g_checked_files_mutex); +} diff --git a/src/enclave/workload/Workload.h b/src/enclave/workload/Workload.h index a9d0c381..fc837253 100644 --- a/src/enclave/workload/Workload.h +++ b/src/enclave/workload/Workload.h @@ -18,6 +18,14 @@ #include "Srd.h" #include "Parameter.h" +// Show information +std::unordered_map g_file_status = { + {FILE_STATUS_UNCONFIRMED, "unconfirmed"}, + {FILE_STATUS_VALID, "valid"}, + {FILE_STATUS_LOST, "lost"}, + {FILE_STATUS_DELETED, "deleted"} +}; + class Workload { public: @@ -26,6 +34,8 @@ class Workload std::vector checked_files; std::vector new_files; std::vector> order_files; + std::set reported_files_idx; + sgx_ec256_public_t pre_pub_key; static Workload *workload; static Workload *get_instance(); @@ -46,6 +56,11 @@ class Workload void set_srd_info(std::string path, long change); json::JSON get_srd_info(); + void set_upgrade(bool flag); + bool is_upgrade(); + + void handle_report_result(); + // Workreport mutex sgx_thread_mutex_t ocall_wr_mutex = SGX_THREAD_MUTEX_INITIALIZER; // Workload mutex @@ -59,6 +74,8 @@ class Workload json::JSON srd_info_json; // Srd info mutex sgx_thread_mutex_t srd_info_mutex = SGX_THREAD_MUTEX_INITIALIZER; + // Is upgrade + bool upgrade = false; }; #endif /* !_CRUST_WORKLOAD_H_ */ diff --git a/test/integration/Makefile b/test/integration/Makefile index 1b0927bb..1a52958c 100644 --- a/test/integration/Makefile +++ b/test/integration/Makefile @@ -4,10 +4,10 @@ build: @./build_test.sh functionality_test: - @./scripts/start_test.sh functionality + @./scripts/start_test.sh -t functionality -p $$PPID -c $(case) benchmark_test: - @./scripts/start_test.sh benchmark + @./scripts/start_test.sh -t benchmark -p $$PPID -c $(case) clean: @rm -rf benchmark.report* case.log sworker.log VERSION src test_app data buildenv.mk diff --git a/test/integration/build_test.sh b/test/integration/build_test.sh index e76a5268..631f101f 100755 --- a/test/integration/build_test.sh +++ b/test/integration/build_test.sh @@ -32,25 +32,61 @@ void ecall_store_metadata() log_err("Store enclave data failed!Error code:%lx\n", crust_status); } } + +void ecall_test_add_file(long file_num) +{ + Workload::get_instance()->test_add_file(file_num); +} + +void ecall_test_valid_file(uint32_t file_num) +{ + Workload::get_instance()->test_valid_file(file_num); +} + +void ecall_test_lost_file(uint32_t file_num) +{ + Workload::get_instance()->test_lost_file(file_num); +} + +void ecall_test_delete_file(uint32_t file_num) +{ + Workload::get_instance()->test_delete_file(file_num); +} EOF } ########## enclave_edl_test ########## function enclave_edl_test() { +cat << EOF > $TMPFILE + public void ecall_validate_srd(); + public void ecall_validate_file(); + public void ecall_store_metadata(); + + public void ecall_test_add_file(long file_num); + public void ecall_test_valid_file(uint32_t file_num); + public void ecall_test_lost_file(uint32_t file_num); + public void ecall_test_delete_file(uint32_t file_num); +EOF + local pos=$(sed -n '/ecall_get_workload()/=' $enclave_edl) - sed -i -e "$pos a \\\t\tpublic void ecall_validate_srd();" \ - -e "$pos a \\\t\tpublic void ecall_validate_file();" \ - -e "$pos a \\\t\tpublic void ecall_store_metadata();" $enclave_edl + sed -i "$pos r $TMPFILE" $enclave_edl } ########## ecalls_cpp_test ########## function ecalls_cpp_test() { +cat << EOF >$TMPFILE + {"Ecall_validate_srd", 0}, + {"Ecall_validate_file", 0}, + {"Ecall_store_metadata", 0}, + {"Ecall_test_add_file", 1}, + {"Ecall_test_valid_file", 1}, + {"Ecall_test_lost_file", 1}, + {"Ecall_test_delete_file", 1}, +EOF local pos=$(sed -n '/{"Ecall_delete_file", 0},/=' $ecalls_cpp) - sed -i -e "$pos a \\\t{\"Ecall_validate_srd\", 0}," \ - -e "$pos a \\\t{\"Ecall_validate_file\", 0}," \ - -e "$pos a \\\t{\"Ecall_store_metadata\", 0}," $ecalls_cpp + sed -i "$pos r $TMPFILE" $ecalls_cpp cat << EOF >>$ecalls_cpp @@ -98,16 +134,85 @@ sgx_status_t Ecall_store_metadata(sgx_enclave_id_t eid) return ret; } + +sgx_status_t Ecall_test_add_file(sgx_enclave_id_t eid, long file_num) +{ + sgx_status_t ret = SGX_SUCCESS; + if (SGX_SUCCESS != (ret = try_get_enclave(__FUNCTION__))) + { + return ret; + } + + ret = ecall_test_add_file(eid, file_num); + + free_enclave(__FUNCTION__); + + return ret; +} + +sgx_status_t Ecall_test_valid_file(sgx_enclave_id_t eid, uint32_t file_num) +{ + sgx_status_t ret = SGX_SUCCESS; + if (SGX_SUCCESS != (ret = try_get_enclave(__FUNCTION__))) + { + return ret; + } + + ret = ecall_test_valid_file(eid, file_num); + + free_enclave(__FUNCTION__); + + return ret; +} + +sgx_status_t Ecall_test_lost_file(sgx_enclave_id_t eid, uint32_t file_num) +{ + sgx_status_t ret = SGX_SUCCESS; + if (SGX_SUCCESS != (ret = try_get_enclave(__FUNCTION__))) + { + return ret; + } + + ret = ecall_test_lost_file(eid, file_num); + + free_enclave(__FUNCTION__); + + return ret; +} + +sgx_status_t Ecall_test_delete_file(sgx_enclave_id_t eid, uint32_t file_num) +{ + sgx_status_t ret = SGX_SUCCESS; + if (SGX_SUCCESS != (ret = try_get_enclave(__FUNCTION__))) + { + return ret; + } + + ret = ecall_test_delete_file(eid, file_num); + + free_enclave(__FUNCTION__); + + return ret; +} EOF } ########## ecalls_h_test ########## function ecalls_h_test() { +cat << EOF > $TMPFILE +sgx_status_t Ecall_validate_srd(sgx_enclave_id_t eid); +sgx_status_t Ecall_validate_file(sgx_enclave_id_t eid); +sgx_status_t Ecall_store_metadata(sgx_enclave_id_t eid); + +sgx_status_t Ecall_test_add_file(sgx_enclave_id_t eid, long file_num); +sgx_status_t Ecall_test_valid_file(sgx_enclave_id_t eid, uint32_t file_num); +sgx_status_t Ecall_test_lost_file(sgx_enclave_id_t eid, uint32_t file_num); +sgx_status_t Ecall_test_delete_file(sgx_enclave_id_t eid, uint32_t file_num); +EOF + local pos=$(sed -n '/std::string show_enclave_thread_info();/=' $ecalls_h) - sed -i -e "$pos a sgx_status_t Ecall_validate_srd(sgx_enclave_id_t eid);" \ - -e "$pos a sgx_status_t Ecall_validate_file(sgx_enclave_id_t eid);" \ - -e "$pos a sgx_status_t Ecall_store_metadata(sgx_enclave_id_t eid);" $ecalls_h + sed -i "$((pos+1)) r $TMPFILE" $ecalls_h } ########## process_cpp_test ########## @@ -154,12 +259,7 @@ cat << EOF > $TMPFILE { // Send signed validation report to crust chain std::string work_str = get_g_enclave_workreport(); - p_log->info("Sign validation report successfully!\\n%s\\n", work_str.c_str()); res.body() = work_str; - // Delete space and line break - remove_char(work_str, '\\\\'); - remove_char(work_str, '\\n'); - remove_char(work_str, ' '); } else if (crust_status == CRUST_BLOCK_HEIGHT_EXPIRED) { @@ -197,6 +297,19 @@ cat << EOF > $TMPFILE goto getcleanup; } + cur_path = urlendpoint->base + "/report/result"; + if (path.compare(cur_path) == 0) + { + res.result(200); + std::string ret_info; + // Confirm new file + report_add_callback(); + ret_info = "Reporting result task has beening added!"; + res.body() = ret_info; + + goto getcleanup; + } + cur_path = urlendpoint->base + "/validate/srd"; if (memcmp(path.c_str(), cur_path.c_str(), cur_path.size()) == 0) { @@ -214,6 +327,42 @@ cat << EOF > $TMPFILE { Ecall_store_metadata(global_eid); } + + cur_path = urlendpoint->base + "/test/add_file"; + if (memcmp(path.c_str(), cur_path.c_str(), cur_path.size()) == 0) + { + json::JSON req_json = json::JSON::Load(req.body()); + long file_num = req_json["file_num"].ToInt(); + Ecall_test_add_file(global_eid, file_num); + res.body() = "Add file successfully!"; + } + + cur_path = urlendpoint->base + "/test/valid_file"; + if (memcmp(path.c_str(), cur_path.c_str(), cur_path.size()) == 0) + { + json::JSON req_json = json::JSON::Load(req.body()); + long file_num = req_json["file_num"].ToInt(); + Ecall_test_valid_file(global_eid, file_num); + res.body() = "Validate file successfully!"; + } + + cur_path = urlendpoint->base + "/test/lost_file"; + if (memcmp(path.c_str(), cur_path.c_str(), cur_path.size()) == 0) + { + json::JSON req_json = json::JSON::Load(req.body()); + uint32_t file_num = req_json["file_num"].ToInt(); + Ecall_test_lost_file(global_eid, file_num); + res.body() = "Lost file successfully!"; + } + + cur_path = urlendpoint->base + "/test/delete_file"; + if (memcmp(path.c_str(), cur_path.c_str(), cur_path.size()) == 0) + { + json::JSON req_json = json::JSON::Load(req.body()); + uint32_t file_num = req_json["file_num"].ToInt(); + Ecall_test_delete_file(global_eid, file_num); + res.body() = "Delete file successfully!"; + } EOF cat << EOF > $TMPFILE2 @@ -440,6 +589,124 @@ EOF sed -i "s/ocall_delete_folder_or_file(/\/\/ocall_delete_folder_or_file(/g" $enclave_srd_cpp } +function enc_wl_h_test() +{ +cat << EOF > $TMPFILE + + void test_add_file(long file_num); + void test_valid_file(uint32_t file_num); + void test_lost_file(uint32_t file_num); + void test_delete_file(uint32_t file_num); +EOF + + local spos=$(sed -n '/handle_report_result(/=' $enclave_workload_h) + ((spos++)) + sed -i "$spos r $TMPFILE" $enclave_workload_h +} + +function enc_wl_cpp_test() +{ +cat << EOF >> $enclave_workload_cpp + +void Workload::test_add_file(long file_num) +{ + sgx_thread_mutex_lock(&g_checked_files_mutex); + long acc = 0; + for (long i = 0; i < file_num; i++) + { + uint8_t *n_u = new uint8_t[32]; + sgx_read_rand(n_u, HASH_LENGTH); + sgx_sha256_hash_t hash; + sgx_sha256_hash_t old_hash; + sgx_sha256_msg(n_u, HASH_LENGTH, &hash); + sgx_sha256_msg(reinterpret_cast(&hash), HASH_LENGTH, &old_hash); + json::JSON file_entry_json; + file_entry_json[FILE_HASH] = reinterpret_cast(hash); + file_entry_json[FILE_OLD_HASH] = reinterpret_cast(old_hash); + file_entry_json[FILE_SIZE] = 10000; + file_entry_json[FILE_OLD_SIZE] = 9999; + file_entry_json[FILE_BLOCK_NUM] = 1000; + // Status indicates current new file's status, which must be one of valid, lost and unconfirmed + file_entry_json[FILE_STATUS] = "000"; + free(n_u); + this->checked_files.push_back(file_entry_json); + acc++; + } + sgx_thread_mutex_unlock(&g_checked_files_mutex); +} + +void Workload::test_valid_file(uint32_t file_num) +{ + sgx_thread_mutex_lock(&g_checked_files_mutex); + for (uint32_t i = 0, j = 0; i < file_num && j < 200;) + { + uint32_t index = 0; + sgx_read_rand(reinterpret_cast(&index), sizeof(uint32_t)); + index = index % this->checked_files.size(); + auto status = &this->checked_files[index][FILE_STATUS]; + if (status->get_char(CURRENT_STATUS) == FILE_STATUS_UNCONFIRMED + || status->get_char(CURRENT_STATUS) == FILE_STATUS_LOST) + { + status->set_char(CURRENT_STATUS, FILE_STATUS_VALID); + i++; + j = 0; + } + else + { + j++; + } + } + sgx_thread_mutex_unlock(&g_checked_files_mutex); +} + +void Workload::test_lost_file(uint32_t file_num) +{ + sgx_thread_mutex_lock(&g_checked_files_mutex); + for (uint32_t i = 0, j = 0; i < file_num && j < 200;) + { + uint32_t index = 0; + sgx_read_rand(reinterpret_cast(&index), sizeof(uint32_t)); + index = index % this->checked_files.size(); + auto status = &this->checked_files[index][FILE_STATUS]; + if (status->get_char(CURRENT_STATUS) == FILE_STATUS_VALID) + { + status->set_char(CURRENT_STATUS, FILE_STATUS_LOST); + i++; + j = 0; + } + else + { + j++; + } + } + sgx_thread_mutex_unlock(&g_checked_files_mutex); +} + +void Workload::test_delete_file(uint32_t file_num) +{ + sgx_thread_mutex_lock(&g_checked_files_mutex); + for (uint32_t i = 0, j = 0; i < file_num && j < 200;) + { + uint32_t index = 0; + sgx_read_rand(reinterpret_cast(&index), sizeof(uint32_t)); + index = index % this->checked_files.size(); + auto status = &this->checked_files[index][FILE_STATUS]; + if (status->get_char(CURRENT_STATUS) != FILE_STATUS_DELETED) + { + status->set_char(CURRENT_STATUS, FILE_STATUS_DELETED); + i++; + j = 0; + } + else + { + j++; + } + } + sgx_thread_mutex_unlock(&g_checked_files_mutex); +} +EOF +} + function enc_srd_h_test() { sed -i "/^#define SRD_MAX_PER_TURN 64/ c #define SRD_MAX_PER_TURN 1000" $enclave_srd_h @@ -560,6 +827,8 @@ enclave_srd_cpp=$encdir/srd/Srd.cpp enclave_srd_h=$encdir/srd/Srd.h enclave_storage_cpp=$encdir/storage/Storage.cpp enclave_parameter_h=$encdir/include/Parameter.h +enclave_workload_cpp=$encdir/workload/Workload.cpp +enclave_workload_h=$encdir/workload/Workload.h testdir=$basedir/test_app configfile=$testdir/etc/Config.json TMPFILE=$basedir/tmp.$$ @@ -597,6 +866,8 @@ enc_report_cpp_test enc_validate_cpp_test enc_srd_cpp_test enc_srd_h_test +enc_wl_cpp_test +enc_wl_h_test #enc_storage_cpp_test #enc_parameter_h_test diff --git a/test/integration/functionality/confirm b/test/integration/functionality/confirm index fd552a95..9c7b9ef0 100755 --- a/test/integration/functionality/confirm +++ b/test/integration/functionality/confirm @@ -7,7 +7,7 @@ function _store_meta() function seal_exit() { - rm $TMPFILE + rm -rf $tmpdir } ########## MAIN BODY ########## @@ -19,14 +19,19 @@ datadir=$instdir/data testdir=$instdir/test_app testfiledir=$testdir/files configfile=$instdir/config/config.json -TMPFILE=$basedir/TMPFILE +tmpdir=$basedir/tmp +TMPFILE=$tmpdir/TMPFILE.$(date +%N)${RANDOM} trap 'seal_exit' EXIT +mkdir -p $tmpdir + . $scriptdir/utils.sh -declare -A hash_2_use_m +print_title "start confirm case" + +declare -A hash_2_use_m data_arry=($(ls $datadir)) data_size=${#data_arry[@]} acc=6 diff --git a/test/integration/functionality/delete b/test/integration/functionality/delete index 3951f945..42e15377 100755 --- a/test/integration/functionality/delete +++ b/test/integration/functionality/delete @@ -7,7 +7,7 @@ function _store_meta() function seal_exit() { - rm $TMPFILE + rm -rf $tmpdir } ########## MAIN BODY ########## @@ -19,14 +19,19 @@ datadir=$instdir/data testdir=$instdir/test_app testfiledir=$testdir/files configfile=$instdir/config/config.json -TMPFILE=$basedir/TMPFILE +tmpdir=$basedir/tmp +TMPFILE=$tmpdir/TMPFILE.$(date +%N)${RANDOM} + +mkdir -p $tmpdir trap 'seal_exit' EXIT . $scriptdir/utils.sh -declare -A hash_2_use_m +print_title "start delete case" + +declare -A hash_2_use_m data_arry=($(ls $datadir)) data_size=${#data_arry[@]} acc=6 diff --git a/test/integration/functionality/restart b/test/integration/functionality/restart new file mode 100755 index 00000000..b778d3f9 --- /dev/null +++ b/test/integration/functionality/restart @@ -0,0 +1,80 @@ +#!/bin/bash +function restart_exit() +{ + local cur_sworkerpid=$(ps -ef | grep -v grep | grep "\b${sworkerpid}\b" | awk '{print $2}') + if [ x"$cur_sworkerpid" = x"$sworkerpid" ]; then + kill -9 $sworkerpid &>/dev/null + wait $sworkerpid &>/dev/null + fi + rm -rf $tmpdir +} + +########## MAIN BODY ########## +# basic variable +basedir=$(cd `dirname $0`;pwd) +instdir=$(cd $basedir/..;pwd) +scriptdir=$instdir/scripts +datadir=$instdir/data +testdir=$instdir/test_app +testfiledir=$testdir/files +configfile=$instdir/config/config.json +testconfigfile=$testdir/etc/Config.json +errfile=$scriptdir/err.log +tmpdir=$basedir/tmp +TMPFILE=$tmpdir/TMPFILE.$(date +%N)${RANDOM} +sworkerlog=$instdir/sworker.log + +trap "restart_exit" EXIT + +mkdir -p $tmpdir + +. $scriptdir/utils.sh + +print_title "start restart case" + + +### Restart crust-sworker +store_metadata &>/dev/null +kill -9 $sworkerpid &>/dev/null +wait $sworkerpid &>/dev/null +sleep 3 +cd $testdir +verbose INFO "Restarting crust-sworker..." h +./bin/crust-sworker -c etc/Config.json --offline --debug &>$sworkerlog & +sworkerpid=$! +sleep 20 +curl -s $baseurl/workload 2>$errfile 1>/dev/null +if [ $? -ne 0 ] ; then + verbose ERROR "failed" t + verbose ERROR "start crust sworker failed! Please check $errfile for details." + kill -9 $sworkerpid + exit 1 +fi +if ! ps -ef | grep -v grep | grep $sworkerpid &>/dev/null; then + verbose ERROR "failed" t + exit 1 +fi +verbose INFO "success" t +cd - &>/dev/null + +# Re-test +res=0 +get_workload &>/dev/null +res=$(($?|$res)) +report_work &>/dev/null +res=$(($?|$res)) +srd 100 &>/dev/null +res=$(($?|$res)) +srd -50 &>/dev/null +res=$(($?|$res)) +store_metadata &>/dev/null +res=$(($?|$res)) +get_workload &>/dev/null +res=$(($?|$res)) +report_work &>/dev/null +res=$(($?|$res)) + +if [ $res -ne 0 ]; then + echo "Test failed after restart!" + exit 1 +fi diff --git a/test/integration/functionality/seal b/test/integration/functionality/seal index 820ca971..b8b82ac0 100755 --- a/test/integration/functionality/seal +++ b/test/integration/functionality/seal @@ -3,7 +3,7 @@ function _seal() { local datapath_l=$1 local storepath_l=$2 - local curtmp=$TMPFILE.$RANDOM + local curtmp=$TMPFILE.$(date +%N)${RANDOM} seal_file $datapath_l $storepath_l &>$curtmp if [ $? -ne 0 ]; then echo "Seal file failed!" @@ -33,9 +33,7 @@ function _store_meta() function seal_exit() { - rm $TMPFILE - rm $LOCKFILE - rm $syncfile + rm -rf $tmpdir } ########## MAIN BODY ########## @@ -47,14 +45,20 @@ datadir=$instdir/data testdir=$instdir/test_app testfiledir=$testdir/files configfile=$instdir/config/config.json -TMPFILE=$basedir/TMPFILE -LOCKFILE=$basedir/LOCKFILE -syncfile=$basedir/syncfile +tmpdir=$basedir/tmp +TMPFILE=$tmpdir/TMPFILE.$(date +%N)${RANDOM} +LOCKFILE=$tmpdir/LOCKFILE +syncfile=$tmpdir/syncfile + +mkdir -p $tmpdir trap 'seal_exit' EXIT . $scriptdir/utils.sh +print_title "start seal case" + + data_arry=($(ls $datadir)) data_size=${#data_arry[@]} timeout=300 diff --git a/test/integration/functionality/srd b/test/integration/functionality/srd index 41e3d3b2..2ffaf5a0 100755 --- a/test/integration/functionality/srd +++ b/test/integration/functionality/srd @@ -7,7 +7,7 @@ function _store_meta() function seal_exit() { - rm $TMPFILE + rm -rf $tmpdir } ########## MAIN BODY ########## @@ -19,14 +19,19 @@ datadir=$instdir/data testdir=$instdir/test_app testfiledir=$testdir/files configfile=$instdir/config/config.json -TMPFILE=$basedir/TMPFILE +tmpdir=$basedir/tmp +TMPFILE=$tmpdir/TMPFILE.$(date +%N)${RANDOM} + +mkdir -p $tmpdir trap 'seal_exit' EXIT . $scriptdir/utils.sh -declare -A hash_2_use_m +print_title "start srd case" + +declare -A hash_2_use_m data_arry=($(ls $datadir)) data_size=${#data_arry[@]} @@ -34,8 +39,21 @@ srd_num=$(get_config ".functionality|.srd_size") srd_paths=$(get_config ".functionality|.srd_paths") srd_max_per_turn=$(get_config ".functionality|.srd_max_per_turn") tmp_num=0 +real_max_per_turn=0 + +# Get current available max per turn +srd_paths_test=($(echo $srd_paths | sed -e 's/,/ /g' -e 's/\[\|\]//g' -e 's/\"//g')) +for path in ${srd_paths_test[@]}; do + tmp=$(df -h $path | tail -n 1 | awk '{print $4}') + tmp=${tmp%[a-zA-Z]*} + ((real_max_per_turn += tmp)) +done +if [ $srd_max_per_turn -gt $real_max_per_turn ]; then + srd_max_per_turn=$real_max_per_turn +fi -srd_disk_change "$srd_paths" "add" +# Srd task +srd_disk_change "$srd_paths" "add" &>/dev/null while [ $tmp_num -lt $srd_num ]; do if [ $((srd_num - tmp_num)) -gt $srd_max_per_turn ]; then cur_turn=$srd_max_per_turn @@ -52,6 +70,6 @@ done _store_meta &>/dev/null get_workload &>$TMPFILE if [ x"$(cat $TMPFILE | jq '.srd|.space')" != x"$srd_num" ]; then - echo "srd failed!Wrong result." + echo "srd failed!Wrong result, expected:$srd_num, real:$(cat $TMPFILE | jq '.srd|.space')" exit 1 fi diff --git a/test/integration/functionality/unseal b/test/integration/functionality/unseal index 84de4e9f..7bcc2668 100755 --- a/test/integration/functionality/unseal +++ b/test/integration/functionality/unseal @@ -3,7 +3,7 @@ function _seal() { local datapath_l=$1 local storepath_l=$2 - local curtmp=$TMPFILE.$RANDOM + local curtmp=$TMPFILE.$(date +%N)${RANDOM} seal_file $datapath_l $storepath_l &>$curtmp if [ $? -ne 0 ]; then echo "Seal file failed!" @@ -28,7 +28,7 @@ function _seal() function _unseal() { local datapath_l=$1 - local curtmp=$TMPFILE.$RANDOM + local curtmp=$TMPFILE.$(date +%N)${RANDOM} true > $syncfile unseal $datapath_l &>$curtmp if [ $? -ne 0 ]; then @@ -58,8 +58,7 @@ function _store_meta() function seal_exit() { - rm $LOCKFILE - rm $syncfile + rm -rf $tmpdir } ########## MAIN BODY ########## @@ -71,14 +70,20 @@ datadir=$instdir/data testdir=$instdir/test_app testfiledir=$testdir/files configfile=$instdir/config/config.json -TMPFILE=$basedir/TMPFILE -LOCKFILE=$basedir/LOCKFILE -syncfile=$basedir/syncfile +tmpdir=$basedir/tmp +TMPFILE=$tmpdir/TMPFILE.$(date +%N)${RANDOM} +LOCKFILE=$tmpdir/LOCKFILE +syncfile=$tmpdir/syncfile + +mkdir -p $tmpdir trap 'seal_exit' EXIT . $scriptdir/utils.sh +print_title "start unseal case" + + data_arry=($(ls $datadir)) data_size=${#data_arry[@]} timeout=300 diff --git a/test/integration/functionality/workreport b/test/integration/functionality/workreport1 similarity index 72% rename from test/integration/functionality/workreport rename to test/integration/functionality/workreport1 index 60789b01..619dfc74 100755 --- a/test/integration/functionality/workreport +++ b/test/integration/functionality/workreport1 @@ -1,7 +1,7 @@ #!/bin/bash function report_exit() { - rm $TMPFILE + rm -rf $tmpdir } ########## MAIN BODY ########## @@ -13,18 +13,30 @@ datadir=$instdir/data testdir=$instdir/test_app testfiledir=$testdir/files configfile=$instdir/config/config.json -TMPFILE=$instdir/TMPFILE.$RANDOM +tmpdir=$basedir/tmp +TMPFILE=$tmpdir/TMPFILE.$(date +%N)${RANDOM} + +mkdir -p $tmpdir trap 'report_exit' EXIT . $scriptdir/utils.sh +print_title "start workreport1 case" + + srd_num=$(get_config ".functionality|.srd_size") srd_paths=$(get_config ".functionality|.srd_paths") srd_max_per_turn=$(get_config ".functionality|.srd_max_per_turn") file_arry=($(get_config ".functionality|.file_arry")) +added_fn_e=${#file_arry[@]} tmp_num=0 + +# Ignore previous infact +report_work &>/dev/null +report_work_result &>/dev/null + # Get workload get_workload &>$TMPFILE if [ $? -ne 0 ]; then @@ -34,9 +46,9 @@ fi workload=$(cat $TMPFILE) # Delete previous srd -srd -$(echo $workload | jq '.srd|.space' | sed 's/"//g' 2>/dev/null) +srd -$(echo $workload | jq '.srd|.space' | sed 's/"//g' 2>/dev/null) &>/dev/null # Make srd volunm -srd_disk_change "$srd_paths" "add" +srd_disk_change "$srd_paths" "add" &>/dev/null while [ $tmp_num -lt $srd_num ]; do if [ $((srd_num - tmp_num)) -gt $srd_max_per_turn ]; then cur_turn=$srd_max_per_turn @@ -52,9 +64,13 @@ while [ $tmp_num -lt $srd_num ]; do done # Delete previous file +deleted_fn_e=0 if [ x"$(echo $workload | jq '.files | .valid | .number' | sed 's/"//g' 2>/dev/null)" != x"null" ]; then for hash in $(echo $workload | jq '.files | .valid | .detail | .[] | .sealed_hash' | sed 's/"//g' 2>/dev/null); do delete_file $hash &>/dev/null + if [ $? -eq 0 ]; then + ((deleted_fn_e++)) + fi done fi # Make file volunm @@ -81,14 +97,22 @@ if [ $? -ne 0 ]; then exit 1 fi # Get report info -files_num=$(cat $TMPFILE | jq '.files | .[] | .hash' | wc -l 2>/dev/null) +ret=0 +added_fn=$(cat $TMPFILE | jq '.added_files | .[] | .hash' | wc -l 2>/dev/null) +deleted_fn=$(cat $TMPFILE | jq '.deleted_files | .[] | .hash' | wc -l 2>/dev/null) reserved=$(cat $TMPFILE | jq '.reserved' 2>/dev/null) reserved_e=$((srd_num * 1024 * 1024 * 1024)) if [ x"$reserved" != x"$reserved_e" ]; then echo "srd number is wrong!expect:${reserved_e}, real:${reserved}" - exit 1 + ret=1 fi -if [ x"$files_num" != x"${#file_arry[@]}" ]; then - echo "file number is wrong!expect:${#file_arry[@]}, real:${files_num}" - exit 1 +if [ x"$added_fn" != x"$added_fn_e" ]; then + echo "added file number is wrong!expect:$added_fn_e, real:$added_fn" + ret=1 fi +if [ x"$deleted_fn" != x"$deleted_fn_e" ]; then + echo "deleted file number is wrong!expect:$deleted_fn_e, real:$deleted_fn" + ret=1 +fi + +exit $ret diff --git a/test/integration/functionality/workreport2 b/test/integration/functionality/workreport2 new file mode 100755 index 00000000..1f553a3c --- /dev/null +++ b/test/integration/functionality/workreport2 @@ -0,0 +1,197 @@ +#!/bin/bash +function _test_add_file() +{ + local num=$1 + test_add_file $num &>/dev/null + if [ $? -ne 0 ]; then + echo "add file failed!!" + exit 1 + fi +} + +function _test_valid_file() +{ + local num=$1 + test_valid_file $num &>/dev/null + if [ $? -ne 0 ]; then + echo "valid file failed!" + exit 1 + fi +} + +function _test_lost_file() +{ + local num=$1 + test_lost_file $num &>/dev/null + if [ $? -ne 0 ]; then + echo "valid file failed!" + exit 1 + fi +} + +function _test_delete_file() +{ + local num=$1 + test_delete_file $num &>/dev/null + if [ $? -ne 0 ]; then + echo "valid file failed!" + exit 1 + fi +} + +function _report() +{ + local not_report=$1 + report_work &>$TMPFILE + if [ $? -ne 0 ]; then + echo "report work failed!" + exit 1 + fi + if [ x"$not_report" = x"" ]; then + report_work_result &>/dev/null + if [ $? -ne 0 ]; then + echo "report work result failed!" + exit 1 + fi + fi + files_size=$(cat $TMPFILE | jq '.files_size') + files_size_added=0 + files_size_deleted=0 + for size in $(cat $TMPFILE | jq '.added_files|.[]|.size'); do + ((files_size_added += $size)) + done + for size in $(cat $TMPFILE | jq '.deleted_files|.[]|.size'); do + ((files_size_deleted += $size)) + done + echo "$files_size" "$files_size_added" "$files_size_deleted" +} + +function report_exit() +{ + rm -rf $tmpdir +} + +########## MAIN BODY ########## +# basic variable +basedir=$(cd `dirname $0`;pwd) +instdir=$(cd $basedir/..;pwd) +scriptdir=$instdir/scripts +testdir=$instdir/test_app +configfile=$instdir/config/config.json +tmpdir=$basedir/tmp +TMPFILE=$tmpdir/TMPFILE.$(date +%N)${RANDOM} + +mkdir -p $tmpdir + +. $scriptdir/utils.sh + +trap 'report_exit' EXIT + +print_title "start workreport2 case" + + +rnum=0 +# Test round 1 +_test_add_file 2000 +_test_valid_file 1500 +cres=($(_report)) +expected=${cres[1]} +real=${cres[0]} +verbose INFO "round$((++rnum)): add file. expected:$expected, real:$real" n +if [ ${cres[0]} -ne ${cres[1]} ]; then + verbose INFO "test failed!expected:$expected, real:$real" n + exit 1 +fi +pres=(${cres[@]}) + +# Test round 2 +cres=($(_report)) +expected=$((${pres[0]}+${cres[1]})) +real=${cres[0]} +verbose INFO "round$((++rnum)): add file. expected:$expected, real:$real" n +if [ $expected -ne $real ]; then + verbose INFO "test failed!expected:$expected, real:$real" n + exit 1 +fi +pres=(${cres[@]}) + +# Test round 3 +_test_delete_file 500 +cres=($(_report)) +expected=$((${pres[0]}+${cres[1]}-${cres[2]})) +real=${cres[0]} +verbose INFO "round$((++rnum)): delete file. expected:$expected, real:$real" n +if [ $expected -ne $real ]; then + verbose INFO "test failed!expected:$expected, real:$real" n + exit 1 +fi +pres=(${cres[@]}) + +# Test round 4 +_test_lost_file 500 +cres=($(_report)) +expected=$((${pres[0]}+${cres[1]}-${cres[2]})) +real=${cres[0]} +verbose INFO "round$((++rnum)): lost file. expected:$expected, real:$real" n +if [ $expected -ne $real ]; then + verbose INFO "test failed!expected:$expected, real:$real" n + exit 1 +fi +pres=(${cres[@]}) + +# Test round 5 +_test_valid_file 500 +cres=($(_report)) +expected=$((${pres[0]}+${cres[1]}-${cres[2]})) +real=${cres[0]} +verbose INFO "round$((++rnum)): valid file. expected:$expected, real:$real" n +if [ $expected -ne $real ]; then + verbose INFO "test failed!expected:$expected, real:$real" n + exit 1 +fi +pres=(${cres[@]}) + +# Test round 6 +_test_add_file 1000 +_test_valid_file 1000 +_test_delete_file 500 +cres=($(_report)) +pres=(${cres[@]}) +_test_lost_file 500 +_report 1 &>/dev/null +_test_valid_file 300 +cres=($(_report)) +expected=$((${pres[0]}+${cres[1]}-${cres[2]})) +real=${cres[0]} +verbose INFO "round$((++rnum)): report failed,report again. expected:$expected, real:$real" n +if [ $expected -ne $real ]; then + verbose INFO "test failed!expected:$expected, real:$real" n + exit 1 +fi +pres=(${cres[@]}) + +# Test round 7 +_test_lost_file 500 +_report &>/dev/null +cres=($(_report)) +expected=$((${pres[0]}+${cres[1]}-${cres[2]})) +real=${cres[0]} +verbose INFO "round$((++rnum)): cheat: inform reporting while not!expected:$expected, real:$real" n +if [ $expected -eq $real ]; then + verbose INFO "test failed!expected:$expected, real:$real" n + exit 1 +fi +pres=(${cres[@]}) + +# Test round 8 +_test_valid_file 500 +cres=($(_report 1)) +pres=(${cres[@]}) +cres=($(_report)) +expected=$((${pres[0]}+${cres[1]}-${cres[2]})) +real=${cres[0]} +verbose INFO "round$((++rnum)): cheat: inform not report while do!expected:$expected, real:$real" n +if [ $expected -eq $real ]; then + verbose INFO "test failed!expected:$expected, real:$real" n + exit 1 +fi diff --git a/test/integration/performance/run_test.sh b/test/integration/performance/run_test.sh index f83caff9..c0a3412e 100755 --- a/test/integration/performance/run_test.sh +++ b/test/integration/performance/run_test.sh @@ -114,7 +114,7 @@ function _validate { while true; do sleep 10 - validate_file &>/dev/null + #validate_file &>/dev/null validate_srd &>/dev/null store_metadata &>/dev/null res_inc "confirm" "success" $validateresfile @@ -196,6 +196,7 @@ function _workreport() report_work &>$instdir/${lfile}.$tag if [ $? -eq 0 ]; then res_inc "report" "success" $reportresfile + report_work_result &>/dev/null else res_inc "report" "failed" $reportresfile fi @@ -327,14 +328,14 @@ data_size=${#data_arry[@]} verbose INFO "current pid: $pid " n # Randomly seal file -_seal & -name2pid_m[_sealpid]=$! +#_seal & +#name2pid_m[_sealpid]=$! # Randomly unseal _unseal & name2pid_m[_unseal]=$! # Randomly srd -_srd & -name2pid_m[_srdpid]=$! +#_srd & +#name2pid_m[_srdpid]=$! # Randomly confirm _confirm & name2pid_m[_confirmpid]=$! diff --git a/test/integration/scripts/start_test.sh b/test/integration/scripts/start_test.sh index baad3d9d..b5651672 100755 --- a/test/integration/scripts/start_test.sh +++ b/test/integration/scripts/start_test.sh @@ -2,17 +2,19 @@ function usage() { cat << EOF - start_test argument: - argument: functionality, benchmark or performance + start_test [option] [args]: + -t: run type:functionality, benchmark or performance + -c: case name + -p: parent pid EOF } function success_exit() { - local cur_pid=$(ps -ef | grep -v grep | grep "\b${pid}\b" | awk '{print $2}') - if [ x"$cur_pid" = x"$pid" ]; then - kill -9 $pid &>/dev/null - wait $pid &>/dev/null + local cur_sworkerpid=$(ps -ef | grep -v grep | grep "\b${sworkerpid}\b" | awk '{print $2}') + if [ x"$cur_sworkerpid" = x"$sworkerpid" ]; then + kill -9 $sworkerpid &>/dev/null + wait $sworkerpid &>/dev/null fi ### Clean test data @@ -20,11 +22,6 @@ function success_exit() rm -rf $datadir &>/dev/null fi - ### Clean tmp dir - if [ x"$tmpdir" != x"" ]; then - rm -rf $tmpdir &>/dev/null - fi - ### Clean err file if [ ! -s "$errfile" ]; then rm $errfile &>/dev/null @@ -34,17 +31,26 @@ function success_exit() rm $TMPFILE &>/dev/null rm $TMPFILE2 &>/dev/null - print_end + if [ x"$killed" = x"false" ]; then + print_end + fi } function kill_process() { # Kill descendent processes - kill -- -$curpid + print_end + killed=true + if [ x"$parent_sworkerpid" != x"" ] && [[ $parent_sworkerpid =~ ^[1-9][0-9]*$ ]]; then + kill -- -$parent_sworkerpid + else + kill -- -$cursworkerpid + fi } function print_end() { + printf "%s%s\n" "$pad" ' ' printf "%s%s\n" "$pad" ' __ __ __' printf "%s%s\n" "$pad" ' / /____ _____/ /_ ___ ____ ____/ /' printf "%s%s\n" "$pad" ' / __/ _ \/ ___/ __/ / _ \/ __ \/ __ / ' @@ -57,7 +63,6 @@ basedir=$(cd `dirname $0`;pwd) instdir=$(cd $basedir/..;pwd) scriptdir=$instdir/scripts datadir=$instdir/data -tmpdir=$instdir/tmp functionalitytestdir=$instdir/functionality benchmarktestdir=$instdir/benchmark performancetestdir=$instdir/performance @@ -68,14 +73,14 @@ testfiledir=$testdir/files sworkerlog=$instdir/sworker.log benchmarkfile=$instdir/benchmark.report_$(date +%Y%m%d%H%M%S) testconfigfile=$testdir/etc/Config.json -baseurl=$(cat $testconfigfile | jq ".base_url") -baseurl=${baseurl:1:${#baseurl}-2} +baseurl=$(cat $testconfigfile | jq ".base_url" | sed 's/"//g') SYNCFILE=$basedir/SYNCFILE TMPFILE=$instdir/TMPFILE TMPFILE2=$instdir/TMPFILE2 -curpid=$$ +cursworkerpid=$$ pad="$(printf '%0.1s' ' '{1..10})" casedir="" +killed=false trap "success_exit" EXIT trap "kill_process" INT @@ -83,7 +88,6 @@ trap "kill_process" INT . $basedir/utils.sh mkdir -p $datadir -mkdir -p $tmpdir mkdir -p $testfiledir export baseurl @@ -97,7 +101,15 @@ printf "%s%s\n" "$pad" ' (__ )| |/ |/ / /_/ / / / ,< / __/ / / /_/ __( printf "%s%s\n\n" "$pad" '/____/ |__/|__/\____/_/ /_/|_|\___/_/ \__/\___/____/\__/ ' -run_type=$1 +while getopts "t:p:c:" opt &>/dev/null; do + case $opt in + t) run_type=$OPTARG;; + p) parent_sworkerpid=$OPTARG;; + c) case_name=$OPTARG;; + *) ;; + esac +done + if [ x"$run_type" = x"functionality" ]; then casedir=$functionalitytestdir elif [ x"$run_type" = x"benchmark" ]; then @@ -110,6 +122,11 @@ else exit 1 fi +if ! ls $casedir | grep "\b${case_name}\b" &>/dev/null; then + verbose ERROR "no $case_name case!" + exit 1 +fi + ### Start crust-sworker cd $testdir @@ -118,17 +135,22 @@ rm -rf files mkdir files verbose INFO "starting crust-sworker..." h ./bin/crust-sworker -c etc/Config.json --offline --debug &>$sworkerlog & -pid=$! +sworkerpid=$! sleep 8 curl -s $baseurl/workload 2>$errfile 1>/dev/null -if [ $? -ne 0 ]; then +if [ $? -ne 0 ] ; then verbose ERROR "failed" t verbose ERROR "start crust sworker failed! Please check $errfile for details." - kill -9 $pid + kill -9 $sworkerpid + exit 1 +fi +if ! ps -ef | grep -v grep | grep $sworkerpid &>/dev/null; then + verbose ERROR "failed" t exit 1 fi verbose INFO "success" t cd - &>/dev/null +export sworkerpid ### Prepare test data verbose INFO "creating test data..." h @@ -147,10 +169,16 @@ verbose INFO "success" t cd $casedir verbose INFO "starting $run_type cases:" n true > $caseresfile -for script in `ls`; do +testcase_arry=($(ls | grep -v "restart")) +testcase_arry[${#testcase_arry[@]}]="restart" +disown -r +for script in ${testcase_arry[@]}; do + if [ x"$case_name" != x"" ] && [ x"$case_name" != x"$script" ]; then + continue + fi true > $SYNCFILE setTimeWait "$(verbose INFO "running test case: $script..." h)" $SYNCFILE & - bash $script $pid &>> $caseresfile + bash $script $sworkerpid &>> $caseresfile checkRes $? "return" "success" "$SYNCFILE" done cd - &>/dev/null diff --git a/test/integration/scripts/utils.sh b/test/integration/scripts/utils.sh index 5a431068..3997a455 100755 --- a/test/integration/scripts/utils.sh +++ b/test/integration/scripts/utils.sh @@ -81,7 +81,12 @@ function seal_file() { local data_path=$1 local store_path=$2 - local tmp_file=tmp_file.${RANDOM}$(date +%N) + local tmp_file="" + if [ x"$tmpdir" = x"" ]; then + tmp_file=tmp_file.${RANDOM}$(date +%N) + else + tmp_file=$tmpdir/tmp_file.${RANDOM}$(date +%N) + fi ### Split file crust_split $data_path $store_path &>$tmp_file @@ -153,11 +158,52 @@ function report_work() curl -s $baseurl/report/work } +function report_work_result() +{ + curl -s $baseurl/report/result +} + function store_metadata() { curl -s $baseurl/store_metadata } +function test_add_file() +{ + local file_num=$1 + if [ x"$file_num" = x"" ]; then + file_num=1000 + fi + curl -s -XGET $baseurl/test/add_file --data-raw "{\"file_num\":$file_num}" +} + +function test_valid_file() +{ + local file_num=$1 + if [ x"$file_num" = x"" ]; then + file_num=1000 + fi + curl -s -XGET $baseurl/test/valid_file --data-raw "{\"file_num\":$file_num}" +} + +function test_lost_file() +{ + local file_num=$1 + if [ x"$file_num" = x"" ]; then + file_num=1000 + fi + curl -s -XGET $baseurl/test/lost_file --data-raw "{\"file_num\":$file_num}" +} + +function test_delete_file() +{ + local file_num=$1 + if [ x"$file_num" = x"" ]; then + file_num=1000 + fi + curl -s -XGET $baseurl/test/delete_file --data-raw "{\"file_num\":$file_num}" +} + function verbose() { local type=$1 @@ -241,6 +287,15 @@ function print_space() printf " %.0s" $(eval "echo {1..$1}") } +function print_title() +{ + local info=$1 + local len=${#info} + local sp=40 + local time="[$(date "+%Y/%m/%d %T.%3N")] [INFO] " + printf "%s #####%$((sp/2))s%-$((sp/2))s#####\n" "$time" "`echo $info | cut -c 1-$(($len/2))`" "`echo $info | cut -c $(($len/2+1))-$len`" +} + function parse_json_array() { local array=$1