diff options
Diffstat (limited to 'testenv')
89 files changed, 5809 insertions, 0 deletions
diff --git a/testenv/ChangeLog b/testenv/ChangeLog new file mode 100644 index 0000000..b0f81ee --- /dev/null +++ b/testenv/ChangeLog @@ -0,0 +1,576 @@ +2014-11-26 Giuseppe Scrivano <gscrivan@redhat.com> + + * Makefile.am (TESTS): Add Test-redirect-crash.py. + * Test-redirect-crash.py: New File. + +2014-11-26 Tim Ruehsen <tim.ruehsen@gmx.de> + + * Makefile.am: Removed Test-auth-both.py from XFAIL_TESTS + +2014-11-21 Tim Ruehsen <tim.ruehsen@gmx.de> + + * server/http/http_server.py: Fixed typo Blackisted to Blacklisted + +2014-11-19 Darshit Shah <darnir@gmail.com> + + * Test-504.py: Add new test case to show how Wget handles 504 Gateway + Timeouts + * Makefile.am: Add Test-504.py to TESTS + +2014-11-17 Tim Ruehsen <tim.ruehsen@gmx.de> + + * server/http/http_server.py: allow case-insensitive auth-type, + send BasIc and DIgest to provoke Wget failures with turkish locales + +2014-11-15 Darshit Shah <darnir@gmail.com> + + * certs/README: Remove trailing whitespaces + +2014-11-11 Tim Ruehsen <tim.ruehsen@gmx.de> + + * recreated the certs and the CRL file, also amended certs/README + +2014-11-10 Tim Ruehsen <tim.ruehsen@gmx.de> + + * removed certs/wget-cert.pem + * added certs/ca-cert.pem, certs/ca-key.pem, certs/server-cert.pem, + certs/server-key.pem and certs/server-crl.pem + * added certs/README for description how to generate the certs and keys + * server/http/http_server.py: amended to work with new certs/ files + * added Test--https-crl.py to test --crl-file + * Makefile.am: added Test--https-crl.py + * Test--https.py: use --ca-certificate of --no-check-certificates + +2014-10-25 Tim Ruehsen <tim.ruehsen@gmx.de> + + * test/base_test.py (gen_cmd_line): generate valgrind command line if requested + * README: amend description of VALGRIND_TESTS + * Makefile.am: set/export VALGRIND_TESTS + +2014-10-01 Darshit Shah <darnir@gmail.com> + + * Makefile.am: Run the tests in Python's Optimizedmode + * conf/__init__.py (gen_hook): Use try..except instead of if..else + * misc/color_terminal.py: System and check will not change while a test is + run. Do not test for them on every invokation of printer() + * server/http/http_server.py: The ssl and re modules are required by + specific functions. Load them lazily + (HTTPSServer.__init__): Lazy load ssl module here + (_handler.parse_range_header): Lazy load re module here + (_Handler.get_rule_list): get() can return a default value. Use it + (_Handler.guess_type): Same + (_Handler.is_authorized): Unused function artefact. Remove + (_Handler.reject_headers): Unused function artefact. Remove + +2014-10-08 Darshit Shah <darnir@gmail.com> + + * Makefile.am: Fix EXTRA_DIST variable for make distcheck + * server/http/http_server.py (HTTPServer.__init__): Fix how CERTFILE is + found when running make dist / make distcheck. + +2014-09-30 Tim Ruehsen <tim.ruehsen@gmx.de> + + * test/base_test.py: Add --track-origins=yes to valgrind testing + +2014-08-08 Darshit Shah <darnir@gmail.com> + + * conf/__init__.py: Add extra newline according to PEP8 + * conf/{authentication,expect_header,expected_files,expected_ret_code, + files_crawled,hook_sample,local_files,reject_header,response,send_header, + server_files,urls,wget_commands}.py: Add docstrings explaining the conf file + and how it should be used + * server/http/http_server (InvalidRangeHeader): Clear TODO and eliminate + this exception. Use ServerError for all such purposes. + (_Handler): Remove reference to InvalidRangeHeader + (_handler.parse_range_header): User ServerError instead of InvalidRangeHeader + (_Handler.do_GET): Add docstring + (_Handler.do_POST): Add docstring. Also create an empty dict for rules if + no rules are supplied. Send the Location header as suggested in RFC 7231 + (_Handler.do_PUT): Don't pop the server file already. Push it to later in .. + (_Handler.send_put): .. Here. If the file exists respond with a 204 No + Content message and pop the file for replacement. Do not send the + Content-Length, Content-Type headers since PUT requests should not respond + with data. + (_Handler.parse_auth_header): Fit line within 80 chars + (_Handler.check_response): Better visual indent + (_Handler.authorize_digest): Better visual indent. + (_Handler.expect_headers): Remove unused function + (_Handler.guess_type): Fix indentation + (HTTPd): Add newline according to PEP8 guidelines + (HTTPSd): Fix indentation + (StoppableHTTPServer): Add docstring + (HTTPSServer): Fix indentation + (WgetHTTPRequestHandler): Merge class into _handler. + (_Handler): Add docstring + (_Handler.parse_range_header): Fix indentation + (ServerError): Split exception into separate file ... + * exc/server_error.py: ... Here + * misc/colour_terminal.py: Add docstring, fix indentation + * test/base_test.py: Fix visual indent + * test/http_test.py: Fit within 80 char lines + +2014-08-04 Darshit Shah <darnir@gmail.com> + + * conf/server_conf.py: Delete file. Server configuration is now done via the + server_conf() method. + * server/http/http_server.py (StppableHTTPServer.server_sett): Delete + method required by the above hook + (HTTPd.server_sett): Same + +2014-07-26 Darshit Shah <darnir@gmail.com> + + * Test-*.py: Remove the '-d' switch from WGET_OPTIONS. + * test/base_test (BaseTest.gen_cmd_line): Add --debug and --no-config to the + list of switches passed to wget unconditionally. + +2014-07-23 Darshit Shah <darnir@gmail.com> + + * test/base_test.py (BaseTest.gen_cmd_line): Add support for running all + tests through valgrind if the relevant environment variable is set + * conf/expected_ret_code (ExpectedRetCode.__call__): Valgrind returns error + code 45 when it detects a memory leak. + * Readme: Update with details about valgrind tests + +2014-07-22 Darshit Shah <darnir@gmail.com> + + * (README): Remove old TODO and document SERVER_WAIT variable + +2014-06-22 Darshit Shah <darnir@gmail.com> + + * (conf.files_crawled): diff is a set object and needs explicit str + conversion. + +2014-03-13 Zihang Chen <chsc4698@gmail.com> + + * base_test.py: + (CommonMethods): Rename to BaseTest. + (BaseTest): Implement __init__ method where the class-wide variables are + initialized. Also variable names like `xxx_list` is renamed to its plural + form, e.g. `server_list` => `servers`. + (BaseTest.init_test_env): Remove name argument due to its unnecessarity. + (BaseTest.get_test_dir): Because the path of the test directory is needed + in multiple methods, this method is implemented. + (BaseTest.get_domain_addr): Rewrite the return statement utilizing str + formatting (which is more Pythonic). + (BaseTest.get_cmd_line): Rename to gen_cmd_line. Change the variables with + capitcal characters to lower ones. Also, the nested for loop is rewritten + to a plain loop using the zip function. + (BaseTest.__gen_local_filesys): Rename to gen_local_fs_snapshot. Move to + ExpectedFiles in conf/expected_files.py and is marked as a static + method. Refactor to a less verbose implementation. + (BaseTest._check_downloaded_files): Rename to __call__ to agree with the + invocation in test case classes. Move to ExpectedFiles in + conf/expected_files.py. + (BaseTest.get_server_rules): Refactor to a more Pythonic form utilizing + dict.items() and is marked static. + (BaseTest.stop_server): (new method) an abstract method which should stop + the currently using servers. + (BaseTest.instantiate_server_by): (new method) an abstract method which + should instantiate a server instance according to the given argument. + (BaseTest.__enter__): (new method) method which initialize the context + manager + (BaseTest.__exit__): (new method) method that finilize the context manager + and deal with the exceptions during the execution of the with statement, + subclasses can override this method for extensibility + * http_test.py: + (HTTPTest.__init__): Add call to super.__init__. Default values of + pre_hook, test_params, post_hook are set to None to avoid a subtle bug of + Python. Argument servers is renamed to protocols. + (HTTPTest.Server_setup): Move to BaseTest and rename to server_setup. + Calls to pre_hook_call, call_test, post_hook_call are removed. + (HTTPTest.hook_call, pre_hook_call, call_test, post_hook_call): Move to + BaseTest for that both HTTP test cases and FTP test cases may use these + methods. + (HTTPTest.init_HTTP_Server, init_HTTPS_Server): Merge and rename to + instantiate_server_by to implement the abstract method in BaseTest. + (HTTPTest.stop_HTTP_Server): Rename to stop_server to implement the + abstract method in BaseTest. Also, pull out the part where remaining + requests are gathered into a new method request_remaining. + (BaseTest.act_retcode): Rename to ret_code because ExpectedRetCode is + moved out from BaseTest, so the name act_retcode is actually a bit + verbose. + * conf/expected_ret_code.py: + (ExpectedRetCode.__call__): Rewrite the str into a more readable form. + * conf/files_crawled.py: + (FilesCrawled.__call__): Refactor this method into a more Pythonic form + utilizing the zip function. + * conf/local_files.py: + (LocalFiles__call__): Rewrite this method with the recommended with + statement. + * conf/server_conf.py: + (ServerConf.__call__): Rewrite this method due to BaseTest.server_list is + renamed to BaseTest.servers. + * conf/server_files.py: + (ServerFiles.__call__): Refactor the nested for loop into a plain one + utilizing the zip function. + * conf/urls.py: + (URLs): Rename url_list to urls. + * conf/wget_commands.py: + (WgetCommands): Rename command_list to commands, rename test_obj.options + to test_obj.wget_options. + * Test--https.py, Test-Proto.py, Test-Parallel-Proto.py: Argument servers + is changed to protocols due to change in the signature of + HTTPTest.__init__. + +2014-03-13 Zihang Chen <chsc4698@gmail.com> + + * test: (new package) package for test case classes + * WgetTest.py: Split into test/base_test.py and test/http_test.py. + * Test-*.py: Optimize the imports according to changes of WgetTest.py + +2014-03-13 Zihang Chen <chsc4698@gmail.com> + + * server: (new package) package for the server classes + * server.http: (new package) package for HTTP server + * server.ftp: (new package) package for FTP server + * HTTPServer.py: Move to server/http/http_server.py. Also change the + CERTFILE to '../certs/wget-cert.pem'. + * FTPServer.py: Move to server/ftp/ftp_server.py. + * WgetTest.py: Optimize import respect to the server classes. + +2014-03-13 Zihang Chen <chsc4698@gmail.com> + + * conf: (new package) package for rule classes and hook methods + * WgetTest.py: + (CommonMethods.Authentication): Move to conf/authentication.py. + (CommonMethods.ExpectHeader): Move to conf/expect_header.py. + (CommonMethods.RejectHeader): Move to conf/reject_header.py. + (CommonMethods.Response): Move to conf/response.py. + (CommonMethods.SendHeader): Move to conf/send_header.py. + (CommonMethods.ServerFiles): Move to conf/server_files.py. + (CommonMethods.LocalFiles): Move to conf/local_files.py. + (CommonMethods.ServerConf): Move to conf/server_conf.py. + (CommonMethods.WgetCommands): Move to conf/wget_commands.py. + (CommonMethods.Urls): Move to conf/urls.py. + (CommonMethods.ExpectedRetcode): Move to conf/expected_retcode.py. + (CommonMethods.ExpectedFiles): Move to conf/expected_files.py. + (CommonMethods.FilesCrawled): Move to conf/files_crawled.py. + (CommonMethods.__check_downloaded_files): Rename to + _check_downloaded_files, so that the method is callable from outside the + class. + (CommomMethods.get_server_rules): Modify so that it utilizes the conf + package. + (HTTPTest): Add a method hook_call(configs, name) to reduce duplications + in pre_hook_call, call_test and post_hook_call utilizing the conf package. + * conf/hook_sample.py: (new file) sample for hooks + * conf/rule_sample.py: (new file) sample for rules + * REAMDE: Update sections about customizing rules and hooks. + +2014-03-13 Zihang Chen <chsc4698@gmail.com> + + * exc: (new package) package for miscellaneous exceptions + * WgetTest.py: Move TestFailed to exc/test_failed.py. + +2014-03-13 Zihang Chen <chsc4698@gmail.com> + + * Test-Proto.py: Fix a typo (line 71: server to servers). + +2014-03-13 Zihang Chen <chsc4698@gmail.com> + + * WgetTest.py: Move WgetFile to package misc. + * README: Modify documentation respect to WgetFile. + * Test-*.py: Optimize imports about WgetFile. + +2014-03-13 Zihang Chen <chsc4698@gmail.com> + + * misc: (new package) package for miscellaneous modules + * ColourTerm.py: Move to package misc and rename to colour_terminal.py, + add print_color functions to reduce the use of string literals like + "BLUE", "RED" etc. + * WgetTest.py: + (CommonMethods.Server_setup): Change invocation to printer to print_blue. + (CommonMethods.FilesCrawled): Change invocation to printer to print_red. + (HTTPTest.__init__): Change invocations to printer to print_red and + print_green respectively. + +2014-01-02 Darshit Shah <darnir@gmail.com> + * Makefile.am: Add new Test--https.py to list of tests and EXTRA_DIST. + Also replace all tabs with spaces in file for conformity. + * Test--https.py: New test to check if Wget works correctly with HTTPS + servers + * HTTPServer.py: Import new modules for use in HTTPS Servers + (HTTPSServer): New class that generates a SSL-wrapped socket for use in a + HTTPS Server. + (HTTPSd): HTTPS daemon class. Analogous to the HTTPd class + * WgetTest.py: Define global variables HTTP and HTTPS to reflect Server + types + (CommonMethods.exec_wget): Add the protocol information to the URL before + passing it to wget + (HTTPTest.__init__): Edit syntax. The servers variable now accepts a list of + servers defined by their type. E.g. HTTP, HTTPS. + (HTTPTest.Server_setup): Reflect change in type of variable servers. + However, we maintin the value of self.servers to allow most of the code to + remain unchanged. + (HTTPTest.init_HTTPS_Server): Initialize a HTTPS Server + * Test-Parallel-Proto.py: Edit to reflect slight change in Test Fiel Syntax. + * Test-Proto.py: Same + +2014-01-02 Darshit Shah <darnir@gmail.com> + + * WgetTest.py (CommonMentods.exec_wget): Wait for n seconds before calling + the Wget executable. + +2013-12-27 Darshit Shah <darnir@gmail.com> + + * WgetTest.py: Add modeline + (CommonMethods.ServerConf): New pre-test hook that sets + BaseHTTPRequestHandler class variables in all available servers + * HTTPServer.py (HTTPd.ServerConf): Call the respective method in the Server + to set the class variables + (StoppableHTTPServer.server_sett): Set the handler class variables + +2013-12-26 Darshit Shah <darnir@gmail.com> + + * WgetTest.py (HTTPTest.call_test): Correct the call to stop_HTTP_Server. + +2013-12-25 Darshit Shah <darnir@gmail.com> + + * WgetTest.py (CommonMehtods.exec_wget): Catch and handle exception if the + Wget executable is not found at src/wget + (HTTPTest.call_test): In case of error during execution, remove all existing + servers before quitting + +2013-12-15 Darshit Shah <darnir@gmail.com> + + * WgetTest.py (HTTPTest.HTTP_setup): Rename to Server_setup so it can be + easily reused for other non-HTTP servers. + (HTTPTest.__init__): Call Server_setup instead of HTTP_setup + (HTTPTest.Server_setup): Split into three more functions, that handle + pre-hooks, test execution and post-hooks respectively. + (HTTPTest.pre_hook_call): Set up and execute the pre-test hooks. Code split + from HTTPTest.Server_setup + (HTTPTest.call_test): Execute wget and log exit code. Code split from + HTTPTest.Server_setup + (HTTPTest.post_hook_call): Set up and execute post-test hooks. Code split + from HTTPTest.Server_setup + +2013-10-14 Giuseppe Scrivano <gscrivan@redhat.com> + + * Makefile.am (XFAIL_TESTS): Remove Test--spider-r.py. + +2013-10-06 Giuseppe Scrivano <gscrivan@redhat.com> + + * Makefile.am (EXTRA_DIST): Distribute test files. + +2013-09-16 Darshit Shah <darnir@gmail.com> + + * README: Update documentation + +2013-09-14 Darshit Shah <darnir@gmail.com> + + * HTTPServer.py (StoppableHTTPServer): Define object variable + request_headers which stores a list of requests received by the server + (StoppableHTTPServer.get_req_headers): Return the list of Request + Headers stored by the server + (_Handler.do_HEAD): Send the Request MEthod string for identification + (_Handler.do_GET): Same + (_Handler.__log_request): Log the request in Request_Headers list + (_Handler.send_head): Make a call to __log_request + * Test--spider-r.py: Add new list, Request_List, which contains all + the requests that Wget is expected to send. This will allow for + fine-grained tests on recursive downloading. + * WgetTest.py (CommonMethods.FilesCrawled): New Post-Test Hook, that + ensures that all the expected Files on the server were accessed as + expected. + (HTTPTest.stop_HTTP_server): On stopping server, asks it to respond + with list of all requests it received. + +2013-09-13 Darshit Shah <darnir@gmail.com> + + * Test--spider-r.py: Test retrieval in recursive spider mode. + * Makefile.am: add new file + +2013-09-13 Darshit Shah <darnir@gmail.com> + + * HTTPServer.py (_Handler.do_HEAD): If requested path is /, respond + with /index.html + (_Handler.do_HEAD): Smartly guess value of Content-Type Header from + file extension + (_Handler.guess_type): Use a preset list of extensions and + Content-Type strings. If the extension matches one in the list, use + that string, else default to "text/plain" + +2013-09-13 Darshit Shah <darnir@gmail.com> + + * WgetTest.py (CommonMethods._replace_substring): New method that will + replace a substring delimited by {{ }} characters by the value of + self.<substring> variable + (CommonMethods.WgetCommands): Use the _replace_substring () call to + replace the substrings in the the command line. + (CommonMethods.ServerFiles): Run the _replace_substring () method on + the File contents too. + +2013-09-11 Darshit Shah <darnir@gmail.com> + + * WgetTest.py (CommonMethods.exec_wget): Expect domain_list instead of + domain. + (CommonMethods.get_cmd_line): Same. Generate command line by + prepending to each file it's respective domain string + (CommonMethods.ServerFiles): Generate file_list and server_rules for + each Server and set the config details + (HTTPTest): New named parameter, servers which signifies number of + servers to spawn + (HTTPTest.HTTP_setup): This method now takes servers as a new + parameter. Instead of storing server and domain, we now store + server_list and domain_list. Each server must be initialized through a + loop. + (HTTPTest.stop_HTTP_server): Stop all servers in a loop. + * Test-Parallel-Proto.py: Prototype test file for multiple servers. + +2013-09-10 Darshit Shah <darnir@gmail.com> + + * WgetTest.py (HTTPTest.stop_HTTP_server): With the threaded servers, + we can simply use the socketserver.shutdown() method to close the + server instead of sending a QUIT command + * HTTPServer.py (StoppabelHTTPServer.serve_forever): Delete method. No + need to override this method anymore. + (WgetHTTPRequestHandler.do_QUIT): No longer required + (HTTPd): Rename self.server to self.server_inst to reduce ambiguity + when referenced from WgetTest + +2013-09-08 Darshit Shah <darnir@gmail.com> + + * README (File Structure): Add explanation about various variables + used consistently across all tests. + +2013-09-07 Darshit Shah <darnir@gmail.com> + + * HTTPServer.py: Remove bunch of old code artefacts + * WgetTest.py: Same + +2013-09-07 Darshit Shah <darnir@gmail.com> + + * HTTPServer.py (StoppableHTTPServer.server_conf): Change global + variable fileSys to an object variable. This is good programming + practice and required for parallel-wget support. + (StoppableHTTPServer.server_forever): Edit overridden method to remove + the global queue variable. No longer required under the new working + (WgetHTTPRequestHandler.do_QUIT): Don't push fileSys through the queue + (_Handler): Rename class __Handler to _Handler to match Python's + encapsulation rules + (_Handler.do_POST): fileSys is now an object variable of the server + (_Handler.do_PUT): Same + (_Handler.send_put): Same + (_Handler.send_head): Same + (HTTPd): New class that wraps around the server for Threading + (create_server): Make new object of HTTPd. + (spawn_server): Start the thread created through create_server + (ret_fileSys): Removed method. No longer required. + * WgetTest.py (HTTPTest.__init__): Don't explicitly set + self.act_retcode. Instead toggle tests_passed boolean to set the + correct return code. + (HTTPTest.HTTP_setup): We no longer call HTTPServer.spawn_server to + start a new instance of the server. + (HTTPTest.init_HTTP_server): We no longer call the old + create_server(), spawn_server() methods. Instead use the new HTTPd + class interface to create new instances of the server + (HTTPTest.stop_HTTP_server): Don't ask server to return fileSys. + +2013-09-07 Darshit Shah <darnir@gmail.com> + + * Test-Post.py: Test basic functionality for sending HTTP POST + requests using the --method command + * Makefile.am: Add new test + +2013-09-06 Darshit Shah <darnir@gmail.com> + + * WgetTest.py (CommonMethods.__check_downloaded_files): Print a + unified diff in case there is a mismatch in the file contents + +2013-09-06 Darshit Shah <darnir@gmail.com> + + * HTTPServer.py (WgetHTTPRequestHandler.test_cookies): Comment out the + old test_cookies code. This is no longer used and was causing problems + with expected cookies. The code will soon be removed anyways + * Test-cookie.py: Add new test for basic cookie functionality + * Test-cookie-401.py: Ensure cookies are saved during a 401 response + * Test-cookie-expires.py: Ensure that the Expires field is correctly + handled + * Test-cookies-domain-mismatch.py: Ensure that mismatched domains are + handled by Wget + * Makefile.am: Add the new tests + +2013-09-06 Darshit Shah <darnir@gmail.com> + + * README: New section on pending work. Will keep updating this to keep + track of work that remains to be done on this implementation + +2013-09-05 Darshit Shah <darnir@gmail.com> + + * Test-auth-with-content-disposition.py: Add test that ensures Content + Disposition works alongwith authentication + * Makefile.am: Add new test + +2013-09-04 Darshit Shah <darnir@gmail.com> + + * Test-c-full.py: Test Continue options + * Makefile.am: Add Test-c-full.py and Test-O + +2013-09-02 Darshit Shah <darnir@gmail.com> + + * Makefile.am: Add new Test + * Test-Head.py: New Test to ensure HEAD requests are handled correctly + +2013-08-31 Darshit Shah <darnir@gmail.com> + + * README: Explain that TEST_NAME needs to be unique + * Test-auth-no-challenge.py: Edit non-unique TEST_NAME + +2013-08-31 Darshit Shah <darnir@gmail.com> + + * HTTPTest.py (ServerError): Define new Exception for handling + internal control flow. + (StoppableHTTPServer.SendHeader): Simply pass. Do nothing. Adding + functionality here seems to crash for no apparent reason. + (stoppableHTTPServer.send_cust_headers): Minor optimization. No need + for extra variable. + (__Handler.Response): Handle explicit Response Code Rules + (__Handler.Authentication): Handle Authentication rules + (__Handler.handle_auth): Actual worker method for authentication + (__Handler.ExpectHeader): Ensure Expected Headers are received + (__Handler.RejectHeader): Ensure Blacklisted Headers are NOT received + (__Handler.send_HEAD): Dynamically call server rule functions based on + the self.rules list. This feature will later be added to POST/PUT, etc + +2013-08-31 Darshit Shah <darnir@gmail.com> + + * WgetTest.py: Remove import module defaultdict. + (CommonMethods.get_server_rules): server_rules should be a dict, not a + defaultdict (list). + * HTTPServer.py (WgetHTTPRequestHandler.get_rule_list): If rule does + not exist, return None. Not an emppty list. + (WgetHTTPRequestHandler.test_cookies): Rule variable is not a list + (__Handler.send_cust_headers): Same + (__Handler.custom_response): Same + (__Handler.is_authorized): Same + (__Handler.expect_headers): Same + (__Handler.reject_headers): Same + +2013-08-31 Darshit Shah <darnir@gmail.com> + + * README: (newfile) Simple help / instructions about using the Test + Environment. + * Makefile.am: (newfile) Makefile for the Test Environment. Uses the + Automake Parallel Test Harness + * WgetTest.py: (newfile) Base module that executes the Test. + * HTTPServer.py: (newfile) Contains the custom HTTP Server for the + Test Environment. Creates an instance of http.server in Python3. + * FTPServer.py: (newfile) Overrides methods from pyftpdlib for use in + the Test Environment. ** Work under progress **. + * ColourTerm.py: (newfile) A custom module to output coloured text to + the terminal. Known to work on POSIX shells. + * Test-Proto.py: (newfile) A prototype Test File. This should be + copied when writing a new Test Case. + * Test-Content-disposition-2.py: Test Content Disposition clobbering + * Test-Content-disposition.py: Test Content Disposition Headers + * Test-O.py: Test Output filename command + * Test-auth-basic-fail.py: Test returncode on auth failure + * Test-auth-basic.py: Test Basic Auth negotiation + * Test-auth-both.py: Test handling of Multiple auth providers. This + test currently fails. + * Test-auth-digest.py: Test Digest Auth Negotiation + * Test-auth-no-challenge-url.py: Ensure --auth-no-challenge is handled + when auth details are in-URL. + * Test-auth-no-challenge.py: Ensure --auth-no-challenge is honoured + * Test-auth-retcode.py: Ensure correct return code after 403 Forbidden + response. diff --git a/testenv/Makefile.am b/testenv/Makefile.am new file mode 100644 index 0000000..39ea76c --- /dev/null +++ b/testenv/Makefile.am @@ -0,0 +1,65 @@ +# Makefile for `wget' utility +# Copyright (C) 2013 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with Wget. If not, see <http://www.gnu.org/licenses/>. + +# Additional permission under GNU GPL version 3 section 7 + +# If you modify this program, or any covered work, by linking or +# combining it with the OpenSSL project's OpenSSL library (or a +# modified version of that library), containing parts covered by the +# terms of the OpenSSL or SSLeay licenses, the Free Software Foundation +# grants you additional permission to convey the resulting work. +# Corresponding Source for a non-source form of such a combination +# shall include the source code for the parts of OpenSSL used as well +# as that of the covered work. + + +AUTOMAKE_OPTIONS = parallel-tests +AM_TESTS_ENVIRONMENT = export WGETRC=/dev/null; MAKE_CHECK=True; export MAKE_CHECK;\ + export PYTHONPATH=$$PYTHONPATH:$(srcdir); export VALGRIND_TESTS="@VALGRIND_TESTS@"; +if HAVE_PYTHON3 + TESTS = Test-auth-basic-fail.py \ + Test-auth-basic.py \ + Test-auth-both.py \ + Test-auth-digest.py \ + Test-auth-no-challenge.py \ + Test-auth-no-challenge-url.py \ + Test-auth-retcode.py \ + Test-auth-with-content-disposition.py \ + Test-c-full.py \ + Test-Content-disposition-2.py \ + Test-Content-disposition.py \ + Test-cookie-401.py \ + Test-cookie-domain-mismatch.py \ + Test-cookie-expires.py \ + Test-cookie.py \ + Test-Head.py \ + Test--https.py \ + Test--https-crl.py \ + Test-O.py \ + Test-Post.py \ + Test-504.py \ + Test--spider-r.py \ + Test-redirect-crash.py + + # added test cases expected to fail here and under TESTS + XFAIL_TESTS = +endif + +EXTRA_DIST = certs conf exc misc server test README $(TESTS) $(XFAIL_TESTS) + +TEST_EXTENSIONS = .py +PY_LOG_COMPILER = python3 +AM_PY_LOG_FLAGS = -O diff --git a/testenv/Makefile.in b/testenv/Makefile.in new file mode 100644 index 0000000..ccd01c6 --- /dev/null +++ b/testenv/Makefile.in @@ -0,0 +1,1800 @@ +# Makefile.in generated by automake 1.13.4 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile for `wget' utility +# Copyright (C) 2013 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with Wget. If not, see <http://www.gnu.org/licenses/>. + +# Additional permission under GNU GPL version 3 section 7 + +# If you modify this program, or any covered work, by linking or +# combining it with the OpenSSL project's OpenSSL library (or a +# modified version of that library), containing parts covered by the +# terms of the OpenSSL or SSLeay licenses, the Free Software Foundation +# grants you additional permission to convey the resulting work. +# Corresponding Source for a non-source form of such a combination +# shall include the source code for the parts of OpenSSL used as well +# as that of the covered work. +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +XFAIL_TESTS = +subdir = testenv +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/build-aux/test-driver ChangeLog README +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/00gnulib.m4 \ + $(top_srcdir)/m4/absolute-header.m4 $(top_srcdir)/m4/alloca.m4 \ + $(top_srcdir)/m4/arpa_inet_h.m4 \ + $(top_srcdir)/m4/asm-underscore.m4 $(top_srcdir)/m4/base32.m4 \ + $(top_srcdir)/m4/btowc.m4 $(top_srcdir)/m4/clock_time.m4 \ + $(top_srcdir)/m4/close.m4 $(top_srcdir)/m4/codeset.m4 \ + $(top_srcdir)/m4/configmake.m4 $(top_srcdir)/m4/dirname.m4 \ + $(top_srcdir)/m4/double-slash-root.m4 $(top_srcdir)/m4/dup2.m4 \ + $(top_srcdir)/m4/eealloc.m4 $(top_srcdir)/m4/environ.m4 \ + $(top_srcdir)/m4/errno_h.m4 $(top_srcdir)/m4/error.m4 \ + $(top_srcdir)/m4/exponentd.m4 $(top_srcdir)/m4/extensions.m4 \ + $(top_srcdir)/m4/extern-inline.m4 \ + $(top_srcdir)/m4/fatal-signal.m4 $(top_srcdir)/m4/fcntl-o.m4 \ + $(top_srcdir)/m4/fcntl.m4 $(top_srcdir)/m4/fcntl_h.m4 \ + $(top_srcdir)/m4/float_h.m4 $(top_srcdir)/m4/fnmatch.m4 \ + $(top_srcdir)/m4/fseek.m4 $(top_srcdir)/m4/fseeko.m4 \ + $(top_srcdir)/m4/fstat.m4 $(top_srcdir)/m4/ftell.m4 \ + $(top_srcdir)/m4/ftello.m4 $(top_srcdir)/m4/futimens.m4 \ + $(top_srcdir)/m4/getaddrinfo.m4 $(top_srcdir)/m4/getdelim.m4 \ + $(top_srcdir)/m4/getdtablesize.m4 $(top_srcdir)/m4/getline.m4 \ + $(top_srcdir)/m4/getopt.m4 $(top_srcdir)/m4/getpass.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/gettime.m4 \ + $(top_srcdir)/m4/gettimeofday.m4 \ + $(top_srcdir)/m4/gl-openssl.m4 $(top_srcdir)/m4/glibc21.m4 \ + $(top_srcdir)/m4/gnulib-common.m4 \ + $(top_srcdir)/m4/gnulib-comp.m4 $(top_srcdir)/m4/hostent.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/iconv_h.m4 \ + $(top_srcdir)/m4/include_next.m4 $(top_srcdir)/m4/inet_ntop.m4 \ + $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intmax_t.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/ioctl.m4 \ + $(top_srcdir)/m4/iswblank.m4 $(top_srcdir)/m4/langinfo_h.m4 \ + $(top_srcdir)/m4/largefile.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libunistring-base.m4 \ + $(top_srcdir)/m4/localcharset.m4 $(top_srcdir)/m4/locale-fr.m4 \ + $(top_srcdir)/m4/locale-ja.m4 $(top_srcdir)/m4/locale-zh.m4 \ + $(top_srcdir)/m4/locale_h.m4 $(top_srcdir)/m4/localeconv.m4 \ + $(top_srcdir)/m4/lock.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/lseek.m4 $(top_srcdir)/m4/lstat.m4 \ + $(top_srcdir)/m4/malloc.m4 $(top_srcdir)/m4/mbchar.m4 \ + $(top_srcdir)/m4/mbiter.m4 $(top_srcdir)/m4/mbrtowc.m4 \ + $(top_srcdir)/m4/mbsinit.m4 $(top_srcdir)/m4/mbsrtowcs.m4 \ + $(top_srcdir)/m4/mbstate_t.m4 $(top_srcdir)/m4/mbtowc.m4 \ + $(top_srcdir)/m4/md5.m4 $(top_srcdir)/m4/memchr.m4 \ + $(top_srcdir)/m4/memrchr.m4 $(top_srcdir)/m4/mkdir.m4 \ + $(top_srcdir)/m4/mkostemp.m4 $(top_srcdir)/m4/mkstemp.m4 \ + $(top_srcdir)/m4/mktime.m4 $(top_srcdir)/m4/mmap-anon.m4 \ + $(top_srcdir)/m4/mode_t.m4 $(top_srcdir)/m4/msvc-inval.m4 \ + $(top_srcdir)/m4/msvc-nothrow.m4 $(top_srcdir)/m4/multiarch.m4 \ + $(top_srcdir)/m4/netdb_h.m4 $(top_srcdir)/m4/netinet_in_h.m4 \ + $(top_srcdir)/m4/nl_langinfo.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/nocrash.m4 $(top_srcdir)/m4/off_t.m4 \ + $(top_srcdir)/m4/open.m4 $(top_srcdir)/m4/pathmax.m4 \ + $(top_srcdir)/m4/pipe2.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/posix_spawn.m4 $(top_srcdir)/m4/printf.m4 \ + $(top_srcdir)/m4/quote.m4 $(top_srcdir)/m4/quotearg.m4 \ + $(top_srcdir)/m4/raise.m4 $(top_srcdir)/m4/rawmemchr.m4 \ + $(top_srcdir)/m4/realloc.m4 $(top_srcdir)/m4/regex.m4 \ + $(top_srcdir)/m4/sched_h.m4 $(top_srcdir)/m4/secure_getenv.m4 \ + $(top_srcdir)/m4/select.m4 $(top_srcdir)/m4/servent.m4 \ + $(top_srcdir)/m4/sha1.m4 $(top_srcdir)/m4/sig_atomic_t.m4 \ + $(top_srcdir)/m4/sigaction.m4 $(top_srcdir)/m4/signal_h.m4 \ + $(top_srcdir)/m4/signalblocking.m4 $(top_srcdir)/m4/sigpipe.m4 \ + $(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/snprintf.m4 \ + $(top_srcdir)/m4/socketlib.m4 $(top_srcdir)/m4/sockets.m4 \ + $(top_srcdir)/m4/socklen.m4 $(top_srcdir)/m4/sockpfaf.m4 \ + $(top_srcdir)/m4/spawn-pipe.m4 $(top_srcdir)/m4/spawn_h.m4 \ + $(top_srcdir)/m4/ssize_t.m4 $(top_srcdir)/m4/stat-time.m4 \ + $(top_srcdir)/m4/stat.m4 $(top_srcdir)/m4/stdalign.m4 \ + $(top_srcdir)/m4/stdbool.m4 $(top_srcdir)/m4/stddef_h.m4 \ + $(top_srcdir)/m4/stdint.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/m4/stdio_h.m4 $(top_srcdir)/m4/stdlib_h.m4 \ + $(top_srcdir)/m4/strcase.m4 $(top_srcdir)/m4/strchrnul.m4 \ + $(top_srcdir)/m4/strerror.m4 $(top_srcdir)/m4/strerror_r.m4 \ + $(top_srcdir)/m4/string_h.m4 $(top_srcdir)/m4/strings_h.m4 \ + $(top_srcdir)/m4/strndup.m4 $(top_srcdir)/m4/strnlen.m4 \ + $(top_srcdir)/m4/strptime.m4 $(top_srcdir)/m4/strtok_r.m4 \ + $(top_srcdir)/m4/strtoll.m4 $(top_srcdir)/m4/sys_ioctl_h.m4 \ + $(top_srcdir)/m4/sys_select_h.m4 \ + $(top_srcdir)/m4/sys_socket_h.m4 \ + $(top_srcdir)/m4/sys_stat_h.m4 $(top_srcdir)/m4/sys_time_h.m4 \ + $(top_srcdir)/m4/sys_types_h.m4 $(top_srcdir)/m4/sys_uio_h.m4 \ + $(top_srcdir)/m4/sys_wait_h.m4 $(top_srcdir)/m4/tempname.m4 \ + $(top_srcdir)/m4/threadlib.m4 $(top_srcdir)/m4/time_h.m4 \ + $(top_srcdir)/m4/time_r.m4 $(top_srcdir)/m4/timegm.m4 \ + $(top_srcdir)/m4/timespec.m4 $(top_srcdir)/m4/tm_gmtoff.m4 \ + $(top_srcdir)/m4/tmpdir.m4 $(top_srcdir)/m4/unistd-safer.m4 \ + $(top_srcdir)/m4/unistd_h.m4 $(top_srcdir)/m4/unlocked-io.m4 \ + $(top_srcdir)/m4/utimbuf.m4 $(top_srcdir)/m4/utimens.m4 \ + $(top_srcdir)/m4/utimes.m4 $(top_srcdir)/m4/vasnprintf.m4 \ + $(top_srcdir)/m4/vasprintf.m4 $(top_srcdir)/m4/vsnprintf.m4 \ + $(top_srcdir)/m4/wait-process.m4 $(top_srcdir)/m4/waitpid.m4 \ + $(top_srcdir)/m4/warn-on-use.m4 $(top_srcdir)/m4/wchar_h.m4 \ + $(top_srcdir)/m4/wchar_t.m4 $(top_srcdir)/m4/wcrtomb.m4 \ + $(top_srcdir)/m4/wctype_h.m4 $(top_srcdir)/m4/wcwidth.m4 \ + $(top_srcdir)/m4/wget.m4 $(top_srcdir)/m4/wint_t.m4 \ + $(top_srcdir)/m4/write.m4 $(top_srcdir)/m4/xalloc.m4 \ + $(top_srcdir)/m4/xsize.m4 $(top_srcdir)/m4/xstrndup.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/src/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red='[0;31m'; \ + grn='[0;32m'; \ + lgn='[1;32m'; \ + blu='[1;34m'; \ + mgn='[0;35m'; \ + brg='[1m'; \ + std='[m'; \ + fi; \ +} +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +RECHECK_LOGS = $(TEST_LOGS) +AM_RECURSIVE_TARGETS = check recheck +TEST_SUITE_LOG = test-suite.log +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.py.log=.log) +PY_LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver +PY_LOG_COMPILE = $(PY_LOG_COMPILER) $(AM_PY_LOG_FLAGS) $(PY_LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +pkglibexecdir = @pkglibexecdir@ +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +ALLOCA_H = @ALLOCA_H@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APPLE_UNIVERSAL_BUILD = @APPLE_UNIVERSAL_BUILD@ +AR = @AR@ +ARFLAGS = @ARFLAGS@ +ASM_SYMBOL_PREFIX = @ASM_SYMBOL_PREFIX@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BITSIZEOF_PTRDIFF_T = @BITSIZEOF_PTRDIFF_T@ +BITSIZEOF_SIG_ATOMIC_T = @BITSIZEOF_SIG_ATOMIC_T@ +BITSIZEOF_SIZE_T = @BITSIZEOF_SIZE_T@ +BITSIZEOF_WCHAR_T = @BITSIZEOF_WCHAR_T@ +BITSIZEOF_WINT_T = @BITSIZEOF_WINT_T@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COMMENT_IF_NO_POD2MAN = @COMMENT_IF_NO_POD2MAN@ +CONFIG_INCLUDE = @CONFIG_INCLUDE@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EMULTIHOP_HIDDEN = @EMULTIHOP_HIDDEN@ +EMULTIHOP_VALUE = @EMULTIHOP_VALUE@ +ENOLINK_HIDDEN = @ENOLINK_HIDDEN@ +ENOLINK_VALUE = @ENOLINK_VALUE@ +EOVERFLOW_HIDDEN = @EOVERFLOW_HIDDEN@ +EOVERFLOW_VALUE = @EOVERFLOW_VALUE@ +ERRNO_H = @ERRNO_H@ +EXEEXT = @EXEEXT@ +FLOAT_H = @FLOAT_H@ +FNMATCH_H = @FNMATCH_H@ +GETADDRINFO_LIB = @GETADDRINFO_LIB@ +GETOPT_H = @GETOPT_H@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GLIBC21 = @GLIBC21@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GNULIB_ACCEPT = @GNULIB_ACCEPT@ +GNULIB_ACCEPT4 = @GNULIB_ACCEPT4@ +GNULIB_ATOLL = @GNULIB_ATOLL@ +GNULIB_BIND = @GNULIB_BIND@ +GNULIB_BTOWC = @GNULIB_BTOWC@ +GNULIB_CALLOC_POSIX = @GNULIB_CALLOC_POSIX@ +GNULIB_CANONICALIZE_FILE_NAME = @GNULIB_CANONICALIZE_FILE_NAME@ +GNULIB_CHDIR = @GNULIB_CHDIR@ +GNULIB_CHOWN = @GNULIB_CHOWN@ +GNULIB_CLOSE = @GNULIB_CLOSE@ +GNULIB_CONNECT = @GNULIB_CONNECT@ +GNULIB_DPRINTF = @GNULIB_DPRINTF@ +GNULIB_DUP = @GNULIB_DUP@ +GNULIB_DUP2 = @GNULIB_DUP2@ +GNULIB_DUP3 = @GNULIB_DUP3@ +GNULIB_DUPLOCALE = @GNULIB_DUPLOCALE@ +GNULIB_ENVIRON = @GNULIB_ENVIRON@ +GNULIB_EUIDACCESS = @GNULIB_EUIDACCESS@ +GNULIB_FACCESSAT = @GNULIB_FACCESSAT@ +GNULIB_FCHDIR = @GNULIB_FCHDIR@ +GNULIB_FCHMODAT = @GNULIB_FCHMODAT@ +GNULIB_FCHOWNAT = @GNULIB_FCHOWNAT@ +GNULIB_FCLOSE = @GNULIB_FCLOSE@ +GNULIB_FCNTL = @GNULIB_FCNTL@ +GNULIB_FDATASYNC = @GNULIB_FDATASYNC@ +GNULIB_FDOPEN = @GNULIB_FDOPEN@ +GNULIB_FFLUSH = @GNULIB_FFLUSH@ +GNULIB_FFS = @GNULIB_FFS@ +GNULIB_FFSL = @GNULIB_FFSL@ +GNULIB_FFSLL = @GNULIB_FFSLL@ +GNULIB_FGETC = @GNULIB_FGETC@ +GNULIB_FGETS = @GNULIB_FGETS@ +GNULIB_FOPEN = @GNULIB_FOPEN@ +GNULIB_FPRINTF = @GNULIB_FPRINTF@ +GNULIB_FPRINTF_POSIX = @GNULIB_FPRINTF_POSIX@ +GNULIB_FPURGE = @GNULIB_FPURGE@ +GNULIB_FPUTC = @GNULIB_FPUTC@ +GNULIB_FPUTS = @GNULIB_FPUTS@ +GNULIB_FREAD = @GNULIB_FREAD@ +GNULIB_FREOPEN = @GNULIB_FREOPEN@ +GNULIB_FSCANF = @GNULIB_FSCANF@ +GNULIB_FSEEK = @GNULIB_FSEEK@ +GNULIB_FSEEKO = @GNULIB_FSEEKO@ +GNULIB_FSTAT = @GNULIB_FSTAT@ +GNULIB_FSTATAT = @GNULIB_FSTATAT@ +GNULIB_FSYNC = @GNULIB_FSYNC@ +GNULIB_FTELL = @GNULIB_FTELL@ +GNULIB_FTELLO = @GNULIB_FTELLO@ +GNULIB_FTRUNCATE = @GNULIB_FTRUNCATE@ +GNULIB_FUTIMENS = @GNULIB_FUTIMENS@ +GNULIB_FWRITE = @GNULIB_FWRITE@ +GNULIB_GETADDRINFO = @GNULIB_GETADDRINFO@ +GNULIB_GETC = @GNULIB_GETC@ +GNULIB_GETCHAR = @GNULIB_GETCHAR@ +GNULIB_GETCWD = @GNULIB_GETCWD@ +GNULIB_GETDELIM = @GNULIB_GETDELIM@ +GNULIB_GETDOMAINNAME = @GNULIB_GETDOMAINNAME@ +GNULIB_GETDTABLESIZE = @GNULIB_GETDTABLESIZE@ +GNULIB_GETGROUPS = @GNULIB_GETGROUPS@ +GNULIB_GETHOSTNAME = @GNULIB_GETHOSTNAME@ +GNULIB_GETLINE = @GNULIB_GETLINE@ +GNULIB_GETLOADAVG = @GNULIB_GETLOADAVG@ +GNULIB_GETLOGIN = @GNULIB_GETLOGIN@ +GNULIB_GETLOGIN_R = @GNULIB_GETLOGIN_R@ +GNULIB_GETPAGESIZE = @GNULIB_GETPAGESIZE@ +GNULIB_GETPEERNAME = @GNULIB_GETPEERNAME@ +GNULIB_GETSOCKNAME = @GNULIB_GETSOCKNAME@ +GNULIB_GETSOCKOPT = @GNULIB_GETSOCKOPT@ +GNULIB_GETSUBOPT = @GNULIB_GETSUBOPT@ +GNULIB_GETTIMEOFDAY = @GNULIB_GETTIMEOFDAY@ +GNULIB_GETUSERSHELL = @GNULIB_GETUSERSHELL@ +GNULIB_GL_UNISTD_H_GETOPT = @GNULIB_GL_UNISTD_H_GETOPT@ +GNULIB_GRANTPT = @GNULIB_GRANTPT@ +GNULIB_GROUP_MEMBER = @GNULIB_GROUP_MEMBER@ +GNULIB_ICONV = @GNULIB_ICONV@ +GNULIB_INET_NTOP = @GNULIB_INET_NTOP@ +GNULIB_INET_PTON = @GNULIB_INET_PTON@ +GNULIB_IOCTL = @GNULIB_IOCTL@ +GNULIB_ISATTY = @GNULIB_ISATTY@ +GNULIB_ISWBLANK = @GNULIB_ISWBLANK@ +GNULIB_ISWCTYPE = @GNULIB_ISWCTYPE@ +GNULIB_LCHMOD = @GNULIB_LCHMOD@ +GNULIB_LCHOWN = @GNULIB_LCHOWN@ +GNULIB_LINK = @GNULIB_LINK@ +GNULIB_LINKAT = @GNULIB_LINKAT@ +GNULIB_LISTEN = @GNULIB_LISTEN@ +GNULIB_LOCALECONV = @GNULIB_LOCALECONV@ +GNULIB_LSEEK = @GNULIB_LSEEK@ +GNULIB_LSTAT = @GNULIB_LSTAT@ +GNULIB_MALLOC_POSIX = @GNULIB_MALLOC_POSIX@ +GNULIB_MBRLEN = @GNULIB_MBRLEN@ +GNULIB_MBRTOWC = @GNULIB_MBRTOWC@ +GNULIB_MBSCASECMP = @GNULIB_MBSCASECMP@ +GNULIB_MBSCASESTR = @GNULIB_MBSCASESTR@ +GNULIB_MBSCHR = @GNULIB_MBSCHR@ +GNULIB_MBSCSPN = @GNULIB_MBSCSPN@ +GNULIB_MBSINIT = @GNULIB_MBSINIT@ +GNULIB_MBSLEN = @GNULIB_MBSLEN@ +GNULIB_MBSNCASECMP = @GNULIB_MBSNCASECMP@ +GNULIB_MBSNLEN = @GNULIB_MBSNLEN@ +GNULIB_MBSNRTOWCS = @GNULIB_MBSNRTOWCS@ +GNULIB_MBSPBRK = @GNULIB_MBSPBRK@ +GNULIB_MBSPCASECMP = @GNULIB_MBSPCASECMP@ +GNULIB_MBSRCHR = @GNULIB_MBSRCHR@ +GNULIB_MBSRTOWCS = @GNULIB_MBSRTOWCS@ +GNULIB_MBSSEP = @GNULIB_MBSSEP@ +GNULIB_MBSSPN = @GNULIB_MBSSPN@ +GNULIB_MBSSTR = @GNULIB_MBSSTR@ +GNULIB_MBSTOK_R = @GNULIB_MBSTOK_R@ +GNULIB_MBTOWC = @GNULIB_MBTOWC@ +GNULIB_MEMCHR = @GNULIB_MEMCHR@ +GNULIB_MEMMEM = @GNULIB_MEMMEM@ +GNULIB_MEMPCPY = @GNULIB_MEMPCPY@ +GNULIB_MEMRCHR = @GNULIB_MEMRCHR@ +GNULIB_MKDIRAT = @GNULIB_MKDIRAT@ +GNULIB_MKDTEMP = @GNULIB_MKDTEMP@ +GNULIB_MKFIFO = @GNULIB_MKFIFO@ +GNULIB_MKFIFOAT = @GNULIB_MKFIFOAT@ +GNULIB_MKNOD = @GNULIB_MKNOD@ +GNULIB_MKNODAT = @GNULIB_MKNODAT@ +GNULIB_MKOSTEMP = @GNULIB_MKOSTEMP@ +GNULIB_MKOSTEMPS = @GNULIB_MKOSTEMPS@ +GNULIB_MKSTEMP = @GNULIB_MKSTEMP@ +GNULIB_MKSTEMPS = @GNULIB_MKSTEMPS@ +GNULIB_MKTIME = @GNULIB_MKTIME@ +GNULIB_NANOSLEEP = @GNULIB_NANOSLEEP@ +GNULIB_NL_LANGINFO = @GNULIB_NL_LANGINFO@ +GNULIB_NONBLOCKING = @GNULIB_NONBLOCKING@ +GNULIB_OBSTACK_PRINTF = @GNULIB_OBSTACK_PRINTF@ +GNULIB_OBSTACK_PRINTF_POSIX = @GNULIB_OBSTACK_PRINTF_POSIX@ +GNULIB_OPEN = @GNULIB_OPEN@ +GNULIB_OPENAT = @GNULIB_OPENAT@ +GNULIB_PCLOSE = @GNULIB_PCLOSE@ +GNULIB_PERROR = @GNULIB_PERROR@ +GNULIB_PIPE = @GNULIB_PIPE@ +GNULIB_PIPE2 = @GNULIB_PIPE2@ +GNULIB_POPEN = @GNULIB_POPEN@ +GNULIB_POSIX_OPENPT = @GNULIB_POSIX_OPENPT@ +GNULIB_POSIX_SPAWN = @GNULIB_POSIX_SPAWN@ +GNULIB_POSIX_SPAWNATTR_DESTROY = @GNULIB_POSIX_SPAWNATTR_DESTROY@ +GNULIB_POSIX_SPAWNATTR_GETFLAGS = @GNULIB_POSIX_SPAWNATTR_GETFLAGS@ +GNULIB_POSIX_SPAWNATTR_GETPGROUP = @GNULIB_POSIX_SPAWNATTR_GETPGROUP@ +GNULIB_POSIX_SPAWNATTR_GETSCHEDPARAM = @GNULIB_POSIX_SPAWNATTR_GETSCHEDPARAM@ +GNULIB_POSIX_SPAWNATTR_GETSCHEDPOLICY = @GNULIB_POSIX_SPAWNATTR_GETSCHEDPOLICY@ +GNULIB_POSIX_SPAWNATTR_GETSIGDEFAULT = @GNULIB_POSIX_SPAWNATTR_GETSIGDEFAULT@ +GNULIB_POSIX_SPAWNATTR_GETSIGMASK = @GNULIB_POSIX_SPAWNATTR_GETSIGMASK@ +GNULIB_POSIX_SPAWNATTR_INIT = @GNULIB_POSIX_SPAWNATTR_INIT@ +GNULIB_POSIX_SPAWNATTR_SETFLAGS = @GNULIB_POSIX_SPAWNATTR_SETFLAGS@ +GNULIB_POSIX_SPAWNATTR_SETPGROUP = @GNULIB_POSIX_SPAWNATTR_SETPGROUP@ +GNULIB_POSIX_SPAWNATTR_SETSCHEDPARAM = @GNULIB_POSIX_SPAWNATTR_SETSCHEDPARAM@ +GNULIB_POSIX_SPAWNATTR_SETSCHEDPOLICY = @GNULIB_POSIX_SPAWNATTR_SETSCHEDPOLICY@ +GNULIB_POSIX_SPAWNATTR_SETSIGDEFAULT = @GNULIB_POSIX_SPAWNATTR_SETSIGDEFAULT@ +GNULIB_POSIX_SPAWNATTR_SETSIGMASK = @GNULIB_POSIX_SPAWNATTR_SETSIGMASK@ +GNULIB_POSIX_SPAWNP = @GNULIB_POSIX_SPAWNP@ +GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE = @GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE@ +GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2 = @GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2@ +GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN = @GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN@ +GNULIB_POSIX_SPAWN_FILE_ACTIONS_DESTROY = @GNULIB_POSIX_SPAWN_FILE_ACTIONS_DESTROY@ +GNULIB_POSIX_SPAWN_FILE_ACTIONS_INIT = @GNULIB_POSIX_SPAWN_FILE_ACTIONS_INIT@ +GNULIB_PREAD = @GNULIB_PREAD@ +GNULIB_PRINTF = @GNULIB_PRINTF@ +GNULIB_PRINTF_POSIX = @GNULIB_PRINTF_POSIX@ +GNULIB_PSELECT = @GNULIB_PSELECT@ +GNULIB_PTHREAD_SIGMASK = @GNULIB_PTHREAD_SIGMASK@ +GNULIB_PTSNAME = @GNULIB_PTSNAME@ +GNULIB_PTSNAME_R = @GNULIB_PTSNAME_R@ +GNULIB_PUTC = @GNULIB_PUTC@ +GNULIB_PUTCHAR = @GNULIB_PUTCHAR@ +GNULIB_PUTENV = @GNULIB_PUTENV@ +GNULIB_PUTS = @GNULIB_PUTS@ +GNULIB_PWRITE = @GNULIB_PWRITE@ +GNULIB_QSORT_R = @GNULIB_QSORT_R@ +GNULIB_RAISE = @GNULIB_RAISE@ +GNULIB_RANDOM = @GNULIB_RANDOM@ +GNULIB_RANDOM_R = @GNULIB_RANDOM_R@ +GNULIB_RAWMEMCHR = @GNULIB_RAWMEMCHR@ +GNULIB_READ = @GNULIB_READ@ +GNULIB_READLINK = @GNULIB_READLINK@ +GNULIB_READLINKAT = @GNULIB_READLINKAT@ +GNULIB_REALLOC_POSIX = @GNULIB_REALLOC_POSIX@ +GNULIB_REALPATH = @GNULIB_REALPATH@ +GNULIB_RECV = @GNULIB_RECV@ +GNULIB_RECVFROM = @GNULIB_RECVFROM@ +GNULIB_REMOVE = @GNULIB_REMOVE@ +GNULIB_RENAME = @GNULIB_RENAME@ +GNULIB_RENAMEAT = @GNULIB_RENAMEAT@ +GNULIB_RMDIR = @GNULIB_RMDIR@ +GNULIB_RPMATCH = @GNULIB_RPMATCH@ +GNULIB_SCANF = @GNULIB_SCANF@ +GNULIB_SECURE_GETENV = @GNULIB_SECURE_GETENV@ +GNULIB_SELECT = @GNULIB_SELECT@ +GNULIB_SEND = @GNULIB_SEND@ +GNULIB_SENDTO = @GNULIB_SENDTO@ +GNULIB_SETENV = @GNULIB_SETENV@ +GNULIB_SETHOSTNAME = @GNULIB_SETHOSTNAME@ +GNULIB_SETLOCALE = @GNULIB_SETLOCALE@ +GNULIB_SETSOCKOPT = @GNULIB_SETSOCKOPT@ +GNULIB_SHUTDOWN = @GNULIB_SHUTDOWN@ +GNULIB_SIGACTION = @GNULIB_SIGACTION@ +GNULIB_SIGNAL_H_SIGPIPE = @GNULIB_SIGNAL_H_SIGPIPE@ +GNULIB_SIGPROCMASK = @GNULIB_SIGPROCMASK@ +GNULIB_SLEEP = @GNULIB_SLEEP@ +GNULIB_SNPRINTF = @GNULIB_SNPRINTF@ +GNULIB_SOCKET = @GNULIB_SOCKET@ +GNULIB_SPRINTF_POSIX = @GNULIB_SPRINTF_POSIX@ +GNULIB_STAT = @GNULIB_STAT@ +GNULIB_STDIO_H_NONBLOCKING = @GNULIB_STDIO_H_NONBLOCKING@ +GNULIB_STDIO_H_SIGPIPE = @GNULIB_STDIO_H_SIGPIPE@ +GNULIB_STPCPY = @GNULIB_STPCPY@ +GNULIB_STPNCPY = @GNULIB_STPNCPY@ +GNULIB_STRCASESTR = @GNULIB_STRCASESTR@ +GNULIB_STRCHRNUL = @GNULIB_STRCHRNUL@ +GNULIB_STRDUP = @GNULIB_STRDUP@ +GNULIB_STRERROR = @GNULIB_STRERROR@ +GNULIB_STRERROR_R = @GNULIB_STRERROR_R@ +GNULIB_STRNCAT = @GNULIB_STRNCAT@ +GNULIB_STRNDUP = @GNULIB_STRNDUP@ +GNULIB_STRNLEN = @GNULIB_STRNLEN@ +GNULIB_STRPBRK = @GNULIB_STRPBRK@ +GNULIB_STRPTIME = @GNULIB_STRPTIME@ +GNULIB_STRSEP = @GNULIB_STRSEP@ +GNULIB_STRSIGNAL = @GNULIB_STRSIGNAL@ +GNULIB_STRSTR = @GNULIB_STRSTR@ +GNULIB_STRTOD = @GNULIB_STRTOD@ +GNULIB_STRTOK_R = @GNULIB_STRTOK_R@ +GNULIB_STRTOLL = @GNULIB_STRTOLL@ +GNULIB_STRTOULL = @GNULIB_STRTOULL@ +GNULIB_STRVERSCMP = @GNULIB_STRVERSCMP@ +GNULIB_SYMLINK = @GNULIB_SYMLINK@ +GNULIB_SYMLINKAT = @GNULIB_SYMLINKAT@ +GNULIB_SYSTEM_POSIX = @GNULIB_SYSTEM_POSIX@ +GNULIB_TIMEGM = @GNULIB_TIMEGM@ +GNULIB_TIME_R = @GNULIB_TIME_R@ +GNULIB_TMPFILE = @GNULIB_TMPFILE@ +GNULIB_TOWCTRANS = @GNULIB_TOWCTRANS@ +GNULIB_TTYNAME_R = @GNULIB_TTYNAME_R@ +GNULIB_UNISTD_H_NONBLOCKING = @GNULIB_UNISTD_H_NONBLOCKING@ +GNULIB_UNISTD_H_SIGPIPE = @GNULIB_UNISTD_H_SIGPIPE@ +GNULIB_UNLINK = @GNULIB_UNLINK@ +GNULIB_UNLINKAT = @GNULIB_UNLINKAT@ +GNULIB_UNLOCKPT = @GNULIB_UNLOCKPT@ +GNULIB_UNSETENV = @GNULIB_UNSETENV@ +GNULIB_USLEEP = @GNULIB_USLEEP@ +GNULIB_UTIMENSAT = @GNULIB_UTIMENSAT@ +GNULIB_VASPRINTF = @GNULIB_VASPRINTF@ +GNULIB_VDPRINTF = @GNULIB_VDPRINTF@ +GNULIB_VFPRINTF = @GNULIB_VFPRINTF@ +GNULIB_VFPRINTF_POSIX = @GNULIB_VFPRINTF_POSIX@ +GNULIB_VFSCANF = @GNULIB_VFSCANF@ +GNULIB_VPRINTF = @GNULIB_VPRINTF@ +GNULIB_VPRINTF_POSIX = @GNULIB_VPRINTF_POSIX@ +GNULIB_VSCANF = @GNULIB_VSCANF@ +GNULIB_VSNPRINTF = @GNULIB_VSNPRINTF@ +GNULIB_VSPRINTF_POSIX = @GNULIB_VSPRINTF_POSIX@ +GNULIB_WAITPID = @GNULIB_WAITPID@ +GNULIB_WCPCPY = @GNULIB_WCPCPY@ +GNULIB_WCPNCPY = @GNULIB_WCPNCPY@ +GNULIB_WCRTOMB = @GNULIB_WCRTOMB@ +GNULIB_WCSCASECMP = @GNULIB_WCSCASECMP@ +GNULIB_WCSCAT = @GNULIB_WCSCAT@ +GNULIB_WCSCHR = @GNULIB_WCSCHR@ +GNULIB_WCSCMP = @GNULIB_WCSCMP@ +GNULIB_WCSCOLL = @GNULIB_WCSCOLL@ +GNULIB_WCSCPY = @GNULIB_WCSCPY@ +GNULIB_WCSCSPN = @GNULIB_WCSCSPN@ +GNULIB_WCSDUP = @GNULIB_WCSDUP@ +GNULIB_WCSLEN = @GNULIB_WCSLEN@ +GNULIB_WCSNCASECMP = @GNULIB_WCSNCASECMP@ +GNULIB_WCSNCAT = @GNULIB_WCSNCAT@ +GNULIB_WCSNCMP = @GNULIB_WCSNCMP@ +GNULIB_WCSNCPY = @GNULIB_WCSNCPY@ +GNULIB_WCSNLEN = @GNULIB_WCSNLEN@ +GNULIB_WCSNRTOMBS = @GNULIB_WCSNRTOMBS@ +GNULIB_WCSPBRK = @GNULIB_WCSPBRK@ +GNULIB_WCSRCHR = @GNULIB_WCSRCHR@ +GNULIB_WCSRTOMBS = @GNULIB_WCSRTOMBS@ +GNULIB_WCSSPN = @GNULIB_WCSSPN@ +GNULIB_WCSSTR = @GNULIB_WCSSTR@ +GNULIB_WCSTOK = @GNULIB_WCSTOK@ +GNULIB_WCSWIDTH = @GNULIB_WCSWIDTH@ +GNULIB_WCSXFRM = @GNULIB_WCSXFRM@ +GNULIB_WCTOB = @GNULIB_WCTOB@ +GNULIB_WCTOMB = @GNULIB_WCTOMB@ +GNULIB_WCTRANS = @GNULIB_WCTRANS@ +GNULIB_WCTYPE = @GNULIB_WCTYPE@ +GNULIB_WCWIDTH = @GNULIB_WCWIDTH@ +GNULIB_WMEMCHR = @GNULIB_WMEMCHR@ +GNULIB_WMEMCMP = @GNULIB_WMEMCMP@ +GNULIB_WMEMCPY = @GNULIB_WMEMCPY@ +GNULIB_WMEMMOVE = @GNULIB_WMEMMOVE@ +GNULIB_WMEMSET = @GNULIB_WMEMSET@ +GNULIB_WRITE = @GNULIB_WRITE@ +GNULIB__EXIT = @GNULIB__EXIT@ +GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ +GNUTLS_LIBS = @GNUTLS_LIBS@ +GREP = @GREP@ +HAVE_ACCEPT4 = @HAVE_ACCEPT4@ +HAVE_ARPA_INET_H = @HAVE_ARPA_INET_H@ +HAVE_ATOLL = @HAVE_ATOLL@ +HAVE_BTOWC = @HAVE_BTOWC@ +HAVE_CANONICALIZE_FILE_NAME = @HAVE_CANONICALIZE_FILE_NAME@ +HAVE_CHOWN = @HAVE_CHOWN@ +HAVE_DECL_ENVIRON = @HAVE_DECL_ENVIRON@ +HAVE_DECL_FCHDIR = @HAVE_DECL_FCHDIR@ +HAVE_DECL_FDATASYNC = @HAVE_DECL_FDATASYNC@ +HAVE_DECL_FPURGE = @HAVE_DECL_FPURGE@ +HAVE_DECL_FREEADDRINFO = @HAVE_DECL_FREEADDRINFO@ +HAVE_DECL_FSEEKO = @HAVE_DECL_FSEEKO@ +HAVE_DECL_FTELLO = @HAVE_DECL_FTELLO@ +HAVE_DECL_GAI_STRERROR = @HAVE_DECL_GAI_STRERROR@ +HAVE_DECL_GETADDRINFO = @HAVE_DECL_GETADDRINFO@ +HAVE_DECL_GETDELIM = @HAVE_DECL_GETDELIM@ +HAVE_DECL_GETDOMAINNAME = @HAVE_DECL_GETDOMAINNAME@ +HAVE_DECL_GETLINE = @HAVE_DECL_GETLINE@ +HAVE_DECL_GETLOADAVG = @HAVE_DECL_GETLOADAVG@ +HAVE_DECL_GETLOGIN_R = @HAVE_DECL_GETLOGIN_R@ +HAVE_DECL_GETNAMEINFO = @HAVE_DECL_GETNAMEINFO@ +HAVE_DECL_GETPAGESIZE = @HAVE_DECL_GETPAGESIZE@ +HAVE_DECL_GETUSERSHELL = @HAVE_DECL_GETUSERSHELL@ +HAVE_DECL_INET_NTOP = @HAVE_DECL_INET_NTOP@ +HAVE_DECL_INET_PTON = @HAVE_DECL_INET_PTON@ +HAVE_DECL_LOCALTIME_R = @HAVE_DECL_LOCALTIME_R@ +HAVE_DECL_MEMMEM = @HAVE_DECL_MEMMEM@ +HAVE_DECL_MEMRCHR = @HAVE_DECL_MEMRCHR@ +HAVE_DECL_OBSTACK_PRINTF = @HAVE_DECL_OBSTACK_PRINTF@ +HAVE_DECL_SETENV = @HAVE_DECL_SETENV@ +HAVE_DECL_SETHOSTNAME = @HAVE_DECL_SETHOSTNAME@ +HAVE_DECL_SNPRINTF = @HAVE_DECL_SNPRINTF@ +HAVE_DECL_STRDUP = @HAVE_DECL_STRDUP@ +HAVE_DECL_STRERROR_R = @HAVE_DECL_STRERROR_R@ +HAVE_DECL_STRNCASECMP = @HAVE_DECL_STRNCASECMP@ +HAVE_DECL_STRNDUP = @HAVE_DECL_STRNDUP@ +HAVE_DECL_STRNLEN = @HAVE_DECL_STRNLEN@ +HAVE_DECL_STRSIGNAL = @HAVE_DECL_STRSIGNAL@ +HAVE_DECL_STRTOK_R = @HAVE_DECL_STRTOK_R@ +HAVE_DECL_TTYNAME_R = @HAVE_DECL_TTYNAME_R@ +HAVE_DECL_UNSETENV = @HAVE_DECL_UNSETENV@ +HAVE_DECL_VSNPRINTF = @HAVE_DECL_VSNPRINTF@ +HAVE_DECL_WCTOB = @HAVE_DECL_WCTOB@ +HAVE_DECL_WCWIDTH = @HAVE_DECL_WCWIDTH@ +HAVE_DPRINTF = @HAVE_DPRINTF@ +HAVE_DUP2 = @HAVE_DUP2@ +HAVE_DUP3 = @HAVE_DUP3@ +HAVE_DUPLOCALE = @HAVE_DUPLOCALE@ +HAVE_EUIDACCESS = @HAVE_EUIDACCESS@ +HAVE_FACCESSAT = @HAVE_FACCESSAT@ +HAVE_FCHDIR = @HAVE_FCHDIR@ +HAVE_FCHMODAT = @HAVE_FCHMODAT@ +HAVE_FCHOWNAT = @HAVE_FCHOWNAT@ +HAVE_FCNTL = @HAVE_FCNTL@ +HAVE_FDATASYNC = @HAVE_FDATASYNC@ +HAVE_FEATURES_H = @HAVE_FEATURES_H@ +HAVE_FFS = @HAVE_FFS@ +HAVE_FFSL = @HAVE_FFSL@ +HAVE_FFSLL = @HAVE_FFSLL@ +HAVE_FSEEKO = @HAVE_FSEEKO@ +HAVE_FSTATAT = @HAVE_FSTATAT@ +HAVE_FSYNC = @HAVE_FSYNC@ +HAVE_FTELLO = @HAVE_FTELLO@ +HAVE_FTRUNCATE = @HAVE_FTRUNCATE@ +HAVE_FUTIMENS = @HAVE_FUTIMENS@ +HAVE_GETDTABLESIZE = @HAVE_GETDTABLESIZE@ +HAVE_GETGROUPS = @HAVE_GETGROUPS@ +HAVE_GETHOSTNAME = @HAVE_GETHOSTNAME@ +HAVE_GETLOGIN = @HAVE_GETLOGIN@ +HAVE_GETOPT_H = @HAVE_GETOPT_H@ +HAVE_GETPAGESIZE = @HAVE_GETPAGESIZE@ +HAVE_GETSUBOPT = @HAVE_GETSUBOPT@ +HAVE_GETTIMEOFDAY = @HAVE_GETTIMEOFDAY@ +HAVE_GRANTPT = @HAVE_GRANTPT@ +HAVE_GROUP_MEMBER = @HAVE_GROUP_MEMBER@ +HAVE_INTTYPES_H = @HAVE_INTTYPES_H@ +HAVE_ISWBLANK = @HAVE_ISWBLANK@ +HAVE_ISWCNTRL = @HAVE_ISWCNTRL@ +HAVE_LANGINFO_CODESET = @HAVE_LANGINFO_CODESET@ +HAVE_LANGINFO_ERA = @HAVE_LANGINFO_ERA@ +HAVE_LANGINFO_H = @HAVE_LANGINFO_H@ +HAVE_LANGINFO_T_FMT_AMPM = @HAVE_LANGINFO_T_FMT_AMPM@ +HAVE_LANGINFO_YESEXPR = @HAVE_LANGINFO_YESEXPR@ +HAVE_LCHMOD = @HAVE_LCHMOD@ +HAVE_LCHOWN = @HAVE_LCHOWN@ +HAVE_LIBGNUTLS = @HAVE_LIBGNUTLS@ +HAVE_LIBSSL = @HAVE_LIBSSL@ +HAVE_LINK = @HAVE_LINK@ +HAVE_LINKAT = @HAVE_LINKAT@ +HAVE_LONG_LONG_INT = @HAVE_LONG_LONG_INT@ +HAVE_LSTAT = @HAVE_LSTAT@ +HAVE_MBRLEN = @HAVE_MBRLEN@ +HAVE_MBRTOWC = @HAVE_MBRTOWC@ +HAVE_MBSINIT = @HAVE_MBSINIT@ +HAVE_MBSLEN = @HAVE_MBSLEN@ +HAVE_MBSNRTOWCS = @HAVE_MBSNRTOWCS@ +HAVE_MBSRTOWCS = @HAVE_MBSRTOWCS@ +HAVE_MEMCHR = @HAVE_MEMCHR@ +HAVE_MEMPCPY = @HAVE_MEMPCPY@ +HAVE_MKDIRAT = @HAVE_MKDIRAT@ +HAVE_MKDTEMP = @HAVE_MKDTEMP@ +HAVE_MKFIFO = @HAVE_MKFIFO@ +HAVE_MKFIFOAT = @HAVE_MKFIFOAT@ +HAVE_MKNOD = @HAVE_MKNOD@ +HAVE_MKNODAT = @HAVE_MKNODAT@ +HAVE_MKOSTEMP = @HAVE_MKOSTEMP@ +HAVE_MKOSTEMPS = @HAVE_MKOSTEMPS@ +HAVE_MKSTEMP = @HAVE_MKSTEMP@ +HAVE_MKSTEMPS = @HAVE_MKSTEMPS@ +HAVE_MSVC_INVALID_PARAMETER_HANDLER = @HAVE_MSVC_INVALID_PARAMETER_HANDLER@ +HAVE_NANOSLEEP = @HAVE_NANOSLEEP@ +HAVE_NETDB_H = @HAVE_NETDB_H@ +HAVE_NETINET_IN_H = @HAVE_NETINET_IN_H@ +HAVE_NL_LANGINFO = @HAVE_NL_LANGINFO@ +HAVE_OPENAT = @HAVE_OPENAT@ +HAVE_OS_H = @HAVE_OS_H@ +HAVE_PCLOSE = @HAVE_PCLOSE@ +HAVE_PIPE = @HAVE_PIPE@ +HAVE_PIPE2 = @HAVE_PIPE2@ +HAVE_POPEN = @HAVE_POPEN@ +HAVE_POSIX_OPENPT = @HAVE_POSIX_OPENPT@ +HAVE_POSIX_SIGNALBLOCKING = @HAVE_POSIX_SIGNALBLOCKING@ +HAVE_POSIX_SPAWN = @HAVE_POSIX_SPAWN@ +HAVE_POSIX_SPAWNATTR_T = @HAVE_POSIX_SPAWNATTR_T@ +HAVE_POSIX_SPAWN_FILE_ACTIONS_T = @HAVE_POSIX_SPAWN_FILE_ACTIONS_T@ +HAVE_PREAD = @HAVE_PREAD@ +HAVE_PSELECT = @HAVE_PSELECT@ +HAVE_PTHREAD_SIGMASK = @HAVE_PTHREAD_SIGMASK@ +HAVE_PTSNAME = @HAVE_PTSNAME@ +HAVE_PTSNAME_R = @HAVE_PTSNAME_R@ +HAVE_PWRITE = @HAVE_PWRITE@ +HAVE_RAISE = @HAVE_RAISE@ +HAVE_RANDOM = @HAVE_RANDOM@ +HAVE_RANDOM_H = @HAVE_RANDOM_H@ +HAVE_RANDOM_R = @HAVE_RANDOM_R@ +HAVE_RAWMEMCHR = @HAVE_RAWMEMCHR@ +HAVE_READLINK = @HAVE_READLINK@ +HAVE_READLINKAT = @HAVE_READLINKAT@ +HAVE_REALPATH = @HAVE_REALPATH@ +HAVE_RENAMEAT = @HAVE_RENAMEAT@ +HAVE_RPMATCH = @HAVE_RPMATCH@ +HAVE_SA_FAMILY_T = @HAVE_SA_FAMILY_T@ +HAVE_SCHED_H = @HAVE_SCHED_H@ +HAVE_SECURE_GETENV = @HAVE_SECURE_GETENV@ +HAVE_SETENV = @HAVE_SETENV@ +HAVE_SETHOSTNAME = @HAVE_SETHOSTNAME@ +HAVE_SIGACTION = @HAVE_SIGACTION@ +HAVE_SIGHANDLER_T = @HAVE_SIGHANDLER_T@ +HAVE_SIGINFO_T = @HAVE_SIGINFO_T@ +HAVE_SIGNED_SIG_ATOMIC_T = @HAVE_SIGNED_SIG_ATOMIC_T@ +HAVE_SIGNED_WCHAR_T = @HAVE_SIGNED_WCHAR_T@ +HAVE_SIGNED_WINT_T = @HAVE_SIGNED_WINT_T@ +HAVE_SIGSET_T = @HAVE_SIGSET_T@ +HAVE_SLEEP = @HAVE_SLEEP@ +HAVE_SPAWN_H = @HAVE_SPAWN_H@ +HAVE_STDINT_H = @HAVE_STDINT_H@ +HAVE_STPCPY = @HAVE_STPCPY@ +HAVE_STPNCPY = @HAVE_STPNCPY@ +HAVE_STRCASECMP = @HAVE_STRCASECMP@ +HAVE_STRCASESTR = @HAVE_STRCASESTR@ +HAVE_STRCHRNUL = @HAVE_STRCHRNUL@ +HAVE_STRINGS_H = @HAVE_STRINGS_H@ +HAVE_STRPBRK = @HAVE_STRPBRK@ +HAVE_STRPTIME = @HAVE_STRPTIME@ +HAVE_STRSEP = @HAVE_STRSEP@ +HAVE_STRTOD = @HAVE_STRTOD@ +HAVE_STRTOLL = @HAVE_STRTOLL@ +HAVE_STRTOULL = @HAVE_STRTOULL@ +HAVE_STRUCT_ADDRINFO = @HAVE_STRUCT_ADDRINFO@ +HAVE_STRUCT_RANDOM_DATA = @HAVE_STRUCT_RANDOM_DATA@ +HAVE_STRUCT_SCHED_PARAM = @HAVE_STRUCT_SCHED_PARAM@ +HAVE_STRUCT_SIGACTION_SA_SIGACTION = @HAVE_STRUCT_SIGACTION_SA_SIGACTION@ +HAVE_STRUCT_SOCKADDR_STORAGE = @HAVE_STRUCT_SOCKADDR_STORAGE@ +HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY = @HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY@ +HAVE_STRUCT_TIMEVAL = @HAVE_STRUCT_TIMEVAL@ +HAVE_STRVERSCMP = @HAVE_STRVERSCMP@ +HAVE_SYMLINK = @HAVE_SYMLINK@ +HAVE_SYMLINKAT = @HAVE_SYMLINKAT@ +HAVE_SYS_BITYPES_H = @HAVE_SYS_BITYPES_H@ +HAVE_SYS_INTTYPES_H = @HAVE_SYS_INTTYPES_H@ +HAVE_SYS_IOCTL_H = @HAVE_SYS_IOCTL_H@ +HAVE_SYS_LOADAVG_H = @HAVE_SYS_LOADAVG_H@ +HAVE_SYS_PARAM_H = @HAVE_SYS_PARAM_H@ +HAVE_SYS_SELECT_H = @HAVE_SYS_SELECT_H@ +HAVE_SYS_SOCKET_H = @HAVE_SYS_SOCKET_H@ +HAVE_SYS_TIME_H = @HAVE_SYS_TIME_H@ +HAVE_SYS_TYPES_H = @HAVE_SYS_TYPES_H@ +HAVE_SYS_UIO_H = @HAVE_SYS_UIO_H@ +HAVE_TIMEGM = @HAVE_TIMEGM@ +HAVE_TYPE_VOLATILE_SIG_ATOMIC_T = @HAVE_TYPE_VOLATILE_SIG_ATOMIC_T@ +HAVE_UNISTD_H = @HAVE_UNISTD_H@ +HAVE_UNLINKAT = @HAVE_UNLINKAT@ +HAVE_UNLOCKPT = @HAVE_UNLOCKPT@ +HAVE_UNSIGNED_LONG_LONG_INT = @HAVE_UNSIGNED_LONG_LONG_INT@ +HAVE_USLEEP = @HAVE_USLEEP@ +HAVE_UTIMENSAT = @HAVE_UTIMENSAT@ +HAVE_VALGRIND = @HAVE_VALGRIND@ +HAVE_VASPRINTF = @HAVE_VASPRINTF@ +HAVE_VDPRINTF = @HAVE_VDPRINTF@ +HAVE_WCHAR_H = @HAVE_WCHAR_H@ +HAVE_WCHAR_T = @HAVE_WCHAR_T@ +HAVE_WCPCPY = @HAVE_WCPCPY@ +HAVE_WCPNCPY = @HAVE_WCPNCPY@ +HAVE_WCRTOMB = @HAVE_WCRTOMB@ +HAVE_WCSCASECMP = @HAVE_WCSCASECMP@ +HAVE_WCSCAT = @HAVE_WCSCAT@ +HAVE_WCSCHR = @HAVE_WCSCHR@ +HAVE_WCSCMP = @HAVE_WCSCMP@ +HAVE_WCSCOLL = @HAVE_WCSCOLL@ +HAVE_WCSCPY = @HAVE_WCSCPY@ +HAVE_WCSCSPN = @HAVE_WCSCSPN@ +HAVE_WCSDUP = @HAVE_WCSDUP@ +HAVE_WCSLEN = @HAVE_WCSLEN@ +HAVE_WCSNCASECMP = @HAVE_WCSNCASECMP@ +HAVE_WCSNCAT = @HAVE_WCSNCAT@ +HAVE_WCSNCMP = @HAVE_WCSNCMP@ +HAVE_WCSNCPY = @HAVE_WCSNCPY@ +HAVE_WCSNLEN = @HAVE_WCSNLEN@ +HAVE_WCSNRTOMBS = @HAVE_WCSNRTOMBS@ +HAVE_WCSPBRK = @HAVE_WCSPBRK@ +HAVE_WCSRCHR = @HAVE_WCSRCHR@ +HAVE_WCSRTOMBS = @HAVE_WCSRTOMBS@ +HAVE_WCSSPN = @HAVE_WCSSPN@ +HAVE_WCSSTR = @HAVE_WCSSTR@ +HAVE_WCSTOK = @HAVE_WCSTOK@ +HAVE_WCSWIDTH = @HAVE_WCSWIDTH@ +HAVE_WCSXFRM = @HAVE_WCSXFRM@ +HAVE_WCTRANS_T = @HAVE_WCTRANS_T@ +HAVE_WCTYPE_H = @HAVE_WCTYPE_H@ +HAVE_WCTYPE_T = @HAVE_WCTYPE_T@ +HAVE_WINSOCK2_H = @HAVE_WINSOCK2_H@ +HAVE_WINT_T = @HAVE_WINT_T@ +HAVE_WMEMCHR = @HAVE_WMEMCHR@ +HAVE_WMEMCMP = @HAVE_WMEMCMP@ +HAVE_WMEMCPY = @HAVE_WMEMCPY@ +HAVE_WMEMMOVE = @HAVE_WMEMMOVE@ +HAVE_WMEMSET = @HAVE_WMEMSET@ +HAVE_WS2TCPIP_H = @HAVE_WS2TCPIP_H@ +HAVE_XLOCALE_H = @HAVE_XLOCALE_H@ +HAVE__BOOL = @HAVE__BOOL@ +HAVE__EXIT = @HAVE__EXIT@ +HOSTENT_LIB = @HOSTENT_LIB@ +ICONV_CONST = @ICONV_CONST@ +ICONV_H = @ICONV_H@ +INCLUDE_NEXT = @INCLUDE_NEXT@ +INCLUDE_NEXT_AS_FIRST_DIRECTIVE = @INCLUDE_NEXT_AS_FIRST_DIRECTIVE@ +INET_NTOP_LIB = @INET_NTOP_LIB@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBGNUTLS = @LIBGNUTLS@ +LIBGNUTLS_PREFIX = @LIBGNUTLS_PREFIX@ +LIBGNU_LIBDEPS = @LIBGNU_LIBDEPS@ +LIBGNU_LTLIBDEPS = @LIBGNU_LTLIBDEPS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBMULTITHREAD = @LIBMULTITHREAD@ +LIBOBJS = @LIBOBJS@ +LIBPSL_CFLAGS = @LIBPSL_CFLAGS@ +LIBPSL_LIBS = @LIBPSL_LIBS@ +LIBPTH = @LIBPTH@ +LIBPTH_PREFIX = @LIBPTH_PREFIX@ +LIBS = @LIBS@ +LIBSOCKET = @LIBSOCKET@ +LIBSSL = @LIBSSL@ +LIBSSL_PREFIX = @LIBSSL_PREFIX@ +LIBTHREAD = @LIBTHREAD@ +LIBUNISTRING_UNITYPES_H = @LIBUNISTRING_UNITYPES_H@ +LIBUNISTRING_UNIWIDTH_H = @LIBUNISTRING_UNIWIDTH_H@ +LIB_CLOCK_GETTIME = @LIB_CLOCK_GETTIME@ +LIB_CRYPTO = @LIB_CRYPTO@ +LIB_POSIX_SPAWN = @LIB_POSIX_SPAWN@ +LIB_SELECT = @LIB_SELECT@ +LOCALCHARSET_TESTS_ENVIRONMENT = @LOCALCHARSET_TESTS_ENVIRONMENT@ +LOCALE_FR = @LOCALE_FR@ +LOCALE_FR_UTF8 = @LOCALE_FR_UTF8@ +LOCALE_JA = @LOCALE_JA@ +LOCALE_ZH_CN = @LOCALE_ZH_CN@ +LTLIBGNUTLS = @LTLIBGNUTLS@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBMULTITHREAD = @LTLIBMULTITHREAD@ +LTLIBOBJS = @LTLIBOBJS@ +LTLIBPTH = @LTLIBPTH@ +LTLIBSSL = @LTLIBSSL@ +LTLIBTHREAD = @LTLIBTHREAD@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NETINET_IN_H = @NETINET_IN_H@ +NETTLE_LIBS = @NETTLE_LIBS@ +NEXT_ARPA_INET_H = @NEXT_ARPA_INET_H@ +NEXT_AS_FIRST_DIRECTIVE_ARPA_INET_H = @NEXT_AS_FIRST_DIRECTIVE_ARPA_INET_H@ +NEXT_AS_FIRST_DIRECTIVE_ERRNO_H = @NEXT_AS_FIRST_DIRECTIVE_ERRNO_H@ +NEXT_AS_FIRST_DIRECTIVE_FCNTL_H = @NEXT_AS_FIRST_DIRECTIVE_FCNTL_H@ +NEXT_AS_FIRST_DIRECTIVE_FLOAT_H = @NEXT_AS_FIRST_DIRECTIVE_FLOAT_H@ +NEXT_AS_FIRST_DIRECTIVE_GETOPT_H = @NEXT_AS_FIRST_DIRECTIVE_GETOPT_H@ +NEXT_AS_FIRST_DIRECTIVE_ICONV_H = @NEXT_AS_FIRST_DIRECTIVE_ICONV_H@ +NEXT_AS_FIRST_DIRECTIVE_LANGINFO_H = @NEXT_AS_FIRST_DIRECTIVE_LANGINFO_H@ +NEXT_AS_FIRST_DIRECTIVE_LOCALE_H = @NEXT_AS_FIRST_DIRECTIVE_LOCALE_H@ +NEXT_AS_FIRST_DIRECTIVE_NETDB_H = @NEXT_AS_FIRST_DIRECTIVE_NETDB_H@ +NEXT_AS_FIRST_DIRECTIVE_NETINET_IN_H = @NEXT_AS_FIRST_DIRECTIVE_NETINET_IN_H@ +NEXT_AS_FIRST_DIRECTIVE_SCHED_H = @NEXT_AS_FIRST_DIRECTIVE_SCHED_H@ +NEXT_AS_FIRST_DIRECTIVE_SIGNAL_H = @NEXT_AS_FIRST_DIRECTIVE_SIGNAL_H@ +NEXT_AS_FIRST_DIRECTIVE_SPAWN_H = @NEXT_AS_FIRST_DIRECTIVE_SPAWN_H@ +NEXT_AS_FIRST_DIRECTIVE_STDDEF_H = @NEXT_AS_FIRST_DIRECTIVE_STDDEF_H@ +NEXT_AS_FIRST_DIRECTIVE_STDINT_H = @NEXT_AS_FIRST_DIRECTIVE_STDINT_H@ +NEXT_AS_FIRST_DIRECTIVE_STDIO_H = @NEXT_AS_FIRST_DIRECTIVE_STDIO_H@ +NEXT_AS_FIRST_DIRECTIVE_STDLIB_H = @NEXT_AS_FIRST_DIRECTIVE_STDLIB_H@ +NEXT_AS_FIRST_DIRECTIVE_STRINGS_H = @NEXT_AS_FIRST_DIRECTIVE_STRINGS_H@ +NEXT_AS_FIRST_DIRECTIVE_STRING_H = @NEXT_AS_FIRST_DIRECTIVE_STRING_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_IOCTL_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_IOCTL_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_SELECT_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_SELECT_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_SOCKET_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_SOCKET_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_STAT_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_STAT_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_TIME_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_TIME_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_TYPES_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_TYPES_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_UIO_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_UIO_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_WAIT_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_WAIT_H@ +NEXT_AS_FIRST_DIRECTIVE_TIME_H = @NEXT_AS_FIRST_DIRECTIVE_TIME_H@ +NEXT_AS_FIRST_DIRECTIVE_UNISTD_H = @NEXT_AS_FIRST_DIRECTIVE_UNISTD_H@ +NEXT_AS_FIRST_DIRECTIVE_WCHAR_H = @NEXT_AS_FIRST_DIRECTIVE_WCHAR_H@ +NEXT_AS_FIRST_DIRECTIVE_WCTYPE_H = @NEXT_AS_FIRST_DIRECTIVE_WCTYPE_H@ +NEXT_ERRNO_H = @NEXT_ERRNO_H@ +NEXT_FCNTL_H = @NEXT_FCNTL_H@ +NEXT_FLOAT_H = @NEXT_FLOAT_H@ +NEXT_GETOPT_H = @NEXT_GETOPT_H@ +NEXT_ICONV_H = @NEXT_ICONV_H@ +NEXT_LANGINFO_H = @NEXT_LANGINFO_H@ +NEXT_LOCALE_H = @NEXT_LOCALE_H@ +NEXT_NETDB_H = @NEXT_NETDB_H@ +NEXT_NETINET_IN_H = @NEXT_NETINET_IN_H@ +NEXT_SCHED_H = @NEXT_SCHED_H@ +NEXT_SIGNAL_H = @NEXT_SIGNAL_H@ +NEXT_SPAWN_H = @NEXT_SPAWN_H@ +NEXT_STDDEF_H = @NEXT_STDDEF_H@ +NEXT_STDINT_H = @NEXT_STDINT_H@ +NEXT_STDIO_H = @NEXT_STDIO_H@ +NEXT_STDLIB_H = @NEXT_STDLIB_H@ +NEXT_STRINGS_H = @NEXT_STRINGS_H@ +NEXT_STRING_H = @NEXT_STRING_H@ +NEXT_SYS_IOCTL_H = @NEXT_SYS_IOCTL_H@ +NEXT_SYS_SELECT_H = @NEXT_SYS_SELECT_H@ +NEXT_SYS_SOCKET_H = @NEXT_SYS_SOCKET_H@ +NEXT_SYS_STAT_H = @NEXT_SYS_STAT_H@ +NEXT_SYS_TIME_H = @NEXT_SYS_TIME_H@ +NEXT_SYS_TYPES_H = @NEXT_SYS_TYPES_H@ +NEXT_SYS_UIO_H = @NEXT_SYS_UIO_H@ +NEXT_SYS_WAIT_H = @NEXT_SYS_WAIT_H@ +NEXT_TIME_H = @NEXT_TIME_H@ +NEXT_UNISTD_H = @NEXT_UNISTD_H@ +NEXT_WCHAR_H = @NEXT_WCHAR_H@ +NEXT_WCTYPE_H = @NEXT_WCTYPE_H@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PCRE_CFLAGS = @PCRE_CFLAGS@ +PCRE_LIBS = @PCRE_LIBS@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POD2MAN = @POD2MAN@ +POSUB = @POSUB@ +PRAGMA_COLUMNS = @PRAGMA_COLUMNS@ +PRAGMA_SYSTEM_HEADER = @PRAGMA_SYSTEM_HEADER@ +PTHREAD_H_DEFINES_STRUCT_TIMESPEC = @PTHREAD_H_DEFINES_STRUCT_TIMESPEC@ +PTRDIFF_T_SUFFIX = @PTRDIFF_T_SUFFIX@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +REPLACE_BTOWC = @REPLACE_BTOWC@ +REPLACE_CALLOC = @REPLACE_CALLOC@ +REPLACE_CANONICALIZE_FILE_NAME = @REPLACE_CANONICALIZE_FILE_NAME@ +REPLACE_CHOWN = @REPLACE_CHOWN@ +REPLACE_CLOSE = @REPLACE_CLOSE@ +REPLACE_DPRINTF = @REPLACE_DPRINTF@ +REPLACE_DUP = @REPLACE_DUP@ +REPLACE_DUP2 = @REPLACE_DUP2@ +REPLACE_DUPLOCALE = @REPLACE_DUPLOCALE@ +REPLACE_FCHOWNAT = @REPLACE_FCHOWNAT@ +REPLACE_FCLOSE = @REPLACE_FCLOSE@ +REPLACE_FCNTL = @REPLACE_FCNTL@ +REPLACE_FDOPEN = @REPLACE_FDOPEN@ +REPLACE_FFLUSH = @REPLACE_FFLUSH@ +REPLACE_FOPEN = @REPLACE_FOPEN@ +REPLACE_FPRINTF = @REPLACE_FPRINTF@ +REPLACE_FPURGE = @REPLACE_FPURGE@ +REPLACE_FREOPEN = @REPLACE_FREOPEN@ +REPLACE_FSEEK = @REPLACE_FSEEK@ +REPLACE_FSEEKO = @REPLACE_FSEEKO@ +REPLACE_FSTAT = @REPLACE_FSTAT@ +REPLACE_FSTATAT = @REPLACE_FSTATAT@ +REPLACE_FTELL = @REPLACE_FTELL@ +REPLACE_FTELLO = @REPLACE_FTELLO@ +REPLACE_FTRUNCATE = @REPLACE_FTRUNCATE@ +REPLACE_FUTIMENS = @REPLACE_FUTIMENS@ +REPLACE_GAI_STRERROR = @REPLACE_GAI_STRERROR@ +REPLACE_GETCWD = @REPLACE_GETCWD@ +REPLACE_GETDELIM = @REPLACE_GETDELIM@ +REPLACE_GETDOMAINNAME = @REPLACE_GETDOMAINNAME@ +REPLACE_GETDTABLESIZE = @REPLACE_GETDTABLESIZE@ +REPLACE_GETGROUPS = @REPLACE_GETGROUPS@ +REPLACE_GETLINE = @REPLACE_GETLINE@ +REPLACE_GETLOGIN_R = @REPLACE_GETLOGIN_R@ +REPLACE_GETPAGESIZE = @REPLACE_GETPAGESIZE@ +REPLACE_GETTIMEOFDAY = @REPLACE_GETTIMEOFDAY@ +REPLACE_GMTIME = @REPLACE_GMTIME@ +REPLACE_ICONV = @REPLACE_ICONV@ +REPLACE_ICONV_OPEN = @REPLACE_ICONV_OPEN@ +REPLACE_ICONV_UTF = @REPLACE_ICONV_UTF@ +REPLACE_INET_NTOP = @REPLACE_INET_NTOP@ +REPLACE_INET_PTON = @REPLACE_INET_PTON@ +REPLACE_IOCTL = @REPLACE_IOCTL@ +REPLACE_ISATTY = @REPLACE_ISATTY@ +REPLACE_ISWBLANK = @REPLACE_ISWBLANK@ +REPLACE_ISWCNTRL = @REPLACE_ISWCNTRL@ +REPLACE_ITOLD = @REPLACE_ITOLD@ +REPLACE_LCHOWN = @REPLACE_LCHOWN@ +REPLACE_LINK = @REPLACE_LINK@ +REPLACE_LINKAT = @REPLACE_LINKAT@ +REPLACE_LOCALECONV = @REPLACE_LOCALECONV@ +REPLACE_LOCALTIME = @REPLACE_LOCALTIME@ +REPLACE_LOCALTIME_R = @REPLACE_LOCALTIME_R@ +REPLACE_LSEEK = @REPLACE_LSEEK@ +REPLACE_LSTAT = @REPLACE_LSTAT@ +REPLACE_MALLOC = @REPLACE_MALLOC@ +REPLACE_MBRLEN = @REPLACE_MBRLEN@ +REPLACE_MBRTOWC = @REPLACE_MBRTOWC@ +REPLACE_MBSINIT = @REPLACE_MBSINIT@ +REPLACE_MBSNRTOWCS = @REPLACE_MBSNRTOWCS@ +REPLACE_MBSRTOWCS = @REPLACE_MBSRTOWCS@ +REPLACE_MBSTATE_T = @REPLACE_MBSTATE_T@ +REPLACE_MBTOWC = @REPLACE_MBTOWC@ +REPLACE_MEMCHR = @REPLACE_MEMCHR@ +REPLACE_MEMMEM = @REPLACE_MEMMEM@ +REPLACE_MKDIR = @REPLACE_MKDIR@ +REPLACE_MKFIFO = @REPLACE_MKFIFO@ +REPLACE_MKNOD = @REPLACE_MKNOD@ +REPLACE_MKSTEMP = @REPLACE_MKSTEMP@ +REPLACE_MKTIME = @REPLACE_MKTIME@ +REPLACE_NANOSLEEP = @REPLACE_NANOSLEEP@ +REPLACE_NL_LANGINFO = @REPLACE_NL_LANGINFO@ +REPLACE_NULL = @REPLACE_NULL@ +REPLACE_OBSTACK_PRINTF = @REPLACE_OBSTACK_PRINTF@ +REPLACE_OPEN = @REPLACE_OPEN@ +REPLACE_OPENAT = @REPLACE_OPENAT@ +REPLACE_PERROR = @REPLACE_PERROR@ +REPLACE_POPEN = @REPLACE_POPEN@ +REPLACE_POSIX_SPAWN = @REPLACE_POSIX_SPAWN@ +REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE = @REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE@ +REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2 = @REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2@ +REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN = @REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN@ +REPLACE_PREAD = @REPLACE_PREAD@ +REPLACE_PRINTF = @REPLACE_PRINTF@ +REPLACE_PSELECT = @REPLACE_PSELECT@ +REPLACE_PTHREAD_SIGMASK = @REPLACE_PTHREAD_SIGMASK@ +REPLACE_PTSNAME = @REPLACE_PTSNAME@ +REPLACE_PTSNAME_R = @REPLACE_PTSNAME_R@ +REPLACE_PUTENV = @REPLACE_PUTENV@ +REPLACE_PWRITE = @REPLACE_PWRITE@ +REPLACE_QSORT_R = @REPLACE_QSORT_R@ +REPLACE_RAISE = @REPLACE_RAISE@ +REPLACE_RANDOM_R = @REPLACE_RANDOM_R@ +REPLACE_READ = @REPLACE_READ@ +REPLACE_READLINK = @REPLACE_READLINK@ +REPLACE_READLINKAT = @REPLACE_READLINKAT@ +REPLACE_REALLOC = @REPLACE_REALLOC@ +REPLACE_REALPATH = @REPLACE_REALPATH@ +REPLACE_REMOVE = @REPLACE_REMOVE@ +REPLACE_RENAME = @REPLACE_RENAME@ +REPLACE_RENAMEAT = @REPLACE_RENAMEAT@ +REPLACE_RMDIR = @REPLACE_RMDIR@ +REPLACE_SELECT = @REPLACE_SELECT@ +REPLACE_SETENV = @REPLACE_SETENV@ +REPLACE_SETLOCALE = @REPLACE_SETLOCALE@ +REPLACE_SLEEP = @REPLACE_SLEEP@ +REPLACE_SNPRINTF = @REPLACE_SNPRINTF@ +REPLACE_SPRINTF = @REPLACE_SPRINTF@ +REPLACE_STAT = @REPLACE_STAT@ +REPLACE_STDIO_READ_FUNCS = @REPLACE_STDIO_READ_FUNCS@ +REPLACE_STDIO_WRITE_FUNCS = @REPLACE_STDIO_WRITE_FUNCS@ +REPLACE_STPNCPY = @REPLACE_STPNCPY@ +REPLACE_STRCASESTR = @REPLACE_STRCASESTR@ +REPLACE_STRCHRNUL = @REPLACE_STRCHRNUL@ +REPLACE_STRDUP = @REPLACE_STRDUP@ +REPLACE_STRERROR = @REPLACE_STRERROR@ +REPLACE_STRERROR_R = @REPLACE_STRERROR_R@ +REPLACE_STRNCAT = @REPLACE_STRNCAT@ +REPLACE_STRNDUP = @REPLACE_STRNDUP@ +REPLACE_STRNLEN = @REPLACE_STRNLEN@ +REPLACE_STRSIGNAL = @REPLACE_STRSIGNAL@ +REPLACE_STRSTR = @REPLACE_STRSTR@ +REPLACE_STRTOD = @REPLACE_STRTOD@ +REPLACE_STRTOK_R = @REPLACE_STRTOK_R@ +REPLACE_STRUCT_LCONV = @REPLACE_STRUCT_LCONV@ +REPLACE_STRUCT_TIMEVAL = @REPLACE_STRUCT_TIMEVAL@ +REPLACE_SYMLINK = @REPLACE_SYMLINK@ +REPLACE_SYMLINKAT = @REPLACE_SYMLINKAT@ +REPLACE_TIMEGM = @REPLACE_TIMEGM@ +REPLACE_TMPFILE = @REPLACE_TMPFILE@ +REPLACE_TOWLOWER = @REPLACE_TOWLOWER@ +REPLACE_TTYNAME_R = @REPLACE_TTYNAME_R@ +REPLACE_UNLINK = @REPLACE_UNLINK@ +REPLACE_UNLINKAT = @REPLACE_UNLINKAT@ +REPLACE_UNSETENV = @REPLACE_UNSETENV@ +REPLACE_USLEEP = @REPLACE_USLEEP@ +REPLACE_UTIMENSAT = @REPLACE_UTIMENSAT@ +REPLACE_VASPRINTF = @REPLACE_VASPRINTF@ +REPLACE_VDPRINTF = @REPLACE_VDPRINTF@ +REPLACE_VFPRINTF = @REPLACE_VFPRINTF@ +REPLACE_VPRINTF = @REPLACE_VPRINTF@ +REPLACE_VSNPRINTF = @REPLACE_VSNPRINTF@ +REPLACE_VSPRINTF = @REPLACE_VSPRINTF@ +REPLACE_WCRTOMB = @REPLACE_WCRTOMB@ +REPLACE_WCSNRTOMBS = @REPLACE_WCSNRTOMBS@ +REPLACE_WCSRTOMBS = @REPLACE_WCSRTOMBS@ +REPLACE_WCSWIDTH = @REPLACE_WCSWIDTH@ +REPLACE_WCTOB = @REPLACE_WCTOB@ +REPLACE_WCTOMB = @REPLACE_WCTOMB@ +REPLACE_WCWIDTH = @REPLACE_WCWIDTH@ +REPLACE_WRITE = @REPLACE_WRITE@ +SCHED_H = @SCHED_H@ +SED = @SED@ +SERVENT_LIB = @SERVENT_LIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SIG_ATOMIC_T_SUFFIX = @SIG_ATOMIC_T_SUFFIX@ +SIZE_T_SUFFIX = @SIZE_T_SUFFIX@ +STDALIGN_H = @STDALIGN_H@ +STDBOOL_H = @STDBOOL_H@ +STDDEF_H = @STDDEF_H@ +STDINT_H = @STDINT_H@ +STRIP = @STRIP@ +SYS_IOCTL_H_HAVE_WINSOCK2_H = @SYS_IOCTL_H_HAVE_WINSOCK2_H@ +SYS_IOCTL_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS = @SYS_IOCTL_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS@ +SYS_TIME_H_DEFINES_STRUCT_TIMESPEC = @SYS_TIME_H_DEFINES_STRUCT_TIMESPEC@ +TIME_H_DEFINES_STRUCT_TIMESPEC = @TIME_H_DEFINES_STRUCT_TIMESPEC@ +UNDEFINE_STRTOK_R = @UNDEFINE_STRTOK_R@ +UNISTD_H_HAVE_WINSOCK2_H = @UNISTD_H_HAVE_WINSOCK2_H@ +UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS = @UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS@ +USE_NLS = @USE_NLS@ +UUID_CFLAGS = @UUID_CFLAGS@ +UUID_LIBS = @UUID_LIBS@ +VALGRIND_TESTS = @VALGRIND_TESTS@ +VERSION = @VERSION@ +WCHAR_T_SUFFIX = @WCHAR_T_SUFFIX@ +WINDOWS_64_BIT_OFF_T = @WINDOWS_64_BIT_OFF_T@ +WINDOWS_64_BIT_ST_SIZE = @WINDOWS_64_BIT_ST_SIZE@ +WINT_T_SUFFIX = @WINT_T_SUFFIX@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gl_LIBOBJS = @gl_LIBOBJS@ +gl_LTLIBOBJS = @gl_LTLIBOBJS@ +gltests_LIBOBJS = @gltests_LIBOBJS@ +gltests_LTLIBOBJS = @gltests_LTLIBOBJS@ +gltests_WITNESS = @gltests_WITNESS@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +lispdir = @lispdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = parallel-tests +AM_TESTS_ENVIRONMENT = export WGETRC=/dev/null; MAKE_CHECK=True; export MAKE_CHECK;\ + export PYTHONPATH=$$PYTHONPATH:$(srcdir); export VALGRIND_TESTS="@VALGRIND_TESTS@"; + +@HAVE_PYTHON3_TRUE@TESTS = Test-auth-basic-fail.py \ +@HAVE_PYTHON3_TRUE@ Test-auth-basic.py \ +@HAVE_PYTHON3_TRUE@ Test-auth-both.py \ +@HAVE_PYTHON3_TRUE@ Test-auth-digest.py \ +@HAVE_PYTHON3_TRUE@ Test-auth-no-challenge.py \ +@HAVE_PYTHON3_TRUE@ Test-auth-no-challenge-url.py \ +@HAVE_PYTHON3_TRUE@ Test-auth-retcode.py \ +@HAVE_PYTHON3_TRUE@ Test-auth-with-content-disposition.py \ +@HAVE_PYTHON3_TRUE@ Test-c-full.py \ +@HAVE_PYTHON3_TRUE@ Test-Content-disposition-2.py \ +@HAVE_PYTHON3_TRUE@ Test-Content-disposition.py \ +@HAVE_PYTHON3_TRUE@ Test-cookie-401.py \ +@HAVE_PYTHON3_TRUE@ Test-cookie-domain-mismatch.py \ +@HAVE_PYTHON3_TRUE@ Test-cookie-expires.py \ +@HAVE_PYTHON3_TRUE@ Test-cookie.py \ +@HAVE_PYTHON3_TRUE@ Test-Head.py \ +@HAVE_PYTHON3_TRUE@ Test--https.py \ +@HAVE_PYTHON3_TRUE@ Test--https-crl.py \ +@HAVE_PYTHON3_TRUE@ Test-O.py \ +@HAVE_PYTHON3_TRUE@ Test-Post.py \ +@HAVE_PYTHON3_TRUE@ Test-504.py \ +@HAVE_PYTHON3_TRUE@ Test--spider-r.py \ +@HAVE_PYTHON3_TRUE@ Test-redirect-crash.py + +EXTRA_DIST = certs conf exc misc server test README $(TESTS) $(XFAIL_TESTS) +TEST_EXTENSIONS = .py +PY_LOG_COMPILER = python3 +AM_PY_LOG_FLAGS = -O +all: all-am + +.SUFFIXES: +.SUFFIXES: .log .py .py$(EXEEXT) .trs +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu testenv/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu testenv/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + else \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ + else \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ + fi; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ + else \ + color_start= color_end=; \ + fi; \ + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +.py.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(PY_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_PY_LOG_DRIVER_FLAGS) $(PY_LOG_DRIVER_FLAGS) -- $(PY_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.py$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(PY_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_PY_LOG_DRIVER_FLAGS) $(PY_LOG_DRIVER_FLAGS) -- $(PY_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: check-am install-am install-strip + +.PHONY: all all-am check check-TESTS check-am clean clean-generic \ + cscopelist-am ctags-am distclean distclean-generic distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am recheck tags-am uninstall uninstall-am + + +@HAVE_PYTHON3_TRUE@ # added test cases expected to fail here and under TESTS + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/testenv/README b/testenv/README new file mode 100644 index 0000000..081a957 --- /dev/null +++ b/testenv/README @@ -0,0 +1,305 @@ +This document describes the working of the GNU Wget Test Suite. + +Install Instructions: +================================================================================ + +This Test Suite exploits the Parallel Test Harness available in GNU Autotools. +Since it uses features from a relatively recent verion of Autotools, the minimum +required version as been bumped up to 1.11. +Run the './configure' command to generate the Makefile and then run 'make check' +to execute the Test Suite. Use the '-j n' option with 'make check' to execute +n tests simultaneously. + +Structure: +================================================================================ + + * server: This package contains custom programmatically configurable servers + (both HTTP and FTP) for testing Wget. The HTTP server runs an instance of + Python's http.server module. The FTP server is to be implemented. + + * test: This package contains the test case classes for HTTP and FTP. The + test case classes includes methods for initializing and cleaning up of the + test environment. + + * Test-Proto.py: This is a prototype Test Case file. The file defines all + the acceptable elements and their uses. Typically, one must copy this file + and edit it for writing Test Cases. + + * exc: This package contains custom exception classes used in this test + suite. + + * conf: This package contains the configuration classes for servers to be + configured with. + + * misc: This package contains several helper modules used in this test + suite. + - colour_terminal.py: A custom module for printing coloured output to + the terminal. Currently it only supports 4 colours in a *nix + environment. + - wget_file.py: Module which contains WgetFile, which is a file data + container object. + +Working: +================================================================================ + +The Test Files are valid Python scripts and the default mask for them is 755. +A singular Test must be invoked in the following manner: +$ ./python3 <Name of Test File> OR +$ ./<Name of Test File> +The script will then initialize the various elements and pass them to an object +of the respective Test Class. A directory with the name <Test name>-test will be +created and the PWD will be changed to this directory. The server is then +spawned with the required configuration elements. A blocking call to Wget is +made with the command line arguments specified in the Test Case along with the +list of URLs that it must download. The server is killed once Wget returns and +the following checks are used to determine the pass/fail status of the test: + * Return Code: The Exit code of Wget is matched against the expected Exit + Code as mentioned in the Test Case File. + * Downloaded Files: Check whether the expected downloaded files exist on + disk. + * File Content: Test whether the file contents were correctly downloaded by + Wget and not corrupted mid-way. + * Excess Files: Check to see whether any unexpected files were downloaded + by Wget. + +Exit Codes: +=============================================================================== + +Following is a list of Exit Status Codes for the tests: +* 0 Test Successful +* 66 Errors/Warnings Reported by Thread Sanitizer (If built with -fsanitize) +* 77 Test Skipped +* 99 Hard Error +* 100 Test Failed + +Tests are skipped when they are either not supported by the platform, or Wget +is not compiled with support for that feature. This feature has not yet been +implemented. + +Hard Errors occur when there are problems with the Environment code. Hard +Error reporting is currently not enabled and all errors are reported as +failures. + +All exceptions should ideally be handled gracefully. If you see any unhandled +exceptions, please file a bug report at <bug-wget@gnu.org> + +Environment Variables: +================================================================================ + +* SERVER_WAIT: Set this environment variable with a value for the number of + seconds the test should sleep between invoking the server and calling the Wget + executable. This is used when one would like to test a different version of + the executable or for running the test through external utilities like gdb and + valgrind. +* NO_CLEANUP: Do not remove the temporary files created by the test. + This will prevent the ${testname}-test directory from being deleted +* VALGRIND_TESTS: If this variable is set and contains the valgrind command line, + the test suite will execute all the tests via this command. + If it is set to "1", valgrind memcheck is enabled with hard coded options. + This variable is set by ./configure --enable-valgrind-tests. + + +File Structure: +================================================================================ + +The test case files are Python scripts. It is believed that Python is a simple +yet elegant language and should be easy for everyone to comprehend. This test +suite is written with the objective of making it easy to write new tests. The +structure has been kept as intuitive as possible and should not require much +effort to get accustomed to. + +All Test Files MUST begin with the following Three Lines: +#!/usr/bin/python3 +from sys import exit +from WgetTest import {HTTPTest|FTPTest} +from misc.wget_file import WgetFile + +It is recommended that a small description of the Test Case is provided next. +This would be very helpful to future contributors. +Next, is the const variable, TEST_NAME that defines the name of the Test. + +Each File in the Test must be represented as a WgetFile object. The WgetFile +Class has the following prototype: +WgetFile (str name, str contents, str timestamp, dict rules) +None except name is a mandatory paramter, one may pass only those parameters +that are required by the File object. + +The timestamp string should be a valid Unix Timestamp as defined in RFC xxxx. +The rules object is a dictionary element, with the key as the Rule Name and +value as the Rule Data. In most cases, the Rule Data is another dictionary. + +Various variables used consistently across all tests are: + * WGET_OPTIONS: The command line string passed to Wget upon invokation. This + string may contain URLs, like in the case where in-URL authentication is + used. Variable names passed like {{var_name}} will be replaced by the + contents of the variable self.var_name before being passed to Wget + * WGET_URLS: This is a list of filenames which will be appended as the URLs + to Wget during invokation. This is a list of lists, where WGET_URLS[0] + represents the list of Filenames called from Server[0], WGET_URLS[1] is a + list of files downloaded from Server[2], etc. + * Files: This variable defines the files that exist in the Server's + filesystem. The Files variable is a list of lists of WgetFile objects. + This means that File[0] is a list of WgetFile objects that lie on Server[0], + File[1] a list of files on Server[1] and so on. + * Existing_Files: This is a list of files that already exist in the + directory from which Wget is invoked. + * ExpectedReturnCode: The Exit Code expected to be returned by Wget after + the test. + * ExpectedDownloadedFiles: A list of files that are expected in the local + directory after Wget has finished executing. This does not include the files + already existing before Wget was launched and must be mentioned again. + * Request_List: An unordered list of Requests that each server must receive. + This too is a list of lists and follows the same convention as others above. + +Both, the HTTPTest and FTPTest modules have the same prototype: +{ + name, + pre_hook, + test_options, + post_hook, + protocols +} +name should be a string, and is usually passed to the TEST_NAME variable, +the three hooks should be Python dict objects and protocols should be a list of +protocols, like [HTTP, HTTPS]. + +Valid File Rules: +================================================================================ + +This section lists the currently supported File Rules and their structure. + + * Authentication: Used when a File must require Authorization for access. + The value for this key is the following dictionary: + |-->Type : Basic|Digest|Both|Both_inline + |-->User : <Username> + --->Pass : <Password> + + * ExpectHeader : The following Headers MUST exist in every Request for the + File. The value for this key is a dictionary object where each header is + represented as: + |-->Header Name : <Header Data> + + * RejectHeader : This list of Headers must NEVER occur in a request. It + uses the same value format as ExpectHeader. + + * SendHeader : This list of Headers will be sent in EVERY response to a + request for the respective file. It follows the same value format as + ExpectHeader. + + * Response : The HTTP Response Code to send to a request for this File. + The value is an Integer that represents a valid HTTP Response Code. + +Pre Test Hooks: +================================================================================ + +The Pre-Test Hooks are executed just after starting the server and just before +spawning an instance of the server. These are usually used for setting up the +Test Environment and Server Rules. The currently supported Pre-Test Hooks are: + + * ServerFiles : A list of WgetFile objects that must exist on the Server + * LocalFiles : A list of WgetFile objects that exist locally on disk + before Wget is executed. + +Since pre_test is a dictionary, one may not assume that the hooks will be +executed in the same order as they are defined. + +Test Options: +================================================================================ + +The test_options dictionary defines the commands to be used when the Test is +executed. The currently supported options are: + + * Urls : A list of the filenames that Wget must attempt to + download. The complete URL will be created and passed to Wget + automatically. (alias URLs) + * WgetCommands : A string consisting of the various commandline switches + sent to Wget upon invokation. Any data placed between {{ }} in this string + will be replaced with the contents of self.<data> before being passed to + Wget. This is particularly useful for getting the hostname and port for a + file. While all Download URL's are passed to Urls, a notable exception is + when in-url authentication is used. In such a case, the URL is specified in + the WgetCommands string. + +Post-Test Hooks: +================================================================================ + +These hooks are executed as soon as the call to Wget returns. The post-test +hooks are usually used to run checks on the data, files downloaded, return code, +etc. The following hooks are currently supported: + + * ExpectedRetcode : This is an integer value of the ReturnCode with which + Wget is expected to exit. (alias ExpectedRetCode) + * ExpectedFiles : This is a list of WgetFile objects of the files that + must exist locally on disk in the Test directory. + * FilesCrawled : This requires a list of the Requests that the server is + expected to receive. The order is un-important since it will vary on the + parallel-wget branch. This hook is used in tests for Recursive mode to + ensure that the website is traversed correctly. + +Writing New Tests: +================================================================================ + +See Test-Proto.py for an example of how to write Test Case files. The +recommended method for writing new Test Case files is to copy Test-Proto.py and +modify it to ones needs. + +In case you require any functionality that is not currently defined in List of +Rules defined above, you should implement a new class in the conf package. The +file name doesn't matter (though it's better to give it an appropriate name). +The new rule or hook class should be like this: +============================================ +from conf import rule + + +@rule() +class MyNewRule: + def __init__(self, rule_arg): + self.rule_arg = rule_arg + # your rule initialization code goes here +============================================ +from conf import hook + + +@hook() +class MyNewHook: + def __init__(self, hook_arg): + self.hook_arg = hook_arg + # your hook initialization code goes here + + def __call__(self, test_obj): + # your hook code goes here +============================================ + +Once a new Test File is created, it must be added to the TESTS variable in +Makefile.am. This way the Test will be executed on running a 'make check'. +If a Test is expected to fail on the current master branch, then the Test should +also be added to the XFAIL_TESTS variable. This will allow expected failures to +pass through. If a test mentioned in the XFAIL_TESTS variable passes, it gets +red-flagged as a XPASS. Currently, tests expected to fail under valgrind are not +explicitly marked as XFAIL. Tests failing under valgrind must always be +considered a blocking error. + +Remember to always name the Test correctly using the TEST_NAME variable. This +is essential since a directory with the Test Name is created and this can +cause synchronization problems when the Parallel Test Harness is used. +One can use the following command on Unix systems to check for TEST_NAME +clashes: +$ grep -r -h "TEST_NAME =" | cut -c13- | uniq -c -d + +Work Remaining: +================================================================================ + +Some amount of work still remains to be done. + * Errors in server-side checks need to be handled more explicitly + * Support parallel-wget branch + * Support to spawn multiple servers is already in place. Need to handle + multiple requests to a server simultaneously. Use THreading MixIn. + * SSL Tests. Use xyne's HTTPS server implemention + * Complete support for FTP Tests + * IRI Support. This shouldn't require much effort + +Requirements: +================================================================================ + +1. Python >= 3.0 +2. Automake >= 1.11 diff --git a/testenv/Test--https-crl.py b/testenv/Test--https-crl.py new file mode 100755 index 0000000..9330a1e --- /dev/null +++ b/testenv/Test--https-crl.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from test.base_test import HTTP, HTTPS +from misc.wget_file import WgetFile +import os + +""" + This test ensures that Wget can download files from HTTPS Servers +""" +TEST_NAME = "HTTPS CRL" +############# File Definitions ############################################### +File1 = "Would you like some Tea?" +File2 = "With lemon or cream?" + +A_File = WgetFile ("File1", File1) +B_File = WgetFile ("File2", File2) + +CAFILE = os.path.abspath(os.path.join(os.getenv('srcdir', '.'), 'certs', 'ca-cert.pem')) +CRLFILE = os.path.abspath(os.path.join(os.getenv('srcdir', '.'), 'certs', 'server-crl.pem')) +WGET_OPTIONS = "--crl-file " + CRLFILE + " --ca-certificate=" + CAFILE +WGET_URLS = [["File1", "File2"]] + +Files = [[A_File, B_File]] + +Servers = [HTTPS] + +ExpectedReturnCode = 5 + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + name=TEST_NAME, + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test, + protocols=Servers +).begin () + +exit (err) diff --git a/testenv/Test--https.py b/testenv/Test--https.py new file mode 100755 index 0000000..b8d4faf --- /dev/null +++ b/testenv/Test--https.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from test.base_test import HTTP, HTTPS +from misc.wget_file import WgetFile +import os + +""" + This test ensures that Wget can download files from HTTPS Servers +""" +TEST_NAME = "HTTPS Downloads" +############# File Definitions ############################################### +File1 = "Would you like some Tea?" +File2 = "With lemon or cream?" +File3 = "Sure you're joking Mr. Feynman" + +A_File = WgetFile ("File1", File1) +B_File = WgetFile ("File2", File2) +C_File = WgetFile ("File3", File3) + +CAFILE = os.path.abspath(os.path.join(os.getenv('srcdir', '.'), 'certs', 'ca-cert.pem')) +WGET_OPTIONS = "--ca-certificate=" + CAFILE +WGET_URLS = [["File1", "File2"]] + +Files = [[A_File, B_File]] +Existing_Files = [C_File] + +Servers = [HTTPS] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [A_File, B_File, C_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, + "LocalFiles" : Existing_Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + name=TEST_NAME, + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test, + protocols=Servers +).begin () + +exit (err) diff --git a/testenv/Test--spider-r.py b/testenv/Test--spider-r.py new file mode 100755 index 0000000..5eb01e4 --- /dev/null +++ b/testenv/Test--spider-r.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test executed Wget in Spider mode with recursive retrieval. +""" +TEST_NAME = "Recursive Spider" +############# File Definitions ############################################### +mainpage = """ +<html> +<head> + <title>Main Page</title> +</head> +<body> + <p> + Some text and a link to a <a href="http://127.0.0.1:{{port}}/secondpage.html">second page</a>. + Also, a <a href="http://127.0.0.1:{{port}}/nonexistent">broken link</a>. + </p> +</body> +</html> +""" + + +secondpage = """ +<html> +<head> + <title>Second Page</title> +</head> +<body> + <p> + Some text and a link to a <a href="http://127.0.0.1:{{port}}/thirdpage.html">third page</a>. + Also, a <a href="http://127.0.0.1:{{port}}/nonexistent">broken link</a>. + </p> +</body> +</html> +""" + +thirdpage = """ +<html> +<head> + <title>Third Page</title> +</head> +<body> + <p> + Some text and a link to a <a href="http://127.0.0.1:{{port}}/dummy.txt">text file</a>. + Also, another <a href="http://127.0.0.1:{{port}}/againnonexistent">broken link</a>. + </p> +</body> +</html> +""" + +dummyfile = "Don't care." + + +index_html = WgetFile ("index.html", mainpage) +secondpage_html = WgetFile ("secondpage.html", secondpage) +thirdpage_html = WgetFile ("thirdpage.html", thirdpage) +dummy_txt = WgetFile ("dummy.txt", dummyfile) + +Request_List = [ + [ + "HEAD /", + "GET /", + "GET /robots.txt", + "HEAD /secondpage.html", + "GET /secondpage.html", + "HEAD /nonexistent", + "HEAD /thirdpage.html", + "GET /thirdpage.html", + "HEAD /dummy.txt", + "HEAD /againnonexistent" + ] +] + +WGET_OPTIONS = "--spider -r" +WGET_URLS = [[""]] + +Files = [[index_html, secondpage_html, thirdpage_html, dummy_txt]] + +ExpectedReturnCode = 8 +ExpectedDownloadedFiles = [] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode, + "FilesCrawled" : Request_List +} + +err = HTTPTest ( + name=TEST_NAME, + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-504.py b/testenv/Test-504.py new file mode 100755 index 0000000..4d82704 --- /dev/null +++ b/testenv/Test-504.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures that Wget handles a 504 Gateway Timeout response + correctly. + Since, we do not have a direct mechanism for conditionally sending responses + via the HTTP Server, I've used a workaround. + The server will always respond to a request for File1 with a 504 Gateway + Timeout. Using the --tries=2 option, we ensure that Wget attempts the file + only twice and then move on to the next file. Finally, check the exact + requests that the Server received and compare them, in order, to the + expected sequence of requests. + + In this case, we expect Wget to attempt File1 twice and File2 once. If Wget + considered 504 as a general Server Error, it would be a fatal failure and + Wget would request File1 only once. +""" +TEST_NAME = "504 Gateway Timeouts" +############# File Definitions ############################################### +File1 = """All happy families are alike; +Each unhappy family is unhappy in its own way""" +File2 = "Anyone for chocochip cookies?" + +File1_rules = { + "Response" : 504 +} + +A_File = WgetFile ("File1", File1, rules=File1_rules) +B_File = WgetFile ("File2", File2) + +Request_List = [ + [ + "GET /File1", + "GET /File1", + "GET /File2", + ] +] + + +WGET_OPTIONS = "--tries=2" +WGET_URLS = [["File1", "File2"]] + +Files = [[A_File, B_File]] + +ExpectedReturnCode = 4 +ExpectedDownloadedFiles = [B_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode, + "FilesCrawled" : Request_List +} + +err = HTTPTest ( + name=TEST_NAME, + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-Content-disposition-2.py b/testenv/Test-Content-disposition-2.py new file mode 100755 index 0000000..44ea77d --- /dev/null +++ b/testenv/Test-Content-disposition-2.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures that Wget parses the Content-Disposition header + correctly and creates the appropriate file when the said filename exists. +""" +TEST_NAME = "Content Disposition Clobber" +############# File Definitions ############################################### +File1 = "Teapot" +File2 = "The Teapot Protocol" + +# use upper case 'I' to provoke Wget failure with turkish locale +File2_rules = { + "SendHeader" : { + "Content-DIsposition" : "Attachment; FILENAME=HTTP.Teapot" + } +} +A_File = WgetFile ("HTTP.Teapot", File1) +B_File = WgetFile ("File2", File2, rules=File2_rules) + +WGET_OPTIONS = "--content-disposition" +WGET_URLS = [["File2"]] + +Files = [[B_File]] +Existing_Files = [A_File] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [WgetFile ("HTTP.Teapot.1", File2), A_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, + "LocalFiles" : Existing_Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + name=TEST_NAME, + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-Content-disposition.py b/testenv/Test-Content-disposition.py new file mode 100755 index 0000000..027a9e8 --- /dev/null +++ b/testenv/Test-Content-disposition.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures that Wget parses the Content-Disposition header + correctly and creates a local file accordingly. +""" +TEST_NAME = "Content Disposition Header" +############# File Definitions ############################################### +File1 = """All that is gold does not glitter, + Not all those who wander are lost; + The old that is strong does not wither, + Deep roots are not reached by the frost. + From the ashes a fire shall be woken, + A light from the shadows shall spring; + Renewed shall be blade that was broken, + The crownless again shall be king.""" + +File1_rules = { + "SendHeader" : { + "Content-Disposition" : "Attachment; filename=JRR.Tolkein" + } +} +A_File = WgetFile ("LOTR", File1, rules=File1_rules) + +WGET_OPTIONS = "--content-disposition" +WGET_URLS = [["LOTR"]] + +Files = [[A_File]] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [WgetFile ("JRR.Tolkein", File1)] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + name=TEST_NAME, + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-Head.py b/testenv/Test-Head.py new file mode 100755 index 0000000..77e5c57 --- /dev/null +++ b/testenv/Test-Head.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures that Wget correctly handles responses to HEAD requests + and does not actually download any data +""" +TEST_NAME = "HEAD Requests" +############# File Definitions ############################################### +File1 = "You shall not pass!" + +A_File = WgetFile ("File1", File1) + +WGET_OPTIONS = "--method=HEAD" +WGET_URLS = [["File1"]] + +Files = [[A_File]] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + name=TEST_NAME, + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-O.py b/testenv/Test-O.py new file mode 100755 index 0000000..90cb146 --- /dev/null +++ b/testenv/Test-O.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures that Wget correctly handles the -O command for output + filenames. +""" +TEST_NAME = "Output Filename Command" +############# File Definitions ############################################### +File1 = "Test Contents." + +A_File = WgetFile ("File1", File1) + +WGET_OPTIONS = "-O NewFile.txt" +WGET_URLS = [["File1"]] + +Files = [[A_File]] +ExistingFiles = [A_File] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [WgetFile ("NewFile.txt", File1)] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + name=TEST_NAME, + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-Post.py b/testenv/Test-Post.py new file mode 100755 index 0000000..223641a --- /dev/null +++ b/testenv/Test-Post.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + Simple test for HTTP POST Requests usiong the --method command +""" +TEST_NAME = "HTTP POST Requests" +############# File Definitions ############################################### +File1 = """A reader lives a thousand lives before he dies, said Jojen. +The man who never reads lives only one""" + +File1_response = """A reader lives a thousand lives before he dies, said Jojen. +The man who never reads lives only one +TestMessage""" + +A_File = WgetFile ("File1", File1) + +WGET_OPTIONS = "--method=post --body-data=TestMessage" +WGET_URLS = [["File1"]] + +Files = [[A_File]] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [WgetFile ("File1", File1_response)] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + name=TEST_NAME, + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-auth-basic-fail.py b/testenv/Test-auth-basic-fail.py new file mode 100755 index 0000000..0badf69 --- /dev/null +++ b/testenv/Test-auth-basic-fail.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures that Wget returns the correct exit code when Basic + authentcation failes due to a username/password error. +""" +TEST_NAME = "Basic Authentication Failure" +############# File Definitions ############################################### +File1 = "I am an invisble man." + +File1_rules = { + "Authentication" : { + "Type" : "Basic", + "User" : "Sauron", + "Pass" : "TheEye" + } +} +A_File = WgetFile ("File1", File1, rules=File1_rules) + +WGET_OPTIONS = "--user=Sauron --password=Eye" +WGET_URLS = [["File1"]] + +Files = [[A_File]] + +ExpectedReturnCode = 6 +ExpectedDownloadedFiles = [] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + name=TEST_NAME, + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-auth-basic.py b/testenv/Test-auth-basic.py new file mode 100755 index 0000000..49bb27b --- /dev/null +++ b/testenv/Test-auth-basic.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures Wget's Basic Authorization Negotiation. + Also, we ensure that Wget saves the host after a successfull auth and + doesn't wait for a challenge the second time. +""" +TEST_NAME = "Basic Authorization" +############# File Definitions ############################################### +File1 = "I am an invisble man." +File2 = "I too am an invisible man." + +File1_rules = { + "Authentication" : { + "Type" : "Basic", + "User" : "Sauron", + "Pass" : "TheEye" + } +} +File2_rules = { + "ExpectHeader" : { + "Authorization" : "Basic U2F1cm9uOlRoZUV5ZQ==" + } +} +A_File = WgetFile ("File1", File1, rules=File1_rules) +B_File = WgetFile ("File2", File2, rules=File2_rules) + +WGET_OPTIONS = "--user=Sauron --password=TheEye" +WGET_URLS = [["File1", "File2"]] + +Files = [[A_File, B_File]] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [A_File, B_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + name=TEST_NAME, + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-auth-both.py b/testenv/Test-auth-both.py new file mode 100755 index 0000000..91d72b8 --- /dev/null +++ b/testenv/Test-auth-both.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures Wget's Basic Authorization Negotiation. + Also, we ensure that Wget saves the host after a successfull auth and + doesn't wait for a challenge the second time. +""" +TEST_NAME = "Multiple authentication support" +############# File Definitions ############################################### +File1 = "Would you like some Tea?" +File2 = "With lemon or cream?" +File3 = "Sure you're joking Mr. Feynman" + +File1_rules = { + "Authentication" : { + "Type" : "Both", + "User" : "Sauron", + "Pass" : "TheEye" + }, + "RejectHeader" : { + "Authorization" : "Basic U2F1cm9uOlRoZUV5ZQ==" + } +} +File2_rules = { + "Authentication" : { + "Type" : "Both_inline", + "User" : "Sauron", + "Pass" : "TheEye" + }, + "RejectHeader" : { + "Authorization" : "Basic U2F1cm9uOlRoZUV5ZQ==" + } +} +File3_rules = { + "Authentication" : { + "Type" : "Digest", + "User" : "Sauron", + "Pass" : "TheEye" + } +} + +A_File = WgetFile ("File1", File1, rules=File1_rules) +B_File = WgetFile ("File2", File2, rules=File2_rules) +C_File = WgetFile ("File3", File3, rules=File3_rules) + +WGET_OPTIONS = "--user=Sauron --password=TheEye" +WGET_URLS = [["File1", "File2", "File3"]] + +Files = [[A_File, B_File, C_File]] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [A_File, B_File, C_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + name=TEST_NAME, + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-auth-digest.py b/testenv/Test-auth-digest.py new file mode 100755 index 0000000..8a73c0d --- /dev/null +++ b/testenv/Test-auth-digest.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures Wget's Digest Authorization Negotiation. +""" +TEST_NAME = "Digest Authorization" +############# File Definitions ############################################### +File1 = "Need a cookie?" + +File1_rules = { + "Authentication" : { + "Type" : "Digest", + "User" : "Pacman", + "Pass" : "Omnomnom" + } +} +A_File = WgetFile ("File1", File1, rules=File1_rules) + +WGET_OPTIONS = "--user=Pacman --password=Omnomnom" +WGET_URLS = [["File1"]] + +Files = [[A_File]] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [A_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + name=TEST_NAME, + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-auth-no-challenge-url.py b/testenv/Test-auth-no-challenge-url.py new file mode 100755 index 0000000..9e06260 --- /dev/null +++ b/testenv/Test-auth-no-challenge-url.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures Wget's Basic Authorization Negotiation, when credentials + are provided in-URL +""" +TEST_NAME = "Auth no challenge in URL" +############# File Definitions ############################################### +File1 = "Need a cookie?" + +File1_rules = { + "Authentication" : { + "Type" : "Basic", + "User" : "Pacman", + "Pass" : "Omnomnom" + }, + "ExpectHeader" : { + "Authorization" : "Basic UGFjbWFuOk9tbm9tbm9t" + } +} +A_File = WgetFile ("File1", File1, rules=File1_rules) + +WGET_OPTIONS = "--auth-no-challenge http://Pacman:Omnomnom@localhost:{{port}}/File1" +WGET_URLS = [[]] + +Files = [[A_File]] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [A_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + name=TEST_NAME, + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-auth-no-challenge.py b/testenv/Test-auth-no-challenge.py new file mode 100755 index 0000000..d155d72 --- /dev/null +++ b/testenv/Test-auth-no-challenge.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures Wget's Basic Authorization Negotiation, when the + --auth-no-challenge command is used. +""" +TEST_NAME = "Auth No Challenge Command" +############# File Definitions ############################################### +File1 = "Need a cookie?" + +File1_rules = { + "Authentication" : { + "Type" : "Basic", + "User" : "Pacman", + "Pass" : "Omnomnom" + }, + "ExpectHeader" : { + "Authorization" : "Basic UGFjbWFuOk9tbm9tbm9t" + } +} +A_File = WgetFile ("File1", File1, rules=File1_rules) + +WGET_OPTIONS = "--auth-no-challenge --user=Pacman --password=Omnomnom" +WGET_URLS = [["File1"]] + +Files = [[A_File]] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [A_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + name=TEST_NAME, + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-auth-retcode.py b/testenv/Test-auth-retcode.py new file mode 100755 index 0000000..13eb583 --- /dev/null +++ b/testenv/Test-auth-retcode.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures that Wget returns the correct return code when sent + a 403 Forbidden by the Server. +""" + +TEST_NAME = "Forbidden Retcode" + +############# File Definitions ############################################### +File1 = "Apples and Oranges? Really?" + +File1_rules = { + "Response" : 403 +} + +A_File = WgetFile ("File1", File1, rules=File1_rules) + +WGET_OPTIONS = "" +WGET_URLS = [["File1"]] + +Files = [[A_File]] + +ExpectedReturnCode = 8 +ExpectedDownloadedFiles = [] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + name=TEST_NAME, + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-auth-with-content-disposition.py b/testenv/Test-auth-with-content-disposition.py new file mode 100755 index 0000000..df28c91 --- /dev/null +++ b/testenv/Test-auth-with-content-disposition.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures that Wget handles Content-Disposition correctly when + coupled with Authentication +""" +TEST_NAME = "Authentication with Content Disposition" +############# File Definitions ############################################### +File1 = "Need a cookie?" + +File1_rules = { + "Authentication" : { + "Type" : "Basic", + "User" : "Pacman", + "Pass" : "Omnomnom" + }, + "SendHeader" : { + "Content-Disposition" : "Attachment; filename=Arch" + } +} +A_File = WgetFile ("File1", File1, rules=File1_rules) + +WGET_OPTIONS = "--user=Pacman --password=Omnomnom --content-disposition" +WGET_URLS = [["File1"]] + +Files = [[A_File]] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [WgetFile ("Arch", File1)] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + name=TEST_NAME, + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-c-full.py b/testenv/Test-c-full.py new file mode 100755 index 0000000..6dc3f5e --- /dev/null +++ b/testenv/Test-c-full.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + Test Wget's response when the file requested already exists on disk with + a filesize greater than or equal to the requested file. +""" +TEST_NAME = "Test continue option" +############# File Definitions ############################################### +File1 = "abababababababababababababababababababababababababababababababababab" +File2 = "ababababababababababababababababababab" + +A_File = WgetFile ("File1", File1) +B_File = WgetFile ("File1", File1) + +C_File = WgetFile ("File2", File1) +D_File = WgetFile ("File2", File2) + +E_File = WgetFile ("File3", File1) + +WGET_OPTIONS = "-c" +WGET_URLS = [["File1", "File2", "File3"]] + +Files = [[A_File, C_File, E_File]] +Existing_Files = [B_File, D_File] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [A_File, C_File, E_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, + "LocalFiles" : Existing_Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + name=TEST_NAME, + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-cookie-401.py b/testenv/Test-cookie-401.py new file mode 100755 index 0000000..4ffb1ff --- /dev/null +++ b/testenv/Test-cookie-401.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures that Wget stores the cookie even in the event of a + 401 Unauthorized Response +""" +TEST_NAME = "Basic Cookie 401 Response" +############# File Definitions ############################################### +File1 = """All happy families are alike; +Each unhappy family is unhappy in its own way""" +File2 = "Anyone for chocochip cookies?" + +File1_rules = { + "SendHeader" : { + "Set-Cookie" : "sess-id=0213; path=/" + }, + "Response" : 401 +} +File2_rules = { + "ExpectHeader" : { + "Cookie" : "sess-id=0213" + }, +} + +A_File = WgetFile ("File1", File1, rules=File1_rules) +B_File = WgetFile ("File2", File2, rules=File2_rules) + +WGET_OPTIONS = "" +WGET_URLS = [["File1", "File2"]] + +Files = [[A_File, B_File]] + +ExpectedReturnCode = 6 +ExpectedDownloadedFiles = [B_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + name=TEST_NAME, + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-cookie-domain-mismatch.py b/testenv/Test-cookie-domain-mismatch.py new file mode 100755 index 0000000..05b3289 --- /dev/null +++ b/testenv/Test-cookie-domain-mismatch.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures that Wget identifies bad servers trying to set cookies + for a different domain and rejects them. +""" +TEST_NAME = "Cookie Domain Mismatch" +############# File Definitions ############################################### +File1 = "Would you care for a cup of coffee?" +File2 = "Anyone for chocochip cookies?" + +File1_rules = { + "SendHeader" : { + # use upper case 'I' to provoke Wget failure with turkish locale + "Set-Cookie" : "sess-id=0213; path=/; DoMAIn=.example.com" + } +} +File2_rules = { + "RejectHeader" : { + "Cookie" : "sess-id=0213" + } +} + +A_File = WgetFile ("File1", File1, rules=File1_rules) +B_File = WgetFile ("File2", File2, rules=File2_rules) + +WGET_OPTIONS = "" +WGET_URLS = [["File1", "File2"]] + +Files = [[A_File, B_File]] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [A_File, B_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + name=TEST_NAME, + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-cookie-expires.py b/testenv/Test-cookie-expires.py new file mode 100755 index 0000000..0624549 --- /dev/null +++ b/testenv/Test-cookie-expires.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures that Wget handles Cookie expiry dates correctly. + Simultaneuously, we also check if multiple cookies to the same domain + are handled correctly +""" +TEST_NAME = "Cookie Expires" +############# File Definitions ############################################### +File1 = "Hello World!" +File2 = "'Ello! This is Amazing!" +File3 = "So what are we looking at?" +File4 = "This was downloaded" + +File1_rules = { + "SendHeader" : { + "Set-Cookie" : "sess-id=0213; path=/" + } +} +File2_rules = { + "ExpectHeader" : { + "Cookie" : "sess-id=0213" + }, + "SendHeader" : { + "Set-Cookie" : "new-sess=N" + } +} +File3_rules = { + "SendHeader" : { + # use upper case 'I' to provoke Wget failure with turkish locale + "Set-Cookie" : "sess-id=0213; path=/; ExPIRes=Sun, 06 Nov 2001 12:32:43 GMT" + }, + "ExpectHeader" : { + "Cookie" : "new-sess=N; sess-id=0213" + } +} +File4_rules = { + "RejectHeader" : { + "Cookie" : "sess-id=0213" + }, + "ExpectHeader" : { + "Cookie" : "new-sess=N" + } +} +A_File = WgetFile ("File1", File1, rules=File1_rules) +B_File = WgetFile ("File2", File2, rules=File2_rules) +C_File = WgetFile ("File3", File3, rules=File3_rules) +D_File = WgetFile ("File4", File4, rules=File4_rules) + +WGET_OPTIONS = "" +WGET_URLS = [["File1", "File2", "File3", "File4"]] + +Files = [[A_File, B_File, C_File, D_File]] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [A_File, B_File, C_File, D_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + name=TEST_NAME, + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-cookie.py b/testenv/Test-cookie.py new file mode 100755 index 0000000..1393518 --- /dev/null +++ b/testenv/Test-cookie.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures that Wget's cookie jar support works correctly. +""" +TEST_NAME = "Basic Cookie Functionality" +############# File Definitions ############################################### +File1 = """All happy families are alike; +Each unhappy family is unhappy in its own way""" +File2 = "Anyone for chocochip cookies?" + +File1_rules = { + "SendHeader" : { + "Set-Cookie" : "sess-id=0213; path=/" + } +} +File2_rules = { + "ExpectHeader" : { + "Cookie" : "sess-id=0213" + } +} + +A_File = WgetFile ("File1", File1, rules=File1_rules) +B_File = WgetFile ("File2", File2, rules=File2_rules) + +WGET_OPTIONS = "" +WGET_URLS = [["File1", "File2"]] + +Files = [[A_File, B_File]] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [A_File, B_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + name=TEST_NAME, + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-redirect-crash.py b/testenv/Test-redirect-crash.py new file mode 100755 index 0000000..ac37b52 --- /dev/null +++ b/testenv/Test-redirect-crash.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile +import os + +# This test caused wget up to 1.16 to crash +#os.environ["LC_ALL"] = "en_US.UTF-8" + +urls = [ + "File%20formats/Images/SVG,%20Scalable%20Vector%20Graphics/html,%20W3C%20v1.2%20rec%20(tiny)/directory", + "File formats/Images/SVG, Scalable Vector Graphics/html, W3C v1.2 rec (tiny)/directory/", + "File%20formats/Images/SVG,%20Scalable%20Vector%20Graphics/html,%20W3C%20v1.2%20rec%20(tiny)/directory/somefile.rng", + "File%20formats/Images/SVG%2C%20Scalable%20Vector%20Graphics/html%2c%20W3C%20v1.2%20rec%20%28tiny%29/directory/somefile.rng", + "File%20formats/Images/SVG%2C%20Scalable%20Vector%20Graphics/html%2c%20W3C%20v1.2%20rec%20%28tiny%29/directory/", + "File%20formats/Images/SVG%2C%20Scalable%20Vector%20Graphics/html%2C%20W3C%20v1.2%20rec%20%28tiny%29/directory"] + + +redirected = [ + "File%20formats/Images/SVG,%20Scalable%20Vector%20Graphics/html,%20W3C%20v1.2%20rec%20(tiny)/directory/" +] + +TEST_NAME = "Redirection crash" +############# File Definitions ############################################### +Index = "" +for i in urls: + Index = Index + "<a href='/%s'></a>" % i + +File1 = "" + +def get_redirect(url): + data = { + "File%20formats/Images/SVG,%20Scalable%20Vector%20Graphics/html,%20W3C%20v1.2%20rec%20(tiny)/directory" : + "File%20formats/Images/SVG,%20Scalable%20Vector%20Graphics/html,%20W3C%20v1.2%20rec%20(tiny)/directory/", + "File%20formats/Images/SVG%2C%20Scalable%20Vector%20Graphics/html%2C%20W3C%20v1.2%20rec%20%28tiny%29/directory" : + "File%20formats/Images/SVG,%20Scalable%20Vector%20Graphics/html,%20W3C%20v1.2%20rec%20(tiny)/directory/" + } + dest = data.get(url) + if dest: + return {"Response" : 301, + "SendHeader" : {"Location" : "/%s" % dest}} + return None + + +index_url = "File%20formats/Images/SVG,%20Scalable%20Vector%20Graphics/html,%20W3C%20v1.2%20rec%20(tiny)/index.html" +Index_File = WgetFile (index_url, Index) +Files = ([Index_File] + [WgetFile(i, File1, rules=get_redirect(i)) for i in (redirected + urls)]) + +WGET_OPTIONS = "--recursive -e robots=off" + +WGET_URLS = [[index_url]] + +ExpectedReturnCode = 0 + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : [Files] +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedRetcode" : ExpectedReturnCode, +} + +err = HTTPTest ( + name=TEST_NAME, + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/certs/README b/testenv/certs/README new file mode 100644 index 0000000..8d62ad6 --- /dev/null +++ b/testenv/certs/README @@ -0,0 +1,77 @@ +To create the server RSA private key: +$ certtool --generate-privkey --outfile server-key.pem --rsa + + +To create a self signed CA certificate: +$ certtool --generate-privkey --outfile ca-key.pem +$ certtool --generate-self-signed --load-privkey ca-key.pem --outfile ca-cert.pem +Common name: GNU Wget +UID: +Organizational unit name: Wget +Organization name: GNU +Locality name: +State or province name: +Country name (2 chars): +Enter the subject's domain component (DC): +This field should not be used in new certificates. +E-mail: +Enter the certificate's serial number in decimal (default: 6080487640893163573): + +Activation/Expiration time. +The certificate will expire in (days): -1 + +Extensions. +Does the certificate belong to an authority? (y/N): y +Path length constraint (decimal, -1 for no constraint): +Is this a TLS web client certificate? (y/N): +Will the certificate be used for IPsec IKE operations? (y/N): +Is this a TLS web server certificate? (y/N): +Enter a dnsName of the subject of the certificate: +Enter a URI of the subject of the certificate: +Enter the IP address of the subject of the certificate: +Enter the e-mail of the subject of the certificate: +Will the certificate be used to sign other certificates? (y/N): y +Will the certificate be used to sign CRLs? (y/N): y +Will the certificate be used to sign code? (y/N): +Will the certificate be used to sign OCSP requests? (y/N): y +Will the certificate be used for time stamping? (y/N): +Enter the URI of the CRL distribution point: + + +To generate a server certificate using the private key only: +$ certtool --generate-certificate --load-privkey server-key.pem --outfile server-cert.pem --load-ca-certificate ca-cert.pem --load-ca-privkey ca-key.pem +Common name: 127.0.0.1 +UID: +Organizational unit name: Wget +Organization name: GNU +Locality name: +State or province name: +Country name (2 chars): +Enter the subject's domain component (DC): +This field should not be used in new certificates. +E-mail: +Enter the certificate's serial number in decimal (default: 6080488276853553635): + +Activation/Expiration time. +The certificate will expire in (days): -1 + +Extensions. +Does the certificate belong to an authority? (y/N): +Is this a TLS web client certificate? (y/N): +Will the certificate be used for IPsec IKE operations? (y/N): +Is this a TLS web server certificate? (y/N): y +Enter a dnsName of the subject of the certificate: 127.0.0.1 +Enter a dnsName of the subject of the certificate: localhost +Enter a dnsName of the subject of the certificate: +Enter a URI of the subject of the certificate: +Enter the IP address of the subject of the certificate: +Will the certificate be used for signing (DHE and RSA-EXPORT ciphersuites)? (Y/n): +Will the certificate be used for encryption (RSA ciphersuites)? (Y/n): + + +To create a CRL for the server certificate: +$ certtool --generate-crl --load-ca-privkey ca-key.pem --load-ca-certificate ca-cert.pem --load-certificate server-cert.pem --outfile server-crl.pem +Generating a signed CRL... +Update times. +The certificate will expire in (days): -1 +CRL Number (default: 6080006793650397145): diff --git a/testenv/certs/ca-cert.pem b/testenv/certs/ca-cert.pem new file mode 100644 index 0000000..b516464 --- /dev/null +++ b/testenv/certs/ca-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDPjCCAiagAwIBAgIIVGI7SyiXCDUwDQYJKoZIhvcNAQELBQAwMDERMA8GA1UE +AxMIR05VIFdnZXQxDTALBgNVBAsTBFdnZXQxDDAKBgNVBAoTA0dOVTAiGA8yMDE0 +MTExMTE2MzczM1oYDzk5OTkxMjMxMjM1OTU5WjAwMREwDwYDVQQDEwhHTlUgV2dl +dDENMAsGA1UECxMEV2dldDEMMAoGA1UEChMDR05VMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAv2IR1/gsaJsn+egtVFbMMMbivK+eVzPY8wEXb2flpe9a +Kkwz824nSSrWfRigQmf/ODkNlK2x91kppfPmWkClUREQB3I4d/sHFnzqCkFKmNwt +VT4DsL47VumgZF6ZjSqTYQD3MDH3VhFj1iKrRMM/aCZXwntD+67sKw6UPXfFbfUO +Recpb7fCZPZFVFYStxgcF7cyH+DADLX5QCEjiLYH1es6FXrdw+ypgwBl+HuLkQ/4 +gE0JLQK5PAKSYeLy0JEBUPovkMXT+r9aPkQBF/9WD6uUPia0ERHbMIT0My84hBrG +9d5u5gXPnH1ZxKIr8iJOYCydVjYndn21zs2IExwL6wIDAQABo1gwVjAPBgNVHRMB +Af8EBTADAQH/MBMGA1UdJQQMMAoGCCsGAQUFBwMJMA8GA1UdDwEB/wQFAwMHBgAw +HQYDVR0OBBYEFPM+TjiESqm+wW/HYaNQ2m4pi+tUMA0GCSqGSIb3DQEBCwUAA4IB +AQCWKV1Txo3xytRSO1PwWK9ce5FhvQW9mubuuWmbEnQt9JaOhO1Og6ZmdPDlAQeo +m0CJZZ0VNeodoBXPGopy3VyzF4ZzUR9leGk3sb1qTSoDCvJd/zLrfukHKugtwuK0 +b1fPnEjBjQ6gQI21coc1tmyX8Qsm7of5n+Ji601WG+FiVmmdEsCjmA/eAvwSbu1E +cAVH476KUt4CrpVPQQVqzFPDz8i4iw/P+Jo+iNmL5S72OG2GfkSJq3XkUYa509W6 +N+8c3p4y0q/PcQ92s1OIHyEPZFRFhm4xw0sHkhD2KVoHseHZjCoYn4/lIzMPnJ6v +EfZUJQXndeJnffbthaUp8Ea2 +-----END CERTIFICATE----- diff --git a/testenv/certs/ca-key.pem b/testenv/certs/ca-key.pem new file mode 100644 index 0000000..ac51f60 --- /dev/null +++ b/testenv/certs/ca-key.pem @@ -0,0 +1,144 @@ +Public Key Info: + Public Key Algorithm: RSA + Key Security Level: Medium (2048 bits) + +modulus: + 00:bf:62:11:d7:f8:2c:68:9b:27:f9:e8:2d:54:56: + cc:30:c6:e2:bc:af:9e:57:33:d8:f3:01:17:6f:67: + e5:a5:ef:5a:2a:4c:33:f3:6e:27:49:2a:d6:7d:18: + a0:42:67:ff:38:39:0d:94:ad:b1:f7:59:29:a5:f3: + e6:5a:40:a5:51:11:10:07:72:38:77:fb:07:16:7c: + ea:0a:41:4a:98:dc:2d:55:3e:03:b0:be:3b:56:e9: + a0:64:5e:99:8d:2a:93:61:00:f7:30:31:f7:56:11: + 63:d6:22:ab:44:c3:3f:68:26:57:c2:7b:43:fb:ae: + ec:2b:0e:94:3d:77:c5:6d:f5:0e:45:e7:29:6f:b7: + c2:64:f6:45:54:56:12:b7:18:1c:17:b7:32:1f:e0: + c0:0c:b5:f9:40:21:23:88:b6:07:d5:eb:3a:15:7a: + dd:c3:ec:a9:83:00:65:f8:7b:8b:91:0f:f8:80:4d: + 09:2d:02:b9:3c:02:92:61:e2:f2:d0:91:01:50:fa: + 2f:90:c5:d3:fa:bf:5a:3e:44:01:17:ff:56:0f:ab: + 94:3e:26:b4:11:11:db:30:84:f4:33:2f:38:84:1a: + c6:f5:de:6e:e6:05:cf:9c:7d:59:c4:a2:2b:f2:22: + 4e:60:2c:9d:56:36:27:76:7d:b5:ce:cd:88:13:1c: + 0b:eb: + +public exponent: + 01:00:01: + +private exponent: + 45:0c:7f:fd:98:a7:85:12:3d:a9:17:90:8b:36:49: + b3:6b:7e:50:af:58:04:84:4b:48:d9:62:f8:29:d7: + 1c:38:30:22:c4:9d:95:bd:6f:65:21:94:83:4b:c8: + 3e:4d:41:32:aa:ba:f0:a2:7e:6c:0c:7a:4f:4a:a1: + 18:7c:ec:68:44:2c:b1:53:0f:76:92:56:2b:51:e4: + 2a:d1:05:b6:02:f2:44:27:fc:b2:de:df:8f:ea:f8: + 98:5d:dd:2e:a6:66:c7:ff:ce:2f:50:47:b9:80:ca: + b1:6e:8e:b6:5f:6f:58:07:45:70:80:82:b5:a2:95: + c8:af:18:e2:d8:7c:9d:bf:c5:a9:da:4f:af:08:37: + 92:27:94:12:c0:94:70:90:ff:e4:05:8b:ed:18:a9: + 19:3c:47:3a:7c:fe:4f:9c:15:ab:f6:7e:48:2a:58: + d7:14:67:96:bd:e6:fa:9f:3a:51:0c:63:49:14:d5: + 9d:e9:a8:24:19:2a:83:e4:fe:e2:ec:db:f9:13:33: + a6:d3:62:d2:6b:7e:a9:5b:93:73:f5:c9:d0:ad:58: + 11:cb:77:d3:13:3c:bf:37:f9:64:95:c7:4c:69:f2: + 6e:b8:36:69:57:93:4a:03:06:58:8a:51:3d:d6:97: + 61:2f:7c:76:33:14:88:51:45:68:4e:29:fe:12:43: + 69: + +prime1: + 00:e0:e6:81:38:18:3e:c8:98:51:71:2d:5f:22:8c: + 93:95:37:17:47:00:4f:6a:87:98:73:8d:f3:c3:02: + f7:e1:9d:a0:5c:a5:10:a6:0d:88:5d:e0:72:10:93: + 24:af:6e:a4:0e:55:5c:03:37:5f:1d:90:41:c2:d6: + e3:a6:ba:20:08:0b:01:31:eb:fc:7e:97:66:3c:fe: + b5:ab:4c:0b:2f:18:16:f3:28:47:70:41:dc:cf:04: + 9c:7e:28:78:3b:3f:31:cf:b1:77:2c:6d:c9:bf:ad: + 19:ff:03:1f:c6:98:9a:60:47:a5:1d:c4:52:c5:9e: + 77:5a:cc:a4:e3:96:81:d4:4d: + +prime2: + 00:d9:d9:0c:6e:81:bb:0e:5d:c6:92:cc:48:70:b8: + da:60:e8:56:e7:2a:20:da:29:0f:c9:f0:9f:b8:9f: + df:d9:a1:68:7e:ce:3e:7c:f2:00:66:68:79:c4:01: + fa:b9:71:3e:73:06:3f:85:5c:83:33:ee:58:77:50: + 89:aa:90:33:d0:6c:aa:6f:34:b2:30:8b:e9:a9:82: + df:e2:7f:04:09:9f:14:9a:db:c7:cb:e5:85:46:b2: + 42:d0:a7:fe:7a:e3:ff:1e:84:9c:36:50:e3:de:fb: + 11:1c:34:09:fe:46:db:45:c3:50:19:f1:25:c0:e3: + 5c:d5:0d:88:13:e1:9a:5d:17: + +coefficient: + 00:ca:79:cb:79:87:91:9f:9a:99:0b:5d:c5:78:21: + a7:60:c6:8a:2d:a5:b5:87:a2:d6:df:b0:17:5f:bf: + e1:ce:f0:ca:89:18:0e:e0:4a:7f:00:e5:41:2d:04: + 5b:05:51:e5:08:89:dd:80:82:c7:94:94:1c:f4:0f: + 1b:9a:d0:72:83:bb:e9:ca:d5:09:0d:4b:c0:b7:6a: + a7:b4:c3:df:4e:f1:7f:0f:57:ad:25:ff:e4:d3:ef: + 05:95:31:ca:00:54:97:4b:2d:56:aa:1a:89:d8:a0: + d6:dc:64:88:88:36:26:92:39:57:8b:da:18:23:77: + c3:e3:39:0e:95:f7:3c:77:fe: + +exp1: + 00:99:f2:8f:4f:93:a1:1e:74:cd:82:f8:78:df:d0: + 74:91:b6:a5:53:6f:cd:ec:f1:26:95:2a:fd:4a:67: + 34:c1:16:c2:17:c8:d1:ed:a8:e3:c8:c7:03:ad:7e: + db:a4:ce:ca:b4:19:10:24:0f:7a:27:65:80:ee:5b: + 64:77:d3:7e:6b:a3:04:cd:64:69:71:4a:37:ac:d6: + fa:0a:68:c2:5b:19:55:54:5b:25:13:9d:b2:05:6f: + 75:a4:12:15:c3:10:8e:0b:4a:c2:76:02:2d:10:ec: + f0:17:94:ce:e2:85:c1:5e:d8:8c:19:25:33:37:9d: + 32:bc:4f:cb:2b:12:f2:8a:1d: + +exp2: + 3e:53:68:c9:1c:f8:a5:6d:92:e8:60:e5:c0:ca:42: + 40:43:78:c9:7e:36:13:f4:77:7d:f1:07:e1:4c:6c: + 40:d9:7b:09:fc:7b:c8:47:7c:71:d0:26:36:3b:d2: + bd:c7:76:74:76:2f:2a:3a:83:97:11:f3:e1:7e:fb: + 43:ff:29:b3:d1:c3:19:39:dc:59:23:4e:60:9e:fe: + ea:d0:28:19:90:97:d6:8e:56:a5:31:2f:66:40:8d: + f9:20:77:20:35:a6:c1:d6:72:d2:df:65:b2:5f:e6: + 4f:49:5c:2a:91:9f:1e:60:78:c4:53:47:d7:dd:b4: + ab:87:c9:8c:d6:98:d1:55: + + +Public Key ID: F3:3E:4E:38:84:4A:A9:BE:C1:6F:C7:61:A3:50:DA:6E:29:8B:EB:54 +Public key's random art: ++--[ RSA 2048]----+ +| | +| | +| | +| .. . | +| Eo . S | +| .+o..+. + | +| .+o.= oo o | +|.o.o* o +. | +|+o+*.. .o. | ++-----------------+ + +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAv2IR1/gsaJsn+egtVFbMMMbivK+eVzPY8wEXb2flpe9aKkwz +824nSSrWfRigQmf/ODkNlK2x91kppfPmWkClUREQB3I4d/sHFnzqCkFKmNwtVT4D +sL47VumgZF6ZjSqTYQD3MDH3VhFj1iKrRMM/aCZXwntD+67sKw6UPXfFbfUORecp +b7fCZPZFVFYStxgcF7cyH+DADLX5QCEjiLYH1es6FXrdw+ypgwBl+HuLkQ/4gE0J +LQK5PAKSYeLy0JEBUPovkMXT+r9aPkQBF/9WD6uUPia0ERHbMIT0My84hBrG9d5u +5gXPnH1ZxKIr8iJOYCydVjYndn21zs2IExwL6wIDAQABAoIBAEUMf/2Yp4USPakX +kIs2SbNrflCvWASES0jZYvgp1xw4MCLEnZW9b2UhlINLyD5NQTKquvCifmwMek9K +oRh87GhELLFTD3aSVitR5CrRBbYC8kQn/LLe34/q+Jhd3S6mZsf/zi9QR7mAyrFu +jrZfb1gHRXCAgrWilcivGOLYfJ2/xanaT68IN5InlBLAlHCQ/+QFi+0YqRk8Rzp8 +/k+cFav2fkgqWNcUZ5a95vqfOlEMY0kU1Z3pqCQZKoPk/uLs2/kTM6bTYtJrfqlb +k3P1ydCtWBHLd9MTPL83+WSVx0xp8m64NmlXk0oDBliKUT3Wl2EvfHYzFIhRRWhO +Kf4SQ2kCgYEA4OaBOBg+yJhRcS1fIoyTlTcXRwBPaoeYc43zwwL34Z2gXKUQpg2I +XeByEJMkr26kDlVcAzdfHZBBwtbjprogCAsBMev8fpdmPP61q0wLLxgW8yhHcEHc +zwScfih4Oz8xz7F3LG3Jv60Z/wMfxpiaYEelHcRSxZ53Wsyk45aB1E0CgYEA2dkM +boG7Dl3GksxIcLjaYOhW5yog2ikPyfCfuJ/f2aFofs4+fPIAZmh5xAH6uXE+cwY/ +hVyDM+5Yd1CJqpAz0GyqbzSyMIvpqYLf4n8ECZ8UmtvHy+WFRrJC0Kf+euP/HoSc +NlDj3vsRHDQJ/kbbRcNQGfElwONc1Q2IE+GaXRcCgYEAmfKPT5OhHnTNgvh439B0 +kbalU2/N7PEmlSr9Smc0wRbCF8jR7ajjyMcDrX7bpM7KtBkQJA96J2WA7ltkd9N+ +a6MEzWRpcUo3rNb6CmjCWxlVVFslE52yBW91pBIVwxCOC0rCdgItEOzwF5TO4oXB +XtiMGSUzN50yvE/LKxLyih0CgYA+U2jJHPilbZLoYOXAykJAQ3jJfjYT9Hd98Qfh +TGxA2XsJ/HvIR3xx0CY2O9K9x3Z0di8qOoOXEfPhfvtD/ymz0cMZOdxZI05gnv7q +0CgZkJfWjlalMS9mQI35IHcgNabB1nLS32WyX+ZPSVwqkZ8eYHjEU0fX3bSrh8mM +1pjRVQKBgQDKect5h5GfmpkLXcV4IadgxootpbWHotbfsBdfv+HO8MqJGA7gSn8A +5UEtBFsFUeUIid2AgseUlBz0Dxua0HKDu+nK1QkNS8C3aqe0w99O8X8PV60l/+TT +7wWVMcoAVJdLLVaqGonYoNbcZIiINiaSOVeL2hgjd8PjOQ6V9zx3/g== +-----END RSA PRIVATE KEY----- diff --git a/testenv/certs/server-cert.pem b/testenv/certs/server-cert.pem new file mode 100644 index 0000000..4ce3886 --- /dev/null +++ b/testenv/certs/server-cert.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDgDCCAmigAwIBAgIIVGI73zrIeeMwDQYJKoZIhvcNAQELBQAwMDERMA8GA1UE +AxMIR05VIFdnZXQxDTALBgNVBAsTBFdnZXQxDDAKBgNVBAoTA0dOVTAiGA8yMDE0 +MTExMTE2NDAwMFoYDzk5OTkxMjMxMjM1OTU5WjAxMRIwEAYDVQQDEwkxMjcuMC4w +LjExDTALBgNVBAsTBFdnZXQxDDAKBgNVBAoTA0dOVTCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAMjC3Gt55EfStl6mE371+pD3/cpR5MLxkdbBss5MlIP2 +TDhiPOItLXml8oxs4BjUm3wfn3GV9iJLmbzbIWL+0kbRkQ2LCPKUf+Cln3z2ZE+r +XwdWlT8gVfv51Opfkp2lLDVUqLfNKRGQgivjSCmLqY2LqeB0SaVNvuaD3EpqZyIH +0E5SZgjqBHgRRtvGkcy0rOmp5SI2NASLugUioXa9OLWjpYDwodsd3ERlL0DJ1aJW +8TC8Tqix4i0osWzar+LXBIin0Qvar9/uRHN0p1kq3p0XgNHKqWpiTT54+WYx7Pem +v4qRXz11swiJzUL+Pw1DurQ9smbzDgAsz7V2FJnUeCcCAwEAAaOBmDCBlTAMBgNV +HRMBAf8EAjAAMB8GA1UdEQQYMBaCCTEyNy4wLjAuMYIJbG9jYWxob3N0MBMGA1Ud +JQQMMAoGCCsGAQUFBwMBMA8GA1UdDwEB/wQFAwMHoAAwHQYDVR0OBBYEFJfm323L +JbKTM/tMKSt0qlUqewbnMB8GA1UdIwQYMBaAFPM+TjiESqm+wW/HYaNQ2m4pi+tU +MA0GCSqGSIb3DQEBCwUAA4IBAQCDmuSD4IGmn0UQ5jhGQquh92Iu59j64Rrg7EIM +zoppciyYR8gDUutOI9CEisxJz6umvAdOo5L981gcFaBv6hHWaE/krAZccR+ZXZP6 +fI9btO8My8O63fYcd2KkLEFqvKDF43i01S2LrqXdPo3uELbFZwxCmUKsexFGsoW1 +CbXbRjnS7w/f72myRmvBeDiNMuGfe1lb4IflybH3DMlKC7i0AN1JKglp+IKn5XAE +neWR03i3UaYJsibIxj0DkTS+hVPu5MXQ9RlF5CkRdFKjGinLE/u70XyAyx0/IeAN +e7c2MJvpdfRmTXm2ew4sNyK9RXo7Bv0Yqkl65iMscF8LNnxL +-----END CERTIFICATE----- diff --git a/testenv/certs/server-crl.pem b/testenv/certs/server-crl.pem new file mode 100644 index 0000000..39c1919 --- /dev/null +++ b/testenv/certs/server-crl.pem @@ -0,0 +1,12 @@ +-----BEGIN X509 CRL----- +MIIB1DCBvQIBATANBgkqhkiG9w0BAQsFADAwMREwDwYDVQQDEwhHTlUgV2dldDEN +MAsGA1UECxMEV2dldDEMMAoGA1UEChMDR05VGA8yMDE0MTExMTE2NDU1NFoYDzk5 +OTkxMjMxMjM1OTU5WjAdMBsCCFRiO986yHnjGA8yMDE0MTExMTE2NDU1NFqgNjA0 +MB8GA1UdIwQYMBaAFPM+TjiESqm+wW/HYaNQ2m4pi+tUMBEGA1UdFAQKAghUYj1E +KHs9ijANBgkqhkiG9w0BAQsFAAOCAQEAZgwqs1VOFG39dFHHMXvBr4eJfhwiG4bC +cL6IvLhvl9ikcyQMHrpOBtNjkCtgclSbJjjTDdera1+zuCWE0WBOJ4mojYdAIOhR +QvSwp4NwAtibu2F/fjeXoo+LEpcRKtLvAotB30eCZ1OPrijsa/HxFILOLlayjns8 +wM4RmQC4o43y1G/1jqM8hGDg4Wz0j1URVuyP+pU55JpubV5LlExy3gIRwevD2lam +q3hiighenJYFO3HGZkYT2SIoSpXZnQqKPJ4HwRBSg/cjOpc1y1lIIvKhmk+Cut6M ++S5HL4pIk8vGYg57nTfOOkj1goqFkfU0DBqvVAZj02ay/VIDu61T1g== +-----END X509 CRL----- diff --git a/testenv/certs/server-key.pem b/testenv/certs/server-key.pem new file mode 100644 index 0000000..80d61cc --- /dev/null +++ b/testenv/certs/server-key.pem @@ -0,0 +1,144 @@ +Public Key Info: + Public Key Algorithm: RSA + Key Security Level: Medium (2048 bits) + +modulus: + 00:c8:c2:dc:6b:79:e4:47:d2:b6:5e:a6:13:7e:f5: + fa:90:f7:fd:ca:51:e4:c2:f1:91:d6:c1:b2:ce:4c: + 94:83:f6:4c:38:62:3c:e2:2d:2d:79:a5:f2:8c:6c: + e0:18:d4:9b:7c:1f:9f:71:95:f6:22:4b:99:bc:db: + 21:62:fe:d2:46:d1:91:0d:8b:08:f2:94:7f:e0:a5: + 9f:7c:f6:64:4f:ab:5f:07:56:95:3f:20:55:fb:f9: + d4:ea:5f:92:9d:a5:2c:35:54:a8:b7:cd:29:11:90: + 82:2b:e3:48:29:8b:a9:8d:8b:a9:e0:74:49:a5:4d: + be:e6:83:dc:4a:6a:67:22:07:d0:4e:52:66:08:ea: + 04:78:11:46:db:c6:91:cc:b4:ac:e9:a9:e5:22:36: + 34:04:8b:ba:05:22:a1:76:bd:38:b5:a3:a5:80:f0: + a1:db:1d:dc:44:65:2f:40:c9:d5:a2:56:f1:30:bc: + 4e:a8:b1:e2:2d:28:b1:6c:da:af:e2:d7:04:88:a7: + d1:0b:da:af:df:ee:44:73:74:a7:59:2a:de:9d:17: + 80:d1:ca:a9:6a:62:4d:3e:78:f9:66:31:ec:f7:a6: + bf:8a:91:5f:3d:75:b3:08:89:cd:42:fe:3f:0d:43: + ba:b4:3d:b2:66:f3:0e:00:2c:cf:b5:76:14:99:d4: + 78:27: + +public exponent: + 01:00:01: + +private exponent: + 00:92:80:1f:f9:0d:e9:d7:bf:9b:f5:55:9b:c4:7a: + 1b:6e:ce:89:14:aa:ce:14:b3:d3:88:b3:b0:97:7a: + aa:a5:e1:85:9d:5f:92:ae:39:e9:85:6b:e3:a3:35: + 90:12:8e:93:27:f0:ab:99:67:a5:45:41:85:de:9a: + c9:b2:43:e1:8e:6c:3f:3d:72:c8:04:bc:f8:d4:26: + 08:4c:58:40:bb:22:83:26:07:b8:c1:68:07:56:e8: + e8:c6:5f:17:ce:92:49:c0:61:16:fd:89:68:fe:b8: + 45:45:61:85:b7:4b:83:5f:17:1b:cf:ff:0b:fe:e4: + cc:f9:ca:1f:66:ee:5e:74:25:94:7a:27:0e:0f:43: + 50:14:48:ad:c6:8a:e1:ac:ff:8e:10:ed:e6:92:48: + c8:94:c1:3a:2c:db:86:71:66:8e:19:93:13:ed:f9: + 47:06:5e:8b:e2:2e:cb:3a:c2:b3:5e:8d:31:e4:c5: + a7:cd:3f:09:70:e4:02:5d:34:2a:4d:b7:f5:06:e2: + f5:3b:8f:b6:ad:4a:22:b8:fe:43:a7:4d:67:ef:c3: + e1:ed:83:e2:d5:f2:d0:37:0f:56:ab:5b:47:69:0a: + 14:03:2c:43:a3:73:e9:05:72:5e:df:68:9c:67:4b: + 08:64:2d:c2:67:23:aa:e5:35:88:56:99:95:17:60: + 20:01: + +prime1: + 00:ea:ca:12:86:c0:25:b8:ab:fd:44:2c:1a:3f:1b: + 19:68:d4:26:6e:9c:ad:6d:35:12:29:9f:40:c2:4c: + 96:ef:8b:08:61:39:08:b7:8a:1f:81:97:71:ff:af: + 5a:5b:db:9a:2f:2f:29:ab:92:bb:c5:51:a2:84:c5: + f4:88:79:ac:a2:b8:17:1e:4a:66:62:be:e5:ab:fd: + 01:42:6b:16:f9:73:7b:cd:3e:f7:5c:5c:95:dd:79: + 73:c4:60:a8:cf:95:80:ba:7d:02:14:9c:7e:58:4f: + 8c:08:2c:b8:46:31:23:b2:1a:c3:38:78:5c:ea:50: + 9d:42:23:31:30:9a:0f:3f:27: + +prime2: + 00:da:e5:d3:66:0f:34:53:8c:e8:bf:5f:1e:46:93: + 47:df:30:57:be:1f:30:6a:7e:e9:f0:6b:3f:61:89: + 51:e2:0b:da:51:09:65:f6:23:3a:61:86:02:46:0a: + cf:11:73:7c:2d:65:bd:64:b8:0e:24:d2:b7:51:8f: + 39:b4:a2:1b:e4:9a:bc:66:31:e2:00:eb:3e:20:06: + 97:0a:a0:bb:82:da:bf:d5:e9:20:77:a7:55:86:69: + ce:eb:38:d3:f4:ad:82:9e:ce:02:05:c5:11:aa:c0: + b9:66:6f:e7:f4:26:57:72:fa:50:0b:ad:76:44:86: + e0:3e:f7:c0:3e:f3:94:9f:01: + +coefficient: + 00:94:f2:42:a9:1a:62:1c:7a:bf:34:1b:a7:87:ae: + bd:3a:d9:f1:8c:4e:f6:f5:27:5a:ae:f1:1e:15:06: + a6:d0:e4:e0:ec:3a:40:02:13:b9:31:9a:cd:3a:c6: + 34:7d:c6:9d:9e:60:5b:ca:03:88:87:56:f0:e1:ea: + 37:96:2b:53:40:b2:78:4e:80:e2:e0:24:8c:83:0e: + f8:77:a4:64:d5:cc:09:6c:d6:52:49:f9:55:61:16: + 72:b5:d2:ea:e1:61:fb:31:24:f0:30:8c:fe:5c:29: + 71:06:09:11:4d:ef:51:a6:33:62:54:d2:c7:de:ba: + 78:17:b1:27:50:f4:ef:c4:3a: + +exp1: + 1f:36:0d:90:6c:2a:97:8a:05:78:f2:83:ea:af:a7: + 89:0f:ea:ab:f9:97:f4:54:81:bd:96:b5:fd:1e:41: + 52:46:a1:2e:8b:6e:65:37:af:48:82:e1:5c:a3:ea: + d7:1b:32:3b:e3:81:1e:95:ba:f0:58:11:ca:a4:a6: + 05:1e:67:9c:99:ec:38:d2:9b:19:b5:56:c2:ae:37: + 64:a4:e7:c0:f1:61:1b:bf:ab:12:54:1c:77:fc:95: + 2f:1d:ca:53:0e:04:b6:c5:b7:69:16:04:95:a8:bd: + 6c:b8:c5:26:4f:91:f7:33:27:90:72:2f:a7:d6:5f: + 91:53:2c:4e:d1:ac:05:31: + +exp2: + 00:83:a4:55:a6:fa:1b:d8:e7:54:0d:ca:f1:55:36: + 3b:b1:f0:cb:c3:cd:d3:fb:27:ca:1e:c9:10:bb:e2: + ae:78:c7:f2:0a:6c:21:82:8e:1b:0d:0d:5f:8e:a9: + ef:6f:aa:49:12:b0:2d:df:45:85:54:05:d9:33:56: + 74:38:ba:89:15:c9:2c:e6:34:b7:9b:1f:de:23:ba: + 72:d9:74:62:70:46:87:b9:e8:52:9b:42:e9:ff:44: + e0:a8:bb:6b:54:a9:88:75:62:a4:fa:bd:52:6b:a3: + 2d:9c:7a:4e:3f:99:53:5c:15:47:50:4e:88:62:9b: + ce:7e:6f:d6:90:c5:42:2b:01: + + +Public Key ID: 97:E6:DF:6D:CB:25:B2:93:33:FB:4C:29:2B:74:AA:55:2A:7B:06:E7 +Public key's random art: ++--[ RSA 2048]----+ +| | +| | +| | +| . | +| S + . | +| .+oo. . | +| .=+oo.+ .| +| +E.=O.oo| +| o+ .=*++o| ++-----------------+ + +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAyMLca3nkR9K2XqYTfvX6kPf9ylHkwvGR1sGyzkyUg/ZMOGI8 +4i0teaXyjGzgGNSbfB+fcZX2IkuZvNshYv7SRtGRDYsI8pR/4KWffPZkT6tfB1aV +PyBV+/nU6l+SnaUsNVSot80pEZCCK+NIKYupjYup4HRJpU2+5oPcSmpnIgfQTlJm +COoEeBFG28aRzLSs6anlIjY0BIu6BSKhdr04taOlgPCh2x3cRGUvQMnVolbxMLxO +qLHiLSixbNqv4tcEiKfRC9qv3+5Ec3SnWSrenReA0cqpamJNPnj5ZjHs96a/ipFf +PXWzCInNQv4/DUO6tD2yZvMOACzPtXYUmdR4JwIDAQABAoIBAQCSgB/5DenXv5v1 +VZvEehtuzokUqs4Us9OIs7CXeqql4YWdX5KuOemFa+OjNZASjpMn8KuZZ6VFQYXe +msmyQ+GObD89csgEvPjUJghMWEC7IoMmB7jBaAdW6OjGXxfOkknAYRb9iWj+uEVF +YYW3S4NfFxvP/wv+5Mz5yh9m7l50JZR6Jw4PQ1AUSK3GiuGs/44Q7eaSSMiUwTos +24ZxZo4ZkxPt+UcGXoviLss6wrNejTHkxafNPwlw5AJdNCpNt/UG4vU7j7atSiK4 +/kOnTWfvw+Htg+LV8tA3D1arW0dpChQDLEOjc+kFcl7faJxnSwhkLcJnI6rlNYhW +mZUXYCABAoGBAOrKEobAJbir/UQsGj8bGWjUJm6crW01EimfQMJMlu+LCGE5CLeK +H4GXcf+vWlvbmi8vKauSu8VRooTF9Ih5rKK4Fx5KZmK+5av9AUJrFvlze80+91xc +ld15c8RgqM+VgLp9AhScflhPjAgsuEYxI7Iawzh4XOpQnUIjMTCaDz8nAoGBANrl +02YPNFOM6L9fHkaTR98wV74fMGp+6fBrP2GJUeIL2lEJZfYjOmGGAkYKzxFzfC1l +vWS4DiTSt1GPObSiG+SavGYx4gDrPiAGlwqgu4Lav9XpIHenVYZpzus40/Stgp7O +AgXFEarAuWZv5/QmV3L6UAutdkSG4D73wD7zlJ8BAoGAHzYNkGwql4oFePKD6q+n +iQ/qq/mX9FSBvZa1/R5BUkahLotuZTevSILhXKPq1xsyO+OBHpW68FgRyqSmBR5n +nJnsONKbGbVWwq43ZKTnwPFhG7+rElQcd/yVLx3KUw4EtsW3aRYElai9bLjFJk+R +9zMnkHIvp9ZfkVMsTtGsBTECgYEAg6RVpvob2OdUDcrxVTY7sfDLw83T+yfKHskQ +u+KueMfyCmwhgo4bDQ1fjqnvb6pJErAt30WFVAXZM1Z0OLqJFcks5jS3mx/eI7py +2XRicEaHuehSm0Lp/0TgqLtrVKmIdWKk+r1Sa6MtnHpOP5lTXBVHUE6IYpvOfm/W +kMVCKwECgYEAlPJCqRpiHHq/NBunh669OtnxjE729SdarvEeFQam0OTg7DpAAhO5 +MZrNOsY0fcadnmBbygOIh1bw4eo3litTQLJ4ToDi4CSMgw74d6Rk1cwJbNZSSflV +YRZytdLq4WH7MSTwMIz+XClxBgkRTe9RpjNiVNLH3rp4F7EnUPTvxDo= +-----END RSA PRIVATE KEY----- diff --git a/testenv/conf/__init__.py b/testenv/conf/__init__.py new file mode 100644 index 0000000..4b5ddc4 --- /dev/null +++ b/testenv/conf/__init__.py @@ -0,0 +1,47 @@ +import os + +# this file implements the mechanism of conf class auto-registration, +# don't modify this file if you have no idea what you're doing + +def gen_hook(): + hook_table = {} + + class Wrapper: + """ + Decorator class which implements the conf class registration. + """ + def __init__(self, alias=None): + self.alias = alias + + def __call__(self, cls): + # register the class object with the name of the class + hook_table[cls.__name__] = cls + if self.alias: + # also register the alias of the class + hook_table[self.alias] = cls + + return cls + + def find_hook(name): + try: + return hook_table[name] + except: + raise AttributeError + + return Wrapper, find_hook + +_register, find_conf = gen_hook() +hook = rule = _register + +__all__ = ['hook', 'rule'] + +for module in os.listdir(os.path.dirname(__file__)): + # import every module under this package except __init__.py, + # so that the decorator `register` applies + # (nothing happens if the script is not loaded) + if module != '__init__.py' and module.endswith('.py'): + module_name = module[:-3] + mod = __import__('%s.%s' % (__name__, module_name), + globals(), + locals()) + __all__.append(module_name) diff --git a/testenv/conf/__pycache__/__init__.cpython-33.pyo b/testenv/conf/__pycache__/__init__.cpython-33.pyo Binary files differnew file mode 100644 index 0000000..9529d50 --- /dev/null +++ b/testenv/conf/__pycache__/__init__.cpython-33.pyo diff --git a/testenv/conf/__pycache__/authentication.cpython-33.pyo b/testenv/conf/__pycache__/authentication.cpython-33.pyo Binary files differnew file mode 100644 index 0000000..bf7cbbc --- /dev/null +++ b/testenv/conf/__pycache__/authentication.cpython-33.pyo diff --git a/testenv/conf/__pycache__/expect_header.cpython-33.pyo b/testenv/conf/__pycache__/expect_header.cpython-33.pyo Binary files differnew file mode 100644 index 0000000..7a17355 --- /dev/null +++ b/testenv/conf/__pycache__/expect_header.cpython-33.pyo diff --git a/testenv/conf/__pycache__/expected_files.cpython-33.pyo b/testenv/conf/__pycache__/expected_files.cpython-33.pyo Binary files differnew file mode 100644 index 0000000..182491b --- /dev/null +++ b/testenv/conf/__pycache__/expected_files.cpython-33.pyo diff --git a/testenv/conf/__pycache__/expected_ret_code.cpython-33.pyo b/testenv/conf/__pycache__/expected_ret_code.cpython-33.pyo Binary files differnew file mode 100644 index 0000000..a02a95b --- /dev/null +++ b/testenv/conf/__pycache__/expected_ret_code.cpython-33.pyo diff --git a/testenv/conf/__pycache__/files_crawled.cpython-33.pyo b/testenv/conf/__pycache__/files_crawled.cpython-33.pyo Binary files differnew file mode 100644 index 0000000..7197bda --- /dev/null +++ b/testenv/conf/__pycache__/files_crawled.cpython-33.pyo diff --git a/testenv/conf/__pycache__/hook_sample.cpython-33.pyo b/testenv/conf/__pycache__/hook_sample.cpython-33.pyo Binary files differnew file mode 100644 index 0000000..d71d665 --- /dev/null +++ b/testenv/conf/__pycache__/hook_sample.cpython-33.pyo diff --git a/testenv/conf/__pycache__/local_files.cpython-33.pyo b/testenv/conf/__pycache__/local_files.cpython-33.pyo Binary files differnew file mode 100644 index 0000000..c36044d --- /dev/null +++ b/testenv/conf/__pycache__/local_files.cpython-33.pyo diff --git a/testenv/conf/__pycache__/reject_header.cpython-33.pyo b/testenv/conf/__pycache__/reject_header.cpython-33.pyo Binary files differnew file mode 100644 index 0000000..4ccf535 --- /dev/null +++ b/testenv/conf/__pycache__/reject_header.cpython-33.pyo diff --git a/testenv/conf/__pycache__/response.cpython-33.pyo b/testenv/conf/__pycache__/response.cpython-33.pyo Binary files differnew file mode 100644 index 0000000..08091a1 --- /dev/null +++ b/testenv/conf/__pycache__/response.cpython-33.pyo diff --git a/testenv/conf/__pycache__/rule_sample.cpython-33.pyo b/testenv/conf/__pycache__/rule_sample.cpython-33.pyo Binary files differnew file mode 100644 index 0000000..36f1d61 --- /dev/null +++ b/testenv/conf/__pycache__/rule_sample.cpython-33.pyo diff --git a/testenv/conf/__pycache__/send_header.cpython-33.pyo b/testenv/conf/__pycache__/send_header.cpython-33.pyo Binary files differnew file mode 100644 index 0000000..17ae67c --- /dev/null +++ b/testenv/conf/__pycache__/send_header.cpython-33.pyo diff --git a/testenv/conf/__pycache__/server_files.cpython-33.pyo b/testenv/conf/__pycache__/server_files.cpython-33.pyo Binary files differnew file mode 100644 index 0000000..1d9f82d --- /dev/null +++ b/testenv/conf/__pycache__/server_files.cpython-33.pyo diff --git a/testenv/conf/__pycache__/urls.cpython-33.pyo b/testenv/conf/__pycache__/urls.cpython-33.pyo Binary files differnew file mode 100644 index 0000000..32f558c --- /dev/null +++ b/testenv/conf/__pycache__/urls.cpython-33.pyo diff --git a/testenv/conf/__pycache__/wget_commands.cpython-33.pyo b/testenv/conf/__pycache__/wget_commands.cpython-33.pyo Binary files differnew file mode 100644 index 0000000..4a6831c --- /dev/null +++ b/testenv/conf/__pycache__/wget_commands.cpython-33.pyo diff --git a/testenv/conf/authentication.py b/testenv/conf/authentication.py new file mode 100644 index 0000000..c87994a --- /dev/null +++ b/testenv/conf/authentication.py @@ -0,0 +1,22 @@ +from conf import rule + +""" Rule: Authentication +This file defines an authentication rule which when applied to any file will +cause the server to prompt the client for the required authentication details +before serving it. +auth_type must be either of: Basic, Digest, Both or Both-inline +When auth_type is Basic or Digest, the server asks for the respective +authentication in its response. When auth_type is Both, the server sends two +Authenticate headers, one requesting Basic and the other requesting Digest +authentication. If auth_type is Both-inline, the server sends only one +Authenticate header, but lists both Basic and Digest as supported mechanisms in +that. +""" + + +@rule() +class Authentication: + def __init__ (self, auth_obj): + self.auth_type = auth_obj['Type'] + self.auth_user = auth_obj['User'] + self.auth_pass = auth_obj['Pass'] diff --git a/testenv/conf/expect_header.py b/testenv/conf/expect_header.py new file mode 100644 index 0000000..055099f --- /dev/null +++ b/testenv/conf/expect_header.py @@ -0,0 +1,12 @@ +from conf import rule + +""" Rule: ExpectHeader +This rule defines a dictionary of headers and their value which the server +should expect in each request for the file to which the rule was applied. +""" + + +@rule() +class ExpectHeader: + def __init__(self, header_obj): + self.headers = header_obj diff --git a/testenv/conf/expected_files.py b/testenv/conf/expected_files.py new file mode 100644 index 0000000..2c8d632 --- /dev/null +++ b/testenv/conf/expected_files.py @@ -0,0 +1,51 @@ +from difflib import unified_diff +import os +import sys +from conf import hook +from exc.test_failed import TestFailed + +""" Post-Test Hook: ExpectedFiles +This is a Post-Test hook that checks the test directory for the files it +contains. A dictionary object is passed to it, which contains a mapping of +filenames and contents of all the files that the directory is expected to +contain. +Raises a TestFailed exception if the expected files are not found or if extra +files are found, else returns gracefully. +""" + + +@hook() +class ExpectedFiles: + def __init__(self, expected_fs): + self.expected_fs = expected_fs + + @staticmethod + def gen_local_fs_snapshot(): + snapshot = {} + for parent, dirs, files in os.walk('.'): + for name in files: + f = {'content': ''} + file_path = os.path.join(parent, name) + with open(file_path) as fp: + f['content'] = fp.read() + snapshot[file_path[2:]] = f + + return snapshot + + def __call__(self, test_obj): + local_fs = self.gen_local_fs_snapshot() + for file in self.expected_fs: + if file.name in local_fs: + local_file = local_fs.pop(file.name) + if file.content != local_file['content']: + for line in unified_diff(local_file['content'], + file.content, + fromfile='Actual', + tofile='Expected'): + print(line, file=sys.stderr) + raise TestFailed('Contents of %s do not match' % file.name) + else: + raise TestFailed('Expected file %s not found.' % file.name) + if local_fs: + print(local_fs) + raise TestFailed('Extra files downloaded.') diff --git a/testenv/conf/expected_ret_code.py b/testenv/conf/expected_ret_code.py new file mode 100644 index 0000000..87cba13 --- /dev/null +++ b/testenv/conf/expected_ret_code.py @@ -0,0 +1,27 @@ +from exc.test_failed import TestFailed +from conf import hook + +""" Post-Test Hook: ExpectedRetCode +This is a post-test hook which checks if the exit code of the Wget instance +under test is the same as that expected. As a result, this is a very important +post test hook which is checked in all the tests. +Returns a TestFailed exception if the return code does not match the expected +value. Else returns gracefully. +""" + + +@hook(alias='ExpectedRetcode') +class ExpectedRetCode: + def __init__(self, expected_ret_code): + self.expected_ret_code = expected_ret_code + + def __call__(self, test_obj): + if test_obj.ret_code != self.expected_ret_code: + if test_obj.ret_code == 45: + failure = "Memory Leak Found by Valgrind" + else: + failure = "Return codes do not match.\n" \ + "Expected: %s\n" \ + "Actual: %s" % (self.expected_ret_code, + test_obj.ret_code) + raise TestFailed(failure) diff --git a/testenv/conf/files_crawled.py b/testenv/conf/files_crawled.py new file mode 100644 index 0000000..334e596 --- /dev/null +++ b/testenv/conf/files_crawled.py @@ -0,0 +1,27 @@ +from misc.colour_terminal import print_red +from conf import hook +from exc.test_failed import TestFailed + +""" Post-Test Hook: FilesCrawled +This is a post test hook that is invoked in tests that check wget's behaviour +in recursive mode. It expects an ordered list of the request lines that Wget +must send to the server. If the requests received by the server do not match +the provided list, IN THE GIVEN ORDER, then it raises a TestFailed exception. +Such a test can be used to check the implementation of the recursion algorithm +in Wget too. +""" + + +@hook() +class FilesCrawled: + def __init__(self, request_headers): + self.request_headers = request_headers + + def __call__(self, test_obj): + for headers, remaining in zip(map(set, self.request_headers), + test_obj.request_remaining()): + diff = headers.symmetric_difference(remaining) + + if diff: + print_red (str(diff)) + raise TestFailed('Not all files were crawled correctly.') diff --git a/testenv/conf/hook_sample.py b/testenv/conf/hook_sample.py new file mode 100644 index 0000000..6230a70 --- /dev/null +++ b/testenv/conf/hook_sample.py @@ -0,0 +1,22 @@ +from exc.test_failed import TestFailed +from conf import hook + +""" Hook: SampleHook +This a sample file for how a new hook should be defined. +Any errors should always be reported by raising a TestFailed exception instead +of returning a true or false value. +""" + + +@hook(alias='SampleHookAlias') +class SampleHook: + def __init__(self, sample_hook_arg): + # do conf initialization here + self.arg = sample_hook_arg + + def __call__(self, test_obj): + # implement hook here + # if you need the test case instance, refer to test_obj + if False: + raise TestFailed ("Reason") + pass diff --git a/testenv/conf/local_files.py b/testenv/conf/local_files.py new file mode 100644 index 0000000..5f9c8fa --- /dev/null +++ b/testenv/conf/local_files.py @@ -0,0 +1,18 @@ +from conf import hook + +""" Pre-Test Hook: LocalFiles +This is a pre-test hook used to generate the specific environment before a test +is run. The LocalFiles hook creates the files which should exist on disk before +invoking Wget. +""" + + +@hook() +class LocalFiles: + def __init__(self, local_files): + self.local_files = local_files + + def __call__(self, _): + for f in self.local_files: + with open(f.name, 'w') as fp: + fp.write(f.content) diff --git a/testenv/conf/reject_header.py b/testenv/conf/reject_header.py new file mode 100644 index 0000000..53e237d --- /dev/null +++ b/testenv/conf/reject_header.py @@ -0,0 +1,13 @@ +from conf import rule + +""" Rule: RejectHeader +This is a server side rule which expects a dictionary object of Headers and +their values which should be blacklisted by the server for a particular file's +requests. +""" + + +@rule() +class RejectHeader: + def __init__ (self, header_obj): + self.headers = header_obj diff --git a/testenv/conf/response.py b/testenv/conf/response.py new file mode 100644 index 0000000..976a9ce --- /dev/null +++ b/testenv/conf/response.py @@ -0,0 +1,11 @@ +from conf import rule + +""" Rule: Response +When this rule is set against a certain file, the server will unconditionally +respond to any request for the said file with the provided response code. """ + + +@rule() +class Response: + def __init__(self, ret_code): + self.response_code = ret_code diff --git a/testenv/conf/rule_sample.py b/testenv/conf/rule_sample.py new file mode 100644 index 0000000..6345a3c --- /dev/null +++ b/testenv/conf/rule_sample.py @@ -0,0 +1,10 @@ +from conf import rule + + +@rule(alias='SampleRuleAlias') +class SampleRule: + def __init__(self, rule): + # do rule initialization here + # you may also need to implement a method the same name of this + # class in server/protocol/protocol_server.py to apply this rule. + self.rule = rule diff --git a/testenv/conf/send_header.py b/testenv/conf/send_header.py new file mode 100644 index 0000000..1ac54cc --- /dev/null +++ b/testenv/conf/send_header.py @@ -0,0 +1,12 @@ +from conf import rule + +""" Rule: SendHeader +Have the server send custom headers when responding to a request for the file +this rule is applied to. The header_obj object is expected to be dictionary +mapping headers to their contents. """ + + +@rule() +class SendHeader: + def __init__(self, header_obj): + self.headers = header_obj diff --git a/testenv/conf/server_files.py b/testenv/conf/server_files.py new file mode 100644 index 0000000..1e9d346 --- /dev/null +++ b/testenv/conf/server_files.py @@ -0,0 +1,26 @@ +from conf import hook + +""" Pre-Test Hook: ServerFiles +This hook is used to define a set of files on the server's virtual filesystem. +server_files is expected to be dictionary that maps filenames to their +contents. In the future, this can be used to add additional metadat to the +files using the WgetFile class too. + +This hook also does some additional processing on the contents of the file. Any +text between {{and}} is replaced by the contents of a class variable of the +same name. This is useful in creating files that contain an absolute link to +another file on the same server. """ + + +@hook() +class ServerFiles: + def __init__(self, server_files): + self.server_files = server_files + + def __call__(self, test_obj): + for server, files in zip(test_obj.servers, self.server_files): + rules = {f.name: test_obj.get_server_rules(f) + for f in files} + files = {f.name: test_obj._replace_substring(f.content) + for f in files} + server.server_conf(files, rules) diff --git a/testenv/conf/urls.py b/testenv/conf/urls.py new file mode 100644 index 0000000..f34c13e --- /dev/null +++ b/testenv/conf/urls.py @@ -0,0 +1,14 @@ +from conf import hook + +""" Pre-Test Hook: URLS +This hook is used to define the paths of the files on the test server that wget +will send a request for. """ + + +@hook(alias='Urls') +class URLs: + def __init__(self, urls): + self.urls = urls + + def __call__(self, test_obj): + test_obj.urls = self.urls diff --git a/testenv/conf/wget_commands.py b/testenv/conf/wget_commands.py new file mode 100644 index 0000000..2b7522e --- /dev/null +++ b/testenv/conf/wget_commands.py @@ -0,0 +1,15 @@ +from conf import hook + +""" Pre-Test Hook: WgetCommands +This hook is used to specify the test specific switches that must be passed to +wget on invokation. Default switches are hard coded in the test suite itself. +""" + + +@hook() +class WgetCommands: + def __init__(self, commands): + self.commands = commands + + def __call__(self, test_obj): + test_obj.wget_options = test_obj._replace_substring(self.commands) diff --git a/testenv/exc/__init__.py b/testenv/exc/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/testenv/exc/__init__.py diff --git a/testenv/exc/__pycache__/__init__.cpython-33.pyo b/testenv/exc/__pycache__/__init__.cpython-33.pyo Binary files differnew file mode 100644 index 0000000..ddd2eb9 --- /dev/null +++ b/testenv/exc/__pycache__/__init__.cpython-33.pyo diff --git a/testenv/exc/__pycache__/server_error.cpython-33.pyo b/testenv/exc/__pycache__/server_error.cpython-33.pyo Binary files differnew file mode 100644 index 0000000..fd7ba4c --- /dev/null +++ b/testenv/exc/__pycache__/server_error.cpython-33.pyo diff --git a/testenv/exc/__pycache__/test_failed.cpython-33.pyo b/testenv/exc/__pycache__/test_failed.cpython-33.pyo Binary files differnew file mode 100644 index 0000000..d87aea5 --- /dev/null +++ b/testenv/exc/__pycache__/test_failed.cpython-33.pyo diff --git a/testenv/exc/server_error.py b/testenv/exc/server_error.py new file mode 100644 index 0000000..b8a37ce --- /dev/null +++ b/testenv/exc/server_error.py @@ -0,0 +1,7 @@ + +class ServerError (Exception): + """ A custom exception which is raised by the test servers. Often used to + handle control flow. """ + + def __init__ (self, err_message): + self.err_message = err_message diff --git a/testenv/exc/test_failed.py b/testenv/exc/test_failed.py new file mode 100644 index 0000000..de5e02a --- /dev/null +++ b/testenv/exc/test_failed.py @@ -0,0 +1,7 @@ + +class TestFailed(Exception): + + """ A Custom Exception raised by the Test Environment. """ + + def __init__ (self, error): + self.error = error diff --git a/testenv/misc/__init__.py b/testenv/misc/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/testenv/misc/__init__.py diff --git a/testenv/misc/__pycache__/__init__.cpython-33.pyo b/testenv/misc/__pycache__/__init__.cpython-33.pyo Binary files differnew file mode 100644 index 0000000..0bb6da3 --- /dev/null +++ b/testenv/misc/__pycache__/__init__.cpython-33.pyo diff --git a/testenv/misc/__pycache__/colour_terminal.cpython-33.pyo b/testenv/misc/__pycache__/colour_terminal.cpython-33.pyo Binary files differnew file mode 100644 index 0000000..43caa7b --- /dev/null +++ b/testenv/misc/__pycache__/colour_terminal.cpython-33.pyo diff --git a/testenv/misc/__pycache__/wget_file.cpython-33.pyo b/testenv/misc/__pycache__/wget_file.cpython-33.pyo Binary files differnew file mode 100644 index 0000000..7ed99db --- /dev/null +++ b/testenv/misc/__pycache__/wget_file.cpython-33.pyo diff --git a/testenv/misc/colour_terminal.py b/testenv/misc/colour_terminal.py new file mode 100644 index 0000000..b0849c1 --- /dev/null +++ b/testenv/misc/colour_terminal.py @@ -0,0 +1,44 @@ +from functools import partial +import platform +from os import getenv + +""" This module allows printing coloured output to the terminal when running a +Wget Test under certain conditions. +The output is coloured only on Linux systems. This is because coloured output +in the terminal on Windows requires too much effort for what is simply a +convenience. This might work on OSX terminals, but without a confirmation, it +remains unsupported. + +Another important aspect is that the coloured output is printed only if the +environment variable MAKE_CHECK is not set. This variable is set when running +the test suite through, `make check`. In that case, the output is not only +printed to the terminal but also copied to a log file where the ANSI escape +codes on;y add clutter. """ + + +T_COLORS = { + 'PURPLE' : '\033[95m', + 'BLUE' : '\033[94m', + 'GREEN' : '\033[92m', + 'YELLOW' : '\033[93m', + 'RED' : '\033[91m', + 'ENDC' : '\033[0m' +} + +system = True if platform.system() == 'Linux' else False +check = False if getenv("MAKE_CHECK") == 'True' else True + +def printer (color, string): + if system and check: + print (T_COLORS.get (color) + string + T_COLORS.get ('ENDC')) + else: + print (string) + + +print_blue = partial(printer, 'BLUE') +print_red = partial(printer, 'RED') +print_green = partial(printer, 'GREEN') +print_purple = partial(printer, 'PURPLE') +print_yellow = partial(printer, 'YELLOW') + +# vim: set ts=8 sw=3 tw=80 et : diff --git a/testenv/misc/wget_file.py b/testenv/misc/wget_file.py new file mode 100644 index 0000000..027dced --- /dev/null +++ b/testenv/misc/wget_file.py @@ -0,0 +1,16 @@ + +class WgetFile: + + """ WgetFile is a File Data Container object """ + + def __init__ ( + self, + name, + content="Test Contents", + timestamp=None, + rules=None + ): + self.name = name + self.content = content + self.timestamp = timestamp + self.rules = rules or {} diff --git a/testenv/server/__init__.py b/testenv/server/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/testenv/server/__init__.py diff --git a/testenv/server/__pycache__/__init__.cpython-33.pyo b/testenv/server/__pycache__/__init__.cpython-33.pyo Binary files differnew file mode 100644 index 0000000..7464383 --- /dev/null +++ b/testenv/server/__pycache__/__init__.cpython-33.pyo diff --git a/testenv/server/ftp/__init__.py b/testenv/server/ftp/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/testenv/server/ftp/__init__.py diff --git a/testenv/server/ftp/ftp_server.py b/testenv/server/ftp/ftp_server.py new file mode 100644 index 0000000..f7d7771 --- /dev/null +++ b/testenv/server/ftp/ftp_server.py @@ -0,0 +1,162 @@ +import os +import re +import threading +import socket +import pyftpdlib.__main__ +from pyftpdlib.ioloop import IOLoop +import pyftpdlib.handlers as Handle +from pyftpdlib.servers import FTPServer +from pyftpdlib.authorizers import DummyAuthorizer +from pyftpdlib._compat import PY3, u, b, getcwdu, callable + +class FTPDHandler (Handle.FTPHandler): + + def ftp_LIST (self, path): + try: + iterator = self.run_as_current_user(self.fs.get_list_dir, path) + except (OSError, FilesystemError): + err = sys.exc_info()[1] + why = _strerror (err) + self.respond ('550 %s. ' % why) + else: + if self.isRule ("Bad List") is True: + iter_list = list () + for flist in iterator: + line = re.compile (r'(\s+)').split (flist.decode ('utf-8')) + line[8] = '0' + iter_l = ''.join (line).encode ('utf-8') + iter_list.append (iter_l) + iterator = (n for n in iter_list) + producer = Handle.BufferedIteratorProducer (iterator) + self.push_dtp_data (producer, isproducer=True, cmd="LIST") + return path + + def ftp_PASV (self, line): + if self._epsvall: + self.respond ("501 PASV not allowed after EPSV ALL.") + return + self._make_epasv(extmode=False) + if self.isRule ("FailPASV") is True: + del self.server.global_rules["FailPASV"] + self.socket.close () + + def isRule (self, rule): + rule_obj = self.server.global_rules[rule] + return False if not rule_obj else rule_obj[0] + +class FTPDServer (FTPServer): + + def set_global_rules (self, rules): + self.global_rules = rules + +class FTPd(threading.Thread): + """A threaded FTP server used for running tests. + + This is basically a modified version of the FTPServer class which + wraps the polling loop into a thread. + + The instance returned can be used to start(), stop() and + eventually re-start() the server. + """ + handler = FTPDHandler + server_class = FTPDServer + + def __init__(self, addr=None): + os.mkdir ('server') + os.chdir ('server') + try: + HOST = socket.gethostbyname ('localhost') + except socket.error: + HOST = 'localhost' + USER = 'user' + PASSWD = '12345' + HOME = getcwdu () + + threading.Thread.__init__(self) + self.__serving = False + self.__stopped = False + self.__lock = threading.Lock() + self.__flag = threading.Event() + if addr is None: + addr = (HOST, 0) + + authorizer = DummyAuthorizer() + authorizer.add_user(USER, PASSWD, HOME, perm='elradfmwM') # full perms + authorizer.add_anonymous(HOME) + self.handler.authorizer = authorizer + # lowering buffer sizes = more cycles to transfer data + # = less false positive test failures + self.handler.dtp_handler.ac_in_buffer_size = 32768 + self.handler.dtp_handler.ac_out_buffer_size = 32768 + self.server = self.server_class(addr, self.handler) + self.host, self.port = self.server.socket.getsockname()[:2] + os.chdir ('..') + + def set_global_rules (self, rules): + self.server.set_global_rules (rules) + + def __repr__(self): + status = [self.__class__.__module__ + "." + self.__class__.__name__] + if self.__serving: + status.append('active') + else: + status.append('inactive') + status.append('%s:%s' % self.server.socket.getsockname()[:2]) + return '<%s at %#x>' % (' '.join(status), id(self)) + + @property + def running(self): + return self.__serving + + def start(self, timeout=0.001): + """Start serving until an explicit stop() request. + Polls for shutdown every 'timeout' seconds. + """ + if self.__serving: + raise RuntimeError("Server already started") + if self.__stopped: + # ensure the server can be started again + FTPd.__init__(self, self.server.socket.getsockname(), self.handler) + self.__timeout = timeout + threading.Thread.start(self) + self.__flag.wait() + + def run(self): + self.__serving = True + self.__flag.set() + while self.__serving: + self.__lock.acquire() + self.server.serve_forever(timeout=self.__timeout, blocking=False) + self.__lock.release() + self.server.close_all() + + def stop(self): + """Stop serving (also disconnecting all currently connected + clients) by telling the serve_forever() loop to stop and + waits until it does. + """ + if not self.__serving: + raise RuntimeError("Server not started yet") + self.__serving = False + self.__stopped = True + self.join() + + +def mk_file_sys (file_list): + os.chdir ('server') + for name, content in file_list.items (): + file_h = open (name, 'w') + file_h.write (content) + file_h.close () + os.chdir ('..') + +def filesys (): + fileSys = dict () + os.chdir ('server') + for parent, dirs, files in os.walk ('.'): + for filename in files: + file_handle = open (filename, 'r') + file_content = file_handle.read () + fileSys[filename] = file_content + os.chdir ('..') + return fileSys diff --git a/testenv/server/http/__init__.py b/testenv/server/http/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/testenv/server/http/__init__.py diff --git a/testenv/server/http/__pycache__/__init__.cpython-33.pyo b/testenv/server/http/__pycache__/__init__.cpython-33.pyo Binary files differnew file mode 100644 index 0000000..ec8a9e6 --- /dev/null +++ b/testenv/server/http/__pycache__/__init__.cpython-33.pyo diff --git a/testenv/server/http/__pycache__/http_server.cpython-33.pyo b/testenv/server/http/__pycache__/http_server.cpython-33.pyo Binary files differnew file mode 100644 index 0000000..b8c7ce2 --- /dev/null +++ b/testenv/server/http/__pycache__/http_server.cpython-33.pyo diff --git a/testenv/server/http/http_server.py b/testenv/server/http/http_server.py new file mode 100644 index 0000000..9128b3e --- /dev/null +++ b/testenv/server/http/http_server.py @@ -0,0 +1,442 @@ +from http.server import HTTPServer, BaseHTTPRequestHandler +from exc.server_error import ServerError +from socketserver import BaseServer +from posixpath import basename, splitext +from base64 import b64encode +from random import random +from hashlib import md5 +import threading +import socket +import os + + +class StoppableHTTPServer (HTTPServer): + """ This class extends the HTTPServer class from default http.server library + in Python 3. The StoppableHTTPServer class is capable of starting an HTTP + server that serves a virtual set of files made by the WgetFile class and + has most of its properties configurable through the server_conf() + method. """ + + request_headers = list () + + """ Define methods for configuring the Server. """ + + def server_conf (self, filelist, conf_dict): + """ Set Server Rules and File System for this instance. """ + self.server_configs = conf_dict + self.fileSys = filelist + + def get_req_headers (self): + return self.request_headers + + +class HTTPSServer (StoppableHTTPServer): + """ The HTTPSServer class extends the StoppableHTTPServer class with + additional support for secure connections through SSL. """ + + def __init__ (self, address, handler): + import ssl + BaseServer.__init__ (self, address, handler) + # step one up because test suite change directory away from $srcdir (don't do that !!!) + CERTFILE = os.path.abspath(os.path.join('..', os.getenv('srcdir', '.'), 'certs', 'server-cert.pem')) + KEYFILE = os.path.abspath(os.path.join('..', os.getenv('srcdir', '.'), 'certs', 'server-key.pem')) + fop = open (CERTFILE) + print (fop.readline()) + self.socket = ssl.wrap_socket ( + sock = socket.socket (self.address_family, self.socket_type), + ssl_version = ssl.PROTOCOL_TLSv1, + certfile = CERTFILE, + keyfile = KEYFILE, + server_side = True + ) + self.server_bind() + self.server_activate() + + +class _Handler (BaseHTTPRequestHandler): + """ This is a private class which tells the server *HOW* to handle each + request. For each HTTP Request Command that the server should be capable of + responding to, there must exist a do_REQUESTNAME() method which details the + steps in which such requests should be processed. The rest of the methods + in this class are auxilliary methods created to help in processing certain + requests. """ + + def get_rule_list (self, name): + return self.rules.get(name) + + # The defailt protocol version of the server we run is HTTP/1.1 not + # HTTP/1.0 which is the default with the http.server module. + protocol_version = 'HTTP/1.1' + + """ Define functions for various HTTP Requests. """ + + def do_HEAD (self): + self.send_head ("HEAD") + + def do_GET (self): + """ Process HTTP GET requests. This is the same as processing HEAD + requests and then actually transmitting the data to the client. If + send_head() does not specify any "start" offset, we send the complete + data, else transmit only partial data. """ + + content, start = self.send_head ("GET") + if content: + if start is None: + self.wfile.write (content.encode ('utf-8')) + else: + self.wfile.write (content.encode ('utf-8')[start:]) + + def do_POST (self): + """ According to RFC 7231 sec 4.3.3, if the resource requested in a POST + request does not exist on the server, the first POST request should + create that resource. PUT requests are otherwise used to create a + resource. Hence, we call the handle for processing PUT requests if the + resource requested does not already exist. + + Currently, when the server recieves a POST request for a resource, we + simply append the body data to the existing file and return the new + file to the client. If the file does not exist, a new file is created + using the contents of the request body. """ + + path = self.path[1:] + if path in self.server.fileSys: + self.rules = self.server.server_configs.get (path) + if not self.rules: + self.rules = dict () + + if not self.custom_response (): + return (None, None) + + body_data = self.get_body_data () + self.send_response (200) + self.send_header ("Content-type", "text/plain") + content = self.server.fileSys.pop (path) + "\n" + body_data + total_length = len (content) + self.server.fileSys[path] = content + self.send_header ("Content-Length", total_length) + self.send_header ("Location", self.path) + self.finish_headers () + try: + self.wfile.write (content.encode ('utf-8')) + except Exception: + pass + else: + self.send_put (path) + + def do_PUT (self): + path = self.path[1:] + self.rules = self.server.server_configs.get (path) + if not self.custom_response (): + return (None, None) + self.send_put (path) + + """ End of HTTP Request Method Handlers. """ + + """ Helper functions for the Handlers. """ + + def parse_range_header (self, header_line, length): + import re + if header_line is None: + return None + if not header_line.startswith ("bytes="): + raise ServerError ("Cannot parse header Range: %s" % + (header_line)) + regex = re.match (r"^bytes=(\d*)\-$", header_line) + range_start = int (regex.group (1)) + if range_start >= length: + raise ServerError ("Range Overflow") + return range_start + + def get_body_data (self): + cLength_header = self.headers.get ("Content-Length") + cLength = int (cLength_header) if cLength_header is not None else 0 + body_data = self.rfile.read (cLength).decode ('utf-8') + return body_data + + def send_put (self, path): + if path in self.server.fileSys: + self.server.fileSys.pop (path, None) + self.send_response (204) + else: + self.rules = dict () + self.send_response (201) + body_data = self.get_body_data () + self.server.fileSys[path] = body_data + self.send_header ("Location", self.path) + self.finish_headers () + + """ This empty method is called automatically when all the rules are + processed for a given request. However, send_header() should only be called + AFTER a response has been sent. But, at the moment of processing the rules, + the appropriate response has not yet been identified. As a result, we defer + the processing of this rule till later. Each do_* request handler MUST call + finish_headers() instead of end_headers(). The finish_headers() method + takes care of sending the appropriate headers before completing the + response. """ + def SendHeader (self, header_obj): + pass + + def send_cust_headers (self): + header_obj = self.get_rule_list ('SendHeader') + if header_obj: + for header in header_obj.headers: + self.send_header (header, header_obj.headers[header]) + + def finish_headers (self): + self.send_cust_headers () + self.end_headers () + + def Response (self, resp_obj): + self.send_response (resp_obj.response_code) + self.finish_headers () + raise ServerError ("Custom Response code sent.") + + def custom_response (self): + codes = self.get_rule_list ('Response') + if codes: + self.send_response (codes.response_code) + self.finish_headers () + return False + else: + return True + + def base64 (self, data): + string = b64encode (data.encode ('utf-8')) + return string.decode ('utf-8') + + def send_challenge (self, auth_type): + auth_type = auth_type.lower() + if auth_type == "both": + self.send_challenge ("basic") + self.send_challenge ("digest") + return + if auth_type == "basic": + challenge_str = 'BasIc realm="Wget-Test"' + elif auth_type == "digest" or auth_type == "both_inline": + self.nonce = md5 (str (random ()).encode ('utf-8')).hexdigest() + self.opaque = md5 (str (random ()).encode ('utf-8')).hexdigest() + # 'DIgest' to provoke a Wget failure with turkish locales + challenge_str = 'DIgest realm="Test", nonce="%s", opaque="%s"' % ( + self.nonce, + self.opaque) + challenge_str += ', qop="auth"' + if auth_type == "both_inline": + # 'BasIc' to provoke a Wget failure with turkish locales + challenge_str = 'BasIc realm="Wget-Test", ' + challenge_str + self.send_header ("WWW-Authenticate", challenge_str) + + def authorize_basic (self, auth_header, auth_rule): + if auth_header is None or auth_header.split(' ')[0].lower() != 'basic': + return False + else: + self.user = auth_rule.auth_user + self.passw = auth_rule.auth_pass + auth_str = "basic " + self.base64 (self.user + ":" + self.passw) + return True if auth_str.lower() == auth_header.lower() else False + + def parse_auth_header (self, auth_header): + n = len("digest ") + auth_header = auth_header[n:].strip() + items = auth_header.split(", ") + keyvals = [i.split("=", 1) for i in items] + keyvals = [(k.strip(), v.strip().replace('"', '')) for k, v in keyvals] + return dict(keyvals) + + def KD (self, secret, data): + return self.H (secret + ":" + data) + + def H (self, data): + return md5 (data.encode ('utf-8')).hexdigest () + + def A1 (self): + return "%s:%s:%s" % (self.user, "Test", self.passw) + + def A2 (self, params): + return "%s:%s" % (self.command, params["uri"]) + + def check_response (self, params): + if "qop" in params: + data_str = params['nonce'] \ + + ":" + params['nc'] \ + + ":" + params['cnonce'] \ + + ":" + params['qop'] \ + + ":" + self.H (self.A2 (params)) + else: + data_str = params['nonce'] + ":" + self.H (self.A2 (params)) + resp = self.KD (self.H (self.A1 ()), data_str) + + return True if resp == params['response'] else False + + def authorize_digest (self, auth_header, auth_rule): + if auth_header is None or auth_header.split(' ')[0].lower() != 'digest': + return False + else: + self.user = auth_rule.auth_user + self.passw = auth_rule.auth_pass + params = self.parse_auth_header (auth_header) + pass_auth = True + if self.user != params['username'] or \ + self.nonce != params['nonce'] or \ + self.opaque != params['opaque']: + pass_auth = False + req_attribs = ['username', 'realm', 'nonce', 'uri', 'response'] + for attrib in req_attribs: + if attrib not in params: + pass_auth = False + if not self.check_response (params): + pass_auth = False + return pass_auth + + def authorize_both (self, auth_header, auth_rule): + return False + + def authorize_both_inline (self, auth_header, auth_rule): + return False + + def Authentication (self, auth_rule): + try: + self.handle_auth (auth_rule) + except ServerError as se: + self.send_response (401, "Authorization Required") + self.send_challenge (auth_rule.auth_type) + self.finish_headers () + raise ServerError (se.__str__()) + + def handle_auth (self, auth_rule): + is_auth = True + auth_header = self.headers.get ("Authorization") + required_auth = auth_rule.auth_type.lower() + if required_auth == "both" or required_auth == "both_inline": + auth_type = auth_header.split(' ')[0].lower() if auth_header else required_auth + else: + auth_type = required_auth + try: + assert hasattr (self, "authorize_" + auth_type) + is_auth = getattr (self, "authorize_" + auth_type) (auth_header, auth_rule) + except AssertionError: + raise ServerError ("Authentication Mechanism " + auth_type + " not supported") + except AttributeError as ae: + raise ServerError (ae.__str__()) + if is_auth is False: + raise ServerError ("Unable to Authenticate") + + + def ExpectHeader (self, header_obj): + exp_headers = header_obj.headers + for header_line in exp_headers: + header_recd = self.headers.get (header_line) + if header_recd is None or header_recd != exp_headers[header_line]: + self.send_error (400, "Expected Header " + header_line + " not found") + self.finish_headers () + raise ServerError ("Header " + header_line + " not found") + + + def RejectHeader (self, header_obj): + rej_headers = header_obj.headers + for header_line in rej_headers: + header_recd = self.headers.get (header_line) + if header_recd is not None and header_recd == rej_headers[header_line]: + self.send_error (400, 'Blacklisted Header ' + header_line + ' received') + self.finish_headers () + raise ServerError ("Header " + header_line + ' received') + + def __log_request (self, method): + req = method + " " + self.path + self.server.request_headers.append (req) + + def send_head (self, method): + """ Common code for GET and HEAD Commands. + This method is overriden to use the fileSys dict. + + The method variable contains whether this was a HEAD or a GET Request. + According to RFC 2616, the server should not differentiate between + the two requests, however, we use it here for a specific test. + """ + + if self.path == "/": + path = "index.html" + else: + path = self.path[1:] + + self.__log_request (method) + + if path in self.server.fileSys: + self.rules = self.server.server_configs.get (path) + + for rule_name in self.rules: + try: + assert hasattr (self, rule_name) + getattr (self, rule_name) (self.rules [rule_name]) + except AssertionError as ae: + msg = "Method " + rule_name + " not defined" + self.send_error (500, msg) + return (None, None) + except ServerError as se: + print (se.__str__()) + return (None, None) + + content = self.server.fileSys.get (path) + content_length = len (content) + try: + self.range_begin = self.parse_range_header ( + self.headers.get ("Range"), content_length) + except ServerError as ae: + # self.log_error("%s", ae.err_message) + if ae.err_message == "Range Overflow": + self.send_response (416) + self.finish_headers () + return (None, None) + else: + self.range_begin = None + if self.range_begin is None: + self.send_response (200) + else: + self.send_response (206) + self.send_header ("Accept-Ranges", "bytes") + self.send_header ("Content-Range", + "bytes %d-%d/%d" % (self.range_begin, + content_length - 1, + content_length)) + content_length -= self.range_begin + cont_type = self.guess_type (path) + self.send_header ("Content-type", cont_type) + self.send_header ("Content-Length", content_length) + self.finish_headers () + return (content, self.range_begin) + else: + self.send_error (404, "Not Found") + return (None, None) + + def guess_type (self, path): + base_name = basename ("/" + path) + name, ext = splitext (base_name) + extension_map = { + ".txt" : "text/plain", + ".css" : "text/css", + ".html" : "text/html" + } + return extension_map.get(ext, "text/plain") + +class HTTPd (threading.Thread): + server_class = StoppableHTTPServer + handler = _Handler + + def __init__ (self, addr=None): + threading.Thread.__init__ (self) + if addr is None: + addr = ('localhost', 0) + self.server_inst = self.server_class (addr, self.handler) + self.server_address = self.server_inst.socket.getsockname()[:2] + + def run (self): + self.server_inst.serve_forever () + + def server_conf (self, file_list, server_rules): + self.server_inst.server_conf (file_list, server_rules) + + +class HTTPSd (HTTPd): + + server_class = HTTPSServer + +# vim: set ts=4 sts=4 sw=4 tw=80 et : diff --git a/testenv/test/__init__.py b/testenv/test/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/testenv/test/__init__.py diff --git a/testenv/test/__pycache__/__init__.cpython-33.pyo b/testenv/test/__pycache__/__init__.cpython-33.pyo Binary files differnew file mode 100644 index 0000000..ed9519e --- /dev/null +++ b/testenv/test/__pycache__/__init__.cpython-33.pyo diff --git a/testenv/test/__pycache__/base_test.cpython-33.pyo b/testenv/test/__pycache__/base_test.cpython-33.pyo Binary files differnew file mode 100644 index 0000000..b60e973 --- /dev/null +++ b/testenv/test/__pycache__/base_test.cpython-33.pyo diff --git a/testenv/test/__pycache__/http_test.cpython-33.pyo b/testenv/test/__pycache__/http_test.cpython-33.pyo Binary files differnew file mode 100644 index 0000000..75681a5 --- /dev/null +++ b/testenv/test/__pycache__/http_test.cpython-33.pyo diff --git a/testenv/test/base_test.py b/testenv/test/base_test.py new file mode 100644 index 0000000..0d98078 --- /dev/null +++ b/testenv/test/base_test.py @@ -0,0 +1,233 @@ +import os +import shutil +import shlex +import traceback +import re +import time +from subprocess import call +from misc.colour_terminal import print_red, print_blue +from exc.test_failed import TestFailed +import conf + +HTTP = "HTTP" +HTTPS = "HTTPS" + + +class BaseTest: + + """ + Class that defines methods common to both HTTP and FTP Tests. + Note that this is an abstract class, subclasses must implement + * stop_server() + * instantiate_server_by(protocol) + """ + + def __init__(self, name, pre_hook, test_params, post_hook, protocols): + """ + Define the class-wide variables (or attributes). + Attributes should not be defined outside __init__. + """ + self.name = name + self.pre_configs = pre_hook or {} # if pre_hook == None, then + # {} (an empty dict object) is + # passed to self.pre_configs + self.test_params = test_params or {} + self.post_configs = post_hook or {} + self.protocols = protocols + + self.servers = [] + self.domains = [] + self.port = -1 + + self.wget_options = '' + self.urls = [] + + self.tests_passed = True + self.init_test_env() + + self.ret_code = 0 + + def get_test_dir(self): + return self.name + '-test' + + def init_test_env(self): + test_dir = self.get_test_dir() + try: + os.mkdir(test_dir) + except FileExistsError: + shutil.rmtree(test_dir) + os.mkdir(test_dir) + os.chdir(test_dir) + + def get_domain_addr(self, addr): + # TODO if there's a multiple number of ports, wouldn't it be + # overridden to the port of the last invocation? + self.port = str(addr[1]) + + return '%s:%s' % (addr[0], self.port) + + def server_setup(self): + print_blue("Running Test %s" % self.name) + for protocol in self.protocols: + instance = self.instantiate_server_by(protocol) + self.servers.append(instance) + + # servers instantiated by different protocols may differ in + # ports and etc. + # so we should record different domains respect to servers. + domain = self.get_domain_addr(instance.server_address) + self.domains.append(domain) + + def exec_wget(self): + cmd_line = self.gen_cmd_line() + params = shlex.split(cmd_line) + print(params) + + if os.getenv("SERVER_WAIT"): + time.sleep(float(os.getenv("SERVER_WAIT"))) + + try: + ret_code = call(params) + except FileNotFoundError: + raise TestFailed("The Wget Executable does not exist at the " + "expected path.") + + return ret_code + + def gen_cmd_line(self): + test_path = os.path.abspath(".") + wget_path = os.path.abspath(os.path.join(test_path, + "..", '..', 'src', "wget")) + wget_options = '--debug --no-config %s' % self.wget_options + + valgrind = os.getenv("VALGRIND_TESTS", "") + if valgrind in ("", "0"): + cmd_line = '%s %s ' % (wget_path, wget_options) + elif valgrind == "1": + cmd_line = 'valgrind --error-exitcode=301 --leak-check=yes --track-origins=yes %s %s ' % (wget_path, wget_options) + else: + cmd_line = '%s %s %s ' % (os.getenv("VALGRIND_TESTS", ""), wget_path, wget_options) + + for protocol, urls, domain in zip(self.protocols, + self.urls, + self.domains): + # zip is function for iterating multiple lists at the same time. + # e.g. for item1, item2 in zip([1, 5, 3], + # ['a', 'e', 'c']): + # print(item1, item2) + # generates the following output: + # 1 a + # 5 e + # 3 c + for url in urls: + cmd_line += '%s://%s/%s ' % (protocol.lower(), domain, url) + + print(cmd_line) + + return cmd_line + + def __test_cleanup(self): + os.chdir('..') + try: + if not os.getenv("NO_CLEANUP"): + shutil.rmtree(self.get_test_dir()) + except: + print ("Unknown Exception while trying to remove Test Environment.") + + def _exit_test (self): + self.__test_cleanup() + + def begin (self): + return 0 if self.tests_passed else 100 + + def call_test(self): + self.hook_call(self.test_params, 'Test Option') + + try: + self.ret_code = self.exec_wget() + except TestFailed as e: + raise e + finally: + self.stop_server() + + def do_test(self): + self.pre_hook_call() + self.call_test() + self.post_hook_call() + + def hook_call(self, configs, name): + for conf_name, conf_arg in configs.items(): + try: + # conf.find_conf(conf_name) returns the required conf class, + # then the class is instantiated with conf_arg, then the + # conf instance is called with this test instance itself to + # invoke the desired hook + conf.find_conf(conf_name)(conf_arg)(self) + except AttributeError: + self.stop_server() + raise TestFailed("%s %s not defined." % + (name, conf_name)) + + def pre_hook_call(self): + self.hook_call(self.pre_configs, 'Pre Test Function') + + def post_hook_call(self): + self.hook_call(self.post_configs, 'Post Test Function') + + def _replace_substring (self, string): + pattern = re.compile ('\{\{\w+\}\}') + match_obj = pattern.search (string) + if match_obj is not None: + rep = match_obj.group() + temp = getattr (self, rep.strip ('{}')) + string = string.replace (rep, temp) + return string + + def instantiate_server_by(self, protocol): + """ + Subclasses must override this method to actually instantiate servers + for test cases. + """ + raise NotImplementedError + + def stop_server(self): + """ + Subclasses must implement this method in order to stop certain + servers of different types. + """ + raise NotImplementedError + + @staticmethod + def get_server_rules(file_obj): + """ + The handling of expect header could be made much better when the + options are parsed in a true and better fashion. For an example, + see the commented portion in Test-basic-auth.py. + """ + server_rules = {} + for rule_name, rule in file_obj.rules.items(): + server_rules[rule_name] = conf.find_conf(rule_name)(rule) + return server_rules + + def __enter__(self): + """ + Initialization for with statement. + """ + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + """ + If the with statement got executed with no exception raised, then + exc_type, exc_val, exc_tb are all None. + """ + if exc_val: + self.tests_passed = False + if exc_type is TestFailed: + print_red('Error: %s.' % exc_val.error) + else: + print_red('Unhandled exception caught.') + print(exc_val) + traceback.print_tb(exc_tb) + self.__test_cleanup() + + return True diff --git a/testenv/test/http_test.py b/testenv/test/http_test.py new file mode 100644 index 0000000..230eff8 --- /dev/null +++ b/testenv/test/http_test.py @@ -0,0 +1,46 @@ +from misc.colour_terminal import print_green +from server.http.http_server import HTTPd, HTTPSd +from test.base_test import BaseTest, HTTP, HTTPS + + +class HTTPTest(BaseTest): + + """ Class for HTTP Tests. """ + + # Temp Notes: It is expected that when pre-hook functions are executed, + # only an empty test-dir exists. pre-hook functions are executed just prior + # to the call to Wget is made. post-hook functions will be executed + # immediately after the call to Wget returns. + + def __init__(self, + name="Unnamed Test", + pre_hook=None, + test_params=None, + post_hook=None, + protocols=(HTTP,)): + super(HTTPTest, self).__init__(name, + pre_hook, + test_params, + post_hook, + protocols) + with self: + # if any exception occurs, self.__exit__ will be immediately called + self.server_setup() + self.do_test() + print_green('Test Passed.') + + def instantiate_server_by(self, protocol): + server = {HTTP: HTTPd, + HTTPS: HTTPSd}[protocol]() + server.start() + + return server + + def request_remaining(self): + return [s.server_inst.get_req_headers() + for s in self.servers] + + def stop_server(self): + for server in self.servers: + server.server_inst.shutdown() +# vim: set ts=4 sts=4 sw=4 tw=80 et : |