From 0dfa763bf8d20212c92ca51f78db52b6ee21bc52 Mon Sep 17 00:00:00 2001 From: Zihang Chen Date: Sun, 9 Mar 2014 21:35:07 +0800 Subject: [PATCH 1/2] refactor project --- testenv/ColourTerm.py | 23 - testenv/FTPServer.py | 162 ------- testenv/HTTPServer.py | 467 ------------------ testenv/Makefile.am | 180 +++---- testenv/README | 524 ++++++++++----------- testenv/Test--https.py | 103 ++-- testenv/Test--spider-r.py | 211 ++++----- testenv/Test-Content-disposition-2.py | 105 +++-- testenv/Test-Content-disposition.py | 111 ++--- testenv/Test-Head.py | 87 ++-- testenv/Test-O.py | 89 ++-- testenv/Test-Parallel-Proto.py | 106 +++-- testenv/Test-Post.py | 95 ++-- testenv/Test-Proto.py | 149 +++--- testenv/Test-auth-basic-fail.py | 102 ++-- testenv/Test-auth-basic.py | 13 +- testenv/Test-auth-both.py | 154 +++--- testenv/Test-auth-digest.py | 99 ++-- testenv/Test-auth-no-challenge-url.py | 107 ++--- testenv/Test-auth-no-challenge.py | 107 ++--- testenv/Test-auth-retcode.py | 98 ++-- testenv/Test-auth-with-content-disposition.py | 107 ++--- testenv/Test-c-full.py | 105 +++-- testenv/Test-cookie-401.py | 117 ++--- testenv/Test-cookie-domain-mismatch.py | 113 ++--- testenv/Test-cookie-expires.py | 159 +++---- testenv/Test-cookie.py | 113 ++--- testenv/WgetTest.py | 337 ------------- testenv/certs/wget-cert.pem | 60 +-- testenv/conf/__init__.py | 35 ++ testenv/conf/authentication.py | 9 + testenv/conf/expect_header.py | 10 + testenv/conf/expected_files.py | 47 ++ testenv/conf/expected_ret_code.py | 18 + testenv/conf/files_crawled.py | 21 + testenv/conf/local_files.py | 15 + testenv/conf/reject_header.py | 7 + testenv/conf/response.py | 9 + testenv/conf/send_header.py | 9 + testenv/conf/server_files.py | 17 + testenv/conf/urls.py | 13 + testenv/conf/wget_commands.py | 12 + testenv/exc/__init__.py | 1 + testenv/exc/test_failed.py | 8 + testenv/misc/__init__.py | 1 + testenv/misc/colour_terminal.py | 39 ++ testenv/misc/constants.py | 5 + testenv/misc/wget_file.py | 18 + testenv/server/__init__.py | 1 + testenv/server/ftp/__init__.py | 1 + testenv/server/ftp/ftp_server.py | 162 +++++++ testenv/server/http/__init__.py | 1 + .../http/__pycache__/__init__.cpython-33.pyc | Bin 0 -> 140 bytes .../http/__pycache__/http_server.cpython-33.pyc | Bin 0 -> 24879 bytes testenv/server/http/http_server.py | 471 ++++++++++++++++++ testenv/test/__init__.py | 1 + testenv/test/base_test.py | 203 ++++++++ testenv/test/http_test.py | 50 ++ 58 files changed, 2804 insertions(+), 2583 deletions(-) delete mode 100644 testenv/ColourTerm.py delete mode 100644 testenv/FTPServer.py delete mode 100644 testenv/HTTPServer.py delete mode 100644 testenv/WgetTest.py create mode 100644 testenv/conf/__init__.py create mode 100644 testenv/conf/authentication.py create mode 100644 testenv/conf/expect_header.py create mode 100644 testenv/conf/expected_files.py create mode 100644 testenv/conf/expected_ret_code.py create mode 100644 testenv/conf/files_crawled.py create mode 100644 testenv/conf/local_files.py create mode 100644 testenv/conf/reject_header.py create mode 100644 testenv/conf/response.py create mode 100644 testenv/conf/send_header.py create mode 100644 testenv/conf/server_files.py create mode 100644 testenv/conf/urls.py create mode 100644 testenv/conf/wget_commands.py create mode 100644 testenv/exc/__init__.py create mode 100644 testenv/exc/test_failed.py create mode 100644 testenv/misc/__init__.py create mode 100644 testenv/misc/colour_terminal.py create mode 100644 testenv/misc/constants.py create mode 100644 testenv/misc/wget_file.py create mode 100644 testenv/server/__init__.py create mode 100644 testenv/server/ftp/__init__.py create mode 100644 testenv/server/ftp/ftp_server.py create mode 100644 testenv/server/http/__init__.py create mode 100644 testenv/server/http/__pycache__/__init__.cpython-33.pyc create mode 100644 testenv/server/http/__pycache__/http_server.cpython-33.pyc create mode 100644 testenv/server/http/http_server.py create mode 100644 testenv/test/__init__.py create mode 100644 testenv/test/base_test.py create mode 100644 testenv/test/http_test.py diff --git a/testenv/ColourTerm.py b/testenv/ColourTerm.py deleted file mode 100644 index d8f6769..0000000 --- a/testenv/ColourTerm.py +++ /dev/null @@ -1,23 +0,0 @@ -import platform -from os import getenv - -T_COLORS = { - 'PURPLE' : '\033[95m', - 'BLUE' : '\033[94m', - 'GREEN' : '\033[92m', - 'YELLOW' : '\033[93m', - 'RED' : '\033[91m', - 'ENDC' : '\033[0m' -} - -def printer (color, string): - if platform.system () == 'Linux': - if getenv ("MAKE_CHECK", "False") == "True": - print (string) - else: - print (T_COLORS.get (color) + string + T_COLORS.get ('ENDC')) - - else: - print (string) - -# vim: set ts=8 sw=3 tw=0 et : diff --git a/testenv/FTPServer.py b/testenv/FTPServer.py deleted file mode 100644 index f7d7771..0000000 --- a/testenv/FTPServer.py +++ /dev/null @@ -1,162 +0,0 @@ -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/HTTPServer.py b/testenv/HTTPServer.py deleted file mode 100644 index e554a10..0000000 --- a/testenv/HTTPServer.py +++ /dev/null @@ -1,467 +0,0 @@ -from http.server import HTTPServer, BaseHTTPRequestHandler -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 re -import ssl -import os - - -class InvalidRangeHeader (Exception): - - """ Create an Exception for handling of invalid Range Headers. """ - # TODO: Eliminate this exception and use only ServerError - - def __init__ (self, err_message): - self.err_message = err_message - -class ServerError (Exception): - def __init__ (self, err_message): - self.err_message = err_message - - -class StoppableHTTPServer (HTTPServer): - - 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 server_sett (self, settings): - for settings_key in settings: - setattr (self.RequestHandlerClass, settings_key, settings[settings_key]) - - def get_req_headers (self): - return self.request_headers - -class HTTPSServer (StoppableHTTPServer): - - def __init__ (self, address, handler): - BaseServer.__init__ (self, address, handler) - print (os.getcwd()) - CERTFILE = os.path.abspath (os.path.join ('..', 'certs', 'wget-cert.pem')) - print (CERTFILE) - 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, - server_side = True - ) - self.server_bind () - self.server_activate () - -class WgetHTTPRequestHandler (BaseHTTPRequestHandler): - - """ Define methods for handling Test Checks. """ - - def get_rule_list (self, name): - r_list = self.rules.get (name) if name in self.rules else None - return r_list - - -class _Handler (WgetHTTPRequestHandler): - - """ Define Handler Methods for different Requests. """ - - InvalidRangeHeader = InvalidRangeHeader - protocol_version = 'HTTP/1.1' - - """ Define functions for various HTTP Requests. """ - - def do_HEAD (self): - self.send_head ("HEAD") - - def do_GET (self): - 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): - path = self.path[1:] - self.rules = self.server.server_configs.get (path) - if not self.custom_response (): - return (None, None) - if path in self.server.fileSys: - 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.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.server.fileSys.pop (path, None) - self.send_put (path) - - """ End of HTTP Request Method Handlers. """ - - """ Helper functions for the Handlers. """ - - def parse_range_header (self, header_line, length): - if header_line is None: - return None - if not header_line.startswith ("bytes="): - raise InvalidRangeHeader ("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 InvalidRangeHeader ("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): - body_data = self.get_body_data () - self.send_response (201) - self.server.fileSys[path] = body_data - self.send_header ("Content-type", "text/plain") - self.send_header ("Content-Length", len (body_data)) - self.finish_headers () - try: - self.wfile.write (body_data.encode ('utf-8')) - except Exception: - pass - - def SendHeader (self, header_obj): - pass -# headers_list = header_obj.headers -# for header_line in headers_list: -# print (header_line + " : " + headers_list[header_line]) -# self.send_header (header_line, headers_list[header_line]) - - 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): - if auth_type == "Both": - self.send_challenge ("Digest") - self.send_challenge ("Basic") - 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 () - challenge_str = 'Digest realm="Test", nonce="%s", opaque="%s"' %( - self.nonce, - self.opaque) - challenge_str += ', qop="auth"' - if auth_type == "Both_inline": - 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] != '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 == auth_header else False - - def parse_auth_header (self, auth_header): - n = len("Digest ") - auth_header = auth_header[n:].strip() - items = auth_header.split(", ") - key_values = [i.split("=", 1) for i in items] - key_values = [(k.strip(), v.strip().replace('"', '')) for k, v in key_values] - return dict(key_values) - - 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] != '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 not attrib 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 - if required_auth == "Both" or required_auth == "Both_inline": - auth_type = auth_header.split(' ')[0] 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_rule + " not supported") - except AttributeError as ae: - raise ServerError (ae.__str__()) - if is_auth is False: - raise ServerError ("Unable to Authenticate") - - def is_authorized (self): - is_auth = True - auth_rule = self.get_rule_list ('Authentication') - if auth_rule: - auth_header = self.headers.get ("Authorization") - req_auth = auth_rule.auth_type - if req_auth == "Both" or req_auth == "Both_inline": - auth_type = auth_header.split(' ')[0] if auth_header else req_auth - else: - auth_type = req_auth - assert hasattr (self, "authorize_" + auth_type) - is_auth = getattr (self, "authorize_" + auth_type) (auth_header, auth_rule) - if is_auth is False: - self.send_response (401) - self.send_challenge (auth_type) - self.finish_headers () - return is_auth - - 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 expect_headers (self): - """ This is modified code to handle a few changes. Should be removed ASAP """ - exp_headers_obj = self.get_rule_list ('ExpectHeader') - if exp_headers_obj: - exp_headers = exp_headers_obj.headers - for header_line in exp_headers: - header_re = self.headers.get (header_line) - if header_re is None or header_re != exp_headers[header_line]: - self.send_error (400, 'Expected Header not Found') - self.end_headers () - return False - return True - - 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, 'Blackisted Header ' + header_line + ' received') - self.finish_headers () - raise ServerError ("Header " + header_line + ' received') - - def reject_headers (self): - rej_headers = self.get_rule_list ("RejectHeader") - if rej_headers: - rej_headers = rej_headers.headers - for header_line in rej_headers: - header_re = self.headers.get (header_line) - if header_re is not None and header_re == rej_headers[header_line]: - self.send_error (400, 'Blacklisted Header was Sent') - self.end_headers () - return False - return True - - 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 InvalidRangeHeader 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" - } - if ext in extension_map: - return extension_map[ext] - else: - return "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) - - def server_sett (self, settings): - self.server_inst.server_sett (settings) - -class HTTPSd (HTTPd): - - server_class = HTTPSServer - -# vim: set ts=4 sts=4 sw=4 tw=80 et : diff --git a/testenv/Makefile.am b/testenv/Makefile.am index c616fa0..e284fac 100644 --- a/testenv/Makefile.am +++ b/testenv/Makefile.am @@ -1,90 +1,90 @@ -# 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 . - -# 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 = MAKE_CHECK=True; export MAKE_CHECK; - -if RACE_CHECKING_IS_ENABLED -RACE_FAIL = Test--spider-r.py -RACE_TESTS = -endif - -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 \ - $(RACE_TESTS) \ - Test-Head.py \ - Test--https.py \ - Test-O.py \ - Test-Post.py \ - Test--spider-r.py - -XFAIL_TESTS = Test-auth-both.py \ - $(RACE_FAIL) - -LOG_COMPILER = python3 - -EXTRA_DIST = ColourTerm.py \ - FTPServer.py \ - HTTPServer.py \ - README \ - Test--spider-r.py \ - Test--https.py \ - Test-Content-disposition-2.py \ - Test-Content-disposition.py \ - Test-Head.py \ - Test-O.py \ - Test-Parallel-Proto.py \ - Test-Post.py \ - Test-Proto.py \ - Test-auth-basic-fail.py \ - Test-auth-basic.py \ - Test-auth-both.py \ - Test-auth-digest.py \ - Test-auth-no-challenge-url.py \ - Test-auth-no-challenge.py \ - Test-auth-retcode.py \ - Test-auth-with-content-disposition.py \ - Test-c-full.py \ - Test-cookie-401.py \ - Test-cookie-domain-mismatch.py \ - Test-cookie-expires.py \ - Test-cookie.py \ - WgetTest.py +# 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 . + +# 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 = MAKE_CHECK=True; export MAKE_CHECK; + +if RACE_CHECKING_IS_ENABLED +RACE_FAIL = Test--spider-r.py +RACE_TESTS = +endif + +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 \ + $(RACE_TESTS) \ + Test-Head.py \ + Test--https.py \ + Test-O.py \ + Test-Post.py \ + Test--spider-r.py + +XFAIL_TESTS = Test-auth-both.py \ + $(RACE_FAIL) + +LOG_COMPILER = python3 + +EXTRA_DIST = ColourTerm.py \ + FTPServer.py \ + HTTPServer.py \ + README \ + Test--spider-r.py \ + Test--https.py \ + Test-Content-disposition-2.py \ + Test-Content-disposition.py \ + Test-Head.py \ + Test-O.py \ + Test-Parallel-Proto.py \ + Test-Post.py \ + Test-Proto.py \ + Test-auth-basic-fail.py \ + Test-auth-basic.py \ + Test-auth-both.py \ + Test-auth-digest.py \ + Test-auth-no-challenge-url.py \ + Test-auth-no-challenge.py \ + Test-auth-retcode.py \ + Test-auth-with-content-disposition.py \ + Test-c-full.py \ + Test-cookie-401.py \ + Test-cookie-domain-mismatch.py \ + Test-cookie-expires.py \ + Test-cookie.py \ + WgetTest.py diff --git a/testenv/README b/testenv/README index 09f226a..0aee658 100644 --- a/testenv/README +++ b/testenv/README @@ -1,262 +1,262 @@ -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. - -File List: -================================================================================ - - * HTTPServer.py: This file contains a custom, programmatically configurable - HTTP Server for testing Wget. It runs an instance of Python's http.server - module. - - * WgetTest.py: This file contains various functions and global variables for - each instance of the server that is initiated. It includes functions to - start and stop the server, to initialze the test environment and to cleanup - after a test. - - * 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. - - * ColourTerm.py: A custom library for printing coloured output to the - terminal. Currently it only supports 4 colours in a *nix environment. - -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 OR -$ ./ -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 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 - -Environment Variables: -================================================================================ - -TODO: Set variables for ONLY_SERVER and WGET_PATH too. -* NO_CLEANUP: Do not remove the temporary files created by the test. - This will prevent the ${testname}-test directory from being deleted - - -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}, 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 (String name, String contents, String 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, - servers -} -name expects the string name, and is usually passed the TEST_NAME variable, -the three hooks, expect python dictionary objects and servers is an integer. - -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 : - --->Pass : - - * 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 :
- - * 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. - * 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. 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. - * 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 add the required code in WgetTest.py. -In most cases, one requires a new Rule to be added for the Server to follow. -In such a case, create a new Class in WgetTest.py with the same name as the Rule -and define an __init__ () function to handle the data. A method must also be -defined in HTTPTest / FTPTest modules to handle the said Rule. - -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. - -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 +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. + +File List: +================================================================================ + + * HTTPServer.py: This file contains a custom, programmatically configurable + HTTP Server for testing Wget. It runs an instance of Python's http.server + module. + + * WgetTest.py: This file contains various functions and global variables for + each instance of the server that is initiated. It includes functions to + start and stop the server, to initialze the test environment and to cleanup + after a test. + + * 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. + + * ColourTerm.py: A custom library for printing coloured output to the + terminal. Currently it only supports 4 colours in a *nix environment. + +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 OR +$ ./ +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 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 + +Environment Variables: +================================================================================ + +TODO: Set variables for ONLY_SERVER and WGET_PATH too. +* NO_CLEANUP: Do not remove the temporary files created by the test. + This will prevent the ${testname}-test directory from being deleted + + +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}, 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 (String name, String contents, String 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, + servers +} +name expects the string name, and is usually passed the TEST_NAME variable, +the three hooks, expect python dictionary objects and servers is an integer. + +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 : + --->Pass : + + * 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 :
+ + * 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. + * 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. 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. + * 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 add the required code in WgetTest.py. +In most cases, one requires a new Rule to be added for the Server to follow. +In such a case, create a new Class in WgetTest.py with the same name as the Rule +and define an __init__ () function to handle the data. A method must also be +defined in HTTPTest / FTPTest modules to handle the said Rule. + +Once a new Test File is created, it must be added to the TESTS variable in +akefile.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. + +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.py b/testenv/Test--https.py index 17252b6..a9fb425 100755 --- a/testenv/Test--https.py +++ b/testenv/Test--https.py @@ -1,51 +1,52 @@ -#!/usr/bin/env python3 -from sys import exit -from WgetTest import HTTPTest, WgetFile, HTTPS, HTTP - -""" - 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) - -WGET_OPTIONS = "-d --no-check-certificate" -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, - servers=Servers -).begin () - -exit (err) +#!/usr/bin/env python3 +from sys import exit +from misc.wget_file import WgetFile +from test.http_test import HTTPTest, HTTPS + + +# 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) + +WGET_OPTIONS = "-d --no-check-certificate" +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 index b770a9f..d60d1c8 100755 --- a/testenv/Test--spider-r.py +++ b/testenv/Test--spider-r.py @@ -1,105 +1,106 @@ -#!/usr/bin/env python3 -from sys import exit -from WgetTest import HTTPTest, WgetFile - -""" - This test executed Wget in Spider mode with recursive retrieval. -""" -TEST_NAME = "Recursive Spider" -############# File Definitions ############################################### -mainpage = """ - - - Main Page - - -

