test_logs.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import asyncio
  2. from typing import List, Union
  3. import pytest
  4. from gpustack.worker.logs import LogOptions, log_generator
  5. @pytest.fixture
  6. def sample_log_file(tmp_path):
  7. log_content = "line1\nline2\nline3\nline4\nline5\n"
  8. log_file = tmp_path / "test.log"
  9. log_file.write_text(log_content)
  10. return log_file
  11. @pytest.fixture
  12. def large_log_file(tmp_path):
  13. # Create a log file with 2KB in two lines
  14. log_content = "line" * 256 + "\n" + "line" * 256 + "\n"
  15. log_file = tmp_path / "large_test.log"
  16. log_file.write_text(log_content)
  17. return log_file
  18. def normalize_newlines(data: Union[str, List[str]]) -> Union[str, List[str]]:
  19. if isinstance(data, str):
  20. return data.replace("\r\n", "\n")
  21. elif isinstance(data, list):
  22. return [line.replace("\r\n", "\n") for line in data]
  23. @pytest.mark.asyncio
  24. async def test_log_generator_default(sample_log_file):
  25. options = LogOptions()
  26. log_path = str(sample_log_file)
  27. result = normalize_newlines(
  28. [line async for line in log_generator(log_path, options)]
  29. )
  30. assert result == [
  31. "line1\n",
  32. "line2\n",
  33. "line3\n",
  34. "line4\n",
  35. "line5\n",
  36. ]
  37. @pytest.mark.asyncio
  38. async def test_log_generator_tail(sample_log_file):
  39. options = LogOptions(tail=2)
  40. log_path = str(sample_log_file)
  41. result = normalize_newlines(
  42. [line async for line in log_generator(log_path, options)]
  43. )
  44. assert result == ["line4\n", "line5\n"]
  45. @pytest.mark.asyncio
  46. async def test_log_generator_follow(sample_log_file):
  47. options = LogOptions(follow=True)
  48. log_path = str(sample_log_file)
  49. generator = log_generator(log_path, options)
  50. result = []
  51. async for line in generator:
  52. result.append(line)
  53. if len(result) == 5:
  54. break
  55. assert normalize_newlines(result) == [
  56. "line1\n",
  57. "line2\n",
  58. "line3\n",
  59. "line4\n",
  60. "line5\n",
  61. ]
  62. # Append a new line to the log file
  63. with open(log_path, "a") as file:
  64. file.write("line6\n")
  65. try:
  66. line6 = await asyncio.wait_for(generator.__anext__(), timeout=1)
  67. assert normalize_newlines(line6) == "line6\n"
  68. except StopAsyncIteration:
  69. pytest.fail("Expected a new line in the log file")
  70. @pytest.mark.asyncio
  71. async def test_log_generator_empty_file(tmp_path):
  72. empty_file = tmp_path / "empty.log"
  73. empty_file.touch()
  74. options = LogOptions(tail=0)
  75. result = [line async for line in log_generator(empty_file, options)]
  76. assert result == []
  77. @pytest.mark.asyncio
  78. async def test_log_generator_tail_larger_than_file(sample_log_file):
  79. options = LogOptions(tail=10)
  80. log_path = str(sample_log_file)
  81. result = normalize_newlines(
  82. [line async for line in log_generator(log_path, options)]
  83. )
  84. assert result == ["line1\n", "line2\n", "line3\n", "line4\n", "line5\n"]
  85. @pytest.mark.asyncio
  86. async def test_log_generator_tail_large_file(large_log_file):
  87. options = LogOptions(tail=1)
  88. log_path = str(large_log_file)
  89. result = normalize_newlines(
  90. [line async for line in log_generator(log_path, options)]
  91. )
  92. assert result == ["line" * 256 + "\n"]
  93. @pytest.mark.asyncio
  94. async def test_log_generator_tail_larger_than_large_file(large_log_file):
  95. options = LogOptions(tail=3)
  96. log_path = str(large_log_file)
  97. result = normalize_newlines(
  98. [line async for line in log_generator(log_path, options)]
  99. )
  100. assert result == ["line" * 256 + "\n", "line" * 256 + "\n"]