testsuite.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. #!/usr/bin/env python
  2. import os
  3. import os.path
  4. import sys
  5. import shutil
  6. from subprocess import call
  7. import importlib
  8. import unittest
  9. import re
  10. from testcases import settings
  11. class Workspace(object):
  12. def __init__(self):
  13. self.root_dir = os.getcwd()
  14. self.build_dir = os.path.join(self.root_dir, "tmpbin")
  15. self.log_dir = os.path.join(self.root_dir, "logs")
  16. self.tests_dir = os.path.join(self.root_dir, "testcases")
  17. self.examples_dir = os.path.join(self.root_dir, "../PubSubClient/examples")
  18. self.examples = []
  19. self.tests = []
  20. if not os.path.isdir("../PubSubClient"):
  21. raise Exception("Cannot find PubSubClient library")
  22. try:
  23. return __import__('ino')
  24. except ImportError:
  25. raise Exception("ino tool not installed")
  26. def init(self):
  27. if os.path.isdir(self.build_dir):
  28. shutil.rmtree(self.build_dir)
  29. os.mkdir(self.build_dir)
  30. if os.path.isdir(self.log_dir):
  31. shutil.rmtree(self.log_dir)
  32. os.mkdir(self.log_dir)
  33. os.chdir(self.build_dir)
  34. call(["ino", "init"])
  35. shutil.copytree("../../PubSubClient", "lib/PubSubClient")
  36. filenames = []
  37. for root, dirs, files in os.walk(self.examples_dir):
  38. filenames += [os.path.join(root, f) for f in files if f.endswith(".ino")]
  39. filenames.sort()
  40. for e in filenames:
  41. self.examples.append(Sketch(self, e))
  42. filenames = []
  43. for root, dirs, files in os.walk(self.tests_dir):
  44. filenames += [os.path.join(root, f) for f in files if f.endswith(".ino")]
  45. filenames.sort()
  46. for e in filenames:
  47. self.tests.append(Sketch(self, e))
  48. def clean(self):
  49. shutil.rmtree(self.build_dir)
  50. class Sketch(object):
  51. def __init__(self, wksp, fn):
  52. self.w = wksp
  53. self.filename = fn
  54. self.basename = os.path.basename(self.filename)
  55. self.build_log = os.path.join(self.w.log_dir, "%s.log" % (os.path.basename(self.filename),))
  56. self.build_err_log = os.path.join(self.w.log_dir, "%s.err.log" % (os.path.basename(self.filename),))
  57. self.build_upload_log = os.path.join(self.w.log_dir, "%s.upload.log" % (os.path.basename(self.filename),))
  58. def build(self):
  59. sys.stdout.write(" Build: ")
  60. sys.stdout.flush()
  61. # Copy sketch over, replacing IP addresses as necessary
  62. fin = open(self.filename, "r")
  63. lines = fin.readlines()
  64. fin.close()
  65. fout = open(os.path.join(self.w.build_dir, "src", "sketch.ino"), "w")
  66. for l in lines:
  67. if re.match(r"^byte server\[\] = {", l):
  68. fout.write("byte server[] = { %s };\n" % (settings.server_ip.replace(".", ", "),))
  69. elif re.match(r"^byte ip\[\] = {", l):
  70. fout.write("byte ip[] = { %s };\n" % (settings.arduino_ip.replace(".", ", "),))
  71. else:
  72. fout.write(l)
  73. fout.flush()
  74. fout.close()
  75. # Run build
  76. fout = open(self.build_log, "w")
  77. ferr = open(self.build_err_log, "w")
  78. rc = call(["ino", "build"], stdout=fout, stderr=ferr)
  79. fout.close()
  80. ferr.close()
  81. if rc == 0:
  82. sys.stdout.write("pass")
  83. sys.stdout.write("\n")
  84. return True
  85. else:
  86. sys.stdout.write("fail")
  87. sys.stdout.write("\n")
  88. with open(self.build_err_log) as f:
  89. for line in f:
  90. print(" " + line)
  91. return False
  92. def upload(self):
  93. sys.stdout.write(" Upload: ")
  94. sys.stdout.flush()
  95. fout = open(self.build_upload_log, "w")
  96. rc = call(["ino", "upload"], stdout=fout, stderr=fout)
  97. fout.close()
  98. if rc == 0:
  99. sys.stdout.write("pass")
  100. sys.stdout.write("\n")
  101. return True
  102. else:
  103. sys.stdout.write("fail")
  104. sys.stdout.write("\n")
  105. with open(self.build_upload_log) as f:
  106. for line in f:
  107. print(" " + line)
  108. return False
  109. def test(self):
  110. # import the matching test case, if it exists
  111. try:
  112. basename = os.path.basename(self.filename)[:-4]
  113. i = importlib.import_module("testcases." + basename)
  114. except:
  115. sys.stdout.write(" Test: no tests found")
  116. sys.stdout.write("\n")
  117. return
  118. c = getattr(i, basename)
  119. testmethods = [m for m in dir(c) if m.startswith("test_")]
  120. testmethods.sort()
  121. tests = []
  122. for m in testmethods:
  123. tests.append(c(m))
  124. result = unittest.TestResult()
  125. c.setUpClass()
  126. if self.upload():
  127. sys.stdout.write(" Test: ")
  128. sys.stdout.flush()
  129. for t in tests:
  130. t.run(result)
  131. print(str(result.testsRun - len(result.failures) - len(result.errors)) + "/" + str(result.testsRun))
  132. if not result.wasSuccessful():
  133. if len(result.failures) > 0:
  134. for f in result.failures:
  135. print("-- " + str(f[0]))
  136. print(f[1])
  137. if len(result.errors) > 0:
  138. print(" Errors:")
  139. for f in result.errors:
  140. print("-- " + str(f[0]))
  141. print(f[1])
  142. c.tearDownClass()
  143. if __name__ == '__main__':
  144. run_tests = True
  145. w = Workspace()
  146. w.init()
  147. for e in w.examples:
  148. print("--------------------------------------")
  149. print("[" + e.basename + "]")
  150. if e.build() and run_tests:
  151. e.test()
  152. for e in w.tests:
  153. print("--------------------------------------")
  154. print("[" + e.basename + "]")
  155. if e.build() and run_tests:
  156. e.test()
  157. w.clean()