- Some text and a link to a second page. - Also, a broken link. -

- - -""" - - -secondpage = """ - - - Second Page - - -

- Some text and a link to a third page. - Also, a broken link. -

- - -""" - -thirdpage = """ - - - Third Page - - -

- Some text and a link to a text file. - Also, another broken link. -

- - -""" - -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 = "-d --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) +#!/usr/bin/env python3 +from sys import exit +from misc.wget_file import WgetFile +from test.http_test import HTTPTest + + +# This test executed Wget in Spider mode with recursive retrieval. + +TEST_NAME = "Recursive Spider" +############# File Definitions ############################################### +mainpage = """ + + + Main Page + + +

+ Some text and a link to a second page. + Also, a broken link. +

+ + +""" + + +secondpage = """ + + + Second Page + + +

+ Some text and a link to a third page. + Also, a broken link. +

+ + +""" + +thirdpage = """ + + + Third Page + + +

+ Some text and a link to a text file. + Also, another broken link. +

+ + +""" + +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 = "-d --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-Content-disposition-2.py b/testenv/Test-Content-disposition-2.py index c2512e1..c95725d 100755 --- a/testenv/Test-Content-disposition-2.py +++ b/testenv/Test-Content-disposition-2.py @@ -1,52 +1,53 @@ -#!/usr/bin/env python3 -from sys import exit -from WgetTest import HTTPTest, 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" - -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 = "-d --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) +#!/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" + +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 = "-d --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 index 0a81dea..1f4c48e 100755 --- a/testenv/Test-Content-disposition.py +++ b/testenv/Test-Content-disposition.py @@ -1,55 +1,56 @@ -#!/usr/bin/env python3 -from sys import exit -from WgetTest import HTTPTest, 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 = "-d --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) +#!/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 = "-d --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 index 49aaa41..c962b06 100755 --- a/testenv/Test-Head.py +++ b/testenv/Test-Head.py @@ -1,43 +1,44 @@ -#!/usr/bin/env python3 -from sys import exit -from WgetTest import HTTPTest, 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 = "-d --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) +#!/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 = "-d --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 index 613fbcd..5e825be 100755 --- a/testenv/Test-O.py +++ b/testenv/Test-O.py @@ -1,44 +1,45 @@ -#!/usr/bin/env python3 -from sys import exit -from WgetTest import HTTPTest, 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 = "-d -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) +#!/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 +# file names. + +TEST_NAME = "Output Filename Command" +############# File Definitions ############################################### +File1 = "Test Contents." + +A_File = WgetFile ("File1", File1) + +WGET_OPTIONS = "-d -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-Parallel-Proto.py b/testenv/Test-Parallel-Proto.py index e7aae2e..9a17acd 100755 --- a/testenv/Test-Parallel-Proto.py +++ b/testenv/Test-Parallel-Proto.py @@ -1,52 +1,54 @@ -#!/usr/bin/env python3 -from sys import exit -from WgetTest import HTTPTest, WgetFile, HTTP, HTTPS - -""" - This is a Prototype Test File for multiple servers. - Ideally this File should be copied and edited to write new tests. -""" -TEST_NAME = "Parallel Prototype" -############# 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) - -WGET_OPTIONS = "-d" -WGET_URLS = [["File1"], ["File2"]] - -Files = [[A_File], [B_File]] -Existing_Files = [C_File] - -Servers = [HTTP, HTTP] - -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, - servers=Servers -).begin () - -exit (err) +#!/usr/bin/env python3 +from sys import exit +from misc.constants import HTTP +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + + +# This is a Prototype Test File for multiple servers. +# Ideally this File should be copied and edited to write new tests. + +TEST_NAME = "Parallel Prototype" +############# 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) + +WGET_OPTIONS = "-d" +WGET_URLS = [["File1"], ["File2"]] + +Files = [[A_File], [B_File]] +Existing_Files = [C_File] + +Servers = [HTTP, HTTP] + +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-Post.py b/testenv/Test-Post.py index 632326f..87a1e63 100755 --- a/testenv/Test-Post.py +++ b/testenv/Test-Post.py @@ -1,47 +1,48 @@ -#!/usr/bin/env python3 -from sys import exit -from WgetTest import HTTPTest, 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 = "-d --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) +#!/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 using 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 = "-d --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-Proto.py b/testenv/Test-Proto.py index eaafdc1..6b2c5cc 100755 --- a/testenv/Test-Proto.py +++ b/testenv/Test-Proto.py @@ -1,73 +1,76 @@ -#!/usr/bin/env python3 -from sys import exit -from WgetTest import HTTPTest, WgetFile, HTTP, HTTPS - -""" - This is a Prototype Test File. - Ideally this File should be copied and edited to write new tests. -""" -TEST_NAME = "Prototype" -############# 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" - }, - "SendHeader" : { - "Content-Disposition" : "Attachment; filename=newfile" - } -} - -A_File = WgetFile ("File1", File1, rules=File1_rules) -B_File = WgetFile ("File2", File2, rules=File2_rules) -C_File = WgetFile ("File3", File3) - -WGET_OPTIONS = "-d --content-disposition --user=Sauron --password=TheEye" -WGET_URLS = [["File1", "File2"]] - -Servers = [HTTP] - -Files = [[A_File, B_File]] -Existing_Files = [C_File] - -ExpectedReturnCode = 0 -ExpectedDownloadedFiles = [A_File, WgetFile ("newfile", File2), 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, - server=Servers -).begin () - -exit (err) +#!/usr/bin/env python3 +from sys import exit +from misc.constants import HTTP +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + + + +# This is a Prototype Test File. +# Ideally this File should be copied and edited to write new tests. + +TEST_NAME = "Prototype" +############# 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" + }, + "SendHeader" : { + "Content-Disposition" : "Attachment; filename=newfile" + } +} + +A_File = WgetFile ("File1", File1, rules=File1_rules) +B_File = WgetFile ("File2", File2, rules=File2_rules) +C_File = WgetFile ("File3", File3) + +WGET_OPTIONS = "-d --content-disposition --user=Sauron --password=TheEye" +WGET_URLS = [["File1", "File2"]] + +Servers = [HTTP] + +Files = [[A_File, B_File]] +Existing_Files = [C_File] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [A_File, WgetFile ("newfile", File2), 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-auth-basic-fail.py b/testenv/Test-auth-basic-fail.py index 894e96d..57e1096 100755 --- a/testenv/Test-auth-basic-fail.py +++ b/testenv/Test-auth-basic-fail.py @@ -1,50 +1,52 @@ -#!/usr/bin/env python3 -from sys import exit -from WgetTest import HTTPTest, 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 = "-d --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) +#!/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 +# authentication fails 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 = "-d --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 index 96141e0..1584650 100755 --- a/testenv/Test-auth-basic.py +++ b/testenv/Test-auth-basic.py @@ -1,12 +1,13 @@ #!/usr/bin/env python3 from sys import exit -from WgetTest import HTTPTest, WgetFile +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. -""" - 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." diff --git a/testenv/Test-auth-both.py b/testenv/Test-auth-both.py index 9837134..2b4ea4e 100755 --- a/testenv/Test-auth-both.py +++ b/testenv/Test-auth-both.py @@ -1,76 +1,78 @@ -#!/usr/bin/env python3 -from sys import exit -from WgetTest import HTTPTest, 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 = "-d --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) +#!/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 successful 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 = "-d --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 index a66b2c9..26ab53a 100755 --- a/testenv/Test-auth-digest.py +++ b/testenv/Test-auth-digest.py @@ -1,49 +1,50 @@ -#!/usr/bin/env python3 -from sys import exit -from WgetTest import HTTPTest, 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 = "-d --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) +#!/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 = "-d --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 index eb88ac5..18a8338 100755 --- a/testenv/Test-auth-no-challenge-url.py +++ b/testenv/Test-auth-no-challenge-url.py @@ -1,53 +1,54 @@ -#!/usr/bin/env python3 -from sys import exit -from WgetTest import HTTPTest, 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 = "-d --auth-no-challenge http://Pacman:address@hidden:{{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) +#!/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 = "-d --auth-no-challenge http://Pacman:address@hidden:{{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 index 774bd59..dea6f33 100755 --- a/testenv/Test-auth-no-challenge.py +++ b/testenv/Test-auth-no-challenge.py @@ -1,53 +1,54 @@ -#!/usr/bin/env python3 -from sys import exit -from WgetTest import HTTPTest, 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 = "-d --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) +#!/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 = "-d --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 index adbcbb0..3af9a90 100755 --- a/testenv/Test-auth-retcode.py +++ b/testenv/Test-auth-retcode.py @@ -1,49 +1,49 @@ -#!/usr/bin/env python3 -from sys import exit -from WgetTest import HTTPTest, 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 = "-d" -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) +#!/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 = "-d" +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 index 50e08ba..7771eb4 100755 --- a/testenv/Test-auth-with-content-disposition.py +++ b/testenv/Test-auth-with-content-disposition.py @@ -1,53 +1,54 @@ -#!/usr/bin/env python3 -from sys import exit -from WgetTest import HTTPTest, 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 = "-d --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) +#!/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 = "-d --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 index 87ffc52..fd632e9 100755 --- a/testenv/Test-c-full.py +++ b/testenv/Test-c-full.py @@ -1,52 +1,53 @@ -#!/usr/bin/env python3 -from sys import exit -from WgetTest import HTTPTest, 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 = "-d -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) +#!/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 file size 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 = "-d -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 index 9ca9641..2627c11 100755 --- a/testenv/Test-cookie-401.py +++ b/testenv/Test-cookie-401.py @@ -1,58 +1,59 @@ -#!/usr/bin/env python3 -from sys import exit -from WgetTest import HTTPTest, 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 = "-d" -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) +#!/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 = "-d" +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 index ae108d9..799bc40 100755 --- a/testenv/Test-cookie-domain-mismatch.py +++ b/testenv/Test-cookie-domain-mismatch.py @@ -1,56 +1,57 @@ -#!/usr/bin/env python3 -from sys import exit -from WgetTest import HTTPTest, 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" : { - "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 = "-d" -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) +#!/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" : { + "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 = "-d" +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 index 2ae3bf9..1a9d256 100755 --- a/testenv/Test-cookie-expires.py +++ b/testenv/Test-cookie-expires.py @@ -1,79 +1,80 @@ -#!/usr/bin/env python3 -from sys import exit -from WgetTest import HTTPTest, 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" : { - "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 = "-d" -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) +#!/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. +# Simultaneously, 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" : { + "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 = "-d" +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 index 7f5b093..b333b1e 100755 --- a/testenv/Test-cookie.py +++ b/testenv/Test-cookie.py @@ -1,56 +1,57 @@ -#!/usr/bin/env python3 -from sys import exit -from WgetTest import HTTPTest, 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 = "-d" -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) +#!/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 = "-d" +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/WgetTest.py b/testenv/WgetTest.py deleted file mode 100644 index 6470d93..0000000 --- a/testenv/WgetTest.py +++ /dev/null @@ -1,337 +0,0 @@ -import os -import shutil -import shlex -import sys -import traceback -import HTTPServer -import re -import time -from subprocess import call -from ColourTerm import printer -from difflib import unified_diff - -HTTP = "HTTP" -HTTPS = "HTTPS" - -""" A Custom Exception raised by the Test Environment. """ - -class TestFailed (Exception): - - def __init__ (self, error): - self.error = error - - -""" Class that defines methods common to both HTTP and FTP Tests. """ - -class CommonMethods: - TestFailed = TestFailed - - def init_test_env (self, name): - testDir = name + "-test" - try: - os.mkdir (testDir) - except FileExistsError: - shutil.rmtree (testDir) - os.mkdir (testDir) - os.chdir (testDir) - self.tests_passed = True - - def get_domain_addr (self, addr): - self.port = str (addr[1]) - return addr[0] + ":" + str(addr[1]) + "/" - - def exec_wget (self, options, urls, domain_list): - cmd_line = self.get_cmd_line (options, urls, domain_list) - params = shlex.split (cmd_line) - print (params) - if os.getenv ("SERVER_WAIT"): - time.sleep (float (os.getenv ("SERVER_WAIT"))) - try: - retcode = call (params) - except FileNotFoundError as filenotfound: - raise TestFailed ( - "The Wget Executable does not exist at the expected path") - return retcode - - def get_cmd_line (self, options, urls, domain_list): - TEST_PATH = os.path.abspath (".") - WGET_PATH = os.path.join (TEST_PATH, "..", "..", "src", "wget") - WGET_PATH = os.path.abspath (WGET_PATH) - cmd_line = WGET_PATH + " " + options + " " - for i in range (0, self.servers): - for url in urls[i]: - protocol = "http://" if self.server_types[i] is "HTTP" else "https://" - cmd_line += protocol + domain_list[i] + url + " " -# for url in urls: -# cmd_line += domain_list[0] + url + " " - print (cmd_line) - return cmd_line - - def __test_cleanup (self): - testDir = self.name + "-test" - os.chdir ('..') - try: - if os.getenv ("NO_CLEANUP") is None: - shutil.rmtree (testDir) - except Exception as ae: - 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 - - """ Methods to check if the Test Case passes or not. """ - - def __gen_local_filesys (self): - file_sys = dict () - for parent, dirs, files in os.walk ('.'): - for name in files: - onefile = dict () - # Create the full path to file, removing the leading ./ - # Might not work on non-unix systems. Someone please test. - filepath = os.path.join (parent, name) - file_handle = open (filepath, 'r') - file_content = file_handle.read () - onefile['content'] = file_content - filepath = filepath[2:] - file_sys[filepath] = onefile - file_handle.close () - return file_sys - - - def __check_downloaded_files (self, exp_filesys): - local_filesys = self.__gen_local_filesys () - for files in exp_filesys: - if files.name in local_filesys: - local_file = local_filesys.pop (files.name) - if files.content != local_file ['content']: - for line in unified_diff (local_file['content'], files.content, fromfile="Actual", tofile="Expected"): - sys.stderr.write (line) - raise TestFailed ("Contents of " + files.name + " do not match") - else: - raise TestFailed ("Expected file " + files.name + " not found") - if local_filesys: - print (local_filesys) - raise TestFailed ("Extra files downloaded.") - - 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 - - - """ Test Rule Definitions """ - """ This should really be taken out soon. All this extra stuff to ensure - re-use of old code is crap. Someone needs to re-write it. The new rework - branch is much better written, but integrating it requires effort. - All these classes should never exist. The whole server needs to modified. - """ - - 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'] - - class ExpectHeader: - def __init__ (self, header_obj): - self.headers = header_obj - - class RejectHeader: - def __init__ (self, header_obj): - self.headers = header_obj - - class Response: - def __init__ (self, retcode): - self.response_code = retcode - - class SendHeader: - def __init__ (self, header_obj): - self.headers = header_obj - - def get_server_rules (self, 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 = dict () - for rule in file_obj.rules: - r_obj = getattr (self, rule) (file_obj.rules[rule]) - server_rules[rule] = r_obj - return server_rules - - """ Pre-Test Hook Function Calls """ - - def ServerFiles (self, server_files): - for i in range (0, self.servers): - file_list = dict () - server_rules = dict () - for file_obj in server_files[i]: - content = self._replace_substring (file_obj.content) - file_list[file_obj.name] = content - rule_obj = self.get_server_rules (file_obj) - server_rules[file_obj.name] = rule_obj - self.server_list[i].server_conf (file_list, server_rules) - - def LocalFiles (self, local_files): - for file_obj in local_files: - file_handler = open (file_obj.name, "w") - file_handler.write (file_obj.content) - file_handler.close () - - def ServerConf (self, server_settings): - for i in range (0, self.servers): - self.server_list[i].server_sett (server_settings) - - """ Test Option Function Calls """ - - def WgetCommands (self, command_list): - self.options = self._replace_substring (command_list) - - def Urls (self, url_list): - self.urls = url_list - - """ Post-Test Hook Function Calls """ - - def ExpectedRetcode (self, retcode): - if self.act_retcode != retcode: - pr = "Return codes do not match.\nExpected: " + str(retcode) + "\nActual: " + str(self.act_retcode) - raise TestFailed (pr) - - def ExpectedFiles (self, exp_filesys): - self.__check_downloaded_files (exp_filesys) - - def FilesCrawled (self, Request_Headers): - for i in range (0, self.servers): - headers = set(Request_Headers[i]) - o_headers = self.Request_remaining[i] - header_diff = headers.symmetric_difference (o_headers) - if len(header_diff) is not 0: - printer ("RED", str (header_diff)) - raise TestFailed ("Not all files were crawled correctly") - - -""" Class for HTTP Tests. """ - -class HTTPTest (CommonMethods): - -# 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=dict(), - test_params=dict(), - post_hook=dict(), - servers=[HTTP] - ): - try: - self.Server_setup (name, pre_hook, test_params, post_hook, servers) - except TestFailed as tf: - printer ("RED", "Error: " + tf.error) - self.tests_passed = False - except Exception as ae: - printer ("RED", "Unhandled Exception Caught.") - print ( ae.__str__ ()) - traceback.print_exc () - self.tests_passed = False - else: - printer ("GREEN", "Test Passed") - finally: - self._exit_test () - - def Server_setup (self, name, pre_hook, test_params, post_hook, servers): - self.name = name - self.server_types = servers - self.servers = len (servers) - printer ("BLUE", "Running Test " + self.name) - self.init_test_env (name) - self.server_list = list() - self.domain_list = list() - for server_type in servers: - server_inst = getattr (self, "init_" + server_type + "_Server") () - self.server_list.append (server_inst) - domain = self.get_domain_addr (server_inst.server_address) - self.domain_list.append (domain) - #self.server = self.init_HTTP_Server () - #self.domain = self.get_domain_addr (self.server.server_address) - - self.pre_hook_call (pre_hook) - self.call_test (test_params) - self.post_hook_call (post_hook) - - def pre_hook_call (self, pre_hook): - for pre_hook_func in pre_hook: - try: - assert hasattr (self, pre_hook_func) - except AssertionError as ae: - self.stop_HTTP_Server () - raise TestFailed ("Pre Test Function " + pre_hook_func + " not defined.") - getattr (self, pre_hook_func) (pre_hook[pre_hook_func]) - - def call_test (self, test_params): - for test_func in test_params: - try: - assert hasattr (self, test_func) - except AssertionError as ae: - self.stop_HTTP_Server () - raise TestFailed ("Test Option " + test_func + " unknown.") - getattr (self, test_func) (test_params[test_func]) - - try: - self.act_retcode = self.exec_wget (self.options, self.urls, self.domain_list) - except TestFailed as tf: - self.stop_HTTP_Server () - raise TestFailed (tf.__str__ ()) - self.stop_HTTP_Server () - - def post_hook_call (self, post_hook): - for post_hook_func in post_hook: - try: - assert hasattr (self, post_hook_func) - except AssertionError as ae: - raise TestFailed ("Post Test Function " + post_hook_func + " not defined.") - getattr (self, post_hook_func) (post_hook[post_hook_func]) - - def init_HTTP_Server (self): - server = HTTPServer.HTTPd () - server.start () - return server - - def init_HTTPS_Server (self): - server = HTTPServer.HTTPSd () - server.start () - return server - - def stop_HTTP_Server (self): - self.Request_remaining = list () - for server in self.server_list: - server_req = server.server_inst.get_req_headers () - self.Request_remaining.append (server_req) - server.server_inst.shutdown () - -""" WgetFile is a File Data Container object """ - -class WgetFile: - - def __init__ ( - self, - name, - content="Test Contents", - timestamp=None, - rules=dict() - ): - self.name = name - self.content = content - self.timestamp = timestamp - self.rules = rules - -# vim: set ts=4 sts=4 sw=4 tw=80 et : diff --git a/testenv/certs/wget-cert.pem b/testenv/certs/wget-cert.pem index b83069e..dc18085 100644 --- a/testenv/certs/wget-cert.pem +++ b/testenv/certs/wget-cert.pem @@ -1,30 +1,30 @@ ------BEGIN PRIVATE KEY----- -MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAMV8qEpuSVUdWaAY -F2N1ljGEJ/907Og5B0aZLeDskmLAOohKMWTiiSx+lseXVD/Zf/LaFfy/+q0Rk5+o -pFEPEEjadvdxogb9HPwjfj48ng74yV1c5ZGRx/aIeIJN9cacfs4J5NlT3ZPiV8/2 -mpBurBYvta5tneUl+lx4NHTEBmjTAgMBAAECgYBHlFlDMRovWYYEuvavPA2GQQpm -UzETMqhqdFbmsZiVZmtQvuOMV3e0wuVPzo/g3Kq9kUJq7AKl/DrvoaZ9IuKZgkDD -0QEBYo/lcxEA9qcfgVs5XLp9ED1mXzJSZ3bmpCDqa2NjG7yFdWzPxc1DXmT05MrF -bZbb0Wao0tvMwoeJYQJBAOql5uOyjDHvLLuS0IFKbYz4LQwAp7Gjs0ZS9qLNhQQn -m5Vr8xS9QwFID693K6aDl3tqSCIwSnyInacj8M8v18sCQQDXdReE2i4LKOVLcQsP -XabN96fFLlnoIh9MqFza4skjhXJWqjBLgJuFqyT5CTbU9TmaoIPXdo4454P1CCgR -KEIZAkAZE7nlQ8Ov4nvJYBtgde/XTP6jdb52QaR7M4qgQ46frwv1oB/Oa5upm2Xx -vq6vkQiza9xhqv+K557RqgmmWtqZAkASoXJmL4OZvXCOZHkDXCLHXqnoOAjYNNMm -Csz0tHWWF7z6V38TmExac6Ef07clFQtlHoooAH1t2D8l2g205hlJAkBfeghbZDdY -16NtVnvtzjjhKqZFqwTSANFV8NSzgb/QiNnX0hsMPt9bbc5VCo77Ly2oP5SvixfZ -kjrIQqDV8MLu ------END PRIVATE KEY----- ------BEGIN CERTIFICATE----- -MIICODCCAaGgAwIBAgIJAOiSkPuPcAwqMA0GCSqGSIb3DQEBBQUAMDUxCzAJBgNV -BAYTAklOMRMwEQYDVQQIDApTb21lLVN0YXRlMREwDwYDVQQKDAhHTlUgV2dldDAe -Fw0xMzEyMDcwNTA3NTRaFw0xNDEyMDcwNTA3NTRaMDUxCzAJBgNVBAYTAklOMRMw -EQYDVQQIDApTb21lLVN0YXRlMREwDwYDVQQKDAhHTlUgV2dldDCBnzANBgkqhkiG -9w0BAQEFAAOBjQAwgYkCgYEAxXyoSm5JVR1ZoBgXY3WWMYQn/3Ts6DkHRpkt4OyS -YsA6iEoxZOKJLH6Wx5dUP9l/8toV/L/6rRGTn6ikUQ8QSNp293GiBv0c/CN+Pjye -DvjJXVzlkZHH9oh4gk31xpx+zgnk2VPdk+JXz/aakG6sFi+1rm2d5SX6XHg0dMQG -aNMCAwEAAaNQME4wHQYDVR0OBBYEFLhtTG9a6v3ihL5DeWKfq6doYI42MB8GA1Ud -IwQYMBaAFLhtTG9a6v3ihL5DeWKfq6doYI42MAwGA1UdEwQFMAMBAf8wDQYJKoZI -hvcNAQEFBQADgYEApTEZX3cgmgdXDJsu7wtkejtq3vuyi6NXBUlHzoYzWaS5wn8P -uDG4G9zd1cwmwrbYA8lS+ANWvkcqjM68gMs1ARMZRS0IrYMCN8bokQw+16sqImZO -THX50Sb5U+9e1IotDWyRBNO10znsoh569BxhJ5WZdIaoKHOJdXEYV+3Y/hg= ------END CERTIFICATE----- +-----BEGIN PRIVATE KEY----- +IICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAMV8qEpuSVUdWaAY +F2N1ljGEJ/907Og5B0aZLeDskmLAOohKMWTiiSx+lseXVD/Zf/LaFfy/+q0Rk5+o +pFEPEEjadvdxogb9HPwjfj48ng74yV1c5ZGRx/aIeIJN9cacfs4J5NlT3ZPiV8/2 +mpBurBYvta5tneUl+lx4NHTEBmjTAgMBAAECgYBHlFlDMRovWYYEuvavPA2GQQpm +UzETMqhqdFbmsZiVZmtQvuOMV3e0wuVPzo/g3Kq9kUJq7AKl/DrvoaZ9IuKZgkDD +0QEBYo/lcxEA9qcfgVs5XLp9ED1mXzJSZ3bmpCDqa2NjG7yFdWzPxc1DXmT05MrF +bZbb0Wao0tvMwoeJYQJBAOql5uOyjDHvLLuS0IFKbYz4LQwAp7Gjs0ZS9qLNhQQn +m5Vr8xS9QwFID693K6aDl3tqSCIwSnyInacj8M8v18sCQQDXdReE2i4LKOVLcQsP +XabN96fFLlnoIh9MqFza4skjhXJWqjBLgJuFqyT5CTbU9TmaoIPXdo4454P1CCgR +KEIZAkAZE7nlQ8Ov4nvJYBtgde/XTP6jdb52QaR7M4qgQ46frwv1oB/Oa5upm2Xx +vq6vkQiza9xhqv+K557RqgmmWtqZAkASoXJmL4OZvXCOZHkDXCLHXqnoOAjYNNMm +Csz0tHWWF7z6V38TmExac6Ef07clFQtlHoooAH1t2D8l2g205hlJAkBfeghbZDdY +16NtVnvtzjjhKqZFqwTSANFV8NSzgb/QiNnX0hsMPt9bbc5VCo77Ly2oP5SvixfZ +kjrIQqDV8MLu +-----END PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +IICODCCAaGgAwIBAgIJAOiSkPuPcAwqMA0GCSqGSIb3DQEBBQUAMDUxCzAJBgNV +BAYTAklOMRMwEQYDVQQIDApTb21lLVN0YXRlMREwDwYDVQQKDAhHTlUgV2dldDAe +Fw0xMzEyMDcwNTA3NTRaFw0xNDEyMDcwNTA3NTRaMDUxCzAJBgNVBAYTAklOMRMw +EQYDVQQIDApTb21lLVN0YXRlMREwDwYDVQQKDAhHTlUgV2dldDCBnzANBgkqhkiG +9w0BAQEFAAOBjQAwgYkCgYEAxXyoSm5JVR1ZoBgXY3WWMYQn/3Ts6DkHRpkt4OyS +YsA6iEoxZOKJLH6Wx5dUP9l/8toV/L/6rRGTn6ikUQ8QSNp293GiBv0c/CN+Pjye +DvjJXVzlkZHH9oh4gk31xpx+zgnk2VPdk+JXz/aakG6sFi+1rm2d5SX6XHg0dMQG +aNMCAwEAAaNQME4wHQYDVR0OBBYEFLhtTG9a6v3ihL5DeWKfq6doYI42MB8GA1Ud +IwQYMBaAFLhtTG9a6v3ihL5DeWKfq6doYI42MAwGA1UdEwQFMAMBAf8wDQYJKoZI +hvcNAQEFBQADgYEApTEZX3cgmgdXDJsu7wtkejtq3vuyi6NXBUlHzoYzWaS5wn8P +uDG4G9zd1cwmwrbYA8lS+ANWvkcqjM68gMs1ARMZRS0IrYMCN8bokQw+16sqImZO +THX50Sb5U+9e1IotDWyRBNO10znsoh569BxhJ5WZdIaoKHOJdXEYV+3Y/hg= +-----END CERTIFICATE----- diff --git a/testenv/conf/__init__.py b/testenv/conf/__init__.py new file mode 100644 index 0000000..bc2c638 --- /dev/null +++ b/testenv/conf/__init__.py @@ -0,0 +1,35 @@ +import os + + +def gen_hook(): + hook_table = {} + + class Wrapper: + def __init__(self, alias=None): + self.alias = alias + + + def __call__(self, cls): + hook_table[cls.__name__] = cls + if self.alias: + hook_table[self.alias] = cls + + return cls + + def find_hook(name): + if name in hook_table: + return hook_table[name] + else: + raise AttributeError + + return Wrapper, find_hook + +register, find_conf = gen_hook() + +for module in os.listdir(os.path.dirname(__file__)): + if module != '__init__.py' and module.endswith('.py'): + module_name = module[:-3] + mod = __import__('%s.%s' % (__name__, module_name), + globals(), + locals()) + diff --git a/testenv/conf/authentication.py b/testenv/conf/authentication.py new file mode 100644 index 0000000..aa1eec1 --- /dev/null +++ b/testenv/conf/authentication.py @@ -0,0 +1,9 @@ +from conf import register + + address@hidden() +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..40f1da0 --- /dev/null +++ b/testenv/conf/expect_header.py @@ -0,0 +1,10 @@ +from conf import register + + address@hidden() +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..00c2735 --- /dev/null +++ b/testenv/conf/expected_files.py @@ -0,0 +1,47 @@ +from difflib import unified_diff +import os +import sys +from conf import register +from exc.test_failed import TestFailed + + address@hidden() +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..97cf392 --- /dev/null +++ b/testenv/conf/expected_ret_code.py @@ -0,0 +1,18 @@ +from exc.test_failed import TestFailed +from conf import register + + address@hidden(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: + 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..1141289 --- /dev/null +++ b/testenv/conf/files_crawled.py @@ -0,0 +1,21 @@ +from misc.colour_terminal import print_red +from conf import register +from exc.test_failed import TestFailed + + address@hidden() +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(diff) + raise TestFailed('Not all files were crawled correctly.') + + diff --git a/testenv/conf/local_files.py b/testenv/conf/local_files.py new file mode 100644 index 0000000..d41d4a0 --- /dev/null +++ b/testenv/conf/local_files.py @@ -0,0 +1,15 @@ +from conf import register + + address@hidden() +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..07dd5a8 --- /dev/null +++ b/testenv/conf/reject_header.py @@ -0,0 +1,7 @@ +from conf import register + + address@hidden() +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..bda9828 --- /dev/null +++ b/testenv/conf/response.py @@ -0,0 +1,9 @@ +from conf import register + + address@hidden() +class Response: + def __init__(self, ret_code): + self.response_code = ret_code + + diff --git a/testenv/conf/send_header.py b/testenv/conf/send_header.py new file mode 100644 index 0000000..4c95046 --- /dev/null +++ b/testenv/conf/send_header.py @@ -0,0 +1,9 @@ +from conf import register + + address@hidden() +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..09d23d6 --- /dev/null +++ b/testenv/conf/server_files.py @@ -0,0 +1,17 @@ +from conf import register + + address@hidden() +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_quotes(f.content) + for f in files} + server.config(files, rules) + diff --git a/testenv/conf/urls.py b/testenv/conf/urls.py new file mode 100644 index 0000000..5bfa9f0 --- /dev/null +++ b/testenv/conf/urls.py @@ -0,0 +1,13 @@ +from conf import register + + address@hidden(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..1064421 --- /dev/null +++ b/testenv/conf/wget_commands.py @@ -0,0 +1,12 @@ +from conf import register + + address@hidden() +class WgetCommands: + def __init__(self, commands): + self.wget_options = commands + + + def __call__(self, test_obj): + test_obj.wget_options = test_obj.replace_quotes(self.wget_options) + diff --git a/testenv/exc/__init__.py b/testenv/exc/__init__.py new file mode 100644 index 0000000..d3f5a12 --- /dev/null +++ b/testenv/exc/__init__.py @@ -0,0 +1 @@ + diff --git a/testenv/exc/test_failed.py b/testenv/exc/test_failed.py new file mode 100644 index 0000000..e8da6ac --- /dev/null +++ b/testenv/exc/test_failed.py @@ -0,0 +1,8 @@ + + +class TestFailed (Exception): + + """ A Custom Exception raised by the Test Environment. """ + + def __init__ (self, error): + self.error = error \ No newline at end of file diff --git a/testenv/misc/__init__.py b/testenv/misc/__init__.py new file mode 100644 index 0000000..d3f5a12 --- /dev/null +++ b/testenv/misc/__init__.py @@ -0,0 +1 @@ + diff --git a/testenv/misc/colour_terminal.py b/testenv/misc/colour_terminal.py new file mode 100644 index 0000000..e230b13 --- /dev/null +++ b/testenv/misc/colour_terminal.py @@ -0,0 +1,39 @@ +from functools import partial +import platform +from os import getenv +import sys + +T_COLORS = { + 'PURPLE' : '\033[95m', + 'BLUE' : '\033[94m', + 'GREEN' : '\033[92m', + 'YELLOW' : '\033[93m', + 'RED' : '\033[91m', + 'ENDC' : '\033[0m' +} + +def printer (color, string): + if platform.system () == 'Linux': + if getenv ("MAKE_CHECK", "False") == "True": + print (string) + else: + print (T_COLORS.get (color) + string + T_COLORS.get ('ENDC')) + + else: + print (string) + + +# Because of grammar checks of pycharm, printers are hard-coded. +# for color in T_COLORS: +# setattr(sys.modules[__name__], +# 'print_%s' % color.lower(), +# partial(printer, color)) + +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=0 et : diff --git a/testenv/misc/constants.py b/testenv/misc/constants.py new file mode 100644 index 0000000..e7da10d --- /dev/null +++ b/testenv/misc/constants.py @@ -0,0 +1,5 @@ + + + +HTTP = "HTTP" +HTTPS = "HTTPS" \ No newline at end of file diff --git a/testenv/misc/wget_file.py b/testenv/misc/wget_file.py new file mode 100644 index 0000000..cbd016f --- /dev/null +++ b/testenv/misc/wget_file.py @@ -0,0 +1,18 @@ + + +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..d3f5a12 --- /dev/null +++ b/testenv/server/__init__.py @@ -0,0 +1 @@ + diff --git a/testenv/server/ftp/__init__.py b/testenv/server/ftp/__init__.py new file mode 100644 index 0000000..d3f5a12 --- /dev/null +++ b/testenv/server/ftp/__init__.py @@ -0,0 +1 @@ + diff --git a/testenv/server/ftp/ftp_server.py b/testenv/server/ftp/ftp_server.py new file mode 100644 index 0000000..31c3757 --- /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..d3f5a12 --- /dev/null +++ b/testenv/server/http/__init__.py @@ -0,0 +1 @@ + diff --git a/testenv/server/http/__pycache__/__init__.cpython-33.pyc b/testenv/server/http/__pycache__/__init__.cpython-33.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cd405236fe8543ed2690ea4d29b8e6998b64904b GIT binary patch literal 140 zcmbQo!^`FMK`NMufq@|zh~a<{$Z`PUViq8g!oU!$0TS`k01^ynM5!)NOg|$(H&wqp zU%xy(wM4%pwYVfTuS~xbq(DDDJ~J<~BtBlRpt6($sKX{VKczG$)edBC IF%UBV0M`B+9RL6T literal 0 HcmV?d00001 diff --git a/testenv/server/http/__pycache__/http_server.cpython-33.pyc b/testenv/server/http/__pycache__/http_server.cpython-33.pyc new file mode 100644 index 0000000000000000000000000000000000000000..690a4e7ed5ae638a7d47f26147dca8497aa7a562 GIT binary patch literal 24879 zcmdU1TWlQHc|Nnei4 zc4oP>6)&BpBzJk{%sFSyIsgBE|K*%BzdJoMwR-Zwqey=lpQ!9P7vRrx zb>|wMTlHL{S5$gxnRF?_oun{BX`;bGs>NDp{KG(address@hiddenICFRZ`_mB$?EBCMq=ahR4x%a!^h;om(aK>#O*Nq2oGR2W_l4?^|(e zVjpf?M_#ki2)n$9+Vxr-ZpT(-lDE%28#b%0AhfJ;WOdMNt6|q8xNZcWTdMLI{NaCg z?*cy28`^3`M(address@hidden&*i8QRWUaaGx7Pfc)%8``x7yKyUuB2*!~gs& z;uFo_>s^oiD~orRHKHXO*M8g#JDqYPjH1eVXwx;yYGHk?+kY4NZk}J=r|@-lqtyt{ zZne&Ct%vd17=#F$x6Vc))7gzUZtJUT84K;(n)!0M)~v7KE;m|1x6aFH-MiVX)RX%Y$_QFj+_Z}JSQ|B2s$8zOs+D?FE^9KFpVI$+ zq;tc_5niMGnF#+$6PqHD>nqVn!Bw)address@hidden za$M;NgGi3DOA%U*TkUq`dR=g6{i+hH_{0Ah3b3Q^mJ$?5-~dnaz)CFB{T#mhaddress@hidden|oFdeo&1uAwsO z&a*FFQd77>5agYx%T$MtlKkoG<6#Q{+aCNFpTbAE(xlgY0RIO}(t?%EB!>NC6N~sn zr}4FYilBM%?T6i+l8Z&address@hidden)address@hidden zPX=j;8Zodv5|E`A z*P?jP7`r{*69(j_PsRHl|4FEzU7&!9HR51rOOvD1W7DI%Vg~8QAO0sFU%)address@hidden zK#W}!k!&g=$H03t;6Gh``w>d42ozeGw?k?=IF&Co%?B{Vd address@hidden&Xuk3K{n)((P2CzC0XZimb#pyg$2P^HSEMumsS?-pfkK&address@hidden address@hidden|rWS-N^CYFro1PI{uweAecBj^i)rnRl_QR8_TY;Y0uEZO{ z-pchzY4Yx7tJc)rRy(vFz|5pQ8Foi-JBsS+$yTS*E=TBe7^~SNNpPv1ccZefhqYt2AHkqAkp8rN>Y-Zc|1 z#R==aJy2;Gzp#+W%Zrz;u3Y}gtC!UAwN`srP+^;?sd*OZh$_Q*hrL`cqsoS+PW3XI=ouPf8+1|ZxzuWgeYOdCP<|p&y;COW56fZ120XD$Lq`p2Fno~n address@hidden>j&address@hidden&yah^W^+Szj zfcyI}rWF!F2!!cL20{?{U>ZRYL|address@hidden)?>9AX$u zqwt&yjwy}M$Z;1upfoBXr16l_2#!4Lf=84_BagbkR~q4w$6RniX*BpL7o1cY(UDUw zcwA{T{)7wWl|address@hidden(jV4DWxBB!P72yMrm~5vo3g6 z=|address@hidden;!g3>address@hidden|QW~B7k_*19^hp<-cfkdv z(cwiGTvYmT7hH0|Wu?*imm!T;zyPMol7NjY{S*_DJpZdXYzS&=YhfpB#(n}OKnAry zd^!8{!qYo=MUr(852DsaxI>^|ikm31B&ol0>HJ0GeJXQ=g#uZVduyxGMh;qKKI?0I z3Lo#h?kv8`$ygVX``IXnRHOK46b&Tuqj;<2?!fqw2hyn#-~xc)KG#`Pv69;yAvnU2 address@hidden>qnn_%Uk6#i#zINTi7U#H#Ag-F zMNTjPHYQoN-D>N99mX;(TUaf%Xe0GGKZ5DI6qPJ^E43g7l2Hue1ZW z*g_^rq$=la5ufNfzQ~$_-=9&EV6|l|z6sY3vH-6z5t7LQbMkphVopV%mX_wpjpBn( zmZ?$(address@hidden>address@hidden&!`!TGD9C9address@hiddenM_y;1d)8lR)Fx0>address@hidden;Z&mPi0E0CrmQ-ik{zYrCIP|J4A z>address@hidden&H4gNYFuCSW}T^{is^yKYiR4FK=Dv7`!ifU$z zd&m`GwlJnvfb zkQ+rs(Dye$*YXtxS8^$iPPWOsrphF%fz^dCXBVjylD##EA-puxAh&4c> zWc9_Eom{V6B#x8KZ$9d-K}Tui9PW~$roE>cK~v$(VlNg?wABfVVy6Bdb`Y?GJrF5Q zo503qao8CoaYa)av8h%0hs-2{INvtGpUo=Co-qSAPh`lExE6PDKgS^A zje%XzeDtPck5_Mq3PnTukC2lrMYPm{p5XV}@d;J}h9dC2pWP_v{b&6h475mZJY*1qw63f|`N< zL;}OdNN<#APbOT~<1Tbr=A(d$B}Y^eamG&`Lb7ZW-Iz=X)RmN)Ky%d{ZoP>QtOa%OAx}c!~noTrUEbMrp1%HGyd9k*RwGI&)i+r`JkWVQeR&BlU;t58^&u~HH zgg}Kgv2RL_2l-v>(d9M;Ybvd#8mIkc3p+DjJaH;IaoTUSE7&8a3z==F{hO`!izh1G zc;iI(I9k}{xu<=3{MW8sJ98dofsM5)*Xd{uB|#c^zSWINonDX`>DVAAV?Dy&2aXe7 address@hidden;|!tJ0p0qU!YSWiDfC9?tc-4-2*DOnfbb9IL0bE+s)wCTWp$Q&PE^tNX3 address@hidden&AP_X{w4oFXvdItcfVBPwF% zK3G}KHvKNKHN?X>mET}}Mh?Zla}WUr5E(Qysq1L(5E~O?Qim)address@hidden)k;F5; z(EaCu>Y_WlFPDsC&>l)address@hidden;Cg=MadDZ z&FB&m>Y7SLT1QuVKz2eu+iG=c?}TNI{GT{Ni?^Ht=ud;address@hidden;1Ea0mk z0q9TktMCJ)1OXUd2DyPxX82MM2o6CrP#$!BAM7#WE>cs7uu0Zvnnj;nQJ6HsLN6%+ z1O+%w`&HV7{GrNczn1ZlI$9T8y?rcwx(sRdvgE!CJOh)address@hidden zDRD_{SmC3&{Q}optF1=+r4Mi=zhcsL7m&address@hidden(address@hidden>Wh address@hiddenB5gTR_3xJ&PjF(@zn4t!5X9J;P-f1w>7^g|W zqC4zF)};dGAQB6a(address@hidden;hOUFkk&address@hidden z%yVla?&z{eVm`&G=z0B_eto~JF_HJO address@hidden;QLBrXsOePp7{yd8$6mu75MB_~zO--m(HGv_+u z%4Kt4#n&o({u%vy<)U5X_O+3uvV9DFIdOfIla)d-qj4%e=5vMx6e1C_&6skADhp>R)oMDHLHt?*ExjSQS`%~`SF+>R; zba&vdX&2{>3D^04QtjsV9saKI;aFG)`*<$;aj!`(O<}Cd^Hex`VefIcWJlnf(M3Ce zv^?8P3-vdXu|JWRf-d%__yX<{^?KRhxhLX6?M%c!bh?HeI*HZmGoAl~=w*uCg)nKc z*f09Ps3VI#PNEw3=f?L43JoA#E(VgRE7F8~BKqA%;`YJBs4#_t<*W*pv!KARoE19{ z%Ex=>yoxC5Mu#g|8k3g{kOD|3hOEeuhpKc6v~Gqwh$LTo6PSTNH1%G|y^*bsu`5fp z?_wNU>^q-$lNFucVecu z%mSt~0T59gk%obOu;Abq=oG^)p-u41g#FG{els>A>QdiemoN%JgEX~w3W?ia(AEY# z2|0+NfGwgsE*>address@hidden>HSih3+Eh9E{t;n*ImUe^Sm|g-WxaG0{20Ma?i&7Y8q!7)MQgknCdRZ!3rEF zZJ>A~nJp(e`FIcQg-RCn5M&nVfxVcBu3_g>!&k@;fyLO5y6twW6NiEL{Oe5~KJ(+2 zpQ}nED${xl>=f4A$czYY_Hi(Q)*?zI{zfIz2`ci>`3U-#Vx&bCHHGTB&B5g*N5!Ry zx^dVmo```oquFbGhUQ4RuP6|_SIen4PEoptz?Okbm`!-Ix{^Z*Q)Osj>H`R$l0;N= z&address@hidden(GY7Uw)mtbT+90@&FWN2orq7Nrb= z^Fe}<5H4b*OgRD}ga&q8Dqqo((xZ~Kwq$KxvIa9vI|^vX?UXf$3v4nn? zAQAZ+6f`sT<%IwQCaddress@hidden@1mrB{MS+&FEI)`x zQI?0*C7irO02Po8p2-UU4ZfZb9QPiQ(Z~H0#a%Xq7BbDk`Jxy|1ipm?HHftNc9+a{ address@hidden<1KY`MNSNLnql;vE6vZuhDYKFl2#S1u?c4gs`W9*B(zObQ+wFAQg07R>TA&hoiPPbpR&i_rKl=K32YabV zY(8wn7s(9dV+SPU#P4d(Q}?M#FV~-v*Up#XSQU?6w4;^Z*9Rc#i>wyGk!$k>Uo{ zN_yNN2nR1!!y1_B{~lpF;buydp9jKR4L89ChA?=A%SR(jzCwmDgxq^Z7|#)5xXTR) zlXGrp@|eK|odT5ujsT*_=fEw+IzJR)5Y|c&24Exouq0T>ciCWp=flMcTsQ0S!d4~n zm*L6%+;D;O)-%TmBp*ipJ;wk%EQbN4X0k8yqcEVaBCUV^jNrqx6b)4$s0=Nmg?XnC zI2DA{3D0ba-nLnUwUSU|FQ(jont`|address@hidden;q-9ewT&l`5!R`E&H8&)CH zJmbrA*7+I+cA~`zBMBY+{Gt(address@hidden&)Xrn2 zVuA^Uj1+c4bB*FxOKeGgO13c_IoSQP{g-NN9Mblu)aSQ9o4EB5ENJNH+jKtYf*>Z1 z{wR}e!Bv5o$7fx;S%(w9Pfq+#;Kbtaddress@hidden zJ)pvSqwWp0GObn~_be1}+{HM2g-`%qOQ2AIhjXR9dKL^oJ=Rq;8w1ok5)!1Ca4}AK z>3r9neeSk_gDH)address@hidden(z|e%G=1emFhAbFSPrWfe~VslEYDHvY~na7;uN65_hh}| address@hidden;U$rYw%SF4LC9w4$Nn;address@hidden(^mGYl_nfU+(xT#(vntjxK#&l zIbXbqYaPC|cF=3sP{;6(tAi>dClQZ$4ufT(V~GUa5$RYTK|sVwdhOv*n+C7;Z4{U; zdjOW`bm9nP)7f5D!%g=2(zIS!9^>L%9jqJ=3x z`H?YaV&~&+Ik3+<9lYJ4$v_E~6MO{9{A547&qeu#sa)0ce7t|F(y1xDf|GDD&eui$ z)&@?;;_Waddress@hidden|06#} zDL*|4RQr9D&`HJG-;;7gDvTd5Q9Gl8w*5$_igYhMqR?wk_xw}AnNz{pQ^C%24zw84 zT6Vgm_FL=~Rnk&wPuu#uy%!0m(uC>RKd}_SQmCGHS_)XHy?E&address@hidden;ubHB;pgG%bS8S9a3xQ>oS address@hidden(ES*b_w>51!jx0i9*cCK=LV6qh&r4 ztdi_#jMla4i|xl8H{}p^kytNDC&x0y0nD;TqUs<@MO41 zX5si5v?E$%u5D(8VeG$BaoMSS4wru*5TgBjn3>1wMaNWZ0Zd8m_`;)X!(b5wp~ z_=n?R6Yd;!By?&NbJr(qBuVb&F$jgiD{f``5&+;rV1S{xugSxM(oCTbA7FXhb*yQ_s%8km@MMDNX_5j{ZZS=LCMIum=&address@hidden)DcM(address@hidden(ZS-d{vX zNZwo^n6kt75)dSLE;!A`an#+gA&rn`hvw9GF&~c8N`#kT&6-E1GYz_zKQJ>Wl11XC zXAuS-6DPq**>lgTx;2_^_EilAIddC9_3Rz{&(bX+pp?6kZVaKoV7CY{y13s$LA_qP z$=(8%>t$-SX4eH$HF_RB>n*UETMWAcFO^|4;>tqQb4M^ptrP`DLOWV*jiCd z6_BbQcsV)BW1YQu*Cy$kLe&+dqhG=o-mr=Fknz#!k?DQYN2X_|r>Dp9nZP&SdNzsg address@hidden`4n$%8}{pSz=Q}i$36LBLcOvg*1>%Hq0FL1>B zUBfZGs}aX36$ySHFMyTx3J823g>}plILNe|1lZ+F<83pOur&z*!Y#hrB*?&*Je7g( zuiygP0?l~0^(=>+)address@hidden;L>1&4$djug%sm&M4lDO address@hidden>+-Hd;|!Lzb(tD~6|}dhw=pUm(1}lesWB1p+I&N^r?u!74bFk-^Yz zYRvG(h-NU@c#ka;yhDr}MlXx| zk{8(i1-K&Fay1L3%Oe329g#14DOiDr$VZF#L|address@hidden address@hidden;x(EUZy*BT6<3@|xD_K5{HXU|33cMQC5Bf{&z~ zt5;+Rmy#)vRXZ&0dXN3P+%Uz!lT1^17AkUOR zNxeNc!GeVIB;address@hidden z2yPgl0Ra5Tu?cb;pRgQ!oVT`-qN=?t7k$SpoAgs-?44%q_4pq-Ddc^;C9sz}{}6J_ address@hidden;JBovYIg1}z*ovX^S$rvg9?N(IVmSapNp_#VBVporN z2L>FgWbbX)4S1M5ai(RfO0-e0U02kT`{G$RF6gG@<(3>NUIju<C&gPl=cMxPS^)maT ea6I_oFONRycjV~4qhm)8;dk=r|G3-75C1R9*?O7) literal 0 HcmV?d00001 diff --git a/testenv/server/http/http_server.py b/testenv/server/http/http_server.py new file mode 100644 index 0000000..c022bd5 --- /dev/null +++ b/testenv/server/http/http_server.py @@ -0,0 +1,471 @@ +from http.server import HTTPServer, BaseHTTPRequestHandler +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 re +import ssl +import os + + +class InvalidRangeHeader (Exception): + + """ Create an Exception for handling of invalid Range Headers. """ + # TODO: Eliminate this exception and use only ServerError + + def __init__ (self, err_message): + self.err_message = err_message + +class ServerError (Exception): + def __init__ (self, err_message): + self.err_message = err_message + + +class StoppableHTTPServer (HTTPServer): + + request_headers = list () + + """ Define methods for configuring the Server. """ + + def config(self, files, rules): + """ Set Server Rules and File System for this instance. """ + self.server_configs = rules + self.fileSys = files + + def server_sett (self, settings): + for settings_key in settings: + setattr (self.RequestHandlerClass, settings_key, settings[settings_key]) + + def get_req_headers (self): + return self.request_headers + +class HTTPSServer (StoppableHTTPServer): + + def __init__ (self, address, handler): + BaseServer.__init__ (self, address, handler) + print (os.getcwd()) + CERTFILE = os.path.abspath(os.path.join('..', 'certs', 'wget-cert.pem')) + print (CERTFILE) + 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, + server_side = True + ) + self.server_bind () + self.server_activate () + +class WgetHTTPRequestHandler (BaseHTTPRequestHandler): + + """ Define methods for handling Test Checks. """ + + def get_rule_list (self, name): + r_list = self.rules.get (name) if name in self.rules else None + return r_list + + +class _Handler (WgetHTTPRequestHandler): + + """ Define Handler Methods for different Requests. """ + + InvalidRangeHeader = InvalidRangeHeader + protocol_version = 'HTTP/1.1' + + """ Define functions for various HTTP Requests. """ + + def do_HEAD (self): + self.send_head ("HEAD") + + def do_GET (self): + 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): + path = self.path[1:] + self.rules = self.server.server_configs.get (path) + if not self.custom_response (): + return (None, None) + if path in self.server.fileSys: + 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.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.server.fileSys.pop (path, None) + self.send_put (path) + + ######################################## + # End of HTTP Request Method Handlers. # + ######################################## + + ###################################### + # Helper functions for the Handlers. # + ###################################### + + def parse_range_header (self, header_line, length): + if header_line is None: + return None + if not header_line.startswith ("bytes="): + raise InvalidRangeHeader ("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 InvalidRangeHeader ("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): + body_data = self.get_body_data () + self.send_response (201) + self.server.fileSys[path] = body_data + self.send_header ("Content-type", "text/plain") + self.send_header ("Content-Length", len (body_data)) + self.finish_headers () + try: + self.wfile.write (body_data.encode ('utf-8')) + except Exception: + pass + + def SendHeader (self, header_obj): + pass +# headers_list = header_obj.headers +# for header_line in headers_list: +# print (header_line + " : " + headers_list[header_line]) +# self.send_header (header_line, headers_list[header_line]) + + 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): + if auth_type == "Both": + self.send_challenge ("Digest") + self.send_challenge ("Basic") + 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 () + challenge_str = 'Digest realm="Test", nonce="%s", opaque="%s"' %( + self.nonce, + self.opaque) + challenge_str += ', qop="auth"' + if auth_type == "Both_inline": + 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] != '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 == auth_header else False + + def parse_auth_header (self, auth_header): + n = len("Digest ") + auth_header = auth_header[n:].strip() + items = auth_header.split(", ") + key_values = [i.split("=", 1) for i in items] + key_values = [(k.strip(), v.strip().replace('"', '')) for k, v in key_values] + return dict(key_values) + + 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] != '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 not attrib 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 + if required_auth == "Both" or required_auth == "Both_inline": + auth_type = auth_header.split(' ')[0] 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_rule + " not supported") + except AttributeError as ae: + raise ServerError (ae.__str__()) + if is_auth is False: + raise ServerError ("Unable to Authenticate") + + def is_authorized (self): + is_auth = True + auth_rule = self.get_rule_list ('Authentication') + if auth_rule: + auth_header = self.headers.get ("Authorization") + req_auth = auth_rule.auth_type + if req_auth == "Both" or req_auth == "Both_inline": + auth_type = auth_header.split(' ')[0] if auth_header else req_auth + else: + auth_type = req_auth + assert hasattr (self, "authorize_" + auth_type) + is_auth = getattr (self, "authorize_" + auth_type) (auth_header, auth_rule) + if is_auth is False: + self.send_response (401) + self.send_challenge (auth_type) + self.finish_headers () + return is_auth + + 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 expect_headers (self): + """ This is modified code to handle a few changes. Should be removed ASAP """ + exp_headers_obj = self.get_rule_list ('ExpectHeader') + if exp_headers_obj: + exp_headers = exp_headers_obj.headers + for header_line in exp_headers: + header_re = self.headers.get (header_line) + if header_re is None or header_re != exp_headers[header_line]: + self.send_error (400, 'Expected Header not Found') + self.end_headers () + return False + return True + + 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, 'Blackisted Header ' + header_line + ' received') + self.finish_headers () + raise ServerError ("Header " + header_line + ' received') + + def reject_headers (self): + rej_headers = self.get_rule_list ("RejectHeader") + if rej_headers: + rej_headers = rej_headers.headers + for header_line in rej_headers: + header_re = self.headers.get (header_line) + if header_re is not None and header_re == rej_headers[header_line]: + self.send_error (400, 'Blacklisted Header was Sent') + self.end_headers () + return False + return True + + 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 InvalidRangeHeader 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" + } + if ext in extension_map: + return extension_map[ext] + else: + return "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 config(self, file_list, server_rules): + self.server_inst.config(file_list, server_rules) + + def server_sett (self, settings): + self.server_inst.server_sett (settings) + +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..d3f5a12 --- /dev/null +++ b/testenv/test/__init__.py @@ -0,0 +1 @@ + diff --git a/testenv/test/base_test.py b/testenv/test/base_test.py new file mode 100644 index 0000000..d4784d4 --- /dev/null +++ b/testenv/test/base_test.py @@ -0,0 +1,203 @@ +import os +import shlex +import shutil +from subprocess import call +import time +import re +import traceback +import conf +from exc.test_failed import TestFailed +from misc.colour_terminal import print_blue, print_red + + +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): + self.name = name + self.pre_configs = pre_hook or {} + 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 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)(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 stop_server(self): + raise NotImplementedError + + + 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 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) + domain = self.get_domain_addr(instance.server_address) + self.domains.append(domain) + + + def instantiate_server_by(self, protocol): + raise NotImplementedError + + + def get_domain_addr(self, addr): + self.port = str(addr[1]) + + return '%s:%s' % (addr[0], self.port) + + + 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")) + + cmd_line = '%s %s ' % (wget_path, self.wget_options) + for protocol, urls, domain in zip(self.protocols, + self.urls, + self.domains): + protocol = protocol.lower() + for url in urls: + cmd_line += '%s://%s/%s ' % (protocol, 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 begin (self): + return 0 if self.tests_passed else 100 + + + def replace_quotes(self, string): + pattern = re.compile ('\{\{\w+\}\}') + match_obj = pattern.search(string) + if match_obj is not None: + rep = str(match_obj.group()) + temp = getattr(self, rep.strip('{}')) + string = string.replace(rep, temp) + return string + + + @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): + return self + + + def __exit__(self, exc_type, exc_val, exc_tb): + 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() + + + # `ServerConf' is actually never referenced. + # def ServerConf (self, server_settings): + # for i in range (0, self.servers): + # self.server_list[i].server_sett (server_settings) diff --git a/testenv/test/http_test.py b/testenv/test/http_test.py new file mode 100644 index 0000000..205238c --- /dev/null +++ b/testenv/test/http_test.py @@ -0,0 +1,50 @@ +from misc.colour_terminal import print_green +from misc.constants import HTTP, HTTPS +from server.http.http_server import HTTPd, HTTPSd +from test.base_test import BaseTest + + +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: + 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 : -- 1.8.3.2