diff --git a/Cargo.lock b/Cargo.lock index bbc1fb0b90..8ef19d83ec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9710,9 +9710,9 @@ dependencies = [ [[package]] name = "test-r" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f222e9ef5e70ba864934fc58a46e076f5fefdec71b2f8638f3da28470361a270" +checksum = "096af9a5318c22b4f7bcf483eeacac44d831ae3ac78f4fab065be61c25713a10" dependencies = [ "ctor", "test-r-core", @@ -9722,9 +9722,9 @@ dependencies = [ [[package]] name = "test-r-core" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e3e1de4496823b3fd5c0b5411900988f79ca2b9c1e33c8a22a48e65934c65d0" +checksum = "be35981a41cf8814f5cf4c01cebdf1a32b5e3b2c77436db13dc6c6f6669485ab" dependencies = [ "anstream", "anstyle", @@ -9745,9 +9745,9 @@ dependencies = [ [[package]] name = "test-r-macro" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46b98fd96e98960e8b99b0840008563f8c528335307287ff6fa7636ac4d0840c" +checksum = "040d55dfc68c3a12628b74488faa4bf39487b32d506e0b03de0edeb468d152be" dependencies = [ "heck 0.5.0", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index 096234cd89..a4316aa0c4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -180,7 +180,7 @@ testcontainers-modules = { version = "0.11.4", features = [ "redis", "minio", ] } -test-r = { version = "1.1.0", default-features = true } +test-r = { version = "1.2.0", default-features = true } thiserror = "2.0.6" tokio = { version = "1.42", features = [ "macros", diff --git a/golem-worker-executor-base/tests/lib.rs b/golem-worker-executor-base/tests/lib.rs index e5adf099de..bad3b0556d 100644 --- a/golem-worker-executor-base/tests/lib.rs +++ b/golem-worker-executor-base/tests/lib.rs @@ -56,10 +56,13 @@ pub mod keyvalue; pub mod measure_test_component_mem; pub mod observability; pub mod rust_rpc; +pub mod rust_rpc_stubless; pub mod scalability; pub mod transactions; pub mod ts_rpc1; +pub mod ts_rpc1_stubless; pub mod ts_rpc2; +pub mod ts_rpc2_stubless; pub mod wasi; test_r::enable!(); @@ -76,14 +79,17 @@ tag_suite!(wasi, group3); tag_suite!(scalability, group4); tag_suite!(hot_update, group4); tag_suite!(rust_rpc, group4); +tag_suite!(rust_rpc_stubless, group4); tag_suite!(guest_languages2, group5); tag_suite!(ts_rpc1, group6); +tag_suite!(ts_rpc1_stubless, group6); tag_suite!(guest_languages3, group7); tag_suite!(ts_rpc2, group8); +tag_suite!(ts_rpc2_stubless, group8); #[derive(Clone)] pub struct WorkerExecutorPerTestDependencies { diff --git a/golem-worker-executor-base/tests/rust_rpc_stubless.rs b/golem-worker-executor-base/tests/rust_rpc_stubless.rs new file mode 100644 index 0000000000..156b2364cc --- /dev/null +++ b/golem-worker-executor-base/tests/rust_rpc_stubless.rs @@ -0,0 +1,768 @@ +// Copyright 2024 Golem Cloud +// +// Licensed 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 test_r::{inherit_test_dep, test}; + +use crate::common::{start, TestContext}; +use crate::{LastUniqueId, Tracing, WorkerExecutorTestDependencies}; +use assert2::check; +use golem_test_framework::dsl::{worker_error_message, TestDslUnsafe}; +use golem_wasm_rpc::Value; +use std::collections::HashMap; +use std::time::SystemTime; +use tracing::{debug, info}; + +inherit_test_dep!(WorkerExecutorTestDependencies); +inherit_test_dep!(LastUniqueId); +inherit_test_dep!(Tracing); + +#[test] +#[tracing::instrument] +#[ignore] +async fn auction_example_1( + last_unique_id: &LastUniqueId, + deps: &WorkerExecutorTestDependencies, + _tracing: &Tracing, +) { + let context = TestContext::new(last_unique_id); + let executor = start(deps, &context).await.unwrap(); + + let registry_component_id = executor.store_component("auction_registry").await; + let auction_component_id = executor.store_component("auction").await; + + let mut env = HashMap::new(); + env.insert( + "AUCTION_COMPONENT_ID".to_string(), + auction_component_id.to_string(), + ); + let registry_worker_id = executor + .start_worker_with(®istry_component_id, "auction-registry-1", vec![], env) + .await; + + let _ = executor.log_output(®istry_worker_id).await; + + let expiration = SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .unwrap() + .as_secs(); + let create_auction_result = executor + .invoke_and_await( + ®istry_worker_id, + "auction:registry/api.{create-auction}", + vec![ + Value::String("test-auction".to_string()), + Value::String("this is a test".to_string()), + Value::F32(100.0), + Value::U64(expiration + 600), + ], + ) + .await; + + let get_auctions_result = executor + .invoke_and_await( + ®istry_worker_id, + "auction:registry/api.{get-auctions}", + vec![], + ) + .await; + + drop(executor); + + println!("result: {:?}", create_auction_result); + println!("result: {:?}", get_auctions_result); + check!(create_auction_result.is_ok()); + + let auction_id = &create_auction_result.unwrap()[0]; + + check!( + get_auctions_result + == Ok(vec![Value::List(vec![Value::Record(vec![ + auction_id.clone(), + Value::String("test-auction".to_string()), + Value::String("this is a test".to_string()), + Value::F32(100.0), + Value::U64(expiration + 600) + ]),])]) + ); +} + +#[test] +#[tracing::instrument] +#[ignore] +async fn auction_example_2( + last_unique_id: &LastUniqueId, + deps: &WorkerExecutorTestDependencies, + _tracing: &Tracing, +) { + let context = TestContext::new(last_unique_id); + let executor = start(deps, &context).await.unwrap(); + + let registry_component_id = executor.store_component("auction_registry").await; + let auction_component_id = executor.store_component("auction").await; + + let mut env = HashMap::new(); + env.insert( + "AUCTION_COMPONENT_ID".to_string(), + auction_component_id.to_string(), + ); + let registry_worker_id = executor + .start_worker_with(®istry_component_id, "auction-registry-2", vec![], env) + .await; + + let _ = executor.log_output(®istry_worker_id).await; + + let expiration = SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .unwrap() + .as_secs(); + let create_auction_result = executor + .invoke_and_await( + ®istry_worker_id, + "auction:registry/api.{create-auction-res}", + vec![ + Value::String("test-auction".to_string()), + Value::String("this is a test".to_string()), + Value::F32(100.0), + Value::U64(expiration + 600), + ], + ) + .await; + + let get_auctions_result = executor + .invoke_and_await( + ®istry_worker_id, + "auction:registry/api.{get-auctions}", + vec![], + ) + .await; + + drop(executor); + + println!("result: {:?}", create_auction_result); + println!("result: {:?}", get_auctions_result); + check!(create_auction_result.is_ok()); + + let auction_id = &create_auction_result.unwrap()[0]; + + check!( + get_auctions_result + == Ok(vec![Value::List(vec![Value::Record(vec![ + auction_id.clone(), + Value::String("test-auction".to_string()), + Value::String("this is a test".to_string()), + Value::F32(100.0), + Value::U64(expiration + 600) + ]),])]) + ); +} + +#[test] +#[tracing::instrument] +#[ignore] +async fn counter_resource_test_1( + last_unique_id: &LastUniqueId, + deps: &WorkerExecutorTestDependencies, + _tracing: &Tracing, +) { + let context = TestContext::new(last_unique_id); + let executor = start(deps, &context).await.unwrap(); + + let counters_component_id = executor.store_component("counters").await; + let caller_component_id = executor.store_component("caller").await; + + let mut env = HashMap::new(); + env.insert( + "COUNTERS_COMPONENT_ID".to_string(), + counters_component_id.to_string(), + ); + let caller_worker_id = executor + .start_worker_with(&caller_component_id, "rpc-counters-1", vec![], env) + .await; + + let result = executor + .invoke_and_await(&caller_worker_id, "test1", vec![]) + .await; + + drop(executor); + + check!( + result + == Ok(vec![Value::List(vec![ + Value::Tuple(vec![Value::String("counter3".to_string()), Value::U64(3)]), + Value::Tuple(vec![Value::String("counter2".to_string()), Value::U64(3)]), + Value::Tuple(vec![Value::String("counter1".to_string()), Value::U64(3)]) + ])]) + ); +} + +#[test] +#[tracing::instrument] +#[ignore] +async fn counter_resource_test_2( + last_unique_id: &LastUniqueId, + deps: &WorkerExecutorTestDependencies, + _tracing: &Tracing, +) { + let context = TestContext::new(last_unique_id); + let executor = start(deps, &context).await.unwrap(); + + let counters_component_id = executor.store_component("counters").await; + let caller_component_id = executor.store_component("caller").await; + + let mut env = HashMap::new(); + env.insert( + "COUNTERS_COMPONENT_ID".to_string(), + counters_component_id.to_string(), + ); + let caller_worker_id = executor + .start_worker_with(&caller_component_id, "rpc-counters-2", vec![], env) + .await; + + let result1 = executor + .invoke_and_await(&caller_worker_id, "test2", vec![]) + .await; + let result2 = executor + .invoke_and_await(&caller_worker_id, "test2", vec![]) + .await; + + drop(executor); + + check!(result1 == Ok(vec![Value::U64(1)])); + check!(result2 == Ok(vec![Value::U64(2)])); +} + +#[test] +#[tracing::instrument] +#[ignore] +async fn counter_resource_test_2_with_restart( + last_unique_id: &LastUniqueId, + deps: &WorkerExecutorTestDependencies, + _tracing: &Tracing, +) { + let context = TestContext::new(last_unique_id); + let executor = start(deps, &context).await.unwrap(); + + let counters_component_id = executor.store_component("counters").await; + let caller_component_id = executor.store_component("caller").await; + + let mut env = HashMap::new(); + env.insert( + "COUNTERS_COMPONENT_ID".to_string(), + counters_component_id.to_string(), + ); + let caller_worker_id = executor + .start_worker_with(&caller_component_id, "rpc-counters-2r", vec![], env) + .await; + + let result1 = executor + .invoke_and_await(&caller_worker_id, "test2", vec![]) + .await; + + drop(executor); + let executor = start(deps, &context).await.unwrap(); + + let result2 = executor + .invoke_and_await(&caller_worker_id, "test2", vec![]) + .await; + + drop(executor); + + check!(result1 == Ok(vec![Value::U64(1)])); + check!(result2 == Ok(vec![Value::U64(2)])); +} + +#[test] +#[tracing::instrument] +#[ignore] +async fn counter_resource_test_3( + last_unique_id: &LastUniqueId, + deps: &WorkerExecutorTestDependencies, + _tracing: &Tracing, +) { + let context = TestContext::new(last_unique_id); + let executor = start(deps, &context).await.unwrap(); + + let counters_component_id = executor.store_component("counters").await; + let caller_component_id = executor.store_component("caller").await; + + let mut env = HashMap::new(); + env.insert( + "COUNTERS_COMPONENT_ID".to_string(), + counters_component_id.to_string(), + ); + let caller_worker_id = executor + .start_worker_with(&caller_component_id, "rpc-counters-3", vec![], env) + .await; + + let result1 = executor + .invoke_and_await(&caller_worker_id, "test3", vec![]) + .await; + let result2 = executor + .invoke_and_await(&caller_worker_id, "test3", vec![]) + .await; + + drop(executor); + + check!(result1 == Ok(vec![Value::U64(1)])); + check!(result2 == Ok(vec![Value::U64(2)])); +} + +#[test] +#[tracing::instrument] +#[ignore] +async fn counter_resource_test_3_with_restart( + last_unique_id: &LastUniqueId, + deps: &WorkerExecutorTestDependencies, + _tracing: &Tracing, +) { + let context = TestContext::new(last_unique_id); + let executor = start(deps, &context).await.unwrap(); + + let counters_component_id = executor.store_component("counters").await; + let caller_component_id = executor.store_component("caller").await; + + let mut env = HashMap::new(); + env.insert( + "COUNTERS_COMPONENT_ID".to_string(), + counters_component_id.to_string(), + ); + let caller_worker_id = executor + .start_worker_with(&caller_component_id, "rpc-counters-3r", vec![], env) + .await; + + let result1 = executor + .invoke_and_await(&caller_worker_id, "test3", vec![]) + .await; + + drop(executor); + let executor = start(deps, &context).await.unwrap(); + + let result2 = executor + .invoke_and_await(&caller_worker_id, "test3", vec![]) + .await; + + drop(executor); + + check!(result1 == Ok(vec![Value::U64(1)])); + check!(result2 == Ok(vec![Value::U64(2)])); +} + +#[test] +#[tracing::instrument] +#[ignore] +async fn context_inheritance( + last_unique_id: &LastUniqueId, + deps: &WorkerExecutorTestDependencies, + _tracing: &Tracing, +) { + let context = TestContext::new(last_unique_id); + let executor = start(deps, &context).await.unwrap(); + + let counters_component_id = executor.store_component("counters").await; + let caller_component_id = executor.store_component("caller").await; + + let mut env = HashMap::new(); + env.insert( + "COUNTERS_COMPONENT_ID".to_string(), + counters_component_id.to_string(), + ); + env.insert("TEST_CONFIG".to_string(), "123".to_string()); + let caller_worker_id = executor + .start_worker_with( + &caller_component_id, + "rpc-counters-4", + vec!["a".to_string(), "b".to_string(), "c".to_string()], + env, + ) + .await; + + let result = executor + .invoke_and_await(&caller_worker_id, "test4", vec![]) + .await; + + drop(executor); + + let result = result.unwrap(); + let result_tuple = match &result[0] { + Value::Tuple(result) => result, + _ => panic!("Unexpected result: {:?}", result), + }; + let args = match &result_tuple[0] { + Value::List(args) => args.clone(), + _ => panic!("Unexpected result: {:?}", result), + }; + let mut env = match &result_tuple[1] { + Value::List(env) => env + .clone() + .into_iter() + .map(|value| match value { + Value::Tuple(tuple) => match (&tuple[0], &tuple[1]) { + (Value::String(key), Value::String(value)) => (key.clone(), value.clone()), + _ => panic!("Unexpected result: {:?}", result), + }, + _ => panic!("Unexpected result: {:?}", result), + }) + .collect::>(), + _ => panic!("Unexpected result: {:?}", result), + }; + env.sort_by_key(|(k, _v)| k.clone()); + + check!( + args == vec![ + Value::String("a".to_string()), + Value::String("b".to_string()), + Value::String("c".to_string()) + ] + ); + check!( + env == vec![ + ( + "COUNTERS_COMPONENT_ID".to_string(), + counters_component_id.to_string() + ), + ( + "GOLEM_COMPONENT_ID".to_string(), + counters_component_id.to_string() + ), + ("GOLEM_COMPONENT_VERSION".to_string(), "0".to_string()), + ( + "GOLEM_WORKER_NAME".to_string(), + "counters_test4".to_string() + ), + ("TEST_CONFIG".to_string(), "123".to_string()) + ] + ); +} + +#[test] +#[tracing::instrument] +#[ignore] +async fn counter_resource_test_5( + last_unique_id: &LastUniqueId, + deps: &WorkerExecutorTestDependencies, + _tracing: &Tracing, +) { + let context = TestContext::new(last_unique_id); + let executor = start(deps, &context).await.unwrap(); + + let counters_component_id = executor.store_component("counters").await; + let caller_component_id = executor.store_component("caller").await; + + let mut env = HashMap::new(); + env.insert( + "COUNTERS_COMPONENT_ID".to_string(), + counters_component_id.to_string(), + ); + let caller_worker_id = executor + .start_worker_with(&caller_component_id, "rpc-counters-5", vec![], env) + .await; + + executor.log_output(&caller_worker_id).await; + + let result = executor + .invoke_and_await(&caller_worker_id, "test5", vec![]) + .await; + + drop(executor); + + check!( + result + == Ok(vec![Value::List(vec![ + Value::U64(3), + Value::U64(3), + Value::U64(3), + ]),]) + ); +} + +#[test] +#[tracing::instrument] +#[ignore] +async fn counter_resource_test_5_with_restart( + last_unique_id: &LastUniqueId, + deps: &WorkerExecutorTestDependencies, + _tracing: &Tracing, +) { + let context = TestContext::new(last_unique_id); + let executor = start(deps, &context).await.unwrap(); + + // using store_unique_component to avoid collision with counter_resource_test_5 + let counters_component_id = executor.store_unique_component("counters").await; + let caller_component_id = executor.store_unique_component("caller").await; + + let mut env = HashMap::new(); + env.insert( + "COUNTERS_COMPONENT_ID".to_string(), + counters_component_id.to_string(), + ); + let caller_worker_id = executor + .start_worker_with(&caller_component_id, "rpc-counters-5r", vec![], env) + .await; + + executor.log_output(&caller_worker_id).await; + + let result1 = executor + .invoke_and_await(&caller_worker_id, "test5", vec![]) + .await; + + drop(executor); + + let executor = start(deps, &context).await.unwrap(); + + let result2 = executor + .invoke_and_await(&caller_worker_id, "test5", vec![]) + .await; + + drop(executor); + + check!( + result1 + == Ok(vec![Value::List(vec![ + Value::U64(3), + Value::U64(3), + Value::U64(3), + ]),]) + ); + // The second call has the same result because new resources are created within test5() + check!( + result2 + == Ok(vec![Value::List(vec![ + Value::U64(3), + Value::U64(3), + Value::U64(3), + ]),]), + ); +} + +#[test] +#[tracing::instrument] +#[ignore] +async fn wasm_rpc_bug_32_test( + last_unique_id: &LastUniqueId, + deps: &WorkerExecutorTestDependencies, + _tracing: &Tracing, +) { + let context = TestContext::new(last_unique_id); + let executor = start(deps, &context).await.unwrap(); + + let counters_component_id = executor.store_component("counters").await; + let caller_component_id = executor.store_component("caller").await; + + let mut env = HashMap::new(); + env.insert( + "COUNTERS_COMPONENT_ID".to_string(), + counters_component_id.to_string(), + ); + let caller_worker_id = executor + .start_worker_with(&caller_component_id, "rpc-counters-bug32", vec![], env) + .await; + + let result = executor + .invoke_and_await( + &caller_worker_id, + "bug-wasm-rpc-i32", + vec![Value::Variant { + case_idx: 0, + case_value: None, + }], + ) + .await; + + drop(executor); + + check!( + result + == Ok(vec![Value::Variant { + case_idx: 0, + case_value: None, + }]) + ); +} + +#[test] +#[tracing::instrument] +#[ignore] +async fn error_message_invalid_uri( + last_unique_id: &LastUniqueId, + deps: &WorkerExecutorTestDependencies, + _tracing: &Tracing, +) { + let context = TestContext::new(last_unique_id); + let executor = start(deps, &context).await.unwrap(); + + let registry_component_id = executor.store_component("auction_registry").await; + + let mut env = HashMap::new(); + env.insert( + "AUCTION_COMPONENT_ID".to_string(), + "invalid-component-id".to_string(), + ); + let registry_worker_id = executor + .start_worker_with( + ®istry_component_id, + "auction-registry-invalid-uri", + vec![], + env, + ) + .await; + + let _ = executor.log_output(®istry_worker_id).await; + + let expiration = SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .unwrap() + .as_secs(); + let create_auction_result = executor + .invoke_and_await( + ®istry_worker_id, + "auction:registry/api.{create-auction}", + vec![ + Value::String("test-auction".to_string()), + Value::String("this is a test".to_string()), + Value::F32(100.0), + Value::U64(expiration + 600), + ], + ) + .await; + + drop(executor); + + debug!( + "Error message: {}", + worker_error_message(&create_auction_result.clone().err().unwrap()) + ); + check!(worker_error_message(&create_auction_result.err().unwrap()) + .contains("Invalid URI: urn:worker:invalid-component-id")); +} + +#[test] +#[tracing::instrument] +#[ignore] +async fn error_message_non_existing_target_component( + last_unique_id: &LastUniqueId, + deps: &WorkerExecutorTestDependencies, + _tracing: &Tracing, +) { + let context = TestContext::new(last_unique_id); + let executor = start(deps, &context).await.unwrap(); + + let registry_component_id = executor.store_component("auction_registry").await; + + let mut env = HashMap::new(); + env.insert( + "AUCTION_COMPONENT_ID".to_string(), + "FB2F8E32-7B94-4699-B6EC-82BCE80FF9F2".to_string(), // valid UUID, but not an existing component + ); + let registry_worker_id = executor + .start_worker_with( + ®istry_component_id, + "auction-registry-non-existing-target", + vec![], + env, + ) + .await; + + let _ = executor.log_output(®istry_worker_id).await; + + let expiration = SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .unwrap() + .as_secs(); + let create_auction_result = executor + .invoke_and_await( + ®istry_worker_id, + "auction:registry/api.{create-auction}", + vec![ + Value::String("test-auction".to_string()), + Value::String("this is a test".to_string()), + Value::F32(100.0), + Value::U64(expiration + 600), + ], + ) + .await; + + drop(executor); + + check!(worker_error_message(&create_auction_result.err().unwrap()) + .contains("Could not find any component with the given id")); +} + +#[test] +#[tracing::instrument] +#[ignore] +async fn ephemeral_worker_invocation_via_rpc1( + last_unique_id: &LastUniqueId, + deps: &WorkerExecutorTestDependencies, + _tracing: &Tracing, +) { + let context = TestContext::new(last_unique_id); + let executor = start(deps, &context).await.unwrap(); + + let ephemeral_component_id = executor.store_ephemeral_component("ephemeral").await; + let caller_component_id = executor.store_component("caller").await; + + let mut env = HashMap::new(); + env.insert( + "EPHEMERAL_COMPONENT_ID".to_string(), + ephemeral_component_id.to_string(), + ); + let caller_worker_id = executor + .start_worker_with(&caller_component_id, "rpc-ephemeral-1", vec![], env) + .await; + + let result = executor + .invoke_and_await(&caller_worker_id, "ephemeral-test1", vec![]) + .await + .unwrap(); + + drop(executor); + + info!("result is: {result:?}"); + + match result.into_iter().next() { + Some(Value::List(items)) => { + let pairs = items + .into_iter() + .filter_map(|item| match item { + Value::Tuple(values) if values.len() == 2 => { + let mut iter = values.into_iter(); + let key = iter.next(); + let value = iter.next(); + match (key, value) { + (Some(Value::String(key)), Some(Value::String(value))) => { + Some((key, value)) + } + _ => None, + } + } + _ => None, + }) + .collect::>(); + + check!(pairs.len() == 3); + let name1 = &pairs[0].0; + let value1 = &pairs[0].1; + let name2 = &pairs[1].0; + let value2 = &pairs[1].1; + let name3 = &pairs[2].0; + let value3 = &pairs[2].1; + + check!(name1 == name2); + check!(name2 != name3); + check!(value1 != value2); + check!(value2 != value3); + } + _ => panic!("Unexpected result value"), + } +} diff --git a/golem-worker-executor-base/tests/ts_rpc1_stubless.rs b/golem-worker-executor-base/tests/ts_rpc1_stubless.rs new file mode 100644 index 0000000000..9c20fac738 --- /dev/null +++ b/golem-worker-executor-base/tests/ts_rpc1_stubless.rs @@ -0,0 +1,191 @@ +// Copyright 2024 Golem Cloud +// +// Licensed 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 test_r::{inherit_test_dep, test}; + +use crate::{common, LastUniqueId, Tracing, WorkerExecutorTestDependencies}; +use assert2::check; +use golem_test_framework::dsl::TestDslUnsafe; +use golem_wasm_rpc::Value; +use std::collections::HashMap; + +inherit_test_dep!(WorkerExecutorTestDependencies); +inherit_test_dep!(LastUniqueId); +inherit_test_dep!(Tracing); + +static COUNTER_COMPONENT_NAME: &str = "counter-ts"; +static CALLER_COMPONENT_NAME: &str = "caller-ts"; + +#[test] +#[tracing::instrument] +#[ignore] +async fn counter_resource_test_1( + last_unique_id: &LastUniqueId, + deps: &WorkerExecutorTestDependencies, + _tracing: &Tracing, +) { + let context = common::TestContext::new(last_unique_id); + let executor = common::start(deps, &context).await.unwrap(); + + let counters_component_id = executor.store_component(COUNTER_COMPONENT_NAME).await; + let caller_component_id = executor.store_component(CALLER_COMPONENT_NAME).await; + + let mut env = HashMap::new(); + env.insert( + "COUNTERS_COMPONENT_ID".to_string(), + counters_component_id.to_string(), + ); + let caller_worker_id = executor + .start_worker_with(&caller_component_id, "rpc-counters-1", vec![], env) + .await; + + let result1 = executor + .invoke_and_await(&caller_worker_id, "test1", vec![]) + .await; + let result2 = executor + .invoke_and_await(&caller_worker_id, "test1", vec![]) + .await; + + drop(executor); + + check!(result1 == Ok(vec![Value::U64(1)])); + check!(result2 == Ok(vec![Value::U64(2)])); +} + +#[test] +#[tracing::instrument] +#[ignore] +async fn counter_resource_test_1_with_restart( + last_unique_id: &LastUniqueId, + deps: &WorkerExecutorTestDependencies, + _tracing: &Tracing, +) { + let context = common::TestContext::new(last_unique_id); + let executor = common::start(deps, &context).await.unwrap(); + + let counters_component_id = executor.store_component(COUNTER_COMPONENT_NAME).await; + let caller_component_id = executor.store_component(CALLER_COMPONENT_NAME).await; + + let mut env = HashMap::new(); + env.insert( + "COUNTERS_COMPONENT_ID".to_string(), + counters_component_id.to_string(), + ); + let caller_worker_id = executor + .start_worker_with(&caller_component_id, "rpc-counters-1r", vec![], env) + .await; + + let result1 = executor + .invoke_and_await(&caller_worker_id, "test1", vec![]) + .await; + + drop(executor); + let executor = common::start(deps, &context).await.unwrap(); + + let result2 = executor + .invoke_and_await(&caller_worker_id, "test1", vec![]) + .await; + + drop(executor); + + check!(result1 == Ok(vec![Value::U64(1)])); + check!(result2 == Ok(vec![Value::U64(2)])); +} + +#[test] +#[tracing::instrument] +#[ignore] +async fn context_inheritance( + last_unique_id: &LastUniqueId, + deps: &WorkerExecutorTestDependencies, + _tracing: &Tracing, +) { + let context = common::TestContext::new(last_unique_id); + let executor = common::start(deps, &context).await.unwrap(); + + let counters_component_id = executor.store_component(COUNTER_COMPONENT_NAME).await; + let caller_component_id = executor.store_component(CALLER_COMPONENT_NAME).await; + + let mut env = HashMap::new(); + env.insert( + "COUNTERS_COMPONENT_ID".to_string(), + counters_component_id.to_string(), + ); + env.insert("TEST_CONFIG".to_string(), "123".to_string()); + let caller_worker_id = executor + .start_worker_with( + &caller_component_id, + "rpc-counters-4", + vec!["a".to_string(), "b".to_string(), "c".to_string()], + env, + ) + .await; + + let result = executor + .invoke_and_await(&caller_worker_id, "test3", vec![]) + .await; + + drop(executor); + + let result = result.unwrap(); + let result_tuple = match &result[0] { + Value::Tuple(result) => result, + _ => panic!("Unexpected result: {:?}", result), + }; + let args = match &result_tuple[0] { + Value::List(args) => args.clone(), + _ => panic!("Unexpected result: {:?}", result), + }; + let mut env = match &result_tuple[1] { + Value::List(env) => env + .clone() + .into_iter() + .map(|value| match value { + Value::Tuple(tuple) => match (&tuple[0], &tuple[1]) { + (Value::String(key), Value::String(value)) => (key.clone(), value.clone()), + _ => panic!("Unexpected result: {:?}", result), + }, + _ => panic!("Unexpected result: {:?}", result), + }) + .collect::>(), + _ => panic!("Unexpected result: {:?}", result), + }; + env.sort_by_key(|(k, _v)| k.clone()); + + check!( + args == vec![ + Value::String("a".to_string()), + Value::String("b".to_string()), + Value::String("c".to_string()) + ] + ); + check!( + env == vec![ + ( + "COUNTERS_COMPONENT_ID".to_string(), + counters_component_id.to_string() + ), + ( + "GOLEM_COMPONENT_ID".to_string(), + counters_component_id.to_string() + ), + ("GOLEM_COMPONENT_VERSION".to_string(), "0".to_string()), + ( + "GOLEM_WORKER_NAME".to_string(), + "counters_test4".to_string() + ), + ("TEST_CONFIG".to_string(), "123".to_string()) + ] + ); +} diff --git a/golem-worker-executor-base/tests/ts_rpc2_stubless.rs b/golem-worker-executor-base/tests/ts_rpc2_stubless.rs new file mode 100644 index 0000000000..18f27e2afd --- /dev/null +++ b/golem-worker-executor-base/tests/ts_rpc2_stubless.rs @@ -0,0 +1,104 @@ +// Copyright 2024 Golem Cloud +// +// Licensed 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 test_r::{inherit_test_dep, test}; + +use crate::{common, LastUniqueId, Tracing, WorkerExecutorTestDependencies}; +use assert2::check; +use golem_test_framework::dsl::TestDslUnsafe; +use golem_wasm_rpc::Value; +use std::collections::HashMap; + +inherit_test_dep!(WorkerExecutorTestDependencies); +inherit_test_dep!(LastUniqueId); +inherit_test_dep!(Tracing); + +static COUNTER_COMPONENT_NAME: &str = "counter-ts"; +static CALLER_COMPONENT_NAME: &str = "caller-ts"; + +#[test] +#[tracing::instrument] +#[ignore] +async fn counter_resource_test_2( + last_unique_id: &LastUniqueId, + deps: &WorkerExecutorTestDependencies, + _tracing: &Tracing, +) { + let context = common::TestContext::new(last_unique_id); + let executor = common::start(deps, &context).await.unwrap(); + + let counters_component_id = executor.store_component(COUNTER_COMPONENT_NAME).await; + let caller_component_id = executor.store_component(CALLER_COMPONENT_NAME).await; + + let mut env = HashMap::new(); + env.insert( + "COUNTERS_COMPONENT_ID".to_string(), + counters_component_id.to_string(), + ); + let caller_worker_id = executor + .start_worker_with(&caller_component_id, "rpc-counters-2", vec![], env) + .await; + + let result1 = executor + .invoke_and_await(&caller_worker_id, "test2", vec![]) + .await; + let result2 = executor + .invoke_and_await(&caller_worker_id, "test2", vec![]) + .await; + + drop(executor); + + check!(result1 == Ok(vec![Value::U64(1)])); + check!(result2 == Ok(vec![Value::U64(2)])); +} + +#[test] +#[tracing::instrument] +#[ignore] +async fn counter_resource_test_2_with_restart( + last_unique_id: &LastUniqueId, + deps: &WorkerExecutorTestDependencies, + _tracing: &Tracing, +) { + let context = common::TestContext::new(last_unique_id); + let executor = common::start(deps, &context).await.unwrap(); + + let counters_component_id = executor.store_component(COUNTER_COMPONENT_NAME).await; + let caller_component_id = executor.store_component(CALLER_COMPONENT_NAME).await; + + let mut env = HashMap::new(); + env.insert( + "COUNTERS_COMPONENT_ID".to_string(), + counters_component_id.to_string(), + ); + let caller_worker_id = executor + .start_worker_with(&caller_component_id, "rpc-counters-2r", vec![], env) + .await; + + let result1 = executor + .invoke_and_await(&caller_worker_id, "test2", vec![]) + .await; + + drop(executor); + let executor = common::start(deps, &context).await.unwrap(); + + let result2 = executor + .invoke_and_await(&caller_worker_id, "test2", vec![]) + .await; + + drop(executor); + + check!(result1 == Ok(vec![Value::U64(1)])); + check!(result2 == Ok(vec![Value::U64(2)])); +} diff --git a/test-components/auction-example/Cargo.lock b/test-components/auction-example/Cargo.lock index 670f07b5d5..a8ac801e67 100644 --- a/test-components/auction-example/Cargo.lock +++ b/test-components/auction-example/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "aho-corasick" @@ -63,6 +63,38 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +[[package]] +name = "camino" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -114,11 +146,34 @@ dependencies = [ "wasi", ] +[[package]] +name = "git-version" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad568aa3db0fcbc81f2f116137f263d7304f512a1209b35b85150d3ef88ad19" +dependencies = [ + "git-version-macro", +] + +[[package]] +name = "git-version-macro" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53010ccb100b96a67bc32c0175f0ed1426b31b655d562898e57325f81c023ac0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "golem-wasm-rpc" version = "0.0.0" dependencies = [ + "cargo_metadata", + "git-version", "prost-build", + "uuid", "wit-bindgen-rt", ] @@ -153,6 +208,12 @@ dependencies = [ "either", ] +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + [[package]] name = "libc" version = "0.2.153" @@ -217,9 +278,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -367,31 +428,58 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "semver" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" +dependencies = [ + "serde", +] + [[package]] name = "serde" -version = "1.0.196" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" +checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.196" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" +checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" dependencies = [ "proc-macro2", "quote", "syn", ] +[[package]] +name = "serde_json" +version = "1.0.133" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + [[package]] name = "syn" -version = "2.0.48" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -411,6 +499,26 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "unicode-ident" version = "1.0.12" @@ -419,9 +527,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "uuid" -version = "1.7.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" dependencies = [ "getrandom", "serde", diff --git a/test-components/auction-example/build.sh b/test-components/auction-example/build.sh index 5300fb9889..86ddb0cbea 100755 --- a/test-components/auction-example/build.sh +++ b/test-components/auction-example/build.sh @@ -7,4 +7,5 @@ cp target/wasm32-wasi/release/auction_stub.wasm target/wasm32-wasi/release/aucti wasm-tools compose -v target/wasm32-wasi/release/auction_registry.wasm -o target/wasm32-wasi/release/auction_registry_composed.wasm cp target/wasm32-wasi/release/auction_registry_composed.wasm .. +cp target/wasm32-wasi/release/auction_registry.wasm .. cp target/wasm32-wasi/release/auction.wasm .. \ No newline at end of file diff --git a/test-components/auction.wasm b/test-components/auction.wasm index 9be00a485e..c716cfabbf 100755 Binary files a/test-components/auction.wasm and b/test-components/auction.wasm differ diff --git a/test-components/auction_registry.wasm b/test-components/auction_registry.wasm new file mode 100644 index 0000000000..fab443ecee Binary files /dev/null and b/test-components/auction_registry.wasm differ diff --git a/test-components/auction_registry_composed.wasm b/test-components/auction_registry_composed.wasm index b3d4d50b54..fb32c57bee 100644 Binary files a/test-components/auction_registry_composed.wasm and b/test-components/auction_registry_composed.wasm differ diff --git a/test-components/caller-ts.wasm b/test-components/caller-ts.wasm new file mode 100644 index 0000000000..7a0db42191 Binary files /dev/null and b/test-components/caller-ts.wasm differ diff --git a/test-components/caller.wasm b/test-components/caller.wasm new file mode 100644 index 0000000000..57794b1680 Binary files /dev/null and b/test-components/caller.wasm differ diff --git a/test-components/caller_composed.wasm b/test-components/caller_composed.wasm index ed5f61f9f1..4b8a778229 100644 Binary files a/test-components/caller_composed.wasm and b/test-components/caller_composed.wasm differ diff --git a/test-components/counters.wasm b/test-components/counters.wasm index d58151ac5c..2a5fdb5bac 100755 Binary files a/test-components/counters.wasm and b/test-components/counters.wasm differ diff --git a/test-components/ephemeral.wasm b/test-components/ephemeral.wasm index 469169168e..8321baf715 100644 Binary files a/test-components/ephemeral.wasm and b/test-components/ephemeral.wasm differ diff --git a/test-components/rpc/Cargo.lock b/test-components/rpc/Cargo.lock index d862db634e..4c98417470 100644 --- a/test-components/rpc/Cargo.lock +++ b/test-components/rpc/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "aho-corasick" @@ -159,11 +159,31 @@ dependencies = [ "wasi", ] +[[package]] +name = "git-version" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad568aa3db0fcbc81f2f116137f263d7304f512a1209b35b85150d3ef88ad19" +dependencies = [ + "git-version-macro", +] + +[[package]] +name = "git-version-macro" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53010ccb100b96a67bc32c0175f0ed1426b31b655d562898e57325f81c023ac0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "golem-rust" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ef0670496530779ccc42076031e1ebce93aee07129b1c410e31bee577be85c" +checksum = "c967eb388fb81f9b9f4df5d5b6634de803f21cd410c1bf687202794a4fbc0267" dependencies = [ "golem-rust-macro", "serde", @@ -174,9 +194,9 @@ dependencies = [ [[package]] name = "golem-rust-macro" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4eb977d485e1d5d0d2fc7db022689b740615639867f932702f7d176f786a8e0" +checksum = "1bb87f831cfe4371427c63f5f4cabcc3bae1b66974c8fbcf22be9274fee3a7d1" dependencies = [ "heck", "proc-macro2", @@ -189,7 +209,9 @@ name = "golem-wasm-rpc" version = "0.0.0" dependencies = [ "cargo_metadata", + "git-version", "prost-build", + "uuid", "wit-bindgen-rt", ] diff --git a/test-components/rpc/build-debug.sh b/test-components/rpc/build-debug.sh index a1d8feb59e..3348f15968 100755 --- a/test-components/rpc/build-debug.sh +++ b/test-components/rpc/build-debug.sh @@ -14,5 +14,6 @@ cp target/wasm32-wasi/debug/ephemeral_stub.wasm target/wasm32-wasi/debug/rpc:eph wasm-tools compose -v target/wasm32-wasi/debug/caller_composed1.wasm -o target/wasm32-wasi/debug/caller_composed.wasm cp target/wasm32-wasi/debug/caller_composed.wasm .. +cp target/wasm32-wasi/debug/caller.wasm .. cp target/wasm32-wasi/debug/counters.wasm .. cp target/wasm32-wasi/debug/ephemeral.wasm .. diff --git a/test-components/rpc/build.sh b/test-components/rpc/build.sh index 5cb4ff2f57..9b77ef5f3f 100755 --- a/test-components/rpc/build.sh +++ b/test-components/rpc/build.sh @@ -14,5 +14,6 @@ cp target/wasm32-wasi/release/ephemeral_stub.wasm target/wasm32-wasi/release/rpc wasm-tools compose -v target/wasm32-wasi/release/caller_composed1.wasm -o target/wasm32-wasi/release/caller_composed.wasm cp target/wasm32-wasi/release/caller_composed.wasm .. +cp target/wasm32-wasi/release/caller.wasm .. cp target/wasm32-wasi/release/counters.wasm .. cp target/wasm32-wasi/release/ephemeral.wasm ..