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/03/23 21:25:09 UTC

[incubator-teaclave] branch develop updated: [tests] Add functional test for execution service

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

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


The following commit(s) were added to refs/heads/develop by this push:
     new 9536e52  [tests] Add functional test for execution service
9536e52 is described below

commit 9536e527d0d0ee7d02bcb8629b262326bf4b7768
Author: Mingshen Sun <bo...@mssun.me>
AuthorDate: Mon Mar 23 11:57:55 2020 -0700

    [tests] Add functional test for execution service
---
 binder/src/proto.rs                               | 12 +++-
 cmake/scripts/test.sh                             | 22 +++++-
 services/execution/enclave/src/service.rs         |  8 +++
 tests/functional/app/Cargo.toml                   |  1 +
 tests/functional/app/src/main.rs                  | 22 +++---
 tests/functional/enclave/src/execution_service.rs | 82 +++++++++++++++++++++++
 tests/functional/enclave/src/lib.rs               | 49 +++++++++++---
 tests/integration/app/src/main.rs                 |  3 +-
 tests/unit/app/src/main.rs                        |  3 +-
 types/src/worker.rs                               |  2 +-
 10 files changed, 177 insertions(+), 27 deletions(-)

diff --git a/binder/src/proto.rs b/binder/src/proto.rs
index e08b19c..95e103a 100644
--- a/binder/src/proto.rs
+++ b/binder/src/proto.rs
@@ -79,8 +79,16 @@ pub struct FinalizeEnclaveInput;
 #[derive(Serialize, Deserialize, Debug)]
 pub struct FinalizeEnclaveOutput;
 
-#[derive(Serialize, Deserialize, Debug)]
-pub struct RunTestInput;
+#[derive(Default, Serialize, Deserialize, Debug)]
+pub struct RunTestInput {
+    pub test_names: Vec<String>,
+}
+
+impl RunTestInput {
+    pub fn new(test_names: Vec<String>) -> Self {
+        Self { test_names }
+    }
+}
 
 #[derive(Serialize, Deserialize, Debug)]
 pub struct RunTestOutput;
