test_command.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. import shutil
  2. import pytest
  3. from gpustack.utils.command import (
  4. is_command_available,
  5. find_parameter,
  6. find_bool_parameter,
  7. get_versioned_command,
  8. extend_args_no_exist,
  9. format_backend_parameters,
  10. )
  11. def test_is_command_available_true(monkeypatch):
  12. # Simulate that shutil.which finds the command
  13. monkeypatch.setattr(shutil, 'which', lambda name: f'/usr/bin/{name}')
  14. assert is_command_available('foo') is True
  15. def test_is_command_available_false(monkeypatch):
  16. # Simulate that shutil.which does not find the command
  17. monkeypatch.setattr(shutil, 'which', lambda name: None)
  18. assert is_command_available('bar') is False
  19. @pytest.mark.parametrize(
  20. 'parameters,param_names,expected',
  21. [
  22. (None, ['foo'], None),
  23. ([], ['foo'], None),
  24. (['--foo=bar'], ['foo'], 'bar'),
  25. (['-f=baz'], ['f'], 'baz'),
  26. (['--foo=bar=baz'], ['foo'], 'bar=baz'),
  27. (['--foo', 'value'], ['foo'], 'value'),
  28. (['-f', 'val'], ['f'], 'val'),
  29. # multiple names: should match first key in parameters
  30. (['--x=5'], ['y', 'x'], '5'),
  31. # missing value after flag
  32. (['--foo'], ['foo'], None),
  33. # key not present
  34. (['--bar=1', '--baz', '2'], ['foo'], None),
  35. # Leading whitespace with = format (most common case)
  36. ([' --max-model-len=8192'], ['max-model-len'], '8192'),
  37. ([' --foo=bar'], ['foo'], 'bar'),
  38. ([' --foo bar'], ['foo'], 'bar'),
  39. # Trailing whitespace before =
  40. (['--foo =bar'], ['foo'], 'bar'),
  41. # Both leading and trailing whitespace
  42. ([' --foo =bar'], ['foo'], 'bar'),
  43. # Multiple spaces around =
  44. (['--foo = bar'], ['foo'], ' bar'),
  45. (['--foo =" bar"'], ['foo'], '" bar"'),
  46. (
  47. [
  48. '--hf-overrides \'{"rope_scaling": {"rope_type":"yarn","factor":4.0,"original_max_position_embeddings":32768}}\''
  49. ],
  50. ['hf-overrides'],
  51. '{"rope_scaling": {"rope_type":"yarn","factor":4.0,"original_max_position_embeddings":32768}}',
  52. ),
  53. (
  54. [
  55. '--hf-overrides={"rope_scaling": {"rope_type":"yarn","factor":4.0,"original_max_position_embeddings":32768}}'
  56. ],
  57. ['hf-overrides'],
  58. '{"rope_scaling": {"rope_type":"yarn","factor":4.0,"original_max_position_embeddings":32768}}',
  59. ),
  60. ],
  61. )
  62. def test_find_parameter(parameters, param_names, expected):
  63. assert find_parameter(parameters, param_names) == expected
  64. @pytest.mark.parametrize(
  65. 'parameters,param_names,expected',
  66. [
  67. # flag present
  68. (['--foo'], ['foo'], True),
  69. (['-f'], ['f'], True),
  70. (['--enable-feature'], ['enable-feature'], True),
  71. # key=value should not count as boolean flag
  72. (['--foo=bar'], ['foo'], False),
  73. # flag not present
  74. (['--bar'], ['foo'], False),
  75. ([], ['foo'], False),
  76. # Leading whitespace
  77. ([' --foo'], ['foo'], True),
  78. ([' --enable-feature'], ['enable-feature'], True),
  79. # Trailing whitespace
  80. (['--foo '], ['foo'], True),
  81. # Both leading and trailing whitespace
  82. ([' --foo '], ['foo'], True),
  83. ],
  84. )
  85. def test_find_bool_parameter(parameters, param_names, expected):
  86. assert find_bool_parameter(parameters, param_names) is expected
  87. @pytest.mark.parametrize(
  88. 'command_name,version,expected',
  89. [
  90. ('mycmd.exe', '1.0', 'mycmd_1.0.exe'),
  91. ('tool', '2.3.4', 'tool_2.3.4'),
  92. ('app.bin', 'v2', 'app.bin_v2'),
  93. ('', 'v', '_v'),
  94. ],
  95. )
  96. def test_get_versioned_command(command_name, version, expected):
  97. assert get_versioned_command(command_name, version) == expected
  98. @pytest.mark.parametrize(
  99. 'initial_args,new_args,expected',
  100. [
  101. # Branch 1: Add tuple (key, value) when key doesn't exist
  102. ([], [('--host', '127.0.0.1')], ['--host', '127.0.0.1']),
  103. # Branch 2: Skip tuple when key already exists (exact match)
  104. (['--host', '0.0.0.0'], [('--host', '127.0.0.1')], ['--host', '0.0.0.0']),
  105. # Branch 3: Skip tuple when key exists with = format
  106. (['--host=0.0.0.0'], [('--host', '127.0.0.1')], ['--host=0.0.0.0']),
  107. # Branch 4: Add single flag when it doesn't exist
  108. ([], ['--enable-metrics'], ['--enable-metrics']),
  109. # Branch 5: Skip single flag when it already exists
  110. (['--enable-metrics'], ['--enable-metrics'], ['--enable-metrics']),
  111. # Mixed: Add multiple arguments
  112. (
  113. ['--port', '8080'],
  114. [('--host', '127.0.0.1'), '--enable-metrics', ('--workers', '4')],
  115. [
  116. '--port',
  117. '8080',
  118. '--host',
  119. '127.0.0.1',
  120. '--enable-metrics',
  121. '--workers',
  122. '4',
  123. ],
  124. ),
  125. # Edge case: No new args to add
  126. (['--existing', 'value'], [], ['--existing', 'value']),
  127. ],
  128. )
  129. def test_extend_args_no_exist(initial_args, new_args, expected):
  130. extend_args_no_exist(initial_args, *new_args)
  131. assert initial_args == expected
  132. @pytest.mark.parametrize(
  133. 'parameters,expected',
  134. [
  135. (
  136. [
  137. '--max-model-len',
  138. '8192',
  139. '--disable-access-log-for-endpoints',
  140. '/metrics',
  141. ],
  142. ['--max-model-len=8192', '--disable-access-log-for-endpoints=/metrics'],
  143. ),
  144. (
  145. ['--enable-prefix-caching', '--max-seq-len=32768'],
  146. ['--enable-prefix-caching', '--max-seq-len=32768'],
  147. ),
  148. (
  149. ['--max-prefill-tokens', '-1', '--no-metrics'],
  150. ['--max-prefill-tokens=-1', '--no-metrics'],
  151. ),
  152. (None, []),
  153. ],
  154. )
  155. def test_format_backend_parameters(parameters, expected):
  156. assert format_backend_parameters(parameters) == expected