You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@teaclave.apache.org by ms...@apache.org on 2020/04/21 01:18:45 UTC

[incubator-teaclave] branch master updated: [tests] Automatic collect test cases into inventory and support to run with predicate (#269)

This is an automated email from the ASF dual-hosted git repository.

mssun pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-teaclave.git


The following commit(s) were added to refs/heads/master by this push:
     new a2230e0  [tests] Automatic collect test cases into inventory and support to run with predicate (#269)
a2230e0 is described below

commit a2230e09e9f158791b70583a26013e2ed1958ef3
Author: Mingshen Sun <bo...@mssun.me>
AuthorDate: Mon Apr 20 18:18:39 2020 -0700

    [tests] Automatic collect test cases into inventory and support to run with predicate (#269)
---
 tests/functional/enclave/Cargo.toml                |  5 ++-
 .../enclave/src/access_control_service.rs          | 26 +++++-------
 .../enclave/src/authentication_service.rs          | 20 ++++------
 .../enclave/src/end_to_end/mesapy_echo.rs          |  2 +
 tests/functional/enclave/src/end_to_end/mod.rs     | 20 ----------
 .../enclave/src/end_to_end/native_echo.rs          |  2 +
 .../enclave/src/end_to_end/native_gbdt_training.rs |  2 +
 tests/functional/enclave/src/execution_service.rs  |  8 +---
 tests/functional/enclave/src/frontend_service.rs   | 46 +++++++---------------
 tests/functional/enclave/src/lib.rs                | 44 ++++-----------------
 tests/functional/enclave/src/management_service.rs | 34 +++++++---------
 tests/functional/enclave/src/scheduler_service.rs  |  9 ++---
 tests/functional/enclave/src/storage_service.rs    | 22 ++++-------
 tests/functional/enclave/src/utils.rs              | 11 ++++++
 tests/utils/Cargo.toml                             |  2 +
 tests/utils/proc_macro/Cargo.toml                  | 13 ++++++
 tests/utils/proc_macro/src/lib.rs                  | 41 +++++++++++++++++++
 tests/utils/src/lib.rs                             | 26 ++++++++++++
 third_party/crates-io                              |  2 +-
 third_party/crates-sgx                             |  2 +-
 20 files changed, 169 insertions(+), 168 deletions(-)

diff --git a/tests/functional/enclave/Cargo.toml b/tests/functional/enclave/Cargo.toml
index ae544cd..a187c33 100644
--- a/tests/functional/enclave/Cargo.toml
+++ b/tests/functional/enclave/Cargo.toml
@@ -28,14 +28,15 @@ mesalock_sgx = [
 cov = ["teaclave_service_enclave_utils/cov"]
 
 [dependencies]
-log         = { version = "0.4.6" }
 anyhow      = { version = "1.0.26" }
+inventory   = { version = "0.1.6" }
+lazy_static = { version = "1.4.0" }
+log         = { version = "0.4.6" }
 serde       = { version = "1.0.92" }
 serde_json  = { version = "1.0.39" }
 thiserror   = { version = "1.0.9" }
 url         = { version = "2.1.1" }
 uuid        = { version = "0.8.1", features = ["v4"] }
-lazy_static = { version = "1.4.0" }
 
 teaclave_attestation           = { path = "../../../attestation" }
 teaclave_config                = { path = "../../../config" }
diff --git a/tests/functional/enclave/src/access_control_service.rs b/tests/functional/enclave/src/access_control_service.rs
index 706c232..06f18fe 100644
--- a/tests/functional/enclave/src/access_control_service.rs
+++ b/tests/functional/enclave/src/access_control_service.rs
@@ -18,23 +18,9 @@
 use crate::utils::*;
 use std::prelude::v1::*;
 use teaclave_proto::teaclave_access_control_service::*;
+use teaclave_test_utils::test_case;
 
-pub fn run_tests() -> bool {
-    use teaclave_test_utils::*;
-
-    run_tests!(
-        test_authorize_data_success,
-        test_authorize_data_fail,
-        test_authorize_function_success,
-        test_authorize_function_fail,
-        test_authorize_task_success,
-        test_authorize_task_fail,
-        test_authorize_staged_task_success,
-        test_authorize_staged_task_fail,
-        test_concurrency,
-    )
-}
-
+#[test_case]
 fn test_authorize_data_success() {
     let mut client = get_access_control_client();
 
@@ -44,6 +30,7 @@ fn test_authorize_data_success() {
     assert!(response_result.unwrap().accept);
 }
 
+#[test_case]
 fn test_authorize_data_fail() {
     let mut client = get_access_control_client();
 
@@ -58,6 +45,7 @@ fn test_authorize_data_fail() {
     assert!(!response_result.unwrap().accept);
 }
 
+#[test_case]
 fn test_authorize_function_success() {
     let mut client = get_access_control_client();
 
@@ -80,6 +68,7 @@ fn test_authorize_function_success() {
     assert!(response_result.unwrap().accept);
 }
 
+#[test_case]
 fn test_authorize_function_fail() {
     let mut client = get_access_control_client();
     let request =
@@ -89,6 +78,7 @@ fn test_authorize_function_fail() {
     assert!(!response_result.unwrap().accept);
 }
 
+#[test_case]
 fn test_authorize_task_success() {
     let mut client = get_access_control_client();
     let request = AuthorizeTaskRequest::new("mock_participant_a", "mock_task");
@@ -102,6 +92,7 @@ fn test_authorize_task_success() {
     assert!(response_result.unwrap().accept);
 }
 
+#[test_case]
 fn test_authorize_task_fail() {
     let mut client = get_access_control_client();
     let request = AuthorizeTaskRequest::new("mock_participant_c", "mock_task");
@@ -110,6 +101,7 @@ fn test_authorize_task_fail() {
     assert!(!response_result.unwrap().accept);
 }
 
+#[test_case]
 fn test_authorize_staged_task_success() {
     let mut client = get_access_control_client();
     let request = AuthorizeStagedTaskRequest {
@@ -131,6 +123,7 @@ fn test_authorize_staged_task_success() {
     assert!(response_result.unwrap().accept);
 }
 
+#[test_case]
 fn test_authorize_staged_task_fail() {
     let mut client = get_access_control_client();
     let request = AuthorizeStagedTaskRequest {
@@ -164,6 +157,7 @@ fn test_authorize_staged_task_fail() {
     assert!(!response_result.unwrap().accept);
 }
 
+#[test_case]
 fn test_concurrency() {
     let mut thread_pool = Vec::new();
     for _i in 0..10 {
diff --git a/tests/functional/enclave/src/authentication_service.rs b/tests/functional/enclave/src/authentication_service.rs
index 5af5854..e85785a 100644
--- a/tests/functional/enclave/src/authentication_service.rs
+++ b/tests/functional/enclave/src/authentication_service.rs
@@ -23,21 +23,9 @@ use teaclave_proto::teaclave_authentication_service::*;
 use teaclave_proto::teaclave_common::*;
 use teaclave_rpc::config::SgxTrustedTlsClientConfig;
 use teaclave_rpc::endpoint::Endpoint;
+use teaclave_test_utils::test_case;
 use teaclave_types::EnclaveInfo;
 
-pub fn run_tests() -> bool {
-    use teaclave_test_utils::*;
-
-    run_tests!(
-        test_login_success,
-        test_login_fail,
-        test_authenticate_success,
-        test_authenticate_fail,
-        test_register_success,
-        test_register_fail,
-    )
-}
-
 fn get_api_client() -> TeaclaveAuthenticationApiClient {
     let runtime_config = RuntimeConfig::from_toml("runtime.config.toml").expect("runtime");
     let enclave_info =
@@ -83,6 +71,7 @@ fn get_internal_client() -> TeaclaveAuthenticationInternalClient {
     TeaclaveAuthenticationInternalClient::new(channel).unwrap()
 }
 
+#[test_case]
 fn test_login_success() {
     let mut client = get_api_client();
     let request = UserRegisterRequest::new("test_login_id1", "test_password");
@@ -95,6 +84,7 @@ fn test_login_success() {
     assert!(response_result.is_ok());
 }
 
+#[test_case]
 fn test_login_fail() {
     let mut client = get_api_client();
     let request = UserRegisterRequest::new("test_login_id2", "test_password");
@@ -107,6 +97,7 @@ fn test_login_fail() {
     assert!(response_result.is_err());
 }
 
+#[test_case]
 fn test_authenticate_success() {
     let mut api_client = get_api_client();
     let mut internal_client = get_internal_client();
@@ -124,6 +115,7 @@ fn test_authenticate_success() {
     assert!(response_result.unwrap().accept);
 }
 
+#[test_case]
 fn test_authenticate_fail() {
     let mut api_client = get_api_client();
     let mut internal_client = get_internal_client();
@@ -139,6 +131,7 @@ fn test_authenticate_fail() {
     assert!(!response_result.unwrap().accept);
 }
 
+#[test_case]
 fn test_register_success() {
     let mut client = get_api_client();
     let request = UserRegisterRequest::new("test_register_id1", "test_password");
@@ -147,6 +140,7 @@ fn test_register_success() {
     assert!(response_result.is_ok());
 }
 
+#[test_case]
 fn test_register_fail() {
     let mut client = get_api_client();
     let request = UserRegisterRequest::new("test_register_id2", "test_password");
diff --git a/tests/functional/enclave/src/end_to_end/mesapy_echo.rs b/tests/functional/enclave/src/end_to_end/mesapy_echo.rs
index b4fe09a..e286ddc 100644
--- a/tests/functional/enclave/src/end_to_end/mesapy_echo.rs
+++ b/tests/functional/enclave/src/end_to_end/mesapy_echo.rs
@@ -16,7 +16,9 @@
 // under the License.
 
 use super::*;
+use teaclave_test_utils::test_case;
 
+#[test_case]
 pub fn test_echo_task_success() {
     // Authenticate user before talking to frontend service
     let mut api_client =
diff --git a/tests/functional/enclave/src/end_to_end/mod.rs b/tests/functional/enclave/src/end_to_end/mod.rs
index 755b61f..f725f3d 100644
--- a/tests/functional/enclave/src/end_to_end/mod.rs
+++ b/tests/functional/enclave/src/end_to_end/mod.rs
@@ -25,26 +25,6 @@ mod mesapy_echo;
 mod native_echo;
 mod native_gbdt_training;
 
-const USERNAME: &str = "alice";
-const PASSWORD: &str = "daHosldOdker0sS";
-
-pub fn run_tests() -> bool {
-    use teaclave_test_utils::*;
-    setup();
-    run_tests!(
-        native_gbdt_training::test_gbdt_training_task,
-        native_echo::test_echo_task_success,
-        mesapy_echo::test_echo_task_success,
-    )
-}
-
-fn setup() {
-    // Register user for the first time
-    let mut api_client =
-        create_authentication_api_client(shared_enclave_info(), AUTH_SERVICE_ADDR).unwrap();
-    register_new_account(&mut api_client, USERNAME, PASSWORD).unwrap();
-}
-
 fn get_task_until(
     client: &mut TeaclaveFrontendClient,
     task_id: &ExternalID,
diff --git a/tests/functional/enclave/src/end_to_end/native_echo.rs b/tests/functional/enclave/src/end_to_end/native_echo.rs
index ccf908d..d86eade 100644
--- a/tests/functional/enclave/src/end_to_end/native_echo.rs
+++ b/tests/functional/enclave/src/end_to_end/native_echo.rs
@@ -16,7 +16,9 @@
 // under the License.
 
 use super::*;
+use teaclave_test_utils::test_case;
 
+#[test_case]
 pub fn test_echo_task_success() {
     // Authenticate user before talking to frontend service
     let mut api_client =
diff --git a/tests/functional/enclave/src/end_to_end/native_gbdt_training.rs b/tests/functional/enclave/src/end_to_end/native_gbdt_training.rs
index e742c9e..ecb1cbe 100644
--- a/tests/functional/enclave/src/end_to_end/native_gbdt_training.rs
+++ b/tests/functional/enclave/src/end_to_end/native_gbdt_training.rs
@@ -17,7 +17,9 @@
 
 use super::*;
 use teaclave_crypto::TeaclaveFile128Key;
+use teaclave_test_utils::test_case;
 
+#[test_case]
 pub fn test_gbdt_training_task() {
     let mut client = authorized_frontend_client();
     let function_id = register_gbdt_function(&mut client);
diff --git a/tests/functional/enclave/src/execution_service.rs b/tests/functional/enclave/src/execution_service.rs
index e0306a0..5ca9f64 100644
--- a/tests/functional/enclave/src/execution_service.rs
+++ b/tests/functional/enclave/src/execution_service.rs
@@ -18,16 +18,12 @@
 use crate::utils::*;
 use std::prelude::v1::*;
 use teaclave_proto::teaclave_storage_service::*;
+use teaclave_test_utils::test_case;
 use teaclave_types::*;
 
 use uuid::Uuid;
 
-pub fn run_tests() -> bool {
-    use teaclave_test_utils::*;
-
-    run_tests!(test_execute_function)
-}
-
+#[test_case]
 fn test_execute_function() {
     let task_id = Uuid::new_v4();
     let task = Task {
diff --git a/tests/functional/enclave/src/frontend_service.rs b/tests/functional/enclave/src/frontend_service.rs
index 08e1484..792fa44 100644
--- a/tests/functional/enclave/src/frontend_service.rs
+++ b/tests/functional/enclave/src/frontend_service.rs
@@ -21,41 +21,10 @@ use std::prelude::v1::*;
 use teaclave_proto::teaclave_common::*;
 use teaclave_proto::teaclave_frontend_service::*;
 use teaclave_proto::teaclave_scheduler_service::*;
+use teaclave_test_utils::test_case;
 use teaclave_types::*;
 use url::Url;
 
-pub fn run_tests() -> bool {
-    use teaclave_test_utils::*;
-
-    setup();
-
-    run_tests!(
-        test_register_input_file,
-        test_register_output_file,
-        test_register_fusion_output,
-        test_register_input_from_output,
-        test_get_output_file,
-        test_get_input_file,
-        test_register_function,
-        test_get_function,
-        test_create_task,
-        test_get_task,
-        test_assign_data,
-        test_approve_task,
-        test_invoke_task,
-    )
-}
-
-const USERNAME: &str = "frontend_user";
-const PASSWORD: &str = "test_password";
-
-fn setup() {
-    // Register user for the first time
-    let mut api_client =
-        create_authentication_api_client(shared_enclave_info(), AUTH_SERVICE_ADDR).unwrap();
-    register_new_account(&mut api_client, USERNAME, PASSWORD).unwrap();
-}
-
 fn authorized_client() -> TeaclaveFrontendClient {
     let mut api_client =
         create_authentication_api_client(shared_enclave_info(), AUTH_SERVICE_ADDR).unwrap();
@@ -68,6 +37,7 @@ fn unauthorized_client() -> TeaclaveFrontendClient {
     create_frontend_client(shared_enclave_info(), FRONTEND_SERVICE_ADDR, cred).unwrap()
 }
 
+#[test_case]
 fn test_register_input_file() {
     let url = Url::parse("https://external-storage.com/filepath?presigned_token").unwrap();
     let cmac = FileAuthTag::mock();
@@ -82,6 +52,7 @@ fn test_register_input_file() {
     assert!(response.is_err());
 }
 
+#[test_case]
 fn test_register_output_file() {
     let url = Url::parse("https://external-storage.com/filepath?presigned_token").unwrap();
     let crypto_info = FileCrypto::default();
@@ -95,6 +66,7 @@ fn test_register_output_file() {
     assert!(response.is_err());
 }
 
+#[test_case]
 fn test_register_fusion_output() {
     let request = RegisterFusionOutputRequest::new(vec!["frontend_user", "mock_user"]);
     let response = authorized_client().register_fusion_output(request);
@@ -105,6 +77,7 @@ fn test_register_fusion_output() {
     assert!(response.is_err());
 }
 
+#[test_case]
 fn test_register_input_from_output() {
     let output_id = ExternalID::try_from("output-00000000-0000-0000-0000-000000000001").unwrap();
 
@@ -117,6 +90,7 @@ fn test_register_input_from_output() {
     assert!(response.is_err());
 }
 
+#[test_case]
 fn test_get_output_file() {
     let mut client = authorized_client();
 
@@ -135,6 +109,7 @@ fn test_get_output_file() {
     assert!(response.is_err());
 }
 
+#[test_case]
 fn test_get_input_file() {
     let mut client = authorized_client();
 
@@ -154,6 +129,7 @@ fn test_get_input_file() {
     assert!(response.is_err());
 }
 
+#[test_case]
 fn test_register_function() {
     let request = RegisterFunctionRequest::default();
     let response = authorized_client().register_function(request);
@@ -164,6 +140,7 @@ fn test_register_function() {
     assert!(response.is_err());
 }
 
+#[test_case]
 fn test_get_function() {
     let function_id =
         ExternalID::try_from("function-00000000-0000-0000-0000-000000000001").unwrap();
@@ -177,6 +154,7 @@ fn test_get_function() {
     assert!(response.is_err());
 }
 
+#[test_case]
 fn test_create_task() {
     let function_id =
         ExternalID::try_from("function-00000000-0000-0000-0000-000000000002").unwrap();
@@ -198,6 +176,7 @@ fn test_create_task() {
     assert!(response.is_err());
 }
 
+#[test_case]
 fn test_get_task() {
     let mut client = authorized_client();
     let function_id =
@@ -220,6 +199,7 @@ fn test_get_task() {
     assert!(response.is_err());
 }
 
+#[test_case]
 fn test_assign_data() {
     let mut client = authorized_client();
     let function_id =
@@ -254,6 +234,7 @@ fn test_assign_data() {
     assert!(response.is_ok());
 }
 
+#[test_case]
 fn test_approve_task() {
     let mut client = authorized_client();
     let function_id =
@@ -287,6 +268,7 @@ fn test_approve_task() {
     assert!(response.is_ok());
 }
 
+#[test_case]
 fn test_invoke_task() {
     let mut client = authorized_client();
     let function_id =
diff --git a/tests/functional/enclave/src/lib.rs b/tests/functional/enclave/src/lib.rs
index 29a0916..701834d 100644
--- a/tests/functional/enclave/src/lib.rs
+++ b/tests/functional/enclave/src/lib.rs
@@ -23,7 +23,6 @@ extern crate sgx_tstd as std;
 #[macro_use]
 extern crate log;
 
-use std::collections::HashMap;
 use std::prelude::v1::*;
 
 use teaclave_binder::proto::{
@@ -44,45 +43,16 @@ mod scheduler_service;
 mod storage_service;
 mod utils;
 
-type BoxedFnTest = Box<dyn Fn() -> bool>;
+use teaclave_test_utils::run_inventory_tests;
 
 #[handle_ecall]
 fn handle_run_test(input: &RunTestInput) -> TeeServiceResult<RunTestOutput> {
-    let test_names = &input.test_names;
-    let v: Vec<(_, BoxedFnTest)> = vec![
-        (
-            "access_control_service",
-            Box::new(access_control_service::run_tests),
-        ),
-        (
-            "authentication_service",
-            Box::new(authentication_service::run_tests),
-        ),
-        ("storage_service", Box::new(storage_service::run_tests)),
-        ("frontend_service", Box::new(frontend_service::run_tests)),
-        (
-            "management_service",
-            Box::new(management_service::run_tests),
-        ),
-        ("scheduler_service", Box::new(scheduler_service::run_tests)),
-        ("execution_service", Box::new(execution_service::run_tests)),
-        ("end_to_end", Box::new(end_to_end::run_tests)),
-    ];
-    let test_map: HashMap<_, BoxedFnTest> =
-        v.into_iter().map(|(k, v)| (k.to_string(), v)).collect();
-
-    let mut ret = true;
-
-    if test_names.is_empty() {
-        for fn_test in test_map.values() {
-            ret &= fn_test();
-        }
-    }
-
-    for name in test_names.iter() {
-        let fn_test = test_map.get(name).unwrap();
-        ret &= fn_test();
-    }
+    utils::setup();
+    let ret = if input.test_names.is_empty() {
+        run_inventory_tests!()
+    } else {
+        run_inventory_tests!(|s: &str| input.test_names.iter().any(|t| s.contains(t)))
+    };
 
     assert_eq!(ret, true);
     Ok(RunTestOutput)
diff --git a/tests/functional/enclave/src/management_service.rs b/tests/functional/enclave/src/management_service.rs
index 37ea704..62b83e1 100644
--- a/tests/functional/enclave/src/management_service.rs
+++ b/tests/functional/enclave/src/management_service.rs
@@ -20,33 +20,15 @@ use std::convert::TryFrom;
 use std::prelude::v1::*;
 use teaclave_proto::teaclave_management_service::*;
 use teaclave_proto::teaclave_scheduler_service::*;
+use teaclave_test_utils::test_case;
 use teaclave_types::*;
 use url::Url;
 
-pub fn run_tests() -> bool {
-    use teaclave_test_utils::*;
-
-    run_tests!(
-        test_register_input_file,
-        test_register_output_file,
-        test_register_fusion_output,
-        test_register_input_from_output,
-        test_get_input_file,
-        test_get_output_file,
-        test_register_function,
-        test_get_function,
-        test_create_task,
-        test_get_task,
-        test_assign_data,
-        test_approve_task,
-        test_invoke_task,
-    )
-}
-
 fn authorized_client(user_id: &str) -> TeaclaveManagementClient {
     get_management_client(user_id)
 }
 
+#[test_case]
 fn test_register_input_file() {
     let url = Url::parse("https://external-storage.com/filepath?presigned_token").unwrap();
     let cmac = FileAuthTag::mock();
@@ -56,6 +38,7 @@ fn test_register_input_file() {
     assert!(response.is_ok());
 }
 
+#[test_case]
 fn test_register_output_file() {
     let url = Url::parse("https://external-storage.com/filepath?presigned_token").unwrap();
     let crypto_info = FileCrypto::new("aes-gcm-128", &[0x90u8; 16], &[0x89u8; 12]).unwrap();
@@ -66,6 +49,7 @@ fn test_register_output_file() {
     assert!(response.is_ok());
 }
 
+#[test_case]
 fn test_register_fusion_output() {
     let request = RegisterFusionOutputRequest::new(vec!["mock_user", "mock_user_b"]);
     let response = authorized_client("mock_user").register_fusion_output(request);
@@ -76,6 +60,7 @@ fn test_register_fusion_output() {
     assert!(response.is_err());
 }
 
+#[test_case]
 fn test_register_input_from_output() {
     let user1_output_id =
         ExternalID::try_from("output-00000000-0000-0000-0000-000000000001").unwrap();
@@ -100,6 +85,7 @@ fn test_register_input_from_output() {
     assert!(response.is_ok());
 }
 
+#[test_case]
 fn test_get_output_file() {
     let url = Url::parse("https://external-storage.com/filepath?presigned_token").unwrap();
     let crypto_info = FileCrypto::default();
@@ -117,6 +103,7 @@ fn test_get_output_file() {
     assert!(response.is_err());
 }
 
+#[test_case]
 fn test_get_input_file() {
     let url = Url::parse("https://external-storage.com/filepath?presigned_token").unwrap();
     let cmac = FileAuthTag::mock();
@@ -136,6 +123,7 @@ fn test_get_input_file() {
     assert!(response.is_err());
 }
 
+#[test_case]
 fn test_register_function() {
     let function_input = FunctionInput::new("input", "input_desc");
     let function_output = FunctionOutput::new("output", "output_desc");
@@ -154,6 +142,7 @@ fn test_register_function() {
     assert!(response.is_ok());
 }
 
+#[test_case]
 fn test_get_function() {
     let function_input = FunctionInput::new("input", "input_desc");
     let function_output = FunctionOutput::new("output", "output_desc");
@@ -206,6 +195,7 @@ fn valid_create_task_request() -> CreateTaskRequest {
         .output_owners_map(output_owners)
 }
 
+#[test_case]
 fn test_create_task() {
     let mut client = authorized_client("mock_user");
 
@@ -233,6 +223,7 @@ fn test_create_task() {
     assert!(response.is_err());
 }
 
+#[test_case]
 fn test_get_task() {
     let mut client = authorized_client("mock_user");
 
@@ -250,6 +241,7 @@ fn test_get_task() {
     }
 }
 
+#[test_case]
 fn test_assign_data() {
     let mut client = authorized_client("mock_user");
     let mut client1 = authorized_client("mock_user1");
@@ -424,6 +416,7 @@ fn test_assign_data() {
     assert!(response.is_err());
 }
 
+#[test_case]
 fn test_approve_task() {
     let mut client = authorized_client("mock_user");
     let mut client1 = authorized_client("mock_user1");
@@ -507,6 +500,7 @@ fn test_approve_task() {
     assert_eq!(response.status, TaskStatus::Approved);
 }
 
+#[test_case]
 fn test_invoke_task() {
     let mut client = authorized_client("mock_user");
     let mut client1 = authorized_client("mock_user1");
diff --git a/tests/functional/enclave/src/scheduler_service.rs b/tests/functional/enclave/src/scheduler_service.rs
index 2ad6b3b..82a0034 100644
--- a/tests/functional/enclave/src/scheduler_service.rs
+++ b/tests/functional/enclave/src/scheduler_service.rs
@@ -19,16 +19,12 @@ use crate::utils::*;
 use std::prelude::v1::*;
 use teaclave_proto::teaclave_scheduler_service::*;
 use teaclave_proto::teaclave_storage_service::*;
+use teaclave_test_utils::test_case;
 use teaclave_types::*;
 
 use uuid::Uuid;
 
-pub fn run_tests() -> bool {
-    use teaclave_test_utils::*;
-
-    run_tests!(test_pull_task, test_update_task_status_result)
-}
-
+#[test_case]
 fn test_pull_task() {
     let function_id = Uuid::new_v4();
     let staged_task = StagedTask::new()
@@ -51,6 +47,7 @@ fn test_pull_task() {
     assert_eq!(response.unwrap().staged_task.function_id, function_id);
 }
 
+#[test_case]
 fn test_update_task_status_result() {
     let task_id = Uuid::new_v4();
     let task = Task {
diff --git a/tests/functional/enclave/src/storage_service.rs b/tests/functional/enclave/src/storage_service.rs
index 6a7aa85..1131377 100644
--- a/tests/functional/enclave/src/storage_service.rs
+++ b/tests/functional/enclave/src/storage_service.rs
@@ -19,20 +19,7 @@ use std::prelude::v1::*;
 use teaclave_config::RuntimeConfig;
 use teaclave_proto::teaclave_storage_service::*;
 use teaclave_rpc::endpoint::Endpoint;
-
-pub fn run_tests() -> bool {
-    use teaclave_test_utils::*;
-
-    run_tests!(
-        test_get_success,
-        test_get_fail,
-        test_put_success,
-        test_delete_success,
-        test_enqueue_success,
-        test_dequeue_success,
-        test_dequeue_fail,
-    )
-}
+use teaclave_test_utils::test_case;
 
 fn get_client() -> TeaclaveStorageClient {
     let runtime_config = RuntimeConfig::from_toml("runtime.config.toml").expect("runtime");
@@ -42,6 +29,7 @@ fn get_client() -> TeaclaveStorageClient {
     TeaclaveStorageClient::new(channel).unwrap()
 }
 
+#[test_case]
 fn test_get_success() {
     let mut client = get_client();
     let request = GetRequest::new("test_get_key");
@@ -50,6 +38,7 @@ fn test_get_success() {
     assert!(response_result.is_ok());
 }
 
+#[test_case]
 fn test_get_fail() {
     let mut client = get_client();
     let request = GetRequest::new("test_key_not_exist");
@@ -57,6 +46,7 @@ fn test_get_fail() {
     assert!(response_result.is_err());
 }
 
+#[test_case]
 fn test_put_success() {
     let mut client = get_client();
     let request = PutRequest::new("test_put_key", "test_put_value");
@@ -71,6 +61,7 @@ fn test_put_success() {
     assert_eq!(response_result.unwrap().value, b"test_put_value");
 }
 
+#[test_case]
 fn test_delete_success() {
     let mut client = get_client();
     let request = DeleteRequest::new("test_delete_key");
@@ -83,6 +74,7 @@ fn test_delete_success() {
     assert!(response_result.is_err());
 }
 
+#[test_case]
 fn test_enqueue_success() {
     let mut client = get_client();
     let request = EnqueueRequest::new("test_enqueue_key", "test_enqueue_value");
@@ -91,6 +83,7 @@ fn test_enqueue_success() {
     assert!(response_result.is_ok());
 }
 
+#[test_case]
 fn test_dequeue_success() {
     let mut client = get_client();
     let request = DequeueRequest::new("test_dequeue_key");
@@ -112,6 +105,7 @@ fn test_dequeue_success() {
     assert_eq!(response_result.unwrap().value, b"2");
 }
 
+#[test_case]
 fn test_dequeue_fail() {
     let mut client = get_client();
     let request = DequeueRequest::new("test_dequeue_key");
diff --git a/tests/functional/enclave/src/utils.rs b/tests/functional/enclave/src/utils.rs
index 909afb5..01f707e 100644
--- a/tests/functional/enclave/src/utils.rs
+++ b/tests/functional/enclave/src/utils.rs
@@ -164,3 +164,14 @@ pub fn login(
 
     Ok(UserCredential::new(username, response.token))
 }
+
+pub const USERNAME: &str = "frontend_user";
+pub const PASSWORD: &str = "test_password";
+
+pub fn setup() {
+    // Register user for the first time
+    let mut api_client =
+        create_authentication_api_client(shared_enclave_info(), AUTH_SERVICE_ADDR).unwrap();
+    // Ignore error if register failed.
+    let _ = register_new_account(&mut api_client, USERNAME, PASSWORD);
+}
diff --git a/tests/utils/Cargo.toml b/tests/utils/Cargo.toml
index f7d07f0..114969d 100644
--- a/tests/utils/Cargo.toml
+++ b/tests/utils/Cargo.toml
@@ -13,4 +13,6 @@ mesalock_sgx = [
 ]
 
 [dependencies]
+inventory   = { version = "0.1.6" }
+teaclave_test_utils_proc_macro = { path = "./proc_macro" }
 sgx_tstd = { version = "1.1.1", features = ["backtrace"], optional = true }
diff --git a/tests/utils/proc_macro/Cargo.toml b/tests/utils/proc_macro/Cargo.toml
new file mode 100644
index 0000000..71313a5
--- /dev/null
+++ b/tests/utils/proc_macro/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "teaclave_test_utils_proc_macro"
+version = "0.0.1"
+edition = "2018"
+publish = false
+
+[lib]
+proc-macro = true
+
+[dependencies]
+proc-macro2 = "1.0"
+quote = "1.0"
+syn = { version = "1.0", features = ["full"] }
\ No newline at end of file
diff --git a/tests/utils/proc_macro/src/lib.rs b/tests/utils/proc_macro/src/lib.rs
new file mode 100644
index 0000000..627459d
--- /dev/null
+++ b/tests/utils/proc_macro/src/lib.rs
@@ -0,0 +1,41 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+extern crate proc_macro;
+use quote::quote;
+use syn::parse_macro_input;
+use syn::ItemFn;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn test_case(_attr: TokenStream, input: TokenStream) -> TokenStream {
+    let f = parse_macro_input!(input as ItemFn);
+    let f_ident = &f.sig.ident;
+    let q = quote!(
+        #f
+
+        inventory::submit!(
+            teaclave_test_utils::TestCase(
+                concat!(module_path!(), "::", stringify!(#f_ident)).to_string(),
+                #f_ident
+            )
+        );
+    );
+
+    q.into()
+}
diff --git a/tests/utils/src/lib.rs b/tests/utils/src/lib.rs
index d631d5a..e061b47 100644
--- a/tests/utils/src/lib.rs
+++ b/tests/utils/src/lib.rs
@@ -23,6 +23,32 @@ extern crate sgx_tstd as std;
 use std::string::String;
 use std::vec::Vec;
 
+pub use teaclave_test_utils_proc_macro::test_case;
+
+pub struct TestCase(pub String, pub fn() -> ());
+
+inventory::collect!(TestCase);
+
+#[macro_export]
+macro_rules! run_inventory_tests {
+    ($predicate:expr) => {{
+        teaclave_test_utils::test_start();
+        let mut ntestcases: u64 = 0u64;
+        let mut failurecases: Vec<String> = Vec::new();
+
+        for t in inventory::iter::<teaclave_test_utils::TestCase>.into_iter() {
+            if $predicate(&t.0) {
+                teaclave_test_utils::test(&mut ntestcases, &mut failurecases, t.1, &t.0);
+            }
+        }
+
+        teaclave_test_utils::test_end(ntestcases, failurecases)
+    }};
+    () => {
+        run_inventory_tests!(|_| true);
+    };
+}
+
 #[macro_export]
 macro_rules! should_panic {
     ($fmt:expr) => {{
diff --git a/third_party/crates-io b/third_party/crates-io
index 8b35aea..12aeb43 160000
--- a/third_party/crates-io
+++ b/third_party/crates-io
@@ -1 +1 @@
-Subproject commit 8b35aea74f2b435f1ba2d3f678192a20539c279b
+Subproject commit 12aeb43d22bd37f575a58b27b78d35a846561c55
diff --git a/third_party/crates-sgx b/third_party/crates-sgx
index 6244519..c0f033e 160000
--- a/third_party/crates-sgx
+++ b/third_party/crates-sgx
@@ -1 +1 @@
-Subproject commit 62445195bacfa7c14a110c205752c4cfc36fa6ea
+Subproject commit c0f033e385818ff79c118c06edd08378d4fe7476


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@teaclave.apache.org
For additional commands, e-mail: commits-help@teaclave.apache.org