dify
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
import pytest
|
||||
|
||||
from core.helper.code_executor.code_executor import CodeExecutionError, CodeExecutor
|
||||
|
||||
CODE_LANGUAGE = "unsupported_language"
|
||||
|
||||
|
||||
def test_unsupported_with_code_template():
|
||||
with pytest.raises(CodeExecutionError) as e:
|
||||
CodeExecutor.execute_workflow_code_template(language=CODE_LANGUAGE, code="", inputs={})
|
||||
assert str(e.value) == f"Unsupported language {CODE_LANGUAGE}"
|
||||
@@ -0,0 +1,47 @@
|
||||
from textwrap import dedent
|
||||
|
||||
from .test_utils import CodeExecutorTestMixin
|
||||
|
||||
|
||||
class TestJavaScriptCodeExecutor(CodeExecutorTestMixin):
|
||||
"""Test class for JavaScript code executor functionality."""
|
||||
|
||||
def test_javascript_plain(self, flask_app_with_containers):
|
||||
"""Test basic JavaScript code execution with console.log output"""
|
||||
CodeExecutor, CodeLanguage = self.code_executor_imports
|
||||
|
||||
code = 'console.log("Hello World")'
|
||||
result_message = CodeExecutor.execute_code(language=CodeLanguage.JAVASCRIPT, preload="", code=code)
|
||||
assert result_message == "Hello World\n"
|
||||
|
||||
def test_javascript_json(self, flask_app_with_containers):
|
||||
"""Test JavaScript code execution with JSON output"""
|
||||
CodeExecutor, CodeLanguage = self.code_executor_imports
|
||||
|
||||
code = dedent("""
|
||||
obj = {'Hello': 'World'}
|
||||
console.log(JSON.stringify(obj))
|
||||
""")
|
||||
result = CodeExecutor.execute_code(language=CodeLanguage.JAVASCRIPT, preload="", code=code)
|
||||
assert result == '{"Hello":"World"}\n'
|
||||
|
||||
def test_javascript_with_code_template(self, flask_app_with_containers):
|
||||
"""Test JavaScript workflow code template execution with inputs"""
|
||||
CodeExecutor, CodeLanguage = self.code_executor_imports
|
||||
JavascriptCodeProvider, _ = self.javascript_imports
|
||||
|
||||
result = CodeExecutor.execute_workflow_code_template(
|
||||
language=CodeLanguage.JAVASCRIPT,
|
||||
code=JavascriptCodeProvider.get_default_code(),
|
||||
inputs={"arg1": "Hello", "arg2": "World"},
|
||||
)
|
||||
assert result == {"result": "HelloWorld"}
|
||||
|
||||
def test_javascript_get_runner_script(self, flask_app_with_containers):
|
||||
"""Test JavaScript template transformer runner script generation"""
|
||||
_, NodeJsTemplateTransformer = self.javascript_imports
|
||||
|
||||
runner_script = NodeJsTemplateTransformer.get_runner_script()
|
||||
assert runner_script.count(NodeJsTemplateTransformer._code_placeholder) == 1
|
||||
assert runner_script.count(NodeJsTemplateTransformer._inputs_placeholder) == 1
|
||||
assert runner_script.count(NodeJsTemplateTransformer._result_tag) == 2
|
||||
@@ -0,0 +1,42 @@
|
||||
import base64
|
||||
|
||||
from .test_utils import CodeExecutorTestMixin
|
||||
|
||||
|
||||
class TestJinja2CodeExecutor(CodeExecutorTestMixin):
|
||||
"""Test class for Jinja2 code executor functionality."""
|
||||
|
||||
def test_jinja2(self, flask_app_with_containers):
|
||||
"""Test basic Jinja2 template execution with variable substitution"""
|
||||
CodeExecutor, CodeLanguage = self.code_executor_imports
|
||||
_, Jinja2TemplateTransformer = self.jinja2_imports
|
||||
|
||||
template = "Hello {{template}}"
|
||||
inputs = base64.b64encode(b'{"template": "World"}').decode("utf-8")
|
||||
code = (
|
||||
Jinja2TemplateTransformer.get_runner_script()
|
||||
.replace(Jinja2TemplateTransformer._code_placeholder, template)
|
||||
.replace(Jinja2TemplateTransformer._inputs_placeholder, inputs)
|
||||
)
|
||||
result = CodeExecutor.execute_code(
|
||||
language=CodeLanguage.JINJA2, preload=Jinja2TemplateTransformer.get_preload_script(), code=code
|
||||
)
|
||||
assert result == "<<RESULT>>Hello World<<RESULT>>\n"
|
||||
|
||||
def test_jinja2_with_code_template(self, flask_app_with_containers):
|
||||
"""Test Jinja2 workflow code template execution with inputs"""
|
||||
CodeExecutor, CodeLanguage = self.code_executor_imports
|
||||
|
||||
result = CodeExecutor.execute_workflow_code_template(
|
||||
language=CodeLanguage.JINJA2, code="Hello {{template}}", inputs={"template": "World"}
|
||||
)
|
||||
assert result == {"result": "Hello World"}
|
||||
|
||||
def test_jinja2_get_runner_script(self, flask_app_with_containers):
|
||||
"""Test Jinja2 template transformer runner script generation"""
|
||||
_, Jinja2TemplateTransformer = self.jinja2_imports
|
||||
|
||||
runner_script = Jinja2TemplateTransformer.get_runner_script()
|
||||
assert runner_script.count(Jinja2TemplateTransformer._code_placeholder) == 1
|
||||
assert runner_script.count(Jinja2TemplateTransformer._inputs_placeholder) == 1
|
||||
assert runner_script.count(Jinja2TemplateTransformer._result_tag) == 2
|
||||
@@ -0,0 +1,47 @@
|
||||
from textwrap import dedent
|
||||
|
||||
from .test_utils import CodeExecutorTestMixin
|
||||
|
||||
|
||||
class TestPython3CodeExecutor(CodeExecutorTestMixin):
|
||||
"""Test class for Python3 code executor functionality."""
|
||||
|
||||
def test_python3_plain(self, flask_app_with_containers):
|
||||
"""Test basic Python3 code execution with print output"""
|
||||
CodeExecutor, CodeLanguage = self.code_executor_imports
|
||||
|
||||
code = 'print("Hello World")'
|
||||
result = CodeExecutor.execute_code(language=CodeLanguage.PYTHON3, preload="", code=code)
|
||||
assert result == "Hello World\n"
|
||||
|
||||
def test_python3_json(self, flask_app_with_containers):
|
||||
"""Test Python3 code execution with JSON output"""
|
||||
CodeExecutor, CodeLanguage = self.code_executor_imports
|
||||
|
||||
code = dedent("""
|
||||
import json
|
||||
print(json.dumps({'Hello': 'World'}))
|
||||
""")
|
||||
result = CodeExecutor.execute_code(language=CodeLanguage.PYTHON3, preload="", code=code)
|
||||
assert result == '{"Hello": "World"}\n'
|
||||
|
||||
def test_python3_with_code_template(self, flask_app_with_containers):
|
||||
"""Test Python3 workflow code template execution with inputs"""
|
||||
CodeExecutor, CodeLanguage = self.code_executor_imports
|
||||
Python3CodeProvider, _ = self.python3_imports
|
||||
|
||||
result = CodeExecutor.execute_workflow_code_template(
|
||||
language=CodeLanguage.PYTHON3,
|
||||
code=Python3CodeProvider.get_default_code(),
|
||||
inputs={"arg1": "Hello", "arg2": "World"},
|
||||
)
|
||||
assert result == {"result": "HelloWorld"}
|
||||
|
||||
def test_python3_get_runner_script(self, flask_app_with_containers):
|
||||
"""Test Python3 template transformer runner script generation"""
|
||||
_, Python3TemplateTransformer = self.python3_imports
|
||||
|
||||
runner_script = Python3TemplateTransformer.get_runner_script()
|
||||
assert runner_script.count(Python3TemplateTransformer._code_placeholder) == 1
|
||||
assert runner_script.count(Python3TemplateTransformer._inputs_placeholder) == 1
|
||||
assert runner_script.count(Python3TemplateTransformer._result_tag) == 2
|
||||
@@ -0,0 +1,115 @@
|
||||
"""
|
||||
Test utilities for code executor integration tests.
|
||||
|
||||
This module provides lazy import functions to avoid module loading issues
|
||||
that occur when modules are imported before the flask_app_with_containers fixture
|
||||
has set up the proper environment variables and configuration.
|
||||
"""
|
||||
|
||||
import importlib
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
pass
|
||||
|
||||
|
||||
def force_reload_code_executor():
|
||||
"""
|
||||
Force reload the code_executor module to reinitialize code_execution_endpoint_url.
|
||||
|
||||
This function should be called after setting up environment variables
|
||||
to ensure the code_execution_endpoint_url is initialized with the correct value.
|
||||
"""
|
||||
try:
|
||||
import core.helper.code_executor.code_executor
|
||||
|
||||
importlib.reload(core.helper.code_executor.code_executor)
|
||||
except Exception as e:
|
||||
# Log the error but don't fail the test
|
||||
print(f"Warning: Failed to reload code_executor module: {e}")
|
||||
|
||||
|
||||
def get_code_executor_imports():
|
||||
"""
|
||||
Lazy import function for core CodeExecutor classes.
|
||||
|
||||
Returns:
|
||||
tuple: (CodeExecutor, CodeLanguage) classes
|
||||
"""
|
||||
from core.helper.code_executor.code_executor import CodeExecutor, CodeLanguage
|
||||
|
||||
return CodeExecutor, CodeLanguage
|
||||
|
||||
|
||||
def get_javascript_imports():
|
||||
"""
|
||||
Lazy import function for JavaScript-specific modules.
|
||||
|
||||
Returns:
|
||||
tuple: (JavascriptCodeProvider, NodeJsTemplateTransformer) classes
|
||||
"""
|
||||
from core.helper.code_executor.javascript.javascript_code_provider import JavascriptCodeProvider
|
||||
from core.helper.code_executor.javascript.javascript_transformer import NodeJsTemplateTransformer
|
||||
|
||||
return JavascriptCodeProvider, NodeJsTemplateTransformer
|
||||
|
||||
|
||||
def get_python3_imports():
|
||||
"""
|
||||
Lazy import function for Python3-specific modules.
|
||||
|
||||
Returns:
|
||||
tuple: (Python3CodeProvider, Python3TemplateTransformer) classes
|
||||
"""
|
||||
from core.helper.code_executor.python3.python3_code_provider import Python3CodeProvider
|
||||
from core.helper.code_executor.python3.python3_transformer import Python3TemplateTransformer
|
||||
|
||||
return Python3CodeProvider, Python3TemplateTransformer
|
||||
|
||||
|
||||
def get_jinja2_imports():
|
||||
"""
|
||||
Lazy import function for Jinja2-specific modules.
|
||||
|
||||
Returns:
|
||||
tuple: (None, Jinja2TemplateTransformer) classes
|
||||
"""
|
||||
from core.helper.code_executor.jinja2.jinja2_transformer import Jinja2TemplateTransformer
|
||||
|
||||
return None, Jinja2TemplateTransformer
|
||||
|
||||
|
||||
class CodeExecutorTestMixin:
|
||||
"""
|
||||
Mixin class providing lazy import methods for code executor tests.
|
||||
|
||||
This mixin helps avoid module loading issues by deferring imports
|
||||
until after the flask_app_with_containers fixture has set up the environment.
|
||||
"""
|
||||
|
||||
def setup_method(self):
|
||||
"""
|
||||
Setup method called before each test method.
|
||||
Force reload the code_executor module to ensure fresh initialization.
|
||||
"""
|
||||
force_reload_code_executor()
|
||||
|
||||
@property
|
||||
def code_executor_imports(self):
|
||||
"""Property to get CodeExecutor and CodeLanguage classes."""
|
||||
return get_code_executor_imports()
|
||||
|
||||
@property
|
||||
def javascript_imports(self):
|
||||
"""Property to get JavaScript-specific classes."""
|
||||
return get_javascript_imports()
|
||||
|
||||
@property
|
||||
def python3_imports(self):
|
||||
"""Property to get Python3-specific classes."""
|
||||
return get_python3_imports()
|
||||
|
||||
@property
|
||||
def jinja2_imports(self):
|
||||
"""Property to get Jinja2-specific classes."""
|
||||
return get_jinja2_imports()
|
||||
Reference in New Issue
Block a user