From 99b811fa7093c45c807a66721cc0a3328307932f Mon Sep 17 00:00:00 2001 From: Fabrice Reix Date: Fri, 12 Feb 2021 13:22:46 +0100 Subject: [PATCH 1/2] Run Tests integ in windows Decode hurlfmt output and error stream as text supports both UTF-8 and UTF-16, both with and with BOM Add optional os-specific expected error file --- contrib/windows/powershell_build.md | 12 +++- integration/integration.py | 16 ++++-- .../error_self_signed_certificate.windows.err | 6 ++ integration/test_echo.py | 12 +++- integration/test_format.py | 15 ++++- integration/test_hurl.py | 57 +++++++++++++++---- integration/test_lint.py | 15 ++++- integration/tests/color.options | 2 +- .../tests/error_file_read_access.windows.err | 7 +++ .../error_multipart_form_data.windows.err | 7 +++ packages/hurl/tests/libcurl.rs | 12 ++-- 11 files changed, 130 insertions(+), 31 deletions(-) create mode 100644 integration/ssl/error_self_signed_certificate.windows.err create mode 100644 integration/tests/error_file_read_access.windows.err create mode 100644 integration/tests/error_multipart_form_data.windows.err diff --git a/contrib/windows/powershell_build.md b/contrib/windows/powershell_build.md index fc524ccb7..8272d804b 100644 --- a/contrib/windows/powershell_build.md +++ b/contrib/windows/powershell_build.md @@ -39,6 +39,7 @@ $env:VCPKGRS_DYNAMIC = [System.Environment]::GetEnvironmentVariable("VCPKGRS_DYN ## Clone hurl project ```powershell +git.exe config --global core.autocrlf false git.exe clone https://github.com/Orange-OpenSource/hurl ``` @@ -74,6 +75,14 @@ cd c:\hurl\integration python server.py ``` +Keep original powershell prompt on background, and open one more separate powershell prompt to launch the ssl server + +```powershell +cd c:\hurl\integration +python ssl/server.py +``` + + Keep original powershell prompt on background, and open one more separate powershell prompt to launch the proxy ```powershell @@ -90,7 +99,8 @@ cargo test --verbose launch hurl integration tests ```powershell -coming soon ... ;) +cd c:\hurl\integration +./integration.py ``` ## Generate version.txt file diff --git a/integration/integration.py b/integration/integration.py index 6b26d0a25..b629eb04d 100755 --- a/integration/integration.py +++ b/integration/integration.py @@ -6,16 +6,20 @@ import test_lint import test_format import test_hurl + +def get_files(glob_expr): + return sorted([f.replace('\\', '/') for f in glob.glob(glob_expr)]) + def main(): # Static run (without server) - [test_echo.test(f) for f in sorted(glob.glob('tests/*.hurl') + glob.glob('tests_error_lint/*.hurl'))] - [test_format.test('json', f) for f in sorted(glob.glob('tests/*.hurl'))] - [test_format.test('html', f) for f in sorted(glob.glob('tests/*.hurl'))] - [test_lint.test(f) for f in sorted(glob.glob('tests_error_lint/*.hurl'))] - [test_hurl.test(f) for f in sorted(glob.glob('tests_error_parser/*.hurl'))] + [test_echo.test(f) for f in get_files('tests/*.hurl') + get_files('tests_error_lint/*.hurl')] + [test_format.test('json', f) for f in get_files('tests/*.hurl')] + [test_format.test('html', f) for f in get_files('tests/*.hurl')] + [test_lint.test(f) for f in get_files('tests_error_lint/*.hurl')] + [test_hurl.test(f) for f in get_files('tests_error_parser/*.hurl')] # Dynamic run (with server) - [test_hurl.test(f) for f in sorted(glob.glob('tests/*.hurl')) + sorted(glob.glob('ssl/*.hurl'))] + [test_hurl.test(f) for f in get_files('tests/*.hurl') + get_files('ssl/*.hurl')] print('test integration ok!') diff --git a/integration/ssl/error_self_signed_certificate.windows.err b/integration/ssl/error_self_signed_certificate.windows.err new file mode 100644 index 000000000..c277e25ec --- /dev/null +++ b/integration/ssl/error_self_signed_certificate.windows.err @@ -0,0 +1,6 @@ +error: SSL Certificate + --> ssl/error_self_signed_certificate.hurl:1:5 + | + 1 | GET https://localhost:8001/hello + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ schannel: SEC_E_UNTRUSTED_ROOT (0x80090325) + | diff --git a/integration/test_echo.py b/integration/test_echo.py index a52814e6c..5c00ae3f9 100755 --- a/integration/test_echo.py +++ b/integration/test_echo.py @@ -6,12 +6,22 @@ import sys import subprocess import codecs +def decode_string(encoded): + if encoded.startswith(codecs.BOM_UTF8): + return encoded.decode('utf-8-sig') + elif encoded.startswith(codecs.BOM_UTF16): + encoded = encoded[len(codecs.BOM_UTF16):] + return encoded.decode('utf-16') + else: + return encoded.decode() + + def test(hurl_file): cmd = ['hurlfmt', '--no-format', hurl_file] print(' '.join(cmd)) result = subprocess.run(cmd, stdout=subprocess.PIPE) expected = codecs.open(hurl_file, encoding='utf-8-sig').read() # Input file can be saved with a BOM - actual = result.stdout.decode("utf-8") + actual = decode_string(result.stdout) if actual != expected: print('>>> error in stdout') print(f'actual: <{actual}>\nexpected: <{expected}>') diff --git a/integration/test_format.py b/integration/test_format.py index 8969fa5d7..98c3fa55f 100755 --- a/integration/test_format.py +++ b/integration/test_format.py @@ -2,16 +2,27 @@ # echo hurl file # The file is parsed and output exactly as the input # +import codecs import sys import subprocess +def decode_string(encoded): + if encoded.startswith(codecs.BOM_UTF8): + return encoded.decode('utf-8-sig') + elif encoded.startswith(codecs.BOM_UTF16): + encoded = encoded[len(codecs.BOM_UTF16):] + return encoded.decode('utf-16') + else: + return encoded.decode() + + def test(format_type, hurl_file): cmd = ['hurlfmt', '--format', format_type, hurl_file] print(' '.join(cmd)) result = subprocess.run(cmd, stdout=subprocess.PIPE) json_file = hurl_file.replace('.hurl','.' + format_type) - expected = open(json_file).read().strip() - actual = result.stdout.decode("utf-8").strip() + expected = open(json_file, encoding='utf-8').read().strip() + actual = decode_string(result.stdout) if actual != expected: print('>>> error in stdout') print(f'actual: <{actual}>\nexpected: <{expected}>') diff --git a/integration/test_hurl.py b/integration/test_hurl.py index 29e064aef..d928e1dd3 100755 --- a/integration/test_hurl.py +++ b/integration/test_hurl.py @@ -1,9 +1,34 @@ #!/usr/bin/env python3 # test hurl file # +import codecs import sys import subprocess import os +import platform + + +def decode_string(encoded): + if encoded.startswith(codecs.BOM_UTF8): + return encoded.decode('utf-8-sig') + elif encoded.startswith(codecs.BOM_UTF16): + encoded = encoded[len(codecs.BOM_UTF16):] + return encoded.decode('utf-16') + else: + return encoded.decode() + + +# return linux, osx or windows +def get_os(): + if platform.system() == 'Linux': + return 'linux' + elif platform.system() == 'Darwin': + return 'osx' + elif platform.system() == 'Windows': + return 'windows' + else: + raise Error('Invalid Platform ' + platform.system()) + def test(hurl_file): @@ -21,29 +46,37 @@ def test(hurl_file): expected = int(open(f).read().strip()) if result.returncode != expected: print('>>> error in return code') - print('expected: {expected} actual:{result.returncode}') + print(f'expected: {expected} actual:{result.returncode}') sys.exit(1) # stdout f = hurl_file.replace('.hurl','.out') if os.path.exists(f): expected = open(f, 'rb').read() - actual = result.stdout + actual = result.stdout if expected != actual: print('>>> error in stdout') print(f'actual: <{actual}>\nexpected: <{expected}>') sys.exit(1) - - # stderr - f = hurl_file.replace('.hurl','.err') - if os.path.exists(f): - expected = open(f).read().strip() - actual = result.stderr.decode("utf-8").strip() - if expected != actual: - print('>>> error in stderr') - print(f'actual: <{actual}>\nexpected: <{expected}>') - sys.exit(1) + # stderr + f = hurl_file.replace('.hurl', '.' + get_os() + '.err') + if os.path.exists(f): + expected = open(f).read().strip() + actual = decode_string(result.stderr).strip() + if expected != actual: + print('>>> error in stderr') + print(f'actual: <{actual}>\nexpected: <{expected}>') + sys.exit(1) + else: + f = hurl_file.replace('.hurl', '.err') + if os.path.exists(f): + expected = open(f).read().strip() + actual = decode_string(result.stderr).strip() + if expected != actual: + print('>>> error in stderr') + print(f'actual: <{actual}>\nexpected: <{expected}>') + sys.exit(1) def main(): for hurl_file in sys.argv[1:]: diff --git a/integration/test_lint.py b/integration/test_lint.py index a0021659f..19b8b3096 100755 --- a/integration/test_lint.py +++ b/integration/test_lint.py @@ -1,9 +1,20 @@ #!/usr/bin/env python3 # lint hurl file # +import codecs import sys import subprocess +def decode_string(encoded): + if encoded.startswith(codecs.BOM_UTF8): + return encoded.decode('utf-8-sig') + elif encoded.startswith(codecs.BOM_UTF16): + encoded = encoded[len(codecs.BOM_UTF16):] + return encoded.decode('utf-16') + else: + return encoded.decode() + + def test(hurl_file): cmd = ['hurlfmt', '--check', hurl_file] print(' '.join(cmd)) @@ -14,7 +25,7 @@ def test(hurl_file): err_file = hurl_file.replace('.hurl','.err') expected = open(err_file).read().strip() - actual = result.stderr.decode("utf-8").strip() + actual = decode_string(result.stderr).strip() if actual != expected: print('>>> error in stderr') print(f'actual: <{actual}>\nexpected: <{expected}>') @@ -25,7 +36,7 @@ def test(hurl_file): result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) err_file = hurl_file.replace('.hurl','.hurl.lint') expected = open(err_file).read().strip() - actual = result.stdout.decode("utf-8").strip() + actual = decode_string(result.stdout).strip() if actual != expected: print('>>> error in stdout') print(f'actual: <{actual}>\nexpected: <{expected}>') diff --git a/integration/tests/color.options b/integration/tests/color.options index 5052887a0..4e1e0d2f7 100644 --- a/integration/tests/color.options +++ b/integration/tests/color.options @@ -1 +1 @@ ---color \ No newline at end of file +--color diff --git a/integration/tests/error_file_read_access.windows.err b/integration/tests/error_file_read_access.windows.err new file mode 100644 index 000000000..8b39ff8ae --- /dev/null +++ b/integration/tests/error_file_read_access.windows.err @@ -0,0 +1,7 @@ +error: File ReadAccess + --> tests/error_file_read_access.hurl:2:6 + | + 2 | file,does_not_exist; + | ^^^^^^^^^^^^^^ File tests\does_not_exist can not be read + | + diff --git a/integration/tests/error_multipart_form_data.windows.err b/integration/tests/error_multipart_form_data.windows.err new file mode 100644 index 000000000..5a98de120 --- /dev/null +++ b/integration/tests/error_multipart_form_data.windows.err @@ -0,0 +1,7 @@ +error: File ReadAccess + --> tests/error_multipart_form_data.hurl:4:15 + | + 4 | upload1: file,unknown; + | ^^^^^^^ File tests\unknown can not be read + | + diff --git a/packages/hurl/tests/libcurl.rs b/packages/hurl/tests/libcurl.rs index 86d85bf83..cb573f5ce 100644 --- a/packages/hurl/tests/libcurl.rs +++ b/packages/hurl/tests/libcurl.rs @@ -537,12 +537,12 @@ fn test_error_ssl() { let mut client = Client::init(options); let request = default_get_request("https://localhost:8001/hello".to_string()); let error = client.execute(&request, 0).err().unwrap(); - assert_eq!( - error, - HttpError::SSLCertificate(Some( - "SSL certificate problem: self signed certificate".to_string() - )) - ); + let message = if cfg!(windows) { + "schannel: SEC_E_UNTRUSTED_ROOT (0x80090325)".to_string() + } else { + "SSL certificate problem: self signed certificate".to_string() + }; + assert_eq!(error, HttpError::SSLCertificate(Some(message))); } #[test] From e21bbea974dd970bc84eb9c4d078ed25e9c179ad Mon Sep 17 00:00:00 2001 From: lepapareil Date: Sat, 20 Feb 2021 19:53:11 +0100 Subject: [PATCH 2/2] add integration test in win contrib docs --- contrib/windows/cmd_build.md | 12 ++++++++++-- contrib/windows/powershell_build.md | 4 ++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/contrib/windows/cmd_build.md b/contrib/windows/cmd_build.md index f3e68ab2d..67b404dd8 100644 --- a/contrib/windows/cmd_build.md +++ b/contrib/windows/cmd_build.md @@ -76,6 +76,13 @@ cd c:\hurl\integration start /B server.py ``` +launch the ssl server + +```cmd +cd c:\hurl\integration +start /B ssl/server.py +``` + launch hurl unit tests ```cmd @@ -85,8 +92,9 @@ cargo test launch hurl integration tests -``` -coming soon ... ;) +```cmd +cd c:\hurl\integration +./integration.py ``` ## Generate version.txt file diff --git a/contrib/windows/powershell_build.md b/contrib/windows/powershell_build.md index 8272d804b..0a73a30b0 100644 --- a/contrib/windows/powershell_build.md +++ b/contrib/windows/powershell_build.md @@ -58,6 +58,10 @@ New-Item -ItemType "Directory" -Path "c:\hurl\target" -Name "win-package" Get-ChildItem -Path "c:\hurl\target\release" -Recurse -Include *.dll -File | Copy-Item -Destination "c:\hurl\target\win-package" Get-ChildItem -Path "c:\hurl\target\release" -Recurse -Include hurl*.exe -File | Copy-Item -Destination "c:\hurl\target\win-package" ((c:\hurl\target\win-package\hurl.exe --version) -Split " ")[1] > c:\hurl\target\win-package\version.txt +$oldpath = Get-ItemProperty -Path HKCU:\Environment -Name Path +$newpath = $oldpath.Path += ";c:\hurl\target\win-package" +Set-ItemProperty -Path HKCU:\Environment -Name Path -Value $newpath +$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") ``` ## Test your app