diff --git a/cmake/scripts/test.sh b/cmake/scripts/test.sh
index c903ea9..c9ef7e8 100755
--- a/cmake/scripts/test.sh
+++ b/cmake/scripts/test.sh
@@ -59,7 +59,7 @@ run_integration_tests() {
 
   popd
 
-  cleanup 
+  cleanup
 }
 
 run_functional_tests() {
@@ -77,11 +77,27 @@ run_functional_tests() {
   sleep 3    # wait for management service and scheduler_service
   ./teaclave_access_control_service &
   ./teaclave_frontend_service &
-  # ./teaclave_execution_service &
   popd
   sleep 3    # wait for other services
-  ./teaclave_functional_tests
 
+  # Run function tests for all except execution service
+  ./teaclave_functional_tests -t \
+    access_control_service \
+    authentication_service \
+    frontend_service \
+    management_service \
+    scheduler_service \
+    storage_service
+
+  # Run tests of execution service separately
+  pushd ${TEACLAVE_SERVICE_INSTALL_DIR}
+  ./teaclave_execution_service &
+  popd
+  sleep 3    # wait for execution services
+
+  ./teaclave_functional_tests -t execution_service
+
+  # Run script tests
   ./scripts/functional_tests.py -v
 
   popd
diff --git a/services/execution/enclave/src/service.rs b/services/execution/enclave/src/service.rs
index d3a3c00..5cae334 100644
--- a/services/execution/enclave/src/service.rs
+++ b/services/execution/enclave/src/service.rs
@@ -27,6 +27,7 @@ use teaclave_types::{ExecutionResult, StagedFunction, StagedTask, TaskStatus};
 use teaclave_worker::Worker;
 
 use anyhow::Result;
+use log::debug;
 use uuid::Uuid;
 
 #[derive(Clone)]
@@ -77,9 +78,12 @@ impl TeaclaveExecutionService {
                     continue;
                 }
             };
+            drop(client); // drop mutex guard
+
             log::debug!("response: {:?}", response);
             let staged_task = response.staged_task;
             let result = self.invoke_task(&staged_task).unwrap();
+            debug!("result: {:?}", result);
             match self.update_task_status(&staged_task.task_id, TaskStatus::Finished) {
                 Ok(_) => (),
                 Err(e) => {
@@ -98,10 +102,12 @@ impl TeaclaveExecutionService {
     }
 
     fn invoke_task(&mut self, task: &StagedTask) -> Result<ExecutionResult> {
+        debug!("invoke_task");
         self.update_task_status(&task.task_id, TaskStatus::Running)?;
         let invocation = prepare_task(&task);
         let worker = Worker::default();
         let summary = worker.invoke_function(invocation)?;
+        debug!("summary: {:?}", summary);
         finalize_task(&task)?;
         let mut result = ExecutionResult::default();
         result.return_value = summary.as_bytes().to_vec();
@@ -110,6 +116,7 @@ impl TeaclaveExecutionService {
     }
 
     fn update_task_result(&mut self, task_id: &Uuid, result: ExecutionResult) -> Result<()> {
+        debug!("update_task_result");
         let request = UpdateTaskResultRequest::new(
             task_id.to_owned(),
             &result.return_value,
@@ -126,6 +133,7 @@ impl TeaclaveExecutionService {
     }
 
     fn update_task_status(&mut self, task_id: &Uuid, task_status: TaskStatus) -> Result<()> {
+        debug!("update_task_status");
         let request = UpdateTaskStatusRequest::new(task_id.to_owned(), task_status);
         let _response = self
             .scheduler_client
diff --git a/tests/functional/app/Cargo.toml b/tests/functional/app/Cargo.toml
index 727a438..e059327 100644
--- a/tests/functional/app/Cargo.toml
+++ b/tests/functional/app/Cargo.toml
@@ -11,6 +11,7 @@ edition = "2018"
 log        = { version = "0.4.6" }
 env_logger = { version = "0.7.1" }
 anyhow     = { version = "1.0.26" }
+structopt  = { version = "0.3" }
 
 teaclave_binder            = { path = "../../../binder", features = ["app"] }
 teaclave_types             = { path = "../../../types" }
diff --git a/tests/functional/app/src/main.rs b/tests/functional/app/src/main.rs
index 95b545f..f3c50ab 100644
--- a/tests/functional/app/src/main.rs
+++ b/tests/functional/app/src/main.rs
@@ -17,22 +17,32 @@
 
 use anyhow;
 use log::error;
+use structopt::StructOpt;
 use teaclave_binder::proto::{ECallCommand, RunTestInput, RunTestOutput};
 use teaclave_binder::TeeBinder;
 use teaclave_types::TeeServiceResult;
 
+#[derive(Debug, StructOpt)]
+struct Cli {
+    /// Names of tests to execute.
+    #[structopt(short = "t", required = false)]
+    test_names: Vec<String>,
+}
+
 fn main() -> anyhow::Result<()> {
+    let args = Cli::from_args();
     env_logger::init();
     let tee = TeeBinder::new(env!("CARGO_PKG_NAME"))?;
-    run(&tee)?;
+    start_enclave_unit_test_driver(&tee, args.test_names)?;
     tee.finalize();
 
     Ok(())
 }
 
-fn start_enclave_unit_test_driver(tee: &TeeBinder) -> anyhow::Result<()> {
+fn start_enclave_unit_test_driver(tee: &TeeBinder, test_names: Vec<String>) -> anyhow::Result<()> {
     let cmd = ECallCommand::RunTest;
-    match tee.invoke::<RunTestInput, TeeServiceResult<RunTestOutput>>(cmd, RunTestInput) {
+    let input = RunTestInput::new(test_names);
+    match tee.invoke::<RunTestInput, TeeServiceResult<RunTestOutput>>(cmd, input) {
         Err(e) => error!("{:?}", e),
         Ok(Err(e)) => error!("{:?}", e),
         _ => (),
@@ -40,9 +50,3 @@ fn start_enclave_unit_test_driver(tee: &TeeBinder) -> anyhow::Result<()> {
 
     Ok(())
 }
-
-fn run(tee: &TeeBinder) -> anyhow::Result<()> {
-    start_enclave_unit_test_driver(tee)?;
-
-    Ok(())
-}
diff --git a/tests/functional/enclave/src/execution_service.rs b/tests/functional/enclave/src/execution_service.rs
new file mode 100644
index 0000000..f9c0d44
--- /dev/null
+++ b/tests/functional/enclave/src/execution_service.rs
@@ -0,0 +1,82 @@
+// 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.
+
+use crate::utils::*;
+use std::collections::HashMap;
+use std::collections::HashSet;
+use std::prelude::v1::*;
+use teaclave_proto::teaclave_storage_service::*;
+use teaclave_types::*;
+
+use uuid::Uuid;
+
+pub fn run_tests() -> bool {
+    use teaclave_test_utils::*;
+
+    run_tests!(test_execute_function)
+}
+
+fn test_execute_function() {
+    let task_id = Uuid::new_v4();
+    let task = Task {
+        task_id,
+        creator: "".to_string(),
+        function_id: "".to_string(),
+        function_owner: "".to_string(),
+        function_arguments: FunctionArguments::default(),
+        input_data_owner_list: HashMap::new(),
+        output_data_owner_list: HashMap::new(),
+        participants: HashSet::new(),
+        approved_user_list: HashSet::new(),
+        input_map: HashMap::new(),
+        output_map: HashMap::new(),
+        return_value: None,
+        output_file_hash: HashMap::new(),
+        status: TaskStatus::Running,
+    };
+
+    let function_id = Uuid::new_v4();
+    let function_name = "echo";
+    let function_arguments = FunctionArguments::new(hashmap!(
+        "message" => "Hello, Teaclave Tests!"
+    ));
+
+    let staged_task = StagedTask::new()
+        .task_id(task_id)
+        .function_id(function_id.clone())
+        .function_name(function_name)
+        .function_arguments(function_arguments);
+
+    let mut storage_client = get_storage_client();
+    let enqueue_request = EnqueueRequest::new(
+        StagedTask::get_queue_key().as_bytes(),
+        staged_task.to_vec().unwrap(),
+    );
+    let _enqueue_response = storage_client.enqueue(enqueue_request).unwrap();
+    let put_request = PutRequest::new(task.key().as_slice(), task.to_vec().unwrap().as_slice());
+    let _put_response = storage_client.put(put_request).unwrap();
+
+    std::thread::sleep(std::time::Duration::from_secs(5));
+
+    let get_request = GetRequest::new(task.key().as_slice());
+    let get_response = storage_client.get(get_request).unwrap();
+    let updated_task = Task::from_slice(get_response.value.as_slice()).unwrap();
+    assert_eq!(
+        updated_task.return_value.unwrap(),
+        b"Hello, Teaclave Tests!"
+    );
+}
diff --git a/tests/functional/enclave/src/lib.rs b/tests/functional/enclave/src/lib.rs
index 6c42584..5476e03 100644
--- a/tests/functional/enclave/src/lib.rs
+++ b/tests/functional/enclave/src/lib.rs
@@ -23,6 +23,7 @@ extern crate sgx_tstd as std;
 #[macro_use]
 extern crate log;
 
+use std::collections::HashMap;
 use std::prelude::v1::*;
 
 use teaclave_binder::proto::{
@@ -31,28 +32,56 @@ use teaclave_binder::proto::{
 };
 use teaclave_binder::{handle_ecall, register_ecall_handler};
 use teaclave_service_enclave_utils::ServiceEnclave;
-use teaclave_test_utils::check_all_passed;
 use teaclave_types;
 use teaclave_types::TeeServiceResult;
 
 mod access_control_service;
 mod authentication_service;
+mod execution_service;
 mod frontend_service;
 mod management_service;
 mod scheduler_service;
 mod storage_service;
 mod utils;
 
+type BoxedFnTest = Box<dyn Fn() -> bool>;
+
 #[handle_ecall]
-fn handle_run_test(_: &RunTestInput) -> TeeServiceResult<RunTestOutput> {
-    let ret = check_all_passed!(
-        access_control_service::run_tests(),
-        authentication_service::run_tests(),
-        storage_service::run_tests(),
-        frontend_service::run_tests(),
-        management_service::run_tests(),
-        scheduler_service::run_tests(),
-    );
+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)),
+    ];
+    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();
+    }
 
     assert_eq!(ret, true);
     Ok(RunTestOutput)
diff --git a/tests/integration/app/src/main.rs b/tests/integration/app/src/main.rs
index 95b545f..1d2133f 100644
--- a/tests/integration/app/src/main.rs
+++ b/tests/integration/app/src/main.rs
@@ -32,7 +32,8 @@ fn main() -> anyhow::Result<()> {
 
 fn start_enclave_unit_test_driver(tee: &TeeBinder) -> anyhow::Result<()> {
     let cmd = ECallCommand::RunTest;
-    match tee.invoke::<RunTestInput, TeeServiceResult<RunTestOutput>>(cmd, RunTestInput) {
+    let input = RunTestInput::default();
+    match tee.invoke::<RunTestInput, TeeServiceResult<RunTestOutput>>(cmd, input) {
         Err(e) => error!("{:?}", e),
         Ok(Err(e)) => error!("{:?}", e),
         _ => (),
diff --git a/tests/unit/app/src/main.rs b/tests/unit/app/src/main.rs
index 16fd76c..ea19a46 100644
--- a/tests/unit/app/src/main.rs
+++ b/tests/unit/app/src/main.rs
@@ -34,7 +34,8 @@ fn main() -> anyhow::Result<()> {
 
 fn start_enclave_unit_test_driver(tee: &TeeBinder) -> anyhow::Result<()> {
     let cmd = ECallCommand::RunTest;
-    match tee.invoke::<RunTestInput, TeeServiceResult<RunTestOutput>>(cmd, RunTestInput) {
+    let input = RunTestInput::default();
+    match tee.invoke::<RunTestInput, TeeServiceResult<RunTestOutput>>(cmd, input) {
         Err(e) => error!("{:?}", e),
         Ok(Err(e)) => error!("{:?}", e),
         _ => (),
diff --git a/types/src/worker.rs b/types/src/worker.rs
index b498bfd..ce1a8af 100644
--- a/types/src/worker.rs
+++ b/types/src/worker.rs
@@ -61,7 +61,7 @@ pub struct WorkerCapability {
     pub functions: HashSet<String>,
 }
 
-#[derive(Default)]
+#[derive(Debug, Default)]
 pub struct ExecutionResult {
     pub return_value: Vec<u8>,
     pub output_file_hash: HashMap<String, String>,


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