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

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

commit 229c09f28928e4c06fcbce3874b5f7603d757e52
Author: GeminiCarrie <[email protected]>
AuthorDate: Wed Jun 14 08:01:13 2023 +0000

    Add function builtin-ordered-set-join
---
 .licenserc.yaml                                    |   1 +
 cmake/tomls/Cargo.sgx_trusted_lib.lock             |  60 ++++---
 cmake/tomls/Cargo.sgx_trusted_lib.toml             |   1 +
 cmake/tomls/Cargo.sgx_untrusted_app.lock           |  22 +++
 executor/Cargo.toml                                |   2 +
 executor/src/builtin.rs                            |   4 +-
 function/Cargo.toml                                |   1 +
 function/README.md                                 |   3 +
 function/src/lib.rs                                |   3 +
 function/src/ordered_set_join.rs                   | 190 +++++++++++++++++++++
 .../fixtures/functions/ordered_set_join/join0.csv  | 120 +++++++++++++
 .../fixtures/functions/ordered_set_join/join1.csv  | 125 ++++++++++++++
 12 files changed, 511 insertions(+), 21 deletions(-)

diff --git a/.licenserc.yaml b/.licenserc.yaml
index ee44f763..8379656b 100644
--- a/.licenserc.yaml
+++ b/.licenserc.yaml
@@ -21,6 +21,7 @@ header:
     copyright-owner: Apache Software Foundation
 
   paths-ignore:
+    - '**/*.csv'
     - '**/*.txt'
     - '**/*.md'
     - '**/*.pem'
diff --git a/cmake/tomls/Cargo.sgx_trusted_lib.lock 
b/cmake/tomls/Cargo.sgx_trusted_lib.lock
index 0a0856fd..7dfa342d 100644
--- a/cmake/tomls/Cargo.sgx_trusted_lib.lock
+++ b/cmake/tomls/Cargo.sgx_trusted_lib.lock
@@ -285,6 +285,25 @@ version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
 
