Env.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. # Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http:#www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. """ Test Env, manages DUT, App and EnvConfig, interface for test cases to access these components """
  15. import os
  16. import threading
  17. import functools
  18. import EnvConfig
  19. def _synced(func):
  20. @functools.wraps(func)
  21. def decorator(self, *args, **kwargs):
  22. with self.lock:
  23. ret = func(self, *args, **kwargs)
  24. return ret
  25. decorator.__doc__ = func.__doc__
  26. return decorator
  27. class Env(object):
  28. """
  29. test env, manages DUTs and env configs.
  30. :keyword app: class for default application
  31. :keyword dut: class for default DUT
  32. :keyword env_tag: test env tag, used to select configs from env config file
  33. :keyword env_config_file: test env config file path
  34. :keyword test_name: test suite name, used when generate log folder name
  35. """
  36. def __init__(self,
  37. app=None,
  38. dut=None,
  39. env_tag=None,
  40. env_config_file=None,
  41. test_name=None,
  42. **kwargs):
  43. self.app_cls = app
  44. self.default_dut_cls = dut
  45. self.config = EnvConfig.Config(env_config_file, env_tag)
  46. self.log_path = self.app_cls.get_log_folder(test_name)
  47. if not os.path.exists(self.log_path):
  48. os.makedirs(self.log_path)
  49. self.allocated_duts = dict()
  50. self.lock = threading.RLock()
  51. @_synced
  52. def get_dut(self, dut_name, app_path, dut_class=None, app_class=None):
  53. """
  54. get_dut(dut_name, app_path, dut_class=None, app_class=None)
  55. :param dut_name: user defined name for DUT
  56. :param app_path: application path, app instance will use this path to process application info
  57. :param dut_class: dut class, if not specified will use default dut class of env
  58. :param app_class: app class, if not specified will use default app of env
  59. :return: dut instance
  60. """
  61. if dut_name in self.allocated_duts:
  62. dut = self.allocated_duts[dut_name]["dut"]
  63. else:
  64. if dut_class is None:
  65. dut_class = self.default_dut_cls
  66. if app_class is None:
  67. app_class = self.app_cls
  68. app_inst = app_class(app_path)
  69. try:
  70. port = self.config.get_variable(dut_name)
  71. except ValueError:
  72. # try to auto detect ports
  73. allocated_ports = [self.allocated_duts[x]["port"] for x in self.allocated_duts]
  74. available_ports = dut_class.list_available_ports()
  75. for port in available_ports:
  76. if port not in allocated_ports:
  77. if dut_class.confirm_dut(port, app_inst):
  78. break
  79. else:
  80. port = None
  81. if port:
  82. try:
  83. dut_config = self.get_variable(dut_name + "_port_config")
  84. except ValueError:
  85. dut_config = dict()
  86. dut = self.default_dut_cls(dut_name, port,
  87. os.path.join(self.log_path, dut_name + ".log"),
  88. app_inst,
  89. **dut_config)
  90. self.allocated_duts[dut_name] = {"port": port, "dut": dut}
  91. else:
  92. raise ValueError("Failed to get DUT")
  93. return dut
  94. @_synced
  95. def close_dut(self, dut_name):
  96. """
  97. close_dut(dut_name)
  98. close one DUT by name if DUT name is valid (the name used by ``get_dut``). otherwise will do nothing.
  99. :param dut_name: user defined name for DUT
  100. :return: None
  101. """
  102. try:
  103. dut = self.allocated_duts.pop(dut_name)["dut"]
  104. dut.close()
  105. except KeyError:
  106. pass
  107. @_synced
  108. def get_variable(self, variable_name):
  109. """
  110. get_variable(variable_name)
  111. get variable from config file. If failed then try to auto-detected it.
  112. :param variable_name: name of the variable
  113. :return: value of variable if successfully found. otherwise None.
  114. """
  115. return self.config.get_variable(variable_name)
  116. @_synced
  117. def get_pc_nic_info(self, nic_name="pc_nic"):
  118. """
  119. get_pc_nic_info(nic_name="pc_nic")
  120. try to get nic info (ip address, ipv6 address, mac address)
  121. :param nic_name: pc nic name. allows passing variable name, nic name value or omitted (to get default nic info).
  122. :return: a dict of address ("ipv4", "ipv6", "mac") if successfully found. otherwise None.
  123. """
  124. # TODO: need to implement auto get nic info method
  125. return self.config.get_variable("nic_info/" + nic_name)
  126. @_synced
  127. def close(self):
  128. """
  129. close()
  130. close all DUTs of the Env.
  131. :return: None
  132. """
  133. for dut_name in self.allocated_duts:
  134. dut = self.allocated_duts[dut_name]["dut"]
  135. dut.close()
  136. self.allocated_duts = dict()