For the start just basic uclient-fetch functionality coverage.
Signed-off-by: Petr Štetiar <ynezz@true.cz>
FIND_LIBRARY(ubox_library NAMES ubox)
ENDIF(BUILD_STATIC)
-ADD_LIBRARY(uclient SHARED uclient.c uclient-http.c uclient-utils.c)
+SET(LIB_SOURCES uclient.c uclient-http.c uclient-utils.c)
+ADD_LIBRARY(uclient SHARED ${LIB_SOURCES})
TARGET_LINK_LIBRARIES(uclient ${ubox_library} dl)
-ADD_EXECUTABLE(uclient-fetch uclient-fetch.c progress.c)
+SET(CLI_SOURCES uclient-fetch.c progress.c)
+ADD_EXECUTABLE(uclient-fetch ${CLI_SOURCES})
TARGET_LINK_LIBRARIES(uclient-fetch uclient)
+IF(UNIT_TESTING)
+ ADD_DEFINITIONS(-DUNIT_TESTING)
+ ENABLE_TESTING()
+ ADD_SUBDIRECTORY(tests)
+
+ IF(CMAKE_C_COMPILER_ID STREQUAL "Clang")
+ ADD_LIBRARY(uclient-san SHARED ${LIB_SOURCES})
+ TARGET_COMPILE_OPTIONS(uclient-san PRIVATE -g -fno-omit-frame-pointer -fsanitize=undefined,address,leak -fno-sanitize-recover=all)
+ TARGET_LINK_OPTIONS(uclient-san PRIVATE -fsanitize=undefined,address,leak)
+ TARGET_LINK_LIBRARIES(uclient-san ${ubox_library} dl)
+
+ ADD_EXECUTABLE(uclient-fetch-san ${CLI_SOURCES})
+ TARGET_COMPILE_OPTIONS(uclient-fetch-san PRIVATE -g -fno-omit-frame-pointer -fsanitize=undefined,address,leak -fno-sanitize-recover=all)
+ TARGET_LINK_OPTIONS(uclient-fetch-san PRIVATE -fsanitize=undefined,address,leak)
+ TARGET_LINK_LIBRARIES(uclient-fetch-san uclient-san ${ubox_library} dl)
+ ENDIF()
+ENDIF()
+
INSTALL(FILES uclient.h uclient-utils.h
DESTINATION include/libubox
)
--- /dev/null
+ADD_SUBDIRECTORY(cram)
--- /dev/null
+FIND_PACKAGE(PythonInterp 3 REQUIRED)
+FILE(GLOB test_cases "test_*.t")
+
+IF(CMAKE_C_COMPILER_ID STREQUAL "Clang")
+ FILE(GLOB test_cases_san "test-san_*.t")
+ENDIF()
+
+SET(PYTHON_VENV_DIR "${CMAKE_CURRENT_BINARY_DIR}/.venv")
+SET(PYTHON_VENV_PIP "${PYTHON_VENV_DIR}/bin/pip")
+SET(PYTHON_VENV_CRAM "${PYTHON_VENV_DIR}/bin/cram")
+
+ADD_CUSTOM_COMMAND(
+ OUTPUT ${PYTHON_VENV_CRAM}
+ COMMAND ${PYTHON_EXECUTABLE} -m venv ${PYTHON_VENV_DIR}
+ COMMAND ${PYTHON_VENV_PIP} install cram
+)
+ADD_CUSTOM_TARGET(prepare-cram-venv ALL DEPENDS ${PYTHON_VENV_CRAM})
+
+ADD_CUSTOM_TARGET(
+ http-server-kill ALL
+ COMMAND pkill --full -9 "${PYTHON_VENV_DIR}/bin/python3 -m http.server 1922 --bind 127.0.0.1" > /dev/null 2>&1 || true
+ DEPENDS ${PYTHON_VENV_CRAM}
+)
+
+ADD_CUSTOM_TARGET(
+ http-server ALL
+ COMMAND ${PYTHON_VENV_DIR}/bin/python3 -m http.server 1922 --bind 127.0.0.1 > /dev/null 2>&1 &
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/server
+ DEPENDS http-server-kill
+)
+
+ADD_TEST(
+ NAME cram
+ COMMAND ${PYTHON_VENV_CRAM} ${test_cases} ${test_cases_san}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+SET_PROPERTY(TEST cram APPEND PROPERTY ENVIRONMENT "BUILD_BIN_DIR=$<TARGET_FILE_DIR:uclient-fetch>")
--- /dev/null
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas accumsan dui
+diam, sit amet vehicula nisl tincidunt non. Duis orci urna, luctus porttitor
+viverra non, interdum id erat. Vivamus in tortor eu augue dignissim imperdiet
+vitae ut ligula. Nunc luctus arcu viverra dolor commodo, et pellentesque
+lectus convallis. Donec molestie gravida venenatis. Curabitur vitae nulla at
+nisi ullamcorper sagittis vitae eget arcu. Sed elementum neque metus, in
+sollicitudin lorem vestibulum sed. Etiam non leo id eros ultrices hendrerit.
+
+Etiam sed luctus lacus. Fusce congue quam varius, cursus enim id, varius
+tellus. Suspendisse at mauris blandit, tempor urna non, pharetra tortor. In
+laoreet turpis a sollicitudin auctor. Duis semper diam mi, at mollis dolor
+tristique a. Sed sed mauris diam. Curabitur vel eleifend lorem. Quisque vel
+erat ac nulla vestibulum elementum. Curabitur euismod mauris lorem, at
+vestibulum justo accumsan eget. Proin pharetra scelerisque est, eget lobortis
+nulla. Ut sit amet tellus pellentesque, fermentum erat vitae, euismod risus.
+Vivamus sed nibh ut neque efficitur lacinia hendrerit accumsan leo.
+Suspendisse feugiat molestie suscipit.
+
+Sed mattis elit non nibh interdum, eu volutpat sem euismod. Nullam eu nibh id
+ligula semper molestie quis at nisi. Nulla vulputate, risus vitae vulputate
+dapibus, ligula erat volutpat dui, in condimentum tortor sapien et eros. Cras
+sed est consectetur, iaculis est a, ultricies felis. Phasellus dignissim neque
+quis urna aliquam, at consequat turpis rutrum. Ut gravida dolor nisi, et
+aliquam massa fermentum sit amet. In eu odio vel libero suscipit dignissim et
+ac justo. Morbi quis sollicitudin elit. Etiam varius vel odio ac dapibus. Sed
+ut lorem auctor, scelerisque lacus sit amet, ultrices lorem. Mauris dui
+mauris, sagittis id fermentum vitae, tincidunt vel sem. Morbi viverra erat
+nulla, et pharetra mauris condimentum maximus. Nam orci ex, semper nec rutrum
+sed, gravida lobortis nisl.
+
+Vivamus eleifend ligula leo, a sodales augue blandit eget. Sed varius molestie
+neque vel placerat. Nam volutpat sodales metus, et blandit ipsum vulputate et.
+Quisque eget quam sit amet nisl blandit varius in ac neque. Pellentesque
+habitant morbi tristique senectus et netus et malesuada fames ac turpis
+egestas. Donec ultricies mattis porta. Pellentesque in sollicitudin lacus.
+
+Duis quis dui consequat lacus ullamcorper pretium at eget justo. Mauris
+placerat dui vel augue rutrum luctus. Fusce mi purus, faucibus nec euismod sit
+amet, condimentum sed sem. Ut dictum arcu et eros volutpat, et gravida erat
+ultricies. Nam auctor, augue vitae cursus tempor, nisi lacus hendrerit massa,
+a varius mauris est sit amet sapien. Cras ac varius turpis. Ut vitae ligula
+neque. Cras nec felis ut orci accumsan maximus. Maecenas sed tempus magna.
+
+Sed metus risus, eleifend vitae viverra nec, volutpat vitae velit. Vivamus
+sodales porttitor urna, quis hendrerit est tempus nec. Mauris ligula ex,
+commodo vitae odio vel, volutpat lacinia libero. Nulla facilisis, ex sit amet
+rhoncus cursus, purus turpis condimentum mi, ac euismod tellus elit eu felis.
+Sed ultrices dolor pulvinar, laoreet lacus in, viverra arcu. Pellentesque a
+turpis felis. Morbi ornare nunc a hendrerit elementum.
+
+Sed laoreet dictum consequat. Maecenas et scelerisque justo, et vulputate
+diam. Vivamus nec erat quis nunc rutrum consectetur. Sed venenatis orci
+ligula, nec luctus massa tristique non. Etiam porta, nunc scelerisque bibendum
+tincidunt, mauris libero consequat odio, eu tempus neque augue eget massa.
+Nulla eu risus fermentum, ornare ipsum a, blandit nulla. Mauris in tempus
+quam, eu rutrum risus. Nunc maximus fringilla ante, et suscipit mi dictum
+laoreet. In sed ligula dictum, maximus neque ut, tincidunt mauris. Sed
+ultricies mauris in neque semper, eu congue nisl ullamcorper. Aliquam ac
+aliquam arcu.
+
+Nulla ante sapien, egestas at mattis vel, vehicula vitae urna. In tempus at
+nibh consequat scelerisque. Etiam interdum placerat erat ut finibus. Sed
+fermentum dignissim ligula, quis vehicula nulla faucibus aliquam. Cras elit
+lacus, porta ut vehicula eget orci aliquam.
--- /dev/null
+check uclient-fetch usage:
+
+ $ [ -n "$BUILD_BIN_DIR" ] && export PATH="$BUILD_BIN_DIR:$PATH"
+ $ alias uc='uclient-fetch-san'
+
+ $ uc
+ Usage: uclient-fetch-san [options] <URL>
+ Options:
+ \t-4\t\t\t\tUse IPv4 only (esc)
+ \t-6\t\t\t\tUse IPv6 only (esc)
+ \t-q\t\t\t\tTurn off status messages (esc)
+ \t-O <file>\t\t\tRedirect output to file (use "-" for stdout) (esc)
+ \t-P <dir>\t\t\tSet directory for output files (esc)
+ \t--user=<user>\t\t\tHTTP authentication username (esc)
+ \t--password=<password>\t\tHTTP authentication password (esc)
+ \t--user-agent|-U <str>\t\tSet HTTP user agent (esc)
+ \t--post-data=STRING\t\tuse the POST method; send STRING as the data (esc)
+ \t--post-file=FILE\t\tuse the POST method; send FILE as the data (esc)
+ \t--spider|-s\t\t\tSpider mode - only check file existence (esc)
+ \t--timeout=N|-T N\t\tSet connect/request timeout to N seconds (esc)
+ \t--proxy=on|off|-Y on|off\tEnable/disable env var configured proxy (esc)
+
+ HTTPS options:
+ \t--ca-certificate=<cert>\t\tLoad CA certificates from file <cert> (esc)
+ \t--no-check-certificate\t\tdon't validate the server's certificate (esc)
+ \t--ciphers=<cipherlist>\t\tSet the cipher list string (esc)
+
+ [1]
+
+download lorem ipsum verbose:
+
+ $ uc -O lorem http://127.0.0.1:1922/lorem
+ Downloading 'http://127.0.0.1:1922/lorem'
+ Connecting to 127.0.0.1:1922
+ Writing to 'lorem'
+ \r (no-eol) (esc)
+ lorem 100% |*******************************| 4111 0:00:00 ETA
+ Download completed (4111 bytes)
+
+ $ md5sum lorem
+ 887943f7c25bd6cec4570c405241b425 lorem
+
+download lorem ipsum quiet:
+
+ $ uc -q -O lorem http://127.0.0.1:1922/lorem
+
+ $ md5sum lorem
+ 887943f7c25bd6cec4570c405241b425 lorem
+
+check that HTTP 404 errors are handled properly:
+
+ $ uc http://127.0.0.1:1922/does-not-exist
+ Downloading 'http://127.0.0.1:1922/does-not-exist'
+ Connecting to 127.0.0.1:1922
+ HTTP error 404
+ [8]
+
+ $ uc -q http://127.0.0.1:1922/does-not-exist
+ [8]
+
+check that SSL works:
+
+ $ uc -q -O /dev/null 'https://www.openwrt.org'
+
+ $ uc -O /dev/null 'https://downloads.openwrt.org/does-not-exist' 2>&1 | grep error
+ HTTP error 404
+
+check handling of certificate issues:
+
+ $ uc -O /dev/null 'https://self-signed.badssl.com/' 2>&1 | grep error
+ Connection error: Invalid SSL certificate
+
+ $ uc -O /dev/null 'https://untrusted-root.badssl.com/' 2>&1 | grep error
+ Connection error: Invalid SSL certificate
+
+ $ uc -O /dev/null 'https://expired.badssl.com/' 2>&1 | grep error
+ Connection error: Invalid SSL certificate
+
+ $ uc --ca-certificate=/dev/null -O /dev/null 'https://www.openwrt.org/' 2>&1 | grep error
+ Connection error: Invalid SSL certificate
+
+check that certificate issues can be disabled:
+
+ $ uc --no-check-certificate -q -O /dev/null 'https://self-signed.badssl.com/'
+
+ $ uc --no-check-certificate -q -O /dev/null 'https://untrusted-root.badssl.com/'
+
+ $ uc --no-check-certificate -q -O /dev/null 'https://expired.badssl.com/'
--- /dev/null
+check uclient-fetch usage:
+
+ $ [ -n "$BUILD_BIN_DIR" ] && export PATH="$BUILD_BIN_DIR:$PATH"
+ $ alias uc='valgrind --quiet --leak-check=full uclient-fetch'
+
+ $ uc
+ Usage: uclient-fetch [options] <URL>
+ Options:
+ \t-4\t\t\t\tUse IPv4 only (esc)
+ \t-6\t\t\t\tUse IPv6 only (esc)
+ \t-q\t\t\t\tTurn off status messages (esc)
+ \t-O <file>\t\t\tRedirect output to file (use "-" for stdout) (esc)
+ \t-P <dir>\t\t\tSet directory for output files (esc)
+ \t--user=<user>\t\t\tHTTP authentication username (esc)
+ \t--password=<password>\t\tHTTP authentication password (esc)
+ \t--user-agent|-U <str>\t\tSet HTTP user agent (esc)
+ \t--post-data=STRING\t\tuse the POST method; send STRING as the data (esc)
+ \t--post-file=FILE\t\tuse the POST method; send FILE as the data (esc)
+ \t--spider|-s\t\t\tSpider mode - only check file existence (esc)
+ \t--timeout=N|-T N\t\tSet connect/request timeout to N seconds (esc)
+ \t--proxy=on|off|-Y on|off\tEnable/disable env var configured proxy (esc)
+
+ HTTPS options:
+ \t--ca-certificate=<cert>\t\tLoad CA certificates from file <cert> (esc)
+ \t--no-check-certificate\t\tdon't validate the server's certificate (esc)
+ \t--ciphers=<cipherlist>\t\tSet the cipher list string (esc)
+
+ [1]
+
+download lorem ipsum verbose:
+
+ $ uc -O lorem http://127.0.0.1:1922/lorem
+ Downloading 'http://127.0.0.1:1922/lorem'
+ Connecting to 127.0.0.1:1922
+ Writing to 'lorem'
+ \r (no-eol) (esc)
+ lorem 100% |*******************************| 4111 0:00:00 ETA
+ Download completed (4111 bytes)
+
+ $ md5sum lorem
+ 887943f7c25bd6cec4570c405241b425 lorem
+
+download lorem ipsum quiet:
+
+ $ uc -q -O lorem http://127.0.0.1:1922/lorem
+
+ $ md5sum lorem
+ 887943f7c25bd6cec4570c405241b425 lorem
+
+check that HTTP 404 errors are handled properly:
+
+ $ uc http://127.0.0.1:1922/does-not-exist
+ Downloading 'http://127.0.0.1:1922/does-not-exist'
+ Connecting to 127.0.0.1:1922
+ HTTP error 404
+ [8]
+
+ $ uc -q http://127.0.0.1:1922/does-not-exist
+ [8]
+
+check that SSL works:
+
+ $ uc -q -O /dev/null 'https://www.openwrt.org'
+
+ $ uc -O /dev/null 'https://downloads.openwrt.org/does-not-exist' 2>&1 | grep error
+ HTTP error 404
+
+check handling of certificate issues:
+
+ $ uc -O /dev/null 'https://self-signed.badssl.com/' 2>&1 | grep error
+ Connection error: Invalid SSL certificate
+
+ $ uc -O /dev/null 'https://untrusted-root.badssl.com/' 2>&1 | grep error
+ Connection error: Invalid SSL certificate
+
+ $ uc -O /dev/null 'https://expired.badssl.com/' 2>&1 | grep error
+ Connection error: Invalid SSL certificate
+
+ $ uc --ca-certificate=/dev/null -O /dev/null 'https://www.openwrt.org/' 2>&1 | grep error
+ Connection error: Invalid SSL certificate
+
+check that certificate issues can be disabled:
+
+ $ uc --no-check-certificate -q -O /dev/null 'https://self-signed.badssl.com/'
+
+ $ uc --no-check-certificate -q -O /dev/null 'https://untrusted-root.badssl.com/'
+
+ $ uc --no-check-certificate -q -O /dev/null 'https://expired.badssl.com/'