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_azure_container_code_executor.py 7.0 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. # File based from: https://github.com/microsoft/autogen/blob/main/test/coding/test_commandline_code_executor.py
  2. # Credit to original authors
  3. import asyncio
  4. import os
  5. import sys
  6. import tempfile
  7. from anyio import open_file
  8. import pytest
  9. from azure.identity import DefaultAzureCredential
  10. from agnext.components.code_executor import CodeBlock, AzureContainerCodeExecutor
  11. from agnext.core import CancellationToken
  12. UNIX_SHELLS = ["bash", "sh", "shell"]
  13. WINDOWS_SHELLS = ["ps1", "pwsh", "powershell"]
  14. PYTHON_VARIANTS = ["python", "Python", "py"]
  15. ENVIRON_KEY_AZURE_POOL_ENDPOINT = "AZURE_POOL_ENDPOINT"
  16. POOL_ENDPOINT = os.getenv(ENVIRON_KEY_AZURE_POOL_ENDPOINT)
  17. @pytest.mark.skipif(
  18. not POOL_ENDPOINT,
  19. reason="do not run if pool endpoint is not defined",
  20. )
  21. @pytest.mark.asyncio
  22. async def test_execute_code() -> None:
  23. assert POOL_ENDPOINT is not None
  24. cancellation_token = CancellationToken()
  25. executor = AzureContainerCodeExecutor(pool_management_endpoint=POOL_ENDPOINT, credential=DefaultAzureCredential())
  26. # Test single code block.
  27. code_blocks = [CodeBlock(code="import sys; print('hello world!')", language="python")]
  28. code_result = await executor.execute_code_blocks(code_blocks, cancellation_token)
  29. assert code_result.exit_code == 0 and "hello world!" in code_result.output
  30. # Test multiple code blocks.
  31. code_blocks = [
  32. CodeBlock(code="import sys; print('hello world!')", language="python"),
  33. CodeBlock(code="a = 100 + 100; print(a)", language="python"),
  34. ]
  35. code_result = await executor.execute_code_blocks(code_blocks, cancellation_token)
  36. assert (
  37. code_result.exit_code == 0
  38. and "hello world!" in code_result.output
  39. and "200" in code_result.output
  40. )
  41. # Test bash script.
  42. if sys.platform not in ["win32"]:
  43. code_blocks = [CodeBlock(code="echo 'hello world!'", language="bash")]
  44. code_result = await executor.execute_code_blocks(code_blocks, cancellation_token)
  45. assert "unknown language" in code_result.output
  46. assert code_result.exit_code == 1
  47. # Test running code.
  48. file_lines = ["import sys", "print('hello world!')", "a = 100 + 100", "print(a)"]
  49. code_blocks = [CodeBlock(code="\n".join(file_lines), language="python")]
  50. code_result = await executor.execute_code_blocks(code_blocks, cancellation_token)
  51. assert (
  52. code_result.exit_code == 0
  53. and "hello world!" in code_result.output
  54. and "200" in code_result.output
  55. )
  56. @pytest.mark.skipif(
  57. not POOL_ENDPOINT,
  58. reason="do not run if pool endpoint is not defined",
  59. )
  60. @pytest.mark.asyncio
  61. async def test_azure_container_code_executor_timeout() -> None:
  62. assert POOL_ENDPOINT is not None
  63. cancellation_token = CancellationToken()
  64. executor = AzureContainerCodeExecutor(pool_management_endpoint=POOL_ENDPOINT, credential=DefaultAzureCredential(), timeout=1)
  65. code_blocks = [CodeBlock(code="import time; time.sleep(10); print('hello world!')", language="python")]
  66. with pytest.raises(asyncio.TimeoutError):
  67. await executor.execute_code_blocks(code_blocks, cancellation_token)
  68. @pytest.mark.skipif(
  69. not POOL_ENDPOINT,
  70. reason="do not run if pool endpoint is not defined",
  71. )
  72. @pytest.mark.asyncio
  73. async def test_azure_container_code_executor_cancellation() -> None:
  74. assert POOL_ENDPOINT is not None
  75. cancellation_token = CancellationToken()
  76. executor = AzureContainerCodeExecutor(pool_management_endpoint=POOL_ENDPOINT, credential=DefaultAzureCredential())
  77. code_blocks = [CodeBlock(code="import time; time.sleep(10); print('hello world!')", language="python")]
  78. coro = executor.execute_code_blocks(code_blocks, cancellation_token)
  79. await asyncio.sleep(1)
  80. cancellation_token.cancel()
  81. with pytest.raises(asyncio.CancelledError):
  82. await coro
  83. @pytest.mark.skipif(
  84. not POOL_ENDPOINT,
  85. reason="do not run if pool endpoint is not defined",
  86. )
  87. @pytest.mark.asyncio
  88. async def test_upload_files() -> None:
  89. assert POOL_ENDPOINT is not None
  90. test_file_1 = "test1.txt"
  91. test_file_1_contents = "test file 1"
  92. test_file_2 = "test2"
  93. test_file_2_contents = "test file 2"
  94. cancellation_token = CancellationToken()
  95. with tempfile.TemporaryDirectory() as temp_dir:
  96. executor = AzureContainerCodeExecutor(pool_management_endpoint=POOL_ENDPOINT, credential=DefaultAzureCredential(), work_dir=temp_dir)
  97. async with await open_file(os.path.join(temp_dir, test_file_1), "w") as f:
  98. await f.write(test_file_1_contents)
  99. async with await open_file(os.path.join(temp_dir, test_file_2), "w") as f:
  100. await f.write(test_file_2_contents)
  101. await executor.upload_files([test_file_1, test_file_2], cancellation_token)
  102. file_list = await executor.get_file_list(cancellation_token)
  103. assert test_file_1 in file_list
  104. assert test_file_2 in file_list
  105. code_blocks = [CodeBlock(code=f"""
  106. with open("{test_file_1}") as f:
  107. print(f.read())
  108. with open("{test_file_2}") as f:
  109. print(f.read())
  110. """, language="python")]
  111. code_result = await executor.execute_code_blocks(code_blocks, cancellation_token)
  112. assert code_result.exit_code == 0
  113. assert test_file_1_contents in code_result.output
  114. assert test_file_2_contents in code_result.output
  115. @pytest.mark.skipif(
  116. not POOL_ENDPOINT,
  117. reason="do not run if pool endpoint is not defined",
  118. )
  119. @pytest.mark.asyncio
  120. async def test_download_files() -> None:
  121. assert POOL_ENDPOINT is not None
  122. test_file_1 = "test1.txt"
  123. test_file_1_contents = "azure test file 1"
  124. test_file_2 = "test2"
  125. test_file_2_contents = "azure test file 2"
  126. cancellation_token = CancellationToken()
  127. with tempfile.TemporaryDirectory() as temp_dir:
  128. executor = AzureContainerCodeExecutor(pool_management_endpoint=POOL_ENDPOINT, credential=DefaultAzureCredential(), work_dir=temp_dir)
  129. code_blocks = [
  130. CodeBlock(code=f"""
  131. with open("{test_file_1}", "w") as f:
  132. f.write("{test_file_1_contents}")
  133. with open("{test_file_2}", "w") as f:
  134. f.write("{test_file_2_contents}")
  135. """, language="python"),
  136. ]
  137. code_result = await executor.execute_code_blocks(code_blocks, cancellation_token)
  138. assert code_result.exit_code == 0
  139. file_list = await executor.get_file_list(cancellation_token)
  140. assert test_file_1 in file_list
  141. assert test_file_2 in file_list
  142. await executor.download_files([test_file_1, test_file_2], cancellation_token)
  143. assert os.path.isfile(os.path.join(temp_dir, test_file_1))
  144. async with await open_file(os.path.join(temp_dir, test_file_1), "r") as f:
  145. content = await f.read()
  146. assert test_file_1_contents in content
  147. assert os.path.isfile(os.path.join(temp_dir, test_file_2))
  148. async with await open_file(os.path.join(temp_dir, test_file_2), "r") as f:
  149. content = await f.read()
  150. assert test_file_2_contents in content