diff --git a/README.md b/README.md index 116f63ff44..0725c4a35b 100644 --- a/README.md +++ b/README.md @@ -982,14 +982,13 @@ Exiv2 optionally uses several different environment variables when building or t | Variable | Default | Platforms | Purpose | |:-- |:-- |:-- |:-- | | EXIV2_BINDIR | **\/build/bin** | All Platforms | Path of built binaries (e.g., exiv2.exe) | -| EXIV2_PORT | **12762**
**12671**
**12760** | Cygwin
MinGW/msys2
Other Platforms | Test TCP/IP Port | | EXIV2_HTTP | **http://localhost** | All Platforms | Test http server | | EXIV2_ECHO | _**not set**_ | All Platforms | For debugging bashTests | | VALGRIND | _**not set**_ | All Platforms | For debugging bashTests | | VERBOSE | _**not set**_ | Makefile platforms | Instructs make to report its actions | | PATH
DYLD\_LIBRARY\_PATH
LD\_LIBRARY\_PATH | $EXIV2\_BINDIR/../lib | Windows
macOS
Other platforms | Path of dynamic libraries | -The Variable EXIV2\_PORT or EXIV2\_HTTP can be set to None to skip http tests. The http server is started with the command `python3 -m http.server $port`. On Windows, you will need to run this manually _**once**_ to authorise the firewall to permit python to use the port. +The Variable EXIV2\_HTTP can be set to None to skip http tests. The http server is started with the command `python3 -m http.server $port`. On Windows, you will need to run this manually _**once**_ to authorise the firewall to permit python to use the port. [TOC](#TOC)
@@ -1071,9 +1070,9 @@ c:\...\exiv2>ctest --test-dir build -C Release If you wish to use an environment variables, use set: ``` -set EXIV2_PORT=54321 +set EXIV2_HTTP="http://127.0.0.1" ctest --test-dir build -C Release --verbose -R bash -set EXIV2_PORT= +set EXIV2_HTTP= ``` [TOC](#TOC) diff --git a/tests/bash_tests/testcases.py b/tests/bash_tests/testcases.py index c366017d5e..1b7de520f4 100644 --- a/tests/bash_tests/testcases.py +++ b/tests/bash_tests/testcases.py @@ -578,17 +578,15 @@ def sniff(*files): return ' '.join(result) exiv2_http = BT.Config.exiv2_http - exiv2_port = BT.Config.exiv2_port - if not exiv2_http or not exiv2_port: - print('Skipped http test. Because of invalid environment variables: EXIV2_HTTP={} EXIV2_PORT={}'.format( - exiv2_http, exiv2_port)) + if not exiv2_http: + print('Skipped http test. Because of invalid environment variables: EXIV2_HTTP={}'.format( + exiv2_http)) return - server_url = f'{exiv2_http}:{exiv2_port}' - server = BT.HttpServer(bind=exiv2_http.lstrip('http://'), - port=exiv2_port, # It can be of type int or str + server = BT.HttpServer(bind=exiv2_http.removeprefix('http://'), work_dir=BT.Config.data_dir) try: server.start() + server_url = f'{exiv2_http}:{server.port}' out = BT.Output() for img in ['table.jpg', 'Reagan.tiff', 'exiv2-bug922a.jpg']: files = ['s0', 's1', 's2', f'{server_url}/{img}'] diff --git a/tests/bash_tests/utils.py b/tests/bash_tests/utils.py index e2e8c793df..0e34cfb9a8 100644 --- a/tests/bash_tests/utils.py +++ b/tests/bash_tests/utils.py @@ -48,10 +48,7 @@ class Config: tmp_dir = os.path.join(exiv2_dir, 'test/tmp') system_name = platform.system() or 'Unknown' # It could be Windows, Linux, etc. exiv2_http = 'http://127.0.0.1' - exiv2_port = '12760' valgrind = '' - if 'EXIV2_PORT' in os.environ: - exiv2_port = os.environ['EXIV2_PORT'] if 'EXIV2_HTTP' in os.environ: exiv2_http = os.environ['EXIV2_HTTP'] if 'VALGRIND' in os.environ: @@ -342,30 +339,49 @@ def error(self, msg): class HttpServer: - def __init__(self, bind='127.0.0.1', port=80, work_dir='.'): + def __init__(self, bind='127.0.0.1', work_dir='.'): self.bind = bind - self.port = int(port) + self.port = -1 self.work_dir = work_dir - def _start(self): + def _start(self, shared_port): """ Equivalent to executing `python3 -m http.server` """ os.chdir(self.work_dir) - server.test(HandlerClass=server.SimpleHTTPRequestHandler, bind=self.bind, port=self.port) + # Loop looking for a free port + for port in range(0x1000,0x10000): + # Share the port number with the parent process + shared_port.value = port + try: + server.test(HandlerClass=server.SimpleHTTPRequestHandler, bind=self.bind, port=port) + except: + continue + shared_port.value = -1 log.error('The HTTP server exits without calling stop()') print(log.to_str()) def start(self): log.info('Starting HTTP server ...') - self.proc = multiprocessing.Process(target=self._start, name=str(self)) + shared_port = multiprocessing.Value('i', -1) + self.proc = multiprocessing.Process(target=self._start, name=str(self), args=(shared_port,)) self.proc.start() - time.sleep(2) - try: - with request.urlopen(f'http://127.0.0.1:{self.port}', timeout=3) as f: - if f.status != 200: - raise RuntimeError() - except Exception as e: - raise RuntimeError(f'Failed to run the HTTP server: {e}') from e - log.info('The HTTP server started') + start_time = time.time() + wait_time = 3 + for i in range(0,30): + self.port = shared_port.value + log.info(f"HTTP server is running on port {self.port}") + try: + with request.urlopen(f'http://{self.bind}:{self.port}', timeout=wait_time) as f: + if f.status != 200: + raise RuntimeError() + log.info('The HTTP server started') + return + except: + # Pause if request.urlopen returned too quickly + delta = start_time + (i+1) * wait_time - time.time() + if delta > 0: + time.sleep(delta) + continue + raise RuntimeError('Failed to run the HTTP server') def stop(self): self.proc.terminate() diff --git a/tests/suite.conf b/tests/suite.conf index 249a97fa93..ab65449ceb 100644 --- a/tests/suite.conf +++ b/tests/suite.conf @@ -7,7 +7,6 @@ exiv2_path: EXIV2_BINDIR dyld_library_path: DYLD_LIBRARY_PATH ld_library_path: LD_LIBRARY_PATH exiv2_http: EXIV2_HTTP -exiv2_port: EXIV2_PORT exiv2_echo: EXIV2_ECHO verbose: VERBOSE valgrind: VALGRIND @@ -17,7 +16,6 @@ exiv2_path: ../build/bin dyld_library_path: ${ENV:exiv2_path}/../lib ld_library_path: ${ENV:exiv2_path}/../lib exiv2_http: http://127.0.0.1 -exiv2_port: 12760 exiv2_echo: verbose: valgrind: diff --git a/tests/system_tests.py b/tests/system_tests.py index a37044021d..2e1fac45b9 100644 --- a/tests/system_tests.py +++ b/tests/system_tests.py @@ -191,7 +191,6 @@ def configure_suite(config_file): BT.Config.data_dir = os.path.abspath(config['paths']['data_path']) BT.Config.tmp_dir = os.path.abspath(config['paths']['tmp_path']) BT.Config.exiv2_http = config['ENV']['exiv2_http'] - BT.Config.exiv2_port = config['ENV']['exiv2_port'] BT.Config.exiv2_echo = config['ENV']['exiv2_echo'] BT.Config.verbose = config['ENV']['verbose'] BT.Config.valgrind = config['ENV']['valgrind']