From 670c96b0b5e66eda9827982098b1e949c18bd9da Mon Sep 17 00:00:00 2001 From: Wolfgang Steitz Date: Sun, 11 Dec 2016 16:00:04 +0100 Subject: [PATCH 01/10] starting a test suite (#777) --- test/README.md | 38 +++++++++ test/settings.py | 11 +++ test/test_mail.py | 203 ++++++++++++++++++++++++++++++++++++++++++++++ test/test_ssh.py | 13 +++ test/test_web.py | 60 ++++++++++++++ 5 files changed, 325 insertions(+) create mode 100644 test/README.md create mode 100644 test/settings.py create mode 100644 test/test_mail.py create mode 100644 test/test_ssh.py create mode 100644 test/test_web.py diff --git a/test/README.md b/test/README.md new file mode 100644 index 00000000..6b1ee05a --- /dev/null +++ b/test/README.md @@ -0,0 +1,38 @@ +This is the mailinabox test suite. IT uses the excellent pytest module to check the functionality +of the different services. + +Usage +===== + +start-up a vagrant box + + vagrant up + +install pytest + + pip install pytest + +run the tests + + pytest + +to just run a subset of the tests (e.g. the ssh related ones): + + pytest test_ssh.py + + +Contributing +============ + +pytest auto-discovers all tests in this directory. The test functions need to be named "test_..." +and there needs to be at least one assert statement. + + +TODO +===== +* calendar +* contacts +* dns + + + diff --git a/test/settings.py b/test/settings.py new file mode 100644 index 00000000..8e37f0d7 --- /dev/null +++ b/test/settings.py @@ -0,0 +1,11 @@ +import socket + +TEST_SERVER = '127.0.0.1' +TEST_DOMAIN = 'mailinabox.lan' +TEST_PORT = 2222 +TEST_PASSWORD = '1234' +TEST_USER = 'me' +TEST_ADDRESS = TEST_USER + '@' + TEST_DOMAIN +TEST_SENDER = "someone@example.com" + +socket.setdefaulttimeout(5) diff --git a/test/test_mail.py b/test/test_mail.py new file mode 100644 index 00000000..32fe0ad2 --- /dev/null +++ b/test/test_mail.py @@ -0,0 +1,203 @@ +from time import sleep +import uuid +import requests +import os +import pytest +import imaplib +import poplib +import smtplib +from email.mime.text import MIMEText + +from settings import * + + +def new_message(from_email, to_email): + """Creates an email (headers & body) with a random subject""" + msg = MIMEText('Testing') + msg['Subject'] = uuid.uuid4().hex[:8] + msg['From'] = from_email + msg['To'] = to_email + return msg.as_string(), msg['subject'] + + +def assert_imap_received(subject): + """Connects with IMAP and asserts the existence of an email, then deletes it""" + + sleep(3) + + # Login to IMAP + m = imaplib.IMAP4_SSL(TEST_DOMAIN, 993) + m.login(TEST_ADDRESS, TEST_PASSWORD) + m.select() + + # Assert the message exists + typ, data = m.search(None, '(SUBJECT \"{}\")'.format(subject)) + assert len(data[0].split()) == 1 + + # Delete it & logout + m.store(data[0].strip(), '+FLAGS', '\\Deleted') + m.expunge() + m.close() + m.logout() + + +def assert_pop3_received(subject): + """Connects with POP3S and asserts the existence of an email, then deletes it""" + + sleep(3) + + # Login to POP3 + mail = poplib.POP3_SSL(TEST_DOMAIN, 995) + mail.user(TEST_ADDRESS) + mail.pass_(TEST_PASSWORD) + + # Assert the message exists + num = len(mail.list()[1]) + resp, text, octets = mail.retr(num) + assert "Subject: " + subject in text + + # Delete it and log out + mail.dele(num) + mail.quit() + + +def test_imap_requires_ssl(): + """IMAP without SSL is NOT available""" + with pytest.raises(socket.timeout): + imaplib.IMAP4(TEST_DOMAIN, 143) + + +def test_pop3_requires_ssl(): + """POP3 without SSL is NOT available""" + with pytest.raises(socket.timeout): + poplib.POP3(TEST_DOMAIN, 110) + + +def test_smtps(): + """Email sent from an MUA via SMTPS is delivered""" + msg, subject = new_message(TEST_ADDRESS, TEST_ADDRESS) + s = smtplib.SMTP(TEST_DOMAIN, 587) + s.starttls() + s.login(TEST_ADDRESS, TEST_PASSWORD) + s.sendmail(TEST_ADDRESS, [TEST_ADDRESS], msg) + s.quit() + assert_imap_received(subject) + + +def test_smtps_tag(): + """Email sent to address with tag is delivered""" + mail_address = TEST_ADDRESS.replace("@", "+sometag@") + msg, subject = new_message(TEST_ADDRESS, mail_address) + s = smtplib.SMTP(TEST_DOMAIN, 587) + s.starttls() + s.login(TEST_ADDRESS, TEST_PASSWORD) + s.sendmail(TEST_ADDRESS, [mail_address], msg) + s.quit() + assert_imap_received(subject) + + +def test_smtps_requires_auth(): + """SMTPS with no authentication is rejected""" + import smtplib + s = smtplib.SMTP(TEST_DOMAIN, 587) + s.starttls() + + #FIXME why does this work without login? + + with pytest.raises(smtplib.SMTPRecipientsRefused): + s.sendmail(TEST_ADDRESS, [TEST_ADDRESS], 'Test') + + s.quit() + + +def test_smtp(): + """Email sent from an MTA is delivered""" + import smtplib + msg, subject = new_message(TEST_SENDER, TEST_ADDRESS) + s = smtplib.SMTP(TEST_DOMAIN, 25) + s.sendmail(TEST_SENDER, [TEST_ADDRESS], msg) + s.quit() + assert_imap_received(subject) + + +def test_smtp_tls(): + """Email sent from an MTA via SMTP+TLS is delivered""" + msg, subject = new_message(TEST_SENDER, TEST_ADDRESS) + s = smtplib.SMTP(TEST_DOMAIN, 25) + s.starttls() + s.sendmail(TEST_SENDER, [TEST_ADDRESS], msg) + s.quit() + assert_imap_received(subject) + + +# FIXME +#def test_smtps_headers(): +# """Email sent from an MUA has DKIM and TLS headers""" +# import smtplib +# import imaplib +# +# # Send a message to admin +# mail_address = "admin@" + TEST_DOMAIN +# msg, subject = new_message(TEST_ADDRESS, mail_address) +# s = smtplib.SMTP(TEST_DOMAIN, 587) +# s.starttls() +# s.login(TEST_ADDRESS, TEST_PASSWORD) +# s.sendmail(TEST_ADDRESS, [mail_address], msg) +# s.quit() +# +# sleep(3) +# +# # Get the message +# m = imaplib.IMAP4_SSL(TEST_DOMAIN, 993) +# m.login(TEST_ADDRESS, TEST_PASSWORD) +# m.select() +# _, res = m.search(None, '(SUBJECT \"{}\")'.format(subject)) +# _, data = m.fetch(res[0], '(RFC822)') +# +# assert 'DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mailinabox.lan;' in data[0][1] +# +# assert 'ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)' in data[0][1] +# +# # Clean up +# m.store(res[0].strip(), '+FLAGS', '\\Deleted') +# m.expunge() +# m.close() +# m.logout() + + +def test_smtp_headers(): + """Email sent from an MTA via SMTP+TLS has TLS headers""" + # Send a message to root + msg, subject = new_message(TEST_SENDER, TEST_ADDRESS) + s = smtplib.SMTP(TEST_DOMAIN, 25) + s.starttls() + s.sendmail(TEST_SENDER, [TEST_ADDRESS], msg) + s.quit() + + sleep(3) + + # Get the message + m = imaplib.IMAP4_SSL(TEST_DOMAIN, 993) + m.login(TEST_ADDRESS, TEST_PASSWORD) + m.select() + _, res = m.search(None, '(SUBJECT \"{}\")'.format(subject)) + _, data = m.fetch(res[0], '(RFC822)') + + assert 'ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)' in data[0][1] + + # Clean up + m.store(res[0].strip(), '+FLAGS', '\\Deleted') + m.expunge() + m.close() + m.logout() + + +def test_pop3s(): + """Connects with POP3S and asserts the existance of an email, then deletes it""" + msg, subject = new_message(TEST_ADDRESS, TEST_ADDRESS) + s = smtplib.SMTP(TEST_DOMAIN, 587) + s.starttls() + s.login(TEST_ADDRESS, TEST_PASSWORD) + s.sendmail(TEST_ADDRESS, [TEST_ADDRESS], msg) + s.quit() + assert_pop3_received(subject) diff --git a/test/test_ssh.py b/test/test_ssh.py new file mode 100644 index 00000000..8340981f --- /dev/null +++ b/test/test_ssh.py @@ -0,0 +1,13 @@ +import pytest + +from settings import * + + +def test_ssh_banner(): + """SSH is responding with its banner""" + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.connect((TEST_SERVER, TEST_PORT)) + data = s.recv(1024) + s.close() + + assert data.startswith("SSH-2.0-OpenSSH") diff --git a/test/test_web.py b/test/test_web.py new file mode 100644 index 00000000..d6dc4001 --- /dev/null +++ b/test/test_web.py @@ -0,0 +1,60 @@ +from time import sleep +import requests +import os +import pytest + +from settings import * + + +def test_web_hosting_http(): + """web hosting is redirecting to https""" + url = 'http://' + TEST_DOMAIN + r = requests.get(url, verify=False) + + # We should be redirected to https + assert r.history[0].status_code == 301 + assert r.url == url.replace("http", "https") + "/" + + assert r.status_code == 200 + assert "this is a mail-in-a-box" in r.content + + +def test_admin_http(): + """Admin page is redirecting to https""" + url = 'http://' + TEST_DOMAIN + "/admin" + r = requests.get(url, verify=False) + + # We should be redirected to https + assert r.history[0].status_code == 301 + assert r.url == url.replace("http", "https") + + assert r.status_code == 200 + assert "Log in here for your Mail-in-a-Box control panel" in r.content + + +def test_webmail_http(): + """Webmail is redirecting to https and displaying login page""" + url = 'http://' + TEST_DOMAIN + "/mail" + r = requests.get(url, verify=False) + + # We should be redirected to https + assert r.history[0].status_code == 301 + assert r.url == url.replace("http", "https") + "/" + + # 200 - We should be at the login page + assert r.status_code == 200 + assert 'Welcome to ' + TEST_DOMAIN + ' Webmail' in r.content + + +def test_owncloud_http(): + """ownCloud is redirecting to https and displaying login page""" + url = 'http://' + TEST_DOMAIN + '/cloud' + r = requests.get(url, verify=False) + + # We should be redirected to https + assert r.history[0].status_code == 301 + assert r.url == url.replace("http", "https") + "/index.php/login" + + # 200 - We should be at the login page + assert r.status_code == 200 + assert 'ownCloud' in r.content From de791511bfecf54943b5a9af271c5f08df4ce8e0 Mon Sep 17 00:00:00 2001 From: Wolfgang Steitz Date: Thu, 15 Dec 2016 23:50:08 +0100 Subject: [PATCH 02/10] test: start testing caldav --- test/README.md | 4 +-- test/common.py | 5 ++++ test/test_caldav.py | 66 +++++++++++++++++++++++++++++++++++++++++++++ test/test_mail.py | 4 +-- 4 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 test/common.py create mode 100644 test/test_caldav.py diff --git a/test/README.md b/test/README.md index 6b1ee05a..170702ed 100644 --- a/test/README.md +++ b/test/README.md @@ -8,9 +8,9 @@ start-up a vagrant box vagrant up -install pytest +install test requirements - pip install pytest + pip install pytest caldav run the tests diff --git a/test/common.py b/test/common.py new file mode 100644 index 00000000..8c20a435 --- /dev/null +++ b/test/common.py @@ -0,0 +1,5 @@ +import uuid + + +def random_id(): + return uuid.uuid4().hex[:8] diff --git a/test/test_caldav.py b/test/test_caldav.py new file mode 100644 index 00000000..32594e11 --- /dev/null +++ b/test/test_caldav.py @@ -0,0 +1,66 @@ +import pytest +import caldav +from time import sleep + +from settings import * +from common import random_id + + +def connect(): + url = "https://" + TEST_DOMAIN + "/cloud/remote.php/dav/calendars/me@mailinabox.lan/personal/" + client = caldav.DAVClient(url, username=TEST_ADDRESS, password=TEST_PASSWORD, ssl_verify_cert=False) + principal = client.principal() + calendars = principal.calendars() + return client, calendars[0] + + +vcal = """BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//Example Corp.//CalDAV Client//EN +BEGIN:VEVENT +UID:{} +DTSTAMP:20170510T182145Z +DTSTART:20170512T170000Z +DTEND:20170512T180000Z +SUMMARY: this is a sample event +END:VEVENT +END:VCALENDAR +""" + + +def create_event(): + uid = random_id() + event = vcal.format(uid) + return event, uid + + +def event_exists(uid): + c, cal = connect() + try: + event = cal.event(uid) + return True + except caldav.lib.error.NotFoundError: + return False + + +def test_addremove_event(): + c, cal = connect() + event, uid = create_event() + cal.add_event(event) + assert event_exists(uid) + + # now delete the event again + event = cal.event(uid) + event.delete() + sleep(3) + assert (not event_exists(uid)) + + +#def test_addremove_calendar(): +# c, cal = connect() +# cal_id = random_id() +# #c.principal().make_calendar(name="test", cal_id=cal_id) +# cal = caldav.Calendar(c, name="TEST", parent=c.principal(), id="12").save() + + + diff --git a/test/test_mail.py b/test/test_mail.py index 32fe0ad2..f4926561 100644 --- a/test/test_mail.py +++ b/test/test_mail.py @@ -1,5 +1,4 @@ from time import sleep -import uuid import requests import os import pytest @@ -9,12 +8,13 @@ import smtplib from email.mime.text import MIMEText from settings import * +from common import random_id def new_message(from_email, to_email): """Creates an email (headers & body) with a random subject""" msg = MIMEText('Testing') - msg['Subject'] = uuid.uuid4().hex[:8] + msg['Subject'] = random_id() msg['From'] = from_email msg['To'] = to_email return msg.as_string(), msg['subject'] From 1194f07ed3ae90128be35646793d5dd628092964 Mon Sep 17 00:00:00 2001 From: Wolfgang Steitz Date: Sun, 18 Dec 2016 19:19:00 +0100 Subject: [PATCH 03/10] tests: basic carddav tests --- test/README.md | 2 +- test/test_caldav.py | 2 +- test/test_carddav.py | 50 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 test/test_carddav.py diff --git a/test/README.md b/test/README.md index 170702ed..8e962020 100644 --- a/test/README.md +++ b/test/README.md @@ -10,7 +10,7 @@ start-up a vagrant box install test requirements - pip install pytest caldav + pip install pytest caldav pycarddav run the tests diff --git a/test/test_caldav.py b/test/test_caldav.py index 32594e11..bea4e698 100644 --- a/test/test_caldav.py +++ b/test/test_caldav.py @@ -7,7 +7,7 @@ from common import random_id def connect(): - url = "https://" + TEST_DOMAIN + "/cloud/remote.php/dav/calendars/me@mailinabox.lan/personal/" + url = "https://" + TEST_DOMAIN + "/cloud/remote.php/dav/calendars/" + TEST_ADDRESS + "/personal/" client = caldav.DAVClient(url, username=TEST_ADDRESS, password=TEST_PASSWORD, ssl_verify_cert=False) principal = client.principal() calendars = principal.calendars() diff --git a/test/test_carddav.py b/test/test_carddav.py new file mode 100644 index 00000000..a19b1435 --- /dev/null +++ b/test/test_carddav.py @@ -0,0 +1,50 @@ +import pytest +from pycarddav import carddav +from time import sleep + +from settings import * +from common import random_id + + +test_vcf = """ +BEGIN:VCARD +VERSION:3.0 +EMAIL;TYPE=PREF:foo@example.com +N:John Doe;;;; +FN:John Doe +REV:2012-08-02T21:16:14+00:00 +PRODID:-//ownCloud//NONSGML Contacts 0.2//EN +UID:c292c7212b +END:VCARD +""" + +def connect(): + url = "https://" + TEST_DOMAIN + "/cloud/remote.php/carddav/addressbooks/" + TEST_ADDRESS + "/contacts/" + return carddav.PyCardDAV(url, user=TEST_ADDRESS, passwd=TEST_PASSWORD, verify=False, write_support=True) + + +def test_adddelete_contact(): + c = connect() + abook = c.get_abook() + prev_len = len(abook) + + url, etag = c.upload_new_card(test_vcf) + abook = c.get_abook() + assert len(abook) == prev_len + 1 + + c.delete_vcard(url, etag) + abook = c.get_abook() + assert len(abook) == prev_len + + +def test_update_contact(): + c = connect() + url, etag = c.upload_new_card(test_vcf) + + card = c.get_vcard(url) + new_card = card.replace("John Doe", "Jane Doe") + c.update_vcard(new_card, url, etag) + + card = c.get_vcard(url) + assert "John Doe" not in card + assert "Jane Doe" in card From f0b0108eb4554d800e8d055e383f1c8e100fd8dc Mon Sep 17 00:00:00 2001 From: Wolfgang Steitz Date: Sun, 18 Dec 2016 19:39:35 +0100 Subject: [PATCH 04/10] tests: update readme --- test/README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/README.md b/test/README.md index 8e962020..9758ec7d 100644 --- a/test/README.md +++ b/test/README.md @@ -30,8 +30,6 @@ and there needs to be at least one assert statement. TODO ===== -* calendar -* contacts * dns From 32b1176a07962cc73c3c70616622173263d887eb Mon Sep 17 00:00:00 2001 From: Wolfgang Steitz Date: Tue, 20 Dec 2016 23:43:34 +0100 Subject: [PATCH 05/10] tests: added test for backup functionality --- test/test_backup.py | 45 +++++++++++++++++++++++++++++++++++++++++++++ test/test_mail.py | 26 ++++++++++++++------------ 2 files changed, 59 insertions(+), 12 deletions(-) create mode 100644 test/test_backup.py diff --git a/test/test_backup.py b/test/test_backup.py new file mode 100644 index 00000000..28be8c94 --- /dev/null +++ b/test/test_backup.py @@ -0,0 +1,45 @@ +import pytest +from time import sleep +from subprocess import check_call, check_output +import smtplib + +from settings import * +from common import random_id +from test_mail import new_message, check_imap_received + + +def test_backup_mail(): + # send a mail, to ensure we have something to backup + msg, subject = new_message(TEST_ADDRESS, TEST_ADDRESS) + s = smtplib.SMTP(TEST_DOMAIN, 587) + s.starttls() + s.login(TEST_ADDRESS, TEST_PASSWORD) + s.sendmail(TEST_ADDRESS, [TEST_ADDRESS], msg) + s.quit() + + # trigger a backup + sleep(2) + cmd_ssh = "sshpass -p vagrant ssh vagrant@{} -p {} ".format(TEST_SERVER, TEST_PORT) + cmd_count = cmd_ssh + "ls -l /home/user-data/backup/encrypted | wc -l" + num_backup_files = int(check_output(cmd_count, shell=True)) + cmd = cmd_ssh + "sudo /vagrant/management/backup.py" + check_call(cmd, shell=True) + num_backup_files_new = int(check_output(cmd_count, shell=True)) + assert num_backup_files_new > num_backup_files + + # delete mail + assert check_imap_received(subject) + assert not check_imap_received(subject) + + # restore backup + path = "/home/user-data" + passphrase = "export PASSPHRASE=\$(sudo cat /home/user-data/backup/secret_key.txt) &&" + # extract to temp directory + restore = "sudo -E duplicity restore --force file://{0}/backup/encrypted {0}/restore &&".format(path) + # move restored backup using rsync, because it allows to overwrite files + move = "sudo rsync -av {0}/restore/* {0}/ &&".format(path) + rm = "sudo rm -rf {0}/restore/".format(path) + check_call(cmd_ssh + "\"" + passphrase + restore + move + rm + "\"", shell=True) + + # check the mail is there again + assert check_imap_received(subject) diff --git a/test/test_mail.py b/test/test_mail.py index f4926561..80003e1f 100644 --- a/test/test_mail.py +++ b/test/test_mail.py @@ -18,9 +18,10 @@ def new_message(from_email, to_email): msg['From'] = from_email msg['To'] = to_email return msg.as_string(), msg['subject'] + -def assert_imap_received(subject): +def check_imap_received(subject): """Connects with IMAP and asserts the existence of an email, then deletes it""" sleep(3) @@ -30,15 +31,16 @@ def assert_imap_received(subject): m.login(TEST_ADDRESS, TEST_PASSWORD) m.select() - # Assert the message exists + # check the message exists typ, data = m.search(None, '(SUBJECT \"{}\")'.format(subject)) - assert len(data[0].split()) == 1 - - # Delete it & logout - m.store(data[0].strip(), '+FLAGS', '\\Deleted') - m.expunge() + res = len(data[0].split()) == 1 + + if res: + m.store(data[0].strip(), '+FLAGS', '\\Deleted') + m.expunge() m.close() m.logout() + return res def assert_pop3_received(subject): @@ -81,7 +83,7 @@ def test_smtps(): s.login(TEST_ADDRESS, TEST_PASSWORD) s.sendmail(TEST_ADDRESS, [TEST_ADDRESS], msg) s.quit() - assert_imap_received(subject) + assert check_imap_received(subject) def test_smtps_tag(): @@ -93,7 +95,7 @@ def test_smtps_tag(): s.login(TEST_ADDRESS, TEST_PASSWORD) s.sendmail(TEST_ADDRESS, [mail_address], msg) s.quit() - assert_imap_received(subject) + assert check_imap_received(subject) def test_smtps_requires_auth(): @@ -117,7 +119,7 @@ def test_smtp(): s = smtplib.SMTP(TEST_DOMAIN, 25) s.sendmail(TEST_SENDER, [TEST_ADDRESS], msg) s.quit() - assert_imap_received(subject) + assert check_imap_received(subject) def test_smtp_tls(): @@ -127,7 +129,7 @@ def test_smtp_tls(): s.starttls() s.sendmail(TEST_SENDER, [TEST_ADDRESS], msg) s.quit() - assert_imap_received(subject) + assert check_imap_received(subject) # FIXME @@ -193,7 +195,7 @@ def test_smtp_headers(): def test_pop3s(): - """Connects with POP3S and asserts the existance of an email, then deletes it""" + """Connects with POP3S and asserts the existance of an email""" msg, subject = new_message(TEST_ADDRESS, TEST_ADDRESS) s = smtplib.SMTP(TEST_DOMAIN, 587) s.starttls() From 815dba94af5c02ff222beed24b9c0bf040af73b2 Mon Sep 17 00:00:00 2001 From: Wolfgang Steitz Date: Mon, 23 Jan 2017 21:12:13 +0100 Subject: [PATCH 06/10] tests: added requirements.txt --- test/README.md | 9 +++------ test/requirements.txt | 3 +++ 2 files changed, 6 insertions(+), 6 deletions(-) create mode 100644 test/requirements.txt diff --git a/test/README.md b/test/README.md index 9758ec7d..805e9d8e 100644 --- a/test/README.md +++ b/test/README.md @@ -10,7 +10,7 @@ start-up a vagrant box install test requirements - pip install pytest caldav pycarddav + pip install -r requirements.txt run the tests @@ -19,8 +19,8 @@ run the tests to just run a subset of the tests (e.g. the ssh related ones): pytest test_ssh.py - - + + Contributing ============ @@ -31,6 +31,3 @@ and there needs to be at least one assert statement. TODO ===== * dns - - - diff --git a/test/requirements.txt b/test/requirements.txt new file mode 100644 index 00000000..6c63d019 --- /dev/null +++ b/test/requirements.txt @@ -0,0 +1,3 @@ +pytest>=3.0.5 +pyCardDAV==0.7.0 +caldav==0.5 From 055ed62f16e0604e534ea438c67a1235371ddb11 Mon Sep 17 00:00:00 2001 From: Wolfgang Steitz Date: Thu, 2 Feb 2017 16:31:54 +0100 Subject: [PATCH 07/10] test: adding / removing calendar check --- test/test_caldav.py | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/test/test_caldav.py b/test/test_caldav.py index bea4e698..7b9964e1 100644 --- a/test/test_caldav.py +++ b/test/test_caldav.py @@ -32,7 +32,7 @@ def create_event(): uid = random_id() event = vcal.format(uid) return event, uid - + def event_exists(uid): c, cal = connect() @@ -48,19 +48,21 @@ def test_addremove_event(): event, uid = create_event() cal.add_event(event) assert event_exists(uid) - - # now delete the event again + + # now delete the event again event = cal.event(uid) event.delete() sleep(3) assert (not event_exists(uid)) - -#def test_addremove_calendar(): -# c, cal = connect() -# cal_id = random_id() -# #c.principal().make_calendar(name="test", cal_id=cal_id) -# cal = caldav.Calendar(c, name="TEST", parent=c.principal(), id="12").save() - - +def test_addremove_calendar(): + c, _ = connect() + cal_id = random_id() + cal = c.principal().make_calendar(name="test", cal_id=cal_id) + matching = [calendar for calendar in c.principal().calendars() if cal_id in str(calendar.url)] + assert len(matching) == 1 + + c.delete(cal.url) + matching = [calendar for calendar in c.principal().calendars() if cal_id in str(calendar.url)] + assert len(matching) == 0 From 12c652d0141140fc9ca53f9d0f6bcf775ebeb4ac Mon Sep 17 00:00:00 2001 From: Wolfgang Steitz Date: Thu, 2 Feb 2017 16:32:52 +0100 Subject: [PATCH 08/10] gitignore: ignore pyc files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index f3cdb1bc..8c4bd1dc 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ tools/__pycache__/ externals/ .env .vagrant +*.pyc From c9cf148b039046cf487a237af77b8ca43a5d54f9 Mon Sep 17 00:00:00 2001 From: Wolfgang Steitz Date: Thu, 2 Feb 2017 16:35:59 +0100 Subject: [PATCH 09/10] test: cleanup README --- test/README.md | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/test/README.md b/test/README.md index 805e9d8e..09df7967 100644 --- a/test/README.md +++ b/test/README.md @@ -1,14 +1,12 @@ -This is the mailinabox test suite. IT uses the excellent pytest module to check the functionality -of the different services. +This is the mailinabox test suite. It uses the excellent pytest module to check the functionality of the different services. -Usage -===== +# Usage start-up a vagrant box vagrant up -install test requirements +install test requirements (using a virtualenv is highly recommended) pip install -r requirements.txt @@ -21,13 +19,6 @@ to just run a subset of the tests (e.g. the ssh related ones): pytest test_ssh.py -Contributing -============ +# Contributing -pytest auto-discovers all tests in this directory. The test functions need to be named "test_..." -and there needs to be at least one assert statement. - - -TODO -===== -* dns +pytest auto-discovers all tests in this directory. The test functions need to be named "test_..." and there needs to be at least one assert statement. From a2350c459150e32bf383f6c79d96b0b680e582e6 Mon Sep 17 00:00:00 2001 From: Wolfgang Steitz Date: Thu, 2 Feb 2017 16:50:39 +0100 Subject: [PATCH 10/10] test: code cleanup --- test/test_backup.py | 9 ++++----- test/test_carddav.py | 2 -- test/test_mail.py | 39 ++------------------------------------- 3 files changed, 6 insertions(+), 44 deletions(-) diff --git a/test/test_backup.py b/test/test_backup.py index 28be8c94..b8edc9da 100644 --- a/test/test_backup.py +++ b/test/test_backup.py @@ -4,7 +4,6 @@ from subprocess import check_call, check_output import smtplib from settings import * -from common import random_id from test_mail import new_message, check_imap_received @@ -16,7 +15,7 @@ def test_backup_mail(): s.login(TEST_ADDRESS, TEST_PASSWORD) s.sendmail(TEST_ADDRESS, [TEST_ADDRESS], msg) s.quit() - + # trigger a backup sleep(2) cmd_ssh = "sshpass -p vagrant ssh vagrant@{} -p {} ".format(TEST_SERVER, TEST_PORT) @@ -26,11 +25,11 @@ def test_backup_mail(): check_call(cmd, shell=True) num_backup_files_new = int(check_output(cmd_count, shell=True)) assert num_backup_files_new > num_backup_files - + # delete mail assert check_imap_received(subject) assert not check_imap_received(subject) - + # restore backup path = "/home/user-data" passphrase = "export PASSPHRASE=\$(sudo cat /home/user-data/backup/secret_key.txt) &&" @@ -40,6 +39,6 @@ def test_backup_mail(): move = "sudo rsync -av {0}/restore/* {0}/ &&".format(path) rm = "sudo rm -rf {0}/restore/".format(path) check_call(cmd_ssh + "\"" + passphrase + restore + move + rm + "\"", shell=True) - + # check the mail is there again assert check_imap_received(subject) diff --git a/test/test_carddav.py b/test/test_carddav.py index a19b1435..a23c96dc 100644 --- a/test/test_carddav.py +++ b/test/test_carddav.py @@ -1,9 +1,7 @@ import pytest from pycarddav import carddav -from time import sleep from settings import * -from common import random_id test_vcf = """ diff --git a/test/test_mail.py b/test/test_mail.py index 80003e1f..227fc0eb 100644 --- a/test/test_mail.py +++ b/test/test_mail.py @@ -18,7 +18,7 @@ def new_message(from_email, to_email): msg['From'] = from_email msg['To'] = to_email return msg.as_string(), msg['subject'] - + def check_imap_received(subject): @@ -34,7 +34,7 @@ def check_imap_received(subject): # check the message exists typ, data = m.search(None, '(SUBJECT \"{}\")'.format(subject)) res = len(data[0].split()) == 1 - + if res: m.store(data[0].strip(), '+FLAGS', '\\Deleted') m.expunge() @@ -132,41 +132,6 @@ def test_smtp_tls(): assert check_imap_received(subject) -# FIXME -#def test_smtps_headers(): -# """Email sent from an MUA has DKIM and TLS headers""" -# import smtplib -# import imaplib -# -# # Send a message to admin -# mail_address = "admin@" + TEST_DOMAIN -# msg, subject = new_message(TEST_ADDRESS, mail_address) -# s = smtplib.SMTP(TEST_DOMAIN, 587) -# s.starttls() -# s.login(TEST_ADDRESS, TEST_PASSWORD) -# s.sendmail(TEST_ADDRESS, [mail_address], msg) -# s.quit() -# -# sleep(3) -# -# # Get the message -# m = imaplib.IMAP4_SSL(TEST_DOMAIN, 993) -# m.login(TEST_ADDRESS, TEST_PASSWORD) -# m.select() -# _, res = m.search(None, '(SUBJECT \"{}\")'.format(subject)) -# _, data = m.fetch(res[0], '(RFC822)') -# -# assert 'DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mailinabox.lan;' in data[0][1] -# -# assert 'ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)' in data[0][1] -# -# # Clean up -# m.store(res[0].strip(), '+FLAGS', '\\Deleted') -# m.expunge() -# m.close() -# m.logout() - - def test_smtp_headers(): """Email sent from an MTA via SMTP+TLS has TLS headers""" # Send a message to root