+[[package]]
+name = "csv"
+version = "1.2.2"
+source = 
"git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9";
+dependencies = [
+ "csv-core",
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "csv-core"
+version = "0.1.10"
+source = 
"git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9";
+dependencies = [
+ "memchr",
+]
+
 [[package]]
 name = "ctor"
 version = "0.1.26"
@@ -375,7 +394,7 @@ checksum = 
"25c7df09945d65ea8d70b3321547ed414bbc540aad5bac6883d021b970f35b04"
 [[package]]
 name = "fastfield_codecs"
 version = "0.3.1"
-source = 
"git+https://github.com/apache/incubator-teaclave-crates#c979a7afdb748716696ce683a250fbb50a98a23f";
+source = 
"git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9";
 dependencies = [
  "fastdivide",
  "itertools 0.10.5",
@@ -532,7 +551,7 @@ dependencies = [
 [[package]]
 name = "gbdt"
 version = "0.1.1"
-source = 
"git+https://github.com/apache/incubator-teaclave-crates#ede1f68d891798fe6cf995e33281f01d59be9320";
+source = 
"git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9";
 dependencies = [
  "cfg-if 0.1.10",
  "rand",
@@ -558,7 +577,7 @@ dependencies = [
 [[package]]
 name = "getrandom"
 version = "0.2.6"
-source = 
"git+https://github.com/apache/incubator-teaclave-crates#ede1f68d891798fe6cf995e33281f01d59be9320";
+source = 
"git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9";
 dependencies = [
  "cfg-if 1.0.0",
  "libc",
@@ -741,7 +760,7 @@ dependencies = [
 [[package]]
 name = "image"
 version = "0.23.14"
-source = 
"git+https://github.com/apache/incubator-teaclave-crates#ede1f68d891798fe6cf995e33281f01d59be9320";
+source = 
"git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9";
 dependencies = [
  "bytemuck",
  "byteorder",
@@ -995,7 +1014,7 @@ dependencies = [
 [[package]]
 name = "mio"
 version = "0.8.6"
-source = 
"git+https://github.com/apache/incubator-teaclave-crates#ede1f68d891798fe6cf995e33281f01d59be9320";
+source = 
"git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9";
 dependencies = [
  "libc",
  "log",
@@ -1148,7 +1167,7 @@ dependencies = [
 [[package]]
 name = "num_cpus"
 version = "1.14.0"
-source = 
"git+https://github.com/apache/incubator-teaclave-crates#ede1f68d891798fe6cf995e33281f01d59be9320";
+source = 
"git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9";
 dependencies = [
  "hermit-abi 0.1.19",
  "libc",
@@ -1222,7 +1241,7 @@ checksum = 
"b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
 [[package]]
 name = "ownedbytes"
 version = "0.4.0"
-source = 
"git+https://github.com/apache/incubator-teaclave-crates#c979a7afdb748716696ce683a250fbb50a98a23f";
+source = 
"git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9";
 dependencies = [
  "stable_deref_trait",
 ]
@@ -1390,7 +1409,7 @@ dependencies = [
 [[package]]
 name = "rand"
 version = "0.8.5"
-source = 
"git+https://github.com/apache/incubator-teaclave-crates#ede1f68d891798fe6cf995e33281f01d59be9320";
+source = 
"git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9";
 dependencies = [
  "libc",
  "rand_chacha",
@@ -1400,7 +1419,7 @@ dependencies = [
 [[package]]
 name = "rand_chacha"
 version = "0.3.1"
-source = 
"git+https://github.com/apache/incubator-teaclave-crates#ede1f68d891798fe6cf995e33281f01d59be9320";
+source = 
"git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9";
 dependencies = [
  "ppv-lite86",
  "rand_core 0.6.4 (git+https://github.com/apache/incubator-teaclave-crates)",
@@ -1418,7 +1437,7 @@ dependencies = [
 [[package]]
 name = "rand_core"
 version = "0.6.4"
-source = 
"git+https://github.com/apache/incubator-teaclave-crates#ede1f68d891798fe6cf995e33281f01d59be9320";
+source = 
"git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9";
 dependencies = [
  "getrandom",
 ]
@@ -1442,7 +1461,7 @@ checksum = 
"ebac11a9d2e11f2af219b8b8d833b76b1ea0e054aa0e8d8e9e4cbde353bdf019"
 [[package]]
 name = "rayon"
 version = "1.7.0"
-source = 
"git+https://github.com/apache/incubator-teaclave-crates#c979a7afdb748716696ce683a250fbb50a98a23f";
+source = 
"git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9";
 dependencies = [
  "either",
  "rayon-core",
@@ -1451,7 +1470,7 @@ dependencies = [
 [[package]]
 name = "rayon-core"
 version = "1.11.0"
-source = 
"git+https://github.com/apache/incubator-teaclave-crates#c979a7afdb748716696ce683a250fbb50a98a23f";
+source = 
"git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9";
 dependencies = [
  "crossbeam-channel",
  "crossbeam-deque",
@@ -1551,7 +1570,7 @@ dependencies = [
 [[package]]
 name = "ring"
 version = "0.16.20"
-source = 
"git+https://github.com/apache/incubator-teaclave-crates#ede1f68d891798fe6cf995e33281f01d59be9320";
+source = 
"git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9";
 dependencies = [
  "cc",
  "libc",
@@ -1590,7 +1609,7 @@ checksum = 
"08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
 [[package]]
 name = "rustface"
 version = "0.1.7"
-source = 
"git+https://github.com/apache/incubator-teaclave-crates#ede1f68d891798fe6cf995e33281f01d59be9320";
+source = 
"git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9";
 dependencies = [
  "byteorder",
  "image",
@@ -1616,7 +1635,7 @@ dependencies = [
 [[package]]
 name = "rustls"
 version = "0.19.1"
-source = 
"git+https://github.com/apache/incubator-teaclave-crates#ede1f68d891798fe6cf995e33281f01d59be9320";
+source = 
"git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9";
 dependencies = [
  "base64 0.13.1",
  "log",
@@ -1647,7 +1666,7 @@ dependencies = [
 [[package]]
 name = "rusty-machine"
 version = "0.5.4"
-source = 
"git+https://github.com/apache/incubator-teaclave-crates#ede1f68d891798fe6cf995e33281f01d59be9320";
+source = 
"git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9";
 dependencies = [
  "num 0.1.42",
  "rand",
@@ -2146,7 +2165,7 @@ dependencies = [
 [[package]]
 name = "tantivy"
 version = "0.19.2"
-source = 
"git+https://github.com/apache/incubator-teaclave-crates#c979a7afdb748716696ce683a250fbb50a98a23f";
+source = 
"git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9";
 dependencies = [
  "aho-corasick 0.7.20",
  "arc-swap",
@@ -2193,12 +2212,12 @@ dependencies = [
 [[package]]
 name = "tantivy-bitpacker"
 version = "0.3.0"
-source = 
"git+https://github.com/apache/incubator-teaclave-crates#c979a7afdb748716696ce683a250fbb50a98a23f";
+source = 
"git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9";
 
 [[package]]
 name = "tantivy-common"
 version = "0.4.0"
-source = 
"git+https://github.com/apache/incubator-teaclave-crates#c979a7afdb748716696ce683a250fbb50a98a23f";
+source = 
"git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9";
 dependencies = [
  "byteorder",
  "ownedbytes",
@@ -2218,7 +2237,7 @@ dependencies = [
 [[package]]
 name = "tantivy-query-grammar"
 version = "0.19.0"
-source = 
"git+https://github.com/apache/incubator-teaclave-crates#c979a7afdb748716696ce683a250fbb50a98a23f";
+source = 
"git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9";
 dependencies = [
  "combine",
  "once_cell",
@@ -2482,6 +2501,7 @@ version = "0.6.0"
 dependencies = [
  "anyhow",
  "base64 0.13.1",
+ "csv",
  "gbdt",
  "hex",
  "image",
diff --git a/cmake/tomls/Cargo.sgx_trusted_lib.toml 
b/cmake/tomls/Cargo.sgx_trusted_lib.toml
index 39c2ced7..f22d8229 100644
--- a/cmake/tomls/Cargo.sgx_trusted_lib.toml
+++ b/cmake/tomls/Cargo.sgx_trusted_lib.toml
@@ -55,6 +55,7 @@ crc               = { git = 
"https://github.com/mrhooray/crc-rs";, rev = "86696be
 simple_asn1       = { git = "https://github.com/acw/simple_asn1";, rev = 
"7db7a48" }
 
 # SGX crates
+csv               = { git = 
"https://github.com/apache/incubator-teaclave-crates"; }
 gbdt              = { git = 
"https://github.com/apache/incubator-teaclave-crates"; }
 getrandom         = { git = 
"https://github.com/apache/incubator-teaclave-crates"; }
 image             = { git = 
"https://github.com/apache/incubator-teaclave-crates"; }
diff --git a/cmake/tomls/Cargo.sgx_untrusted_app.lock 
b/cmake/tomls/Cargo.sgx_untrusted_app.lock
index 935c8877..3dba2cd6 100644
--- a/cmake/tomls/Cargo.sgx_untrusted_app.lock
+++ b/cmake/tomls/Cargo.sgx_untrusted_app.lock
@@ -228,6 +228,27 @@ dependencies = [
  "cfg-if 1.0.0",
 ]
 
+[[package]]
+name = "csv"
+version = "1.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "626ae34994d3d8d668f4269922248239db4ae42d538b14c398b74a52208e8086"
+dependencies = [
+ "csv-core",
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "csv-core"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90"
+dependencies = [
+ "memchr",
+]
+
 [[package]]
 name = "ctor"
 version = "0.1.26"
@@ -2259,6 +2280,7 @@ version = "0.6.0"
 dependencies = [
  "anyhow",
  "base64 0.13.1",
+ "csv",
  "gbdt",
  "hex",
  "image",
diff --git a/executor/Cargo.toml b/executor/Cargo.toml
index 44caaa21..5b392004 100644
--- a/executor/Cargo.toml
+++ b/executor/Cargo.toml
@@ -60,6 +60,7 @@ full_builtin_function = [
   "builtin_logistic_regression_train",
   "builtin_password_check",
   "builtin_online_decrypt",
+  "builtin_ordered_set_join",
   "builtin_ordered_set_intersect",
   "builtin_principal_components_analysis",
   "builtin_private_join_and_compute",
@@ -74,6 +75,7 @@ builtin_logistic_regression_predict = []
 builtin_logistic_regression_train = []
 builtin_password_check = []
 builtin_online_decrypt = []
+builtin_ordered_set_join = []
 builtin_ordered_set_intersect = []
 builtin_principal_components_analysis = []
 builtin_private_join_and_compute = []
diff --git a/executor/src/builtin.rs b/executor/src/builtin.rs
index b0f03605..9f836b14 100644
--- a/executor/src/builtin.rs
+++ b/executor/src/builtin.rs
@@ -17,7 +17,7 @@
 
 use teaclave_function::{
     Echo, FaceDetection, GbdtPredict, GbdtTrain, LogisticRegressionPredict,
-    LogisticRegressionTrain, OnlineDecrypt, OrderedSetIntersect, PasswordCheck,
+    LogisticRegressionTrain, OnlineDecrypt, OrderedSetIntersect, 
OrderedSetJoin, PasswordCheck,
     PrincipalComponentsAnalysis, PrivateJoinAndCompute, RsaSign,
 };
 use teaclave_types::{FunctionArguments, FunctionRuntime, TeaclaveExecutor};
@@ -52,6 +52,8 @@ impl TeaclaveExecutor for BuiltinFunctionExecutor {
             OnlineDecrypt::NAME => OnlineDecrypt::new().run(arguments, 
runtime),
             #[cfg(feature = "builtin_private_join_and_compute")]
             PrivateJoinAndCompute::NAME => 
PrivateJoinAndCompute::new().run(arguments, runtime),
+            #[cfg(feature = "builtin_ordered_set_join")]
+            OrderedSetJoin::NAME => OrderedSetJoin::new().run(arguments, 
runtime),
             #[cfg(feature = "builtin_ordered_set_intersect")]
             OrderedSetIntersect::NAME => 
OrderedSetIntersect::new().run(arguments, runtime),
             #[cfg(feature = "builtin_rsa_sign")]
diff --git a/function/Cargo.toml b/function/Cargo.toml
index bb2a1839..64e1ad71 100644
--- a/function/Cargo.toml
+++ b/function/Cargo.toml
@@ -50,6 +50,7 @@ enclave_unit_test = [
 [dependencies]
 log           = { version = "0.4.17", features = ["release_max_level_info"] }
 anyhow        = { version = "1.0.26" }
+csv           = { version = "1" }
 serde_json    = { version = "1.0.39" }
 serde         = { version = "1.0.92", features = ["derive"] }
 thiserror     = { version = "1.0.9" }
diff --git a/function/README.md b/function/README.md
index c27adc0f..a89cac7c 100644
--- a/function/README.md
+++ b/function/README.md
@@ -24,6 +24,9 @@ Currently, we have these built-in functions:
     intersection of their ordered sets without revealing anything except for 
the
     elements in the intersection. Users should calculate hash values of each 
item
     and upload them as a sorted list.
+  - `builtin-ordered-set-join`: Allow two parties to combine their CSV files 
in a unique
+    and sorted column. The CSV files uploaded by users should be sorted by the 
specified
+    column.
   - `builtin-rsa-sign`: Signing data with RSA key.
   - `builtin-face-detection`: An implementation of Funnel-Structured cascade,
     which is designed for real-time multi-view face detection.
diff --git a/function/src/lib.rs b/function/src/lib.rs
index 789b4a68..1f77b2e5 100644
--- a/function/src/lib.rs
+++ b/function/src/lib.rs
@@ -25,6 +25,7 @@ mod logistic_regression_predict;
 mod logistic_regression_train;
 mod online_decrypt;
 mod ordered_set_intersect;
+mod ordered_set_join;
 mod password_check;
 mod principal_components_analysis;
 mod private_join_and_compute;
@@ -38,6 +39,7 @@ pub use 
logistic_regression_predict::LogisticRegressionPredict;
 pub use logistic_regression_train::LogisticRegressionTrain;
 pub use online_decrypt::OnlineDecrypt;
 pub use ordered_set_intersect::OrderedSetIntersect;
+pub use ordered_set_join::OrderedSetJoin;
 pub use password_check::PasswordCheck;
 pub use principal_components_analysis::PrincipalComponentsAnalysis;
 pub use private_join_and_compute::PrivateJoinAndCompute;
@@ -58,6 +60,7 @@ pub mod tests {
             logistic_regression_train::tests::run_tests(),
             password_check::tests::run_tests(),
             online_decrypt::tests::run_tests(),
+            ordered_set_join::tests::run_tests(),
             ordered_set_intersect::tests::run_tests(),
             principal_components_analysis::tests::run_tests(),
             private_join_and_compute::tests::run_tests(),
diff --git a/function/src/ordered_set_join.rs b/function/src/ordered_set_join.rs
new file mode 100644
index 00000000..9650eb96
--- /dev/null
+++ b/function/src/ordered_set_join.rs
@@ -0,0 +1,190 @@
+// 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 anyhow::{anyhow, ensure};
+use csv::{ReaderBuilder, StringRecord, Writer};
+use std::cmp;
+use std::convert::TryFrom;
+use teaclave_types::{FunctionArguments, FunctionRuntime};
+
+// Input data should be sorted by the specified index column.
+const IN_DATA1: &str = "input_data1";
+const IN_DATA2: &str = "input_data2";
+// fusion output data
+const OUT_RESULT: &str = "output_result";
+
+#[derive(Default)]
+pub struct OrderedSetJoin;
+
+#[derive(serde::Deserialize)]
+pub struct OrderedSetJoinArguments {
+    // Start from 0.
+    left_column: usize,
+    right_column: usize,
+    ascending: bool,
+    // If it is set to true, drop the selected column of all files from the 
results.
+    // If it is set to false, only keep the selected column of the first file.
+    drop: bool,
+}
+
+impl TryFrom<FunctionArguments> for OrderedSetJoinArguments {
+    type Error = anyhow::Error;
+
+    fn try_from(arguments: FunctionArguments) -> Result<Self, Self::Error> {
+        use anyhow::Context;
+        serde_json::from_str(&arguments.into_string()).context("Cannot 
deserialize arguments")
+    }
+}
+
+impl OrderedSetJoin {
+    pub const NAME: &'static str = "builtin-ordered-set-join";
+
+    pub fn new() -> Self {
+        Default::default()
+    }
+
+    pub fn run(
+        &self,
+        arguments: FunctionArguments,
+        runtime: FunctionRuntime,
+    ) -> anyhow::Result<String> {
+        let args = OrderedSetJoinArguments::try_from(arguments)?;
+        let mut rdr1 = ReaderBuilder::new()
+            .has_headers(false)
+            .from_reader(runtime.open_input(IN_DATA1)?);
+        let mut rdr2 = ReaderBuilder::new()
+            .has_headers(false)
+            .from_reader(runtime.open_input(IN_DATA2)?);
+        let mut wtr = Writer::from_writer(runtime.create_output(OUT_RESULT)?);
+
+        let mut record1 = StringRecord::new();
+        let mut record2 = StringRecord::new();
+        let mut count = 0;
+        ensure!(rdr1.read_record(&mut record1)?, "input1 is empty");
+        ensure!(rdr2.read_record(&mut record2)?, "input2 is empty");
+
+        loop {
+            let fields1 = record1
+                .get(args.left_column)
+                .ok_or_else(|| anyhow!("invalid index"))?;
+            let fields2 = record2
+                .get(args.right_column)
+                .ok_or_else(|| anyhow!("invalid index"))?;
+            let order = &fields1.cmp(fields2);
+
+            match order {
+                cmp::Ordering::Equal => {
+                    let new_record1 = if args.drop {
+                        drop_column(&record1, args.left_column)
+                    } else {
+                        record1.clone()
+                    };
+                    let new_record2 = drop_column(&record2, args.right_column);
+                    wtr.write_record(new_record1.iter().chain(&new_record2))?;
+                    count += 1;
+                    if !rdr1.read_record(&mut record1)? || 
!rdr2.read_record(&mut record2)? {
+                        break;
+                    }
+                }
+                cmp::Ordering::Less => {
+                    if args.ascending {
+                        if !rdr1.read_record(&mut record1)? {
+                            break;
+                        }
+                    } else if !rdr2.read_record(&mut record2)? {
+                        break;
+                    }
+                }
+                cmp::Ordering::Greater => {
+                    if args.ascending {
+                        if !rdr2.read_record(&mut record2)? {
+                            break;
+                        }
+                    } else if !rdr1.read_record(&mut record1)? {
+                        break;
+                    }
+                }
+            }
+        }
+
+        Ok(format!("{} records", count))
+    }
+}
+
+pub fn drop_column(column: &StringRecord, index: usize) -> StringRecord {
+    StringRecord::from(
+        column
+            .iter()
+            .enumerate()
+            .filter_map(|(i, e)| if i != index { Some(e) } else { None })
+            .collect::<Vec<_>>(),
+    )
+}
+
+#[cfg(feature = "enclave_unit_test")]
+pub mod tests {
+    use super::*;
+    use serde_json::json;
+    use std::path::Path;
+    use std::untrusted::fs;
+    use teaclave_crypto::*;
+    use teaclave_runtime::*;
+    use teaclave_test_utils::*;
+    use teaclave_types::*;
+
+    pub fn run_tests() -> bool {
+        run_tests!(test_ordered_set_join)
+    }
+
+    fn test_ordered_set_join() {
+        let arguments = FunctionArguments::from_json(json!({
+            "left_column": 0,
+            "right_column": 0,
+            "ascending":true,
+            "drop":true
+        }))
+        .unwrap();
+
+        let base = Path::new("fixtures/functions/ordered_set_join");
+
+        let user1_input = base.join("join0.csv");
+        let output = base.join("output_join.csv");
+
+        let user2_input = base.join("join1.csv");
+
+        let input_files = StagedFiles::new(hashmap!(
+            IN_DATA1 =>
+            StagedFileInfo::new(&user1_input, TeaclaveFile128Key::random(), 
FileAuthTag::mock()),
+            IN_DATA2 =>
+            StagedFileInfo::new(&user2_input, TeaclaveFile128Key::random(), 
FileAuthTag::mock()),
+        ));
+
+        let output_files = StagedFiles::new(hashmap!(
+            OUT_RESULT =>
+            StagedFileInfo::new(&output, TeaclaveFile128Key::random(), 
FileAuthTag::mock()),
+        ));
+
+        let runtime = Box::new(RawIoRuntime::new(input_files, output_files));
+        let summary = OrderedSetJoin::new().run(arguments, runtime).unwrap();
+        assert_eq!("120 records".to_string(), summary);
+
+        let expected_output = "fixtures/functions/gbdt_training/train.txt";
+        let result = fs::read_to_string(&output).unwrap();
+        let expected = fs::read_to_string(expected_output).unwrap();
+        assert_eq!(result.trim(), expected.trim());
+    }
+}
diff --git a/tests/fixtures/functions/ordered_set_join/join0.csv 
b/tests/fixtures/functions/ordered_set_join/join0.csv
new file mode 100644
index 00000000..67881a3e
--- /dev/null
+++ b/tests/fixtures/functions/ordered_set_join/join0.csv
@@ -0,0 +1,120 @@
+100000,4.8,3.0
+100001,5.1,3.7
+100002,6.7,2.5
+100003,5.5,2.4
+100004,4.8,3.4
+100005,6.9,3.1
+100006,5.4,3.9
+100007,6.9,3.1
+100008,6.5,3.0
+100009,5.0,2.3
+100010,5.4,3.4
+100011,5.7,4.4
+100012,5.0,3.3
+100013,4.4,3.2
+100014,4.9,3.1
+100015,6.9,3.2
+100016,7.7,3.8
+100017,5.5,2.4
+100018,7.7,3.0
+100019,6.4,2.8
+100020,5.8,2.7
+100021,4.6,3.6
+100022,7.2,3.2
+100023,6.3,3.3
+100024,6.7,3.3
+100025,6.5,3.2
+100026,6.9,3.1
+100027,6.1,2.6
+100028,5.9,3.0
+100029,4.4,2.9
+100030,5.8,2.7
+100031,4.8,3.1
+100032,6.4,2.8
+100033,5.1,3.5
+100034,6.3,3.3
+100035,6.0,2.7
+100036,5.4,3.0
+100037,5.5,2.6
+100038,6.4,3.1
+100039,6.3,3.4
+100040,5.2,3.5
+100041,6.5,3.0
+100042,5.6,2.9
+100043,6.0,2.2
+100044,5.4,3.4
+100045,4.9,3.1
+100046,4.6,3.1
+100047,5.1,2.5
+100048,5.0,2.0
+100049,5.8,2.7
+100050,5.9,3.2
+100051,6.8,3.2
+100052,6.6,2.9
+100053,5.0,3.2
+100054,6.8,2.8
+100055,5.6,3.0
+100056,5.0,3.6
+100057,5.6,2.7
+100058,4.4,3.0
+100059,5.2,3.4
+100060,6.1,3.0
+100061,5.0,3.0
+100062,4.9,2.5
+100063,4.7,3.2
+100064,4.3,3.0
+100065,7.9,3.8
+100066,6.4,3.2
+100067,6.4,2.9
+100068,5.1,3.8
+100069,5.2,2.7
+100070,5.1,3.4
+100071,6.0,3.4
+100072,4.7,3.2
+100073,4.8,3.0
+100074,5.6,2.5
+100075,6.7,3.0
+100076,6.5,3.0
+100077,4.6,3.2
+100078,6.7,3.3
+100079,6.2,2.8
+100080,5.7,3.8
+100081,6.3,2.8
+100082,5.7,3.0
+100083,6.3,2.3
+100084,4.9,2.4
+100085,7.2,3.6
+100086,5.7,2.8
+100087,5.5,4.2
+100088,6.6,3.0
+100089,5.9,3.0
+100090,5.7,2.8
+100091,6.2,2.2
+100092,5.1,3.3
+100093,6.2,2.9
+100094,6.3,2.5
+100095,5.5,3.5
+100096,5.1,3.8
+100097,6.1,2.8
+100098,6.1,2.8
+100099,5.2,4.1
+100100,5.6,3.0
+100101,6.3,2.7
+100102,5.7,2.5
+100103,5.7,2.6
+100104,6.4,2.7
+100105,7.7,2.8
+100106,5.5,2.3
+100107,5.3,3.7
+100108,6.7,3.1
+100109,6.2,3.4
+100110,5.8,4.0
+100111,7.3,2.9
+100112,6.3,2.9
+100113,5.8,2.8
+100114,6.8,3.0
+100115,5.1,3.8
+100116,6.5,2.8
+100117,7.4,2.8
+100118,4.9,3.0
+100119,5.8,2.7
diff --git a/tests/fixtures/functions/ordered_set_join/join1.csv 
b/tests/fixtures/functions/ordered_set_join/join1.csv
new file mode 100644
index 00000000..b58f219b
--- /dev/null
+++ b/tests/fixtures/functions/ordered_set_join/join1.csv
@@ -0,0 +1,125 @@
+100000,1.4,0.3,3.0
+100001,1.5,0.4,3.0
+100002,5.8,1.8,2.0
+100003,3.7,1.0,1.0
+100004,1.6,0.2,3.0
+100005,5.4,2.1,2.0
+100006,1.7,0.4,3.0
+100007,4.9,1.5,1.0
+100008,5.5,1.8,2.0
+100009,3.3,1.0,1.0
+100010,1.5,0.4,3.0
+100011,1.5,0.4,3.0
+100012,1.4,0.2,3.0
+100013,1.3,0.2,3.0
+100014,1.5,0.2,3.0
+100015,5.7,2.3,2.0
+100016,6.7,2.2,2.0
+100017,3.8,1.1,1.0
+100018,6.1,2.3,2.0
+100019,5.6,2.2,2.0
+100020,5.1,1.9,2.0
+100021,1.0,0.2,3.0
+100022,6.0,1.8,2.0
+100023,4.7,1.6,1.0
+100024,5.7,2.5,2.0
+100025,5.1,2.0,2.0
+100026,5.1,2.3,2.0
+100027,5.6,1.4,2.0
+100028,4.2,1.5,1.0
+100029,1.4,0.2,3.0
+100030,4.1,1.0,1.0
+100031,1.6,0.2,3.0
+100032,5.6,2.1,2.0
+100033,1.4,0.3,3.0
+100034,6.0,2.5,2.0
+100035,5.1,1.6,1.0
+100036,4.5,1.5,1.0
+100037,4.4,1.2,1.0
+100038,5.5,1.8,2.0
+100039,5.6,2.4,2.0
+100040,1.5,0.2,3.0
+100041,5.8,2.2,2.0
+100042,3.6,1.3,1.0
+100043,5.0,1.5,2.0
+100044,1.7,0.2,3.0
+100045,1.5,0.1,3.0
+100046,1.5,0.2,3.0
+100047,3.0,1.1,1.0
+100048,3.5,1.0,1.0
+100049,3.9,1.2,1.0
+100050,4.8,1.8,1.0
+100051,5.9,2.3,2.0
+100052,4.6,1.3,1.0
+100053,1.2,0.2,3.0
+100054,4.8,1.4,1.0
+100055,4.5,1.5,1.0
+100056,1.4,0.2,3.0
+100057,4.2,1.3,1.0
+100058,1.3,0.2,3.0
+100059,1.4,0.2,3.0
+100060,4.6,1.4,1.0
+100061,1.6,0.2,3.0
+100062,4.5,1.7,2.0
+100063,1.6,0.2,3.0
+100064,1.1,0.1,3.0
+100065,6.4,2.0,2.0
+100066,4.5,1.5,1.0
+100067,4.3,1.3,1.0
+100068,1.9,0.4,3.0
+100069,3.9,1.4,1.0
+100070,1.5,0.2,3.0
+100071,4.5,1.6,1.0
+100072,1.3,0.2,3.0
+100073,1.4,0.1,3.0
+100074,3.9,1.1,1.0
+100075,5.0,1.7,1.0
+100076,5.2,2.0,2.0
+100077,1.4,0.2,3.0
+100078,5.7,2.1,2.0
+100079,4.8,1.8,2.0
+100080,1.7,0.3,3.0
+100081,5.1,1.5,2.0
+100082,4.2,1.2,1.0
+100083,4.4,1.3,1.0
+100084,3.3,1.0,1.0
+100085,6.1,2.5,2.0
+100086,4.5,1.3,1.0
+100087,1.4,0.2,3.0
+100088,4.4,1.4,1.0
+100089,5.1,1.8,2.0
+100090,4.1,1.3,1.0
+100091,4.5,1.5,1.0
+100092,1.7,0.5,3.0
+100093,4.3,1.3,1.0
+100094,5.0,1.9,2.0
+100095,1.3,0.2,3.0
+100096,1.5,0.3,3.0
+100097,4.7,1.2,1.0
+100098,4.0,1.3,1.0
+100099,1.5,0.1,3.0
+100100,4.1,1.3,1.0
+100101,4.9,1.8,2.0
+100102,5.0,2.0,2.0
+100103,3.5,1.0,1.0
+100104,5.3,1.9,2.0
+100105,6.7,2.0,2.0
+100106,4.0,1.3,1.0
+100107,1.5,0.2,3.0
+100108,4.4,1.4,1.0
+100109,5.4,2.3,2.0
+100110,1.2,0.2,3.0
+100111,6.3,1.8,2.0
+100112,5.6,1.8,2.0
+100113,5.1,2.4,2.0
+100114,5.5,2.1,2.0
+100115,1.6,0.2,3.0
+100116,4.6,1.5,1.0
+100117,6.1,1.9,2.0
+100118,1.4,0.2,3.0
+100119,5.1,1.9,2.0
+100120,5.1,1.9,2.0
+100121,1.4,0.2,3.0
+100122,5.1,1.9,2.0
+100123,5.1,1.9,2.0
+100124,3.3,0.1,3.0


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to