Mercurial > libervia-backend
comparison tests/e2e/run_e2e.py @ 3498:d78b5eae912a
tests: update following names change
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 16 Apr 2021 18:32:34 +0200 |
parents | 7550ae9cfbac |
children | 8ee0140cc8b6 |
comparison
equal
deleted
inserted
replaced
3497:73e04040d577 | 3498:d78b5eae912a |
---|---|
23 import tempfile | 23 import tempfile |
24 from textwrap import dedent | 24 from textwrap import dedent |
25 from datetime import datetime | 25 from datetime import datetime |
26 import sh | 26 import sh |
27 import io | 27 import io |
28 import re | |
29 import sat_templates | 28 import sat_templates |
30 import libervia | 29 import libervia |
31 from sat.core import exceptions | 30 from sat.core import exceptions |
31 from sat.tools.common import regex | |
32 import yaml | 32 import yaml |
33 try: | 33 try: |
34 from yaml import CLoader as Loader, CDumper as Dumper | 34 from yaml import CLoader as Loader, CDumper as Dumper |
35 except ImportError: | 35 except ImportError: |
36 from yaml import Loader, Dumper | 36 from yaml import Loader, Dumper |
46 dev_mode_inst = dedent("""\ | 46 dev_mode_inst = dedent("""\ |
47 Here is a short script to start working with a logged account: | 47 Here is a short script to start working with a logged account: |
48 | 48 |
49 from helium import * | 49 from helium import * |
50 start_firefox() | 50 start_firefox() |
51 go_to("https://libervia.test:8443/login") | 51 go_to("https://libervia-web.test:8443/login") |
52 write("account1", "login") | 52 write("account1", "login") |
53 write("test", "password") | 53 write("test", "password") |
54 click("log in") | 54 click("log in") |
55 """) | 55 """) |
56 report_buffer = io.StringIO() | 56 report_buffer = io.StringIO() |
57 live_out_buf = [] | |
58 live_err_buf = [] | |
57 | 59 |
58 | 60 |
59 def live_out(data): | 61 def live_out(data): |
60 sys.stdout.write(data) | 62 if live_out_buf: |
63 # we may get bytes when buffer is reached and we are in the middle of an unicode | |
64 # sequence. In this case we buffer it, and print it when it's complete | |
65 if isinstance(data, str): | |
66 data = b''.join(live_out_buf).decode() + data | |
67 live_out_buf.clear() | |
68 else: | |
69 live_out_buf.append(data) | |
70 return | |
71 try: | |
72 sys.stdout.write(data) | |
73 except TypeError: | |
74 live_out_buf.append(data) | |
75 return | |
61 sys.stdout.flush() | 76 sys.stdout.flush() |
62 report_buffer.write(data) | 77 report_buffer.write(data) |
63 | 78 |
64 | 79 |
65 def live_err(data): | 80 def live_err(data): |
66 sys.stderr.write(data) | 81 if live_err_buf: |
82 if isinstance(data, str): | |
83 data = b''.join(live_err_buf).decode() + data | |
84 live_err_buf.clear() | |
85 else: | |
86 live_err_buf.append(data) | |
87 return | |
88 try: | |
89 sys.stderr.write(data) | |
90 except TypeError: | |
91 live_err_buf.append(data) | |
92 return | |
67 sys.stderr.flush() | 93 sys.stderr.flush() |
68 report_buffer.write(data) | 94 report_buffer.write(data) |
69 | 95 |
70 | 96 |
71 def get_opt(opt_name): | 97 def get_opt(opt_name): |
80 return False | 106 return False |
81 | 107 |
82 | 108 |
83 def set_env(override, name, value="1"): | 109 def set_env(override, name, value="1"): |
84 """Set environement variable""" | 110 """Set environement variable""" |
85 environment = override["services"]["sat"].setdefault("environment", {}) | 111 environment = override["services"]["backend"].setdefault("environment", {}) |
86 environment[name] = value | 112 environment[name] = value |
87 | 113 |
114 def write_report_log(path, log_raw, with_ansi=False): | |
115 log_raw = str(log_raw) | |
116 if with_ansi: | |
117 # we save 2 versions: one with ANSI escape codes | |
118 report_ansi = path.with_suffix(".ansi") | |
119 with report_ansi.open('w') as f: | |
120 f.write(log_raw) | |
121 # and one cleaner, without them | |
122 report_log = path.with_suffix(".log") | |
123 with report_log.open('w') as f: | |
124 f.write(regex.RE_ANSI_REMOVE.sub('', log_raw)) | |
125 else: | |
126 report_log = path.with_suffix(".log") | |
127 with report_log.open('w') as f: | |
128 f.write(log_raw) | |
88 | 129 |
89 def use_e2e_env(): | 130 def use_e2e_env(): |
90 visual = get_opt(OPT_VISUAL) | 131 visual = get_opt(OPT_VISUAL) |
91 keep_containers = get_opt(OPT_KEEP_CONTAINERS) | 132 keep_containers = get_opt(OPT_KEEP_CONTAINERS) |
92 keep_profiles = get_opt(OPT_KEEP_PROFILES) | 133 keep_profiles = get_opt(OPT_KEEP_PROFILES) |
103 | 144 |
104 for p in Path.cwd().parents: | 145 for p in Path.cwd().parents: |
105 package_path = p / "sat" | 146 package_path = p / "sat" |
106 docker_path = p / "docker" | 147 docker_path = p / "docker" |
107 if package_path.is_dir() and docker_path.is_dir(): | 148 if package_path.is_dir() and docker_path.is_dir(): |
108 sat_root_path = p | 149 backend_root_path = p |
109 break | 150 break |
110 else: | 151 else: |
111 raise exceptions.NotFound( | 152 raise exceptions.NotFound( |
112 "Can't find root of SàT code, are you sure that you are running the test " | 153 "Can't find root of SàT code, are you sure that you are running the test " |
113 "from the backend repository?" | 154 "from the backend repository?" |
114 ) | 155 ) |
115 | 156 |
116 libervia_path = Path(libervia.__file__).parent.resolve() | 157 libervia_web_path = Path(libervia.__file__).parent.resolve() |
117 libervia_root_path = libervia_path.parent | 158 libervia_web_root_path = libervia_web_path.parent |
118 if (libervia_root_path / ".hg").is_dir(): | 159 if (libervia_web_root_path / ".hg").is_dir(): |
119 libervia_source = libervia_root_path | 160 libervia_web_source = libervia_web_root_path |
120 libervia_target = "/src/libervia" | 161 libervia_web_target = "/src/libervia" |
121 else: | 162 else: |
122 libervia_source = libervia_path | 163 libervia_web_source = libervia_web_path |
123 libervia_target = "/src/libervia/libervia" | 164 libervia_web_target = "/src/libervia/libervia" |
124 | 165 |
125 sat_templates_path = Path(sat_templates.__file__).parent.resolve() | 166 sat_templates_path = Path(sat_templates.__file__).parent.resolve() |
126 sat_templates_root_path = sat_templates_path.parent | 167 sat_templates_root_path = sat_templates_path.parent |
127 if (sat_templates_root_path / ".hg").is_dir(): | 168 if (sat_templates_root_path / ".hg").is_dir(): |
128 sat_templates_source = sat_templates_root_path | 169 sat_templates_source = sat_templates_root_path |
129 sat_templates_target = "/src/sat_templates" | 170 sat_templates_target = "/src/sat_templates" |
130 else: | 171 else: |
131 sat_templates_source = sat_templates_path | 172 sat_templates_source = sat_templates_path |
132 sat_templates_target = "/src/sat_templates/sat_templates" | 173 sat_templates_target = "/src/sat_templates/sat_templates" |
133 | 174 |
134 compose_e2e_path = docker_path / "docker-compose_e2e.yml" | 175 compose_e2e_path = docker_path / "docker-compose-e2e.yml" |
135 if not compose_e2e_path.is_file(): | 176 if not compose_e2e_path.is_file(): |
136 raise exceptions.NotFound('"docker-compose_e2e.yml" file can\'t be found') | 177 raise exceptions.NotFound('"docker-compose-e2e.yml" file can\'t be found') |
137 | 178 |
138 with tempfile.TemporaryDirectory(prefix="sat_test_e2e_") as temp_dir: | 179 with tempfile.TemporaryDirectory(prefix="sat_test_e2e_") as temp_dir: |
139 override_path = Path(temp_dir) / "test_override.yml" | 180 override_path = Path(temp_dir) / "test_override.yml" |
140 override = yaml.load( | 181 override = yaml.load( |
141 dedent(f"""\ | 182 dedent(f"""\ |
142 version: "3.6" | 183 version: "3.6" |
143 services: | 184 services: |
144 sat: | 185 backend: |
145 volumes: | 186 volumes: |
146 - type: bind | 187 - type: bind |
147 source: {sat_root_path} | 188 source: {backend_root_path} |
148 target: /src/sat | 189 target: /src/sat |
149 read_only: true | 190 read_only: true |
150 libervia: | 191 web: |
151 volumes: | 192 volumes: |
152 - type: bind | 193 - type: bind |
153 source: {sat_root_path} | 194 source: {backend_root_path} |
154 target: /src/sat | 195 target: /src/sat |
155 read_only: true | 196 read_only: true |
156 - type: bind | 197 - type: bind |
157 source: {libervia_source} | 198 source: {libervia_web_source} |
158 target: {libervia_target} | 199 target: {libervia_web_target} |
159 read_only: true | 200 read_only: true |
160 - type: bind | 201 - type: bind |
161 source: {sat_templates_source} | 202 source: {sat_templates_source} |
162 target: {sat_templates_target} | 203 target: {sat_templates_target} |
163 read_only: true | 204 read_only: true |
165 ), | 206 ), |
166 Loader=Loader | 207 Loader=Loader |
167 ) | 208 ) |
168 | 209 |
169 if keep_profiles: | 210 if keep_profiles: |
170 set_env(override, "SAT_TEST_E2E_KEEP_PROFILES") | 211 set_env(override, "LIBERVIA_TEST_E2E_KEEP_PROFILES") |
171 | 212 |
172 if visual: | 213 if visual: |
173 set_env(override, "SAT_TEST_E2E_LIBERVIA_NO_HEADLESS") | 214 set_env(override, "LIBERVIA_TEST_E2E_WEB_NO_HEADLESS") |
174 | 215 |
175 if keep_browser: | 216 if keep_browser: |
176 set_env(override, "SAT_TEST_E2E_LIBERVIA_KEEP_BROWSER") | 217 set_env(override, "LIBERVIA_TEST_E2E_WEB_KEEP_BROWSER") |
177 | 218 |
178 with override_path.open("w") as f: | 219 with override_path.open("w") as f: |
179 yaml.dump(override, f, Dumper=Dumper) | 220 yaml.dump(override, f, Dumper=Dumper) |
180 | 221 |
181 docker_compose = sh.docker_compose.bake( | 222 docker_compose = sh.docker_compose.bake( |
182 "-f", compose_e2e_path, "-f", override_path) | 223 "-f", compose_e2e_path, "-f", override_path) |
183 docker_compose.up("-d") | 224 docker_compose.up("-d") |
184 | 225 |
185 p = docker_compose.exec( | 226 p = docker_compose.exec( |
186 "-T", "--workdir", "/src/sat/tests", "sat", | 227 "-T", "--workdir", "/src/sat/tests", "backend", |
187 "pytest", "-o", "cache_dir=/tmp", *sys.argv[1:], color="yes", | 228 "pytest", "-o", "cache_dir=/tmp", *sys.argv[1:], color="yes", |
188 _in=sys.stdin, _out=live_out, _out_bufsize=0, _err=live_err, _err_bufsize=0, | 229 _in=sys.stdin, _out=live_out, _out_bufsize=0, _err=live_err, _err_bufsize=0, |
189 _bg=True | 230 _bg=True |
190 ) | 231 ) |
191 if visual: | 232 if visual: |
192 vnc_port = docker_compose.port("sat", "5900").split(':', 1)[1].strip() | 233 vnc_port = docker_compose.port("backend", "5900").split(':', 1)[1].strip() |
193 p_vnc = sh.vncviewer( | 234 p_vnc = sh.vncviewer( |
194 f"localhost:{vnc_port}", | 235 f"localhost:{vnc_port}", |
195 _bg=True, | 236 _bg=True, |
196 # vncviewer exits with 1 when we send an SIGTERM to it, and it's printed | 237 # vncviewer exits with 1 when we send an SIGTERM to it, and it's printed |
197 # before we can catch it (it's happening in a thread). Thus we set exit | 238 # before we can catch it (it's happening in a thread). Thus we set exit |
202 p_vnc = None | 243 p_vnc = None |
203 | 244 |
204 try: | 245 try: |
205 p.wait() | 246 p.wait() |
206 except sh.ErrorReturnCode as e: | 247 except sh.ErrorReturnCode as e: |
207 sat_cont_id = docker_compose.ps("-q", "sat").strip() | 248 libervia_cont_id = docker_compose.ps("-q", "backend").strip() |
208 report_dest = Path(f"reports_{datetime.now().isoformat()}/") | 249 report_dest = Path(f"report_{datetime.now().isoformat()}/") |
209 # we need to make `report_dest` explicitely local with "./", otherwise | 250 # we need to make `report_dest` explicitely local with "./", otherwise |
210 # docker parse takes it as a container path due to the presence of ":" | 251 # docker parse takes it as a container path due to the presence of ":" |
211 # with `isoformat()`. | 252 # with `isoformat()`. |
212 sh.docker.cp(f"{sat_cont_id}:/reports", f"./{report_dest}") | 253 sh.docker.cp(f"{libervia_cont_id}:/reports", f"./{report_dest}") |
213 # we save 2 versions: one with ANSI escape codes | 254 write_report_log( |
214 report_ansi = report_dest / "report.ansi" | 255 report_dest/"report", |
215 with report_ansi.open('w') as f: | 256 report_buffer.getvalue(), |
216 f.write(report_buffer.getvalue()) | 257 with_ansi=True |
217 # and one without (cf. https://stackoverflow.com/a/14693789) | 258 ) |
218 ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])') | 259 write_report_log( |
219 report_log = report_dest / "report.log" | 260 report_dest/"backend", |
220 with report_log.open('w') as f: | 261 docker_compose.logs("--no-log-prefix", "backend") |
221 f.write(ansi_escape.sub('', report_buffer.getvalue())) | 262 ) |
222 | 263 write_report_log( |
264 report_dest/"web", | |
265 docker_compose.logs("--no-log-prefix", "web") | |
266 ) | |
223 print(f"report saved to {report_dest}") | 267 print(f"report saved to {report_dest}") |
224 sys.exit(e.exit_code) | 268 sys.exit(e.exit_code) |
225 finally: | 269 finally: |
226 if p_vnc is not None and p_vnc.is_alive() and not keep_vnc: | 270 if p_vnc is not None and p_vnc.is_alive() and not keep_vnc: |
227 p_vnc.terminate() | 271 p_vnc.terminate() |