From 36a4b8493f8daea3638be2d5068db2bf7709737e Mon Sep 17 00:00:00 2001 From: Bo Lu Date: Thu, 8 Dec 2022 15:38:12 +1100 Subject: [PATCH 1/6] add more stripe test cases --- wrappers/src/fdw/stripe_fdw/README.md | 3 + wrappers/src/fdw/stripe_fdw/stripe_fdw.rs | 24 ++- wrappers/src/fdw/stripe_fdw/tests.rs | 221 ++++++++++++++++++++-- 3 files changed, 234 insertions(+), 14 deletions(-) diff --git a/wrappers/src/fdw/stripe_fdw/README.md b/wrappers/src/fdw/stripe_fdw/README.md index b2f55c4d..97339dac 100644 --- a/wrappers/src/fdw/stripe_fdw/README.md +++ b/wrappers/src/fdw/stripe_fdw/README.md @@ -87,6 +87,9 @@ end $$; -- create foreign tables create foreign table stripe_balance ( + balance_type text, + amount bigint, + currency text, attrs jsonb ) server my_stripe_server diff --git a/wrappers/src/fdw/stripe_fdw/stripe_fdw.rs b/wrappers/src/fdw/stripe_fdw/stripe_fdw.rs index a03bf1b1..093cc330 100644 --- a/wrappers/src/fdw/stripe_fdw/stripe_fdw.rs +++ b/wrappers/src/fdw/stripe_fdw/stripe_fdw.rs @@ -50,8 +50,22 @@ fn body_to_rows( let single_wrapped: Vec = if is_list { Vec::new() } else if is_balance { - let obj = value.as_object().and_then(|v| v.get("available")).unwrap(); - obj.as_array().unwrap().to_vec() + // specially transform balance object to 2 rows + let mut ret = Vec::new(); + for bal_type in vec!["available", "pending"] { + let mut obj = value + .as_object() + .and_then(|v| v.get(bal_type)) + .and_then(|v| v.as_array()) + .map(|v| v[0].as_object().unwrap().clone()) + .unwrap(); + obj.insert( + "balance_type".to_string(), + JsonValue::String(bal_type.to_owned()), + ); + ret.push(JsonValue::Object(obj)); + } + ret } else { // wrap a single object in vec value @@ -284,7 +298,11 @@ impl StripeFdw { match obj { "balance" => body_to_rows( resp_body, - vec![("amount", "i64"), ("currency", "string")], + vec![ + ("balance_type", "string"), + ("amount", "i64"), + ("currency", "string"), + ], tgt_cols, ), "balance_transactions" => body_to_rows( diff --git a/wrappers/src/fdw/stripe_fdw/tests.rs b/wrappers/src/fdw/stripe_fdw/tests.rs index ad535581..e4cac388 100644 --- a/wrappers/src/fdw/stripe_fdw/tests.rs +++ b/wrappers/src/fdw/stripe_fdw/tests.rs @@ -25,9 +25,11 @@ mod tests { c.update( r#" - CREATE FOREIGN TABLE balance ( + CREATE FOREIGN TABLE stripe_balance ( + balance_type text, amount bigint, - currency text + currency text, + attrs jsonb ) SERVER my_stripe_server OPTIONS ( @@ -40,14 +42,129 @@ mod tests { c.update( r#" - CREATE FOREIGN TABLE customers ( + CREATE FOREIGN TABLE stripe_balance_transactions ( + id text, + amount bigint, + currency text, + description text, + fee bigint, + net bigint, + status text, + type text, + created timestamp, + attrs jsonb + ) + SERVER my_stripe_server + OPTIONS ( + object 'balance_transactions' -- source object in stripe, required + ) + "#, + None, + None, + ); + + c.update( + r#" + CREATE FOREIGN TABLE stripe_charges ( + id text, + amount bigint, + currency text, + customer text, + description text, + invoice text, + payment_intent text, + status text, + created timestamp, + attrs jsonb + ) + SERVER my_stripe_server + OPTIONS ( + object 'charges' -- source object in stripe, required + ) + "#, + None, + None, + ); + + c.update( + r#" + CREATE FOREIGN TABLE stripe_customers ( + id text, + email text, + name text, + description text, + created timestamp, + attrs jsonb + ) + SERVER my_stripe_server + OPTIONS ( + object 'customers', -- source object in stripe, required + rowid_column 'id' + ) + "#, + None, + None, + ); + + c.update( + r#" + CREATE FOREIGN TABLE stripe_invoices ( + id text, + customer text, + subscription text, + status text, + total bigint, + currency text, + period_start timestamp, + period_end timestamp, + attrs jsonb + ) + SERVER my_stripe_server + OPTIONS ( + object 'invoices' -- source object in stripe, required + ) + "#, + None, + None, + ); + + c.update( + r#" + CREATE FOREIGN TABLE stripe_payment_intents ( id text, - email text + customer text, + amount bigint, + currency text, + payment_method text, + created timestamp, + attrs jsonb ) SERVER my_stripe_server OPTIONS ( - object 'customers' -- source object in stripe, required + object 'payment_intents' -- source object in stripe, required + ) + "#, + None, + None, + ); + + c.update( + r#" + CREATE FOREIGN TABLE stripe_products ( + id text, + name text, + active bool, + default_price text, + description text, + created timestamp, + updated timestamp, + attrs jsonb ) + SERVER my_stripe_server + OPTIONS ( + object 'products', -- source object in stripe, required + rowid_column 'id' + ) "#, None, None, @@ -55,15 +172,18 @@ mod tests { c.update( r#" - CREATE FOREIGN TABLE subscriptions ( + CREATE FOREIGN TABLE stripe_subscriptions ( + id text, customer text, currency text, - current_period_start bigint, - current_period_end bigint + current_period_start timestamp, + current_period_end timestamp, + attrs jsonb ) SERVER my_stripe_server OPTIONS ( - object 'subscriptions' -- source object in stripe, required + object 'subscriptions', -- source object in stripe, required + rowid_column 'id' ) "#, None, @@ -71,7 +191,7 @@ mod tests { ); let results = c - .select("SELECT * FROM balance", None, None) + .select("SELECT * FROM stripe_balance", None, None) .filter_map(|r| { r.by_name("amount") .ok() @@ -83,7 +203,86 @@ mod tests { assert_eq!(results, vec![(0, "usd")]); let results = c - .select("SELECT * FROM subscriptions", None, None) + .select("SELECT * FROM stripe_balance_transactions", None, None) + .filter_map(|r| { + r.by_name("amount") + .ok() + .and_then(|v| v.value::()) + .zip(r.by_name("currency").ok().and_then(|v| v.value::<&str>())) + .zip(r.by_name("fee").ok().and_then(|v| v.value::())) + .zip(r.by_name("status").ok().and_then(|v| v.value::<&str>())) + .zip(r.by_name("type").ok().and_then(|v| v.value::<&str>())) + }) + .collect::>(); + + assert_eq!(results, vec![(((((100, "usd"), 0), "available"), "charge"))]); + + let results = c + .select("SELECT * FROM stripe_charges", None, None) + .filter_map(|r| { + r.by_name("amount") + .ok() + .and_then(|v| v.value::()) + .zip(r.by_name("currency").ok().and_then(|v| v.value::<&str>())) + .zip(r.by_name("status").ok().and_then(|v| v.value::<&str>())) + }) + .collect::>(); + + assert_eq!(results, vec![(((100, "usd"), "succeeded"))]); + + let results = c + .select("SELECT * FROM stripe_customers", None, None) + .filter_map(|r| { + r.by_name("id") + .ok() + .and_then(|v| v.value::<&str>()) + .zip(r.by_name("created").ok().and_then(|v| v.value::())) + }) + .collect::>(); + + assert_eq!(results, vec![("cus_MJiBgSUgeWFN0z", 1234567890000)]); + + let results = c + .select("SELECT * FROM stripe_invoices", None, None) + .filter_map(|r| { + r.by_name("customer") + .ok() + .and_then(|v| v.value::<&str>()) + .zip(r.by_name("total").ok().and_then(|v| v.value::())) + .zip(r.by_name("currency").ok().and_then(|v| v.value::<&str>())) + .zip(r.by_name("status").ok().and_then(|v| v.value::<&str>())) + }) + .collect::>(); + + assert_eq!(results, vec![((("cus_MJiBgSUgeWFN0z", 1000), "usd"), "draft")]); + + let results = c + .select("SELECT * FROM stripe_payment_intents", None, None) + .filter_map(|r| { + r.by_name("amount") + .ok() + .and_then(|v| v.value::()) + .zip(r.by_name("currency").ok().and_then(|v| v.value::<&str>())) + }) + .collect::>(); + + assert_eq!(results, vec![(1099, "usd")]); + + let results = c + .select("SELECT * FROM stripe_products", None, None) + .filter_map(|r| { + r.by_name("name") + .ok() + .and_then(|v| v.value::<&str>()) + .zip(r.by_name("active").ok().and_then(|v| v.value::())) + .zip(r.by_name("description").ok().and_then(|v| v.value::<&str>())) + }) + .collect::>(); + + assert_eq!(results, vec![(("T-shirt", true), "Comfortable gray cotton t-shirt")]); + + let results = c + .select("SELECT * FROM stripe_subscriptions", None, None) .filter_map(|r| { r.by_name("customer") .ok() From 7c34ee392b996f0078a9a1934a6ce2d06ff58981 Mon Sep 17 00:00:00 2001 From: Bo Lu Date: Thu, 8 Dec 2022 16:45:36 +1100 Subject: [PATCH 2/6] fix stripe test case --- wrappers/src/fdw/stripe_fdw/tests.rs | 31 +++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/wrappers/src/fdw/stripe_fdw/tests.rs b/wrappers/src/fdw/stripe_fdw/tests.rs index e4cac388..940e81a6 100644 --- a/wrappers/src/fdw/stripe_fdw/tests.rs +++ b/wrappers/src/fdw/stripe_fdw/tests.rs @@ -193,14 +193,18 @@ mod tests { let results = c .select("SELECT * FROM stripe_balance", None, None) .filter_map(|r| { - r.by_name("amount") + r.by_name("balance_type") .ok() - .and_then(|v| v.value::()) + .and_then(|v| v.value::<&str>()) + .zip(r.by_name("amount").ok().and_then(|v| v.value::())) .zip(r.by_name("currency").ok().and_then(|v| v.value::<&str>())) }) .collect::>(); - assert_eq!(results, vec![(0, "usd")]); + assert_eq!( + results, + vec![("available", 0, "usd"), ("pending", 0, "usd")] + ); let results = c .select("SELECT * FROM stripe_balance_transactions", None, None) @@ -215,7 +219,10 @@ mod tests { }) .collect::>(); - assert_eq!(results, vec![(((((100, "usd"), 0), "available"), "charge"))]); + assert_eq!( + results, + vec![(((((100, "usd"), 0), "available"), "charge"))] + ); let results = c .select("SELECT * FROM stripe_charges", None, None) @@ -254,7 +261,10 @@ mod tests { }) .collect::>(); - assert_eq!(results, vec![((("cus_MJiBgSUgeWFN0z", 1000), "usd"), "draft")]); + assert_eq!( + results, + vec![((("cus_MJiBgSUgeWFN0z", 1000), "usd"), "draft")] + ); let results = c .select("SELECT * FROM stripe_payment_intents", None, None) @@ -275,11 +285,18 @@ mod tests { .ok() .and_then(|v| v.value::<&str>()) .zip(r.by_name("active").ok().and_then(|v| v.value::())) - .zip(r.by_name("description").ok().and_then(|v| v.value::<&str>())) + .zip( + r.by_name("description") + .ok() + .and_then(|v| v.value::<&str>()), + ) }) .collect::>(); - assert_eq!(results, vec![(("T-shirt", true), "Comfortable gray cotton t-shirt")]); + assert_eq!( + results, + vec![(("T-shirt", true), "Comfortable gray cotton t-shirt")] + ); let results = c .select("SELECT * FROM stripe_subscriptions", None, None) From 709856f486b6f89293bc83475e8f3f3bf8ab269d Mon Sep 17 00:00:00 2001 From: Bo Lu Date: Thu, 8 Dec 2022 17:03:47 +1100 Subject: [PATCH 3/6] fix stripe test case --- wrappers/src/fdw/stripe_fdw/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wrappers/src/fdw/stripe_fdw/tests.rs b/wrappers/src/fdw/stripe_fdw/tests.rs index 940e81a6..40279e09 100644 --- a/wrappers/src/fdw/stripe_fdw/tests.rs +++ b/wrappers/src/fdw/stripe_fdw/tests.rs @@ -203,7 +203,7 @@ mod tests { assert_eq!( results, - vec![("available", 0, "usd"), ("pending", 0, "usd")] + vec![(("available", 0), "usd"), (("pending", 0), "usd")] ); let results = c From 781ef4e191e40c44af8f3e7e36af880fa53da2e3 Mon Sep 17 00:00:00 2001 From: Bo Lu Date: Thu, 8 Dec 2022 17:21:17 +1100 Subject: [PATCH 4/6] fix stripe test case --- wrappers/src/fdw/stripe_fdw/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wrappers/src/fdw/stripe_fdw/tests.rs b/wrappers/src/fdw/stripe_fdw/tests.rs index 40279e09..5e366d66 100644 --- a/wrappers/src/fdw/stripe_fdw/tests.rs +++ b/wrappers/src/fdw/stripe_fdw/tests.rs @@ -247,7 +247,7 @@ mod tests { }) .collect::>(); - assert_eq!(results, vec![("cus_MJiBgSUgeWFN0z", 1234567890000)]); + assert_eq!(results, vec![("cus_MJiBgSUgeWFN0z", 287883090000000)]); let results = c .select("SELECT * FROM stripe_invoices", None, None) From 2e268d5fe6f5be3d74f550f129a01ec34a4d589a Mon Sep 17 00:00:00 2001 From: Bo Lu Date: Thu, 8 Dec 2022 23:30:56 +1100 Subject: [PATCH 5/6] add modify test --- wrappers/src/fdw/stripe_fdw/tests.rs | 80 ++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/wrappers/src/fdw/stripe_fdw/tests.rs b/wrappers/src/fdw/stripe_fdw/tests.rs index 5e366d66..3321b702 100644 --- a/wrappers/src/fdw/stripe_fdw/tests.rs +++ b/wrappers/src/fdw/stripe_fdw/tests.rs @@ -325,6 +325,86 @@ mod tests { 287883090000000 )] ); + + // test insert + c.update( + r#" + INSERT INTO stripe_customers(email, name, description) + VALUES ('test@test.com', 'test name', null) + "#, + None, + None, + ); + + let results = c + .select( + "SELECT * FROM stripe_customers WHERE email = 'test@test.com'", + None, + None, + ) + .filter_map(|r| { + r.by_name("email") + .ok() + .and_then(|v| v.value::<&str>()) + .zip(r.by_name("name").ok().and_then(|v| v.value::<&str>())) + }) + .collect::>(); + + assert_eq!(results, vec![("test@test.com", "test name")]); + + // test update + c.update( + r#" + UPDATE stripe_customers + SET description = 'hello fdw' + WHERE email = 'test@test.com' + "#, + None, + None, + ); + + let results = c + .select( + "SELECT * FROM stripe_customers WHERE email = 'test@test.com'", + None, + None, + ) + .filter_map(|r| { + r.by_name("email").ok().and_then(|v| v.value::<&str>()).zip( + r.by_name("description") + .ok() + .and_then(|v| v.value::<&str>()), + ) + }) + .collect::>(); + + assert_eq!(results, vec![("test@test.com", "hello fdw")]); + + // test delete + c.update( + r#" + DELETE FROM stripe_customers WHERE email = 'test@test.com' + "#, + None, + None, + ); + + let results = c + .select( + "SELECT * FROM stripe_customers WHERE email = 'test@test.com'", + None, + None, + ) + .filter_map(|r| { + r.by_name("email").ok().and_then(|v| v.value::<&str>()).zip( + r.by_name("description") + .ok() + .and_then(|v| v.value::<&str>()), + ) + }) + .collect::>(); + + assert!(results.is_empty()); }); } } From fbc46a53860df9804e412b177665338c1de29206 Mon Sep 17 00:00:00 2001 From: Bo Lu Date: Fri, 9 Dec 2022 00:02:17 +1100 Subject: [PATCH 6/6] comment out modify test cases --- wrappers/src/fdw/stripe_fdw/tests.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/wrappers/src/fdw/stripe_fdw/tests.rs b/wrappers/src/fdw/stripe_fdw/tests.rs index 3321b702..d558009d 100644 --- a/wrappers/src/fdw/stripe_fdw/tests.rs +++ b/wrappers/src/fdw/stripe_fdw/tests.rs @@ -326,6 +326,12 @@ mod tests { )] ); + // Stripe mock container is currently stateless, so we cannot test + // data modify for now but will keep the code below for future use. + // + // ref: https://github.com/stripe/stripe-mock + + /* // test insert c.update( r#" @@ -405,6 +411,7 @@ mod tests { .collect::>(); assert!(results.is_empty()); + */ }); } }