diff --git a/README.md b/README.md index 973909a..565912c 100644 --- a/README.md +++ b/README.md @@ -48,11 +48,11 @@ import ( ) func main() { - logHandler := slog.NewTextHandler(os.Stdout, nil) + logger := slog.New(slog.NewTextHandler(os.Stdout, nil)) script := ` // The ctx object from the Go inputData map - name := ctx.get("name", "Roberto") + name := ctx["name"] p := "." if ctx.get("excited") { @@ -73,7 +73,7 @@ func main() { evaluator, _ := polyscript.FromRisorStringWithData( script, inputData, - logHandler, + logger.Handler(), ) ctx := context.Background() @@ -102,7 +102,7 @@ However, when using `StaticProvider`, each evaluation will always use the same i The `ContextProvider` retrieves dynamic data from the context object sent to Eval. This is useful when input data changes at runtime: ```go -evaluator, _ := polyscript.FromRisorString(script, logHandler) +evaluator, _ := polyscript.FromRisorString(script, logger.Handler()) ctx := context.Background() runtimeData := map[string]any{"name": "Billie Jean", "relationship": false} @@ -123,7 +123,7 @@ staticData := map[string]any{ } // Create the evaluator with the static data -evaluator, _ := polyscript.FromRisorStringWithData(script, staticData, logHandler) +evaluator, _ := polyscript.FromRisorStringWithData(script, staticData, logger.Handler()) // For each request, prepare dynamic data requestData := map[string]any{"userId": 123} @@ -183,7 +183,7 @@ staticData := map[string]any{"name": "World"} evaluator, err := polyscript.FromStarlarkStringWithData( scriptContent, staticData, - logHandler, + logger.Handler(), ) // Execute with a context @@ -200,7 +200,7 @@ staticData := map[string]any{"input": "World"} evaluator, err := polyscript.FromExtismFileWithData( "/path/to/module.wasm", staticData, - logHandler, + logger.Handler(), "greet", // entryPoint ) diff --git a/examples/data-prep/risor/main_test.go b/examples/data-prep/risor/main_test.go index a2dfac0..5ff6e07 100644 --- a/examples/data-prep/risor/main_test.go +++ b/examples/data-prep/risor/main_test.go @@ -81,7 +81,30 @@ func TestEvalAndExtractResult(t *testing.T) { assert.NotNil(t, result, "Result should not be nil") // Check basic result fields - assert.Contains(t, result, "greeting", "Result should contain a greeting") + assert.Contains(t, + result, "greeting", + "Result should contain a greeting") + + // Verify actual dynamic data is returned, not the fallback values + greeting := result["greeting"] + require.IsType(t, "", greeting, "Greeting should be a string") + assert.Equal(t, + "Hello, World!", greeting, + "Should use actual name 'World', not fallback 'Default'") + + userID := result["user_id"] + require.IsType(t, "", userID, "user_id should be a string") + assert.Equal(t, + "user-123", userID, + "Should use actual user_id, not fallback 'unknown'") + + timestamp := result["timestamp"] + require.IsType(t, + "", timestamp, + "timestamp should be a string") + assert.NotEqual(t, + "Unknown", timestamp, + "Should use actual timestamp, not fallback 'Unknown'") } // TestFullExecution tests the entire execution flow as an integration test @@ -110,4 +133,32 @@ func TestFullExecution(t *testing.T) { assert.Contains(t, result, "greeting", "Result should have greeting") assert.Contains(t, result, "user_id", "Result should have user_id") assert.Contains(t, result, "app_info", "Result should have app_info") + + // Verify the dynamic data is returned, not the fallback values + greeting := result["greeting"] + require.IsType(t, "", greeting, "Greeting should be a string") + assert.Equal( + t, + "Hello, World!", + greeting, + "Should use actual name 'World', not fallback 'Default'", + ) + + userID := result["user_id"] + require.IsType(t, "", userID, "user_id should be a string") + assert.Equal(t, "user-123", userID, "Should use actual user_id, not fallback 'unknown'") + + timestamp := result["timestamp"] + require.IsType(t, "", timestamp, "timestamp should be a string") + assert.NotEqual(t, "Unknown", timestamp, "Should use actual timestamp, not fallback 'Unknown'") + + message := result["message"] + require.IsType(t, "", message, "message should be a string") + assert.Contains( + t, + message, + "admin", + "Should use actual user role 'admin', not fallback 'guest'", + ) + assert.NotContains(t, message, "guest", "Should not contain fallback role 'guest'") } diff --git a/examples/data-prep/risor/testdata/script.risor b/examples/data-prep/risor/testdata/script.risor index 3f1ece3..2cbd298 100644 --- a/examples/data-prep/risor/testdata/script.risor +++ b/examples/data-prep/risor/testdata/script.risor @@ -1,27 +1,24 @@ // Wrap everything in a function for Risor syntax func process() { - // Script has access to ctx variable passed from Go - // Access data with fallbacks for compatibility with both patterns - input_data := ctx.get("input_data", {}) // Access static config data (set at compile time) app_version := ctx.get("app_version", "unknown") environment := ctx.get("environment", "unknown") config := ctx.get("config", {}) - // Get name from runtime data - name := input_data.get("name", "Default") + // Get name from runtime data (added via AddDataToContext) + name := ctx.get("name", "Default") // Get timestamp from runtime data - timestamp := input_data.get("timestamp", "Unknown") + timestamp := ctx.get("timestamp", "Unknown") // Process user data from runtime data - user_data := input_data.get("user_data", {}) + user_data := ctx.get("user_data", {}) user_role := user_data.get("role", "guest") user_id := user_data.get("id", "unknown") // Access request data if available - request := input_data.get("request", {}) + request := ctx.get("request", {}) request_method := request.get("Method", "") request_path := request.get("URL_Path", "") diff --git a/examples/data-prep/starlark/main_test.go b/examples/data-prep/starlark/main_test.go index 8bed1c7..06a814d 100644 --- a/examples/data-prep/starlark/main_test.go +++ b/examples/data-prep/starlark/main_test.go @@ -83,12 +83,27 @@ func TestEvalAndExtractResult(t *testing.T) { assert.Contains(t, result, "greeting", "Result should contain a greeting") assert.Contains(t, result, "app_info", "Result should contain app info") + // Verify actual dynamic data is used, not fallback values + greeting := result["greeting"] + require.IsType(t, "", greeting, "Greeting should be a string") + assert.Equal(t, + "Hello, World!", greeting, + "Should use actual name 'World', not fallback 'Default'") + + userID := result["user_id"] + require.IsType(t, "", userID, "user_id should be a string") + assert.Equal(t, "user-123", userID, "Should use actual user_id, not fallback 'unknown'") + + timestamp := result["timestamp"] + require.IsType(t, "", timestamp, "timestamp should be a string") + assert.NotEqual(t, "Unknown", timestamp, "Should use actual timestamp, not fallback 'Unknown'") + // Verify app info contains data from static provider - appInfo, hasAppInfo := result["app_info"].(map[string]any) - if assert.True(t, hasAppInfo, "app_info should be a map") { - assert.Equal(t, "1.0.0-test", appInfo["version"], "Should have correct app version") - assert.Equal(t, "test", appInfo["environment"], "Should have test environment") - } + appInfo := result["app_info"] + require.IsType(t, map[string]any{}, appInfo, "app_info should be a map") + appInfoMap := appInfo.(map[string]any) + assert.Equal(t, "1.0.0-test", appInfoMap["version"], "Should have correct app version") + assert.Equal(t, "test", appInfoMap["environment"], "Should have test environment") } // TestFullExecution tests the entire execution flow as an integration test @@ -115,4 +130,32 @@ func TestFullExecution(t *testing.T) { assert.Contains(t, result, "user_id", "Result should have user_id from dynamic data") assert.Contains(t, result, "app_info", "Result should have app_info from static data") assert.Contains(t, result, "request_info", "Result should have request_info from HTTP request") + + // Verify the dynamic data is returned, not the fallback values + greeting := result["greeting"] + require.IsType(t, "", greeting, "Greeting should be a string") + assert.Equal( + t, + "Hello, World!", + greeting, + "Should use actual name 'World', not fallback 'Default'", + ) + + userID := result["user_id"] + require.IsType(t, "", userID, "user_id should be a string") + assert.Equal(t, "user-123", userID, "Should use actual user_id, not fallback 'unknown'") + + timestamp := result["timestamp"] + require.IsType(t, "", timestamp, "timestamp should be a string") + assert.NotEqual(t, "Unknown", timestamp, "Should use actual timestamp, not fallback 'Unknown'") + + message := result["message"] + require.IsType(t, "", message, "message should be a string") + assert.Contains( + t, + message, + "admin", + "Should use actual user role 'admin', not fallback 'guest'", + ) + assert.NotContains(t, message, "guest", "Should not contain fallback role 'guest'") } diff --git a/examples/data-prep/starlark/testdata/script.star b/examples/data-prep/starlark/testdata/script.star index 0e8d176..6e03916 100644 --- a/examples/data-prep/starlark/testdata/script.star +++ b/examples/data-prep/starlark/testdata/script.star @@ -1,26 +1,23 @@ # Script has access to ctx variable passed from Go def process_data(): - # Access data with fallbacks for compatibility with both patterns - input_data = ctx.get("input_data", {}) - # Access static config data (set at compile time) app_version = ctx.get("app_version", "unknown") environment = ctx.get("environment", "unknown") config = ctx.get("config", {}) - # Get name from runtime data - name = input_data.get("name", "Default") + # Get name from runtime data (added via AddDataToContext) + name = ctx.get("name", "Default") # Get timestamp from runtime data - timestamp = input_data.get("timestamp", "Unknown") + timestamp = ctx.get("timestamp", "Unknown") # Process user data from runtime data - user_data = input_data.get("user_data", {}) + user_data = ctx.get("user_data", {}) user_role = user_data.get("role", "guest") user_id = user_data.get("id", "unknown") # Access request data if available - request = input_data.get("request", {}) + request = ctx.get("request", {}) request_method = request.get("Method", "") request_path = request.get("URL_Path", "") diff --git a/examples/multiple-instantiation/extism/main_test.go b/examples/multiple-instantiation/extism/main_test.go index 146001b..295c6ab 100644 --- a/examples/multiple-instantiation/extism/main_test.go +++ b/examples/multiple-instantiation/extism/main_test.go @@ -22,13 +22,11 @@ func TestRunMultipleTimes(t *testing.T) { for i, result := range results { assert.NotNil(t, result, "Result at index %d should not be nil", i) - greeting, ok := result["greeting"] - require.True(t, ok, "Result at index %d should have a greeting field", i) + greeting := result["greeting"] + require.IsType(t, "", greeting, "Greeting at index %d should be a string", i) assert.Equal(t, expectedResults[i], greeting, "Result at index %d should have the correct greeting", i, ) - - require.IsType(t, "", greeting, "Greeting at index %d should be a string", i) } } diff --git a/examples/multiple-instantiation/risor/main_test.go b/examples/multiple-instantiation/risor/main_test.go index ce9f1a0..c77c494 100644 --- a/examples/multiple-instantiation/risor/main_test.go +++ b/examples/multiple-instantiation/risor/main_test.go @@ -45,13 +45,11 @@ func TestRunMultipleTimes(t *testing.T) { result := results[i] require.NotNil(t, result, "Result at index %d should not be nil", i) - greeting, exists := result["greeting"] - require.True(t, exists, "Result should have a greeting field") + greeting := result["greeting"] require.IsType(t, "", greeting, "Greeting should be a string") assert.Equal(t, expected.greeting, greeting, "Should have the correct greeting") - length, exists := result["length"] - require.True(t, exists, "Result should have a length field") + length := result["length"] require.IsType(t, int64(0), length, "Length should be int64") assert.Equal(t, expected.length, length, "Should have the correct length") }) diff --git a/examples/multiple-instantiation/starlark/main_test.go b/examples/multiple-instantiation/starlark/main_test.go index 267fa9d..32ce8e2 100644 --- a/examples/multiple-instantiation/starlark/main_test.go +++ b/examples/multiple-instantiation/starlark/main_test.go @@ -46,13 +46,11 @@ func TestRunMultipleTimes(t *testing.T) { result := results[i] require.NotNil(t, result, "Result at index %d should not be nil", i) - greeting, exists := result["greeting"] - require.True(t, exists, "Result should have a greeting field") + greeting := result["greeting"] require.IsType(t, "", greeting, "Greeting should be a string") assert.Equal(t, expected.greeting, greeting, "Should have the correct greeting") - length, exists := result["length"] - require.True(t, exists, "Result should have a length field") + length := result["length"] require.IsType(t, int64(0), length, "Length should be int64") assert.Equal(t, expected.length, length, "Should have the correct length") }) diff --git a/examples/simple/extism/main_test.go b/examples/simple/extism/main_test.go index e0b6ebe..e3578e0 100644 --- a/examples/simple/extism/main_test.go +++ b/examples/simple/extism/main_test.go @@ -12,8 +12,7 @@ func TestRunExtismExample(t *testing.T) { require.NoError(t, err, "runExtismExample should not return an error") require.NotNil(t, result, "Result should not be nil") - greeting, exists := result["greeting"] - require.True(t, exists, "Result should have a greeting field") + greeting := result["greeting"] require.IsType(t, "", greeting, "Greeting should be a string") assert.Equal(t, "Hello, World!", greeting, "Should have the correct greeting") } diff --git a/examples/simple/risor/main_test.go b/examples/simple/risor/main_test.go index 775750e..06ad21d 100644 --- a/examples/simple/risor/main_test.go +++ b/examples/simple/risor/main_test.go @@ -12,13 +12,11 @@ func TestRunRisorExample(t *testing.T) { require.NoError(t, err, "runRisorExample should not return an error") require.NotNil(t, result, "Result should not be nil") - greeting, exists := result["greeting"] - require.True(t, exists, "Result should have a greeting field") + greeting := result["greeting"] require.IsType(t, "", greeting, "Greeting should be a string") assert.Equal(t, "Hello, World!", greeting, "Should have the correct greeting") - length, exists := result["length"] - require.True(t, exists, "Result should have a length field") + length := result["length"] require.IsType(t, int64(0), length, "Length should be int64") assert.Equal(t, int64(13), length, "Should have the correct length") } diff --git a/examples/simple/starlark/main_test.go b/examples/simple/starlark/main_test.go index 5827bd1..d2ecbe5 100644 --- a/examples/simple/starlark/main_test.go +++ b/examples/simple/starlark/main_test.go @@ -12,13 +12,11 @@ func TestRunStarlarkExample(t *testing.T) { require.NoError(t, err, "runStarlarkExample should not return an error") require.NotNil(t, result, "Result should not be nil") - greeting, exists := result["greeting"] - require.True(t, exists, "Result should have a greeting field") + greeting := result["greeting"] require.IsType(t, "", greeting, "Greeting should be a string") assert.Equal(t, "Hello, World!", greeting, "Should have the correct greeting") - length, exists := result["length"] - require.True(t, exists, "Result should have a length field") + length := result["length"] require.IsType(t, int64(0), length, "Length should be int64") assert.Equal(t, int64(13), length, "Should have the correct length") }