You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

test_http_tool.py 8.1 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. import json
  2. import httpx
  3. import pytest
  4. from autogen_core import CancellationToken, Component, ComponentModel
  5. from autogen_ext.tools.http import HttpTool
  6. from pydantic import ValidationError
  7. def test_tool_schema_generation(test_config: ComponentModel) -> None:
  8. tool = HttpTool.load_component(test_config)
  9. schema = tool.schema
  10. assert schema["name"] == "TestHttpTool"
  11. assert "description" in schema
  12. assert schema["description"] == "A test HTTP tool"
  13. assert "parameters" in schema
  14. assert schema["parameters"]["type"] == "object"
  15. assert "properties" in schema["parameters"]
  16. assert schema["parameters"]["properties"]["query"]["description"] == "The test query"
  17. assert schema["parameters"]["properties"]["query"]["type"] == "string"
  18. assert schema["parameters"]["properties"]["value"]["description"] == "A test value"
  19. assert schema["parameters"]["properties"]["value"]["type"] == "integer"
  20. assert "required" in schema["parameters"]
  21. assert set(schema["parameters"]["required"]) == {"query", "value"}
  22. def test_tool_properties(test_config: ComponentModel) -> None:
  23. tool = HttpTool.load_component(test_config)
  24. assert tool.name == "TestHttpTool"
  25. assert tool.description == "A test HTTP tool"
  26. assert tool.server_params.host == "localhost"
  27. assert tool.server_params.port == 8000
  28. assert tool.server_params.path == "/test"
  29. assert tool.server_params.scheme == "http"
  30. assert tool.server_params.method == "POST"
  31. def test_component_base_class(test_config: ComponentModel) -> None:
  32. tool = HttpTool.load_component(test_config)
  33. assert tool.dump_component() is not None
  34. assert HttpTool.load_component(tool.dump_component(), HttpTool) is not None
  35. assert isinstance(tool, Component)
  36. @pytest.mark.asyncio
  37. async def test_post_request(test_config: ComponentModel, test_server: None) -> None:
  38. tool = HttpTool.load_component(test_config)
  39. result = await tool.run_json({"query": "test query", "value": 42}, CancellationToken())
  40. assert isinstance(result, str)
  41. assert json.loads(result)["result"] == "Received: test query with value 42"
  42. @pytest.mark.asyncio
  43. async def test_post_request_json_return(test_config: ComponentModel, test_server: None) -> None:
  44. # Modify config to use json return type
  45. config = test_config.model_copy()
  46. config.config["return_type"] = "json"
  47. tool = HttpTool.load_component(config)
  48. result = await tool.run_json({"query": "test query", "value": 45}, CancellationToken())
  49. assert isinstance(result, dict)
  50. assert result["result"] == "Received: test query with value 45"
  51. @pytest.mark.asyncio
  52. async def test_get_request(test_config: ComponentModel, test_server: None) -> None:
  53. # Modify config for GET request
  54. config = test_config.model_copy()
  55. config.config["method"] = "GET"
  56. tool = HttpTool.load_component(config)
  57. result = await tool.run_json({"query": "test query", "value": 42}, CancellationToken())
  58. assert isinstance(result, str)
  59. assert json.loads(result)["result"] == "Received: test query with value 42"
  60. @pytest.mark.asyncio
  61. async def test_put_request(test_config: ComponentModel, test_server: None) -> None:
  62. # Modify config for PUT request
  63. config = test_config.model_copy()
  64. config.config["method"] = "PUT"
  65. tool = HttpTool.load_component(config)
  66. result = await tool.run_json({"query": "test query", "value": 42}, CancellationToken())
  67. assert isinstance(result, str)
  68. assert json.loads(result)["result"] == "Received: test query with value 42"
  69. @pytest.mark.asyncio
  70. async def test_path_params(test_config: ComponentModel, test_server: None) -> None:
  71. # Modify config to use path parameters
  72. config = test_config.model_copy()
  73. config.config["path"] = "/test/{query}/{value}"
  74. tool = HttpTool.load_component(config)
  75. result = await tool.run_json({"query": "test query", "value": 42}, CancellationToken())
  76. assert isinstance(result, str)
  77. assert json.loads(result)["result"] == "Received: test query with value 42"
  78. @pytest.mark.asyncio
  79. async def test_path_params_and_body(test_config: ComponentModel, test_server: None) -> None:
  80. # Modify config to use path parameters and include body parameters
  81. config = test_config.model_copy()
  82. config.config["method"] = "PUT"
  83. config.config["path"] = "/test/{query}/{value}"
  84. config.config["json_schema"] = {
  85. "type": "object",
  86. "properties": {
  87. "query": {"type": "string", "description": "The test query"},
  88. "value": {"type": "integer", "description": "A test value"},
  89. "extra": {"type": "string", "description": "Extra body parameter"},
  90. },
  91. "required": ["query", "value", "extra"],
  92. }
  93. tool = HttpTool.load_component(config)
  94. result = await tool.run_json({"query": "test query", "value": 42, "extra": "extra data"}, CancellationToken())
  95. assert isinstance(result, str)
  96. assert json.loads(result)["result"] == "Received: test query with value 42 and extra extra data"
  97. @pytest.mark.asyncio
  98. async def test_delete_request(test_config: ComponentModel, test_server: None) -> None:
  99. # Modify config for DELETE request
  100. config = test_config.model_copy()
  101. config.config["method"] = "DELETE"
  102. tool = HttpTool.load_component(config)
  103. result = await tool.run_json({"query": "test query", "value": 42}, CancellationToken())
  104. assert isinstance(result, str)
  105. assert json.loads(result)["result"] == "Received: test query with value 42"
  106. @pytest.mark.asyncio
  107. async def test_patch_request(test_config: ComponentModel, test_server: None) -> None:
  108. # Modify config for PATCH request
  109. config = test_config.model_copy()
  110. config.config["method"] = "PATCH"
  111. tool = HttpTool.load_component(config)
  112. result = await tool.run_json({"query": "test query", "value": 42}, CancellationToken())
  113. assert isinstance(result, str)
  114. assert json.loads(result)["result"] == "Received: test query with value 42"
  115. @pytest.mark.asyncio
  116. async def test_invalid_schema(test_config: ComponentModel, test_server: None) -> None:
  117. # Create an invalid schema missing required properties
  118. config: ComponentModel = test_config.model_copy()
  119. config.config["host"] = True # Incorrect type
  120. with pytest.raises(ValidationError):
  121. # Should fail when trying to create model from invalid schema
  122. HttpTool.load_component(config)
  123. @pytest.mark.asyncio
  124. async def test_invalid_request(test_config: ComponentModel, test_server: None) -> None:
  125. # Use an invalid URL
  126. config = test_config.model_copy()
  127. config.config["host"] = "fake"
  128. tool = HttpTool.load_component(config)
  129. with pytest.raises(httpx.ConnectError):
  130. await tool.run_json({"query": "test query", "value": 42}, CancellationToken())
  131. def test_config_serialization(test_config: ComponentModel) -> None:
  132. tool = HttpTool.load_component(test_config)
  133. config = tool.dump_component()
  134. assert config.config["name"] == test_config.config["name"]
  135. assert config.config["description"] == test_config.config["description"]
  136. assert config.config["host"] == test_config.config["host"]
  137. assert config.config["port"] == test_config.config["port"]
  138. assert config.config["path"] == test_config.config["path"]
  139. assert config.config["scheme"] == test_config.config["scheme"]
  140. assert config.config["method"] == test_config.config["method"]
  141. assert config.config["headers"] == test_config.config["headers"]
  142. def test_config_deserialization(test_config: ComponentModel) -> None:
  143. tool = HttpTool.load_component(test_config)
  144. assert tool.name == test_config.config["name"]
  145. assert tool.description == test_config.config["description"]
  146. assert tool.server_params.host == test_config.config["host"]
  147. assert tool.server_params.port == test_config.config["port"]
  148. assert tool.server_params.path == test_config.config["path"]
  149. assert tool.server_params.scheme == test_config.config["scheme"]
  150. assert tool.server_params.method == test_config.config["method"]
  151. assert tool.server_params.headers == test_config.config["headers"]