Skip to content

Commit

Permalink
test: use instant accounts instead of mailadm
Browse files Browse the repository at this point in the history
  • Loading branch information
link2xt committed Oct 30, 2023
1 parent 1d80659 commit 6aae027
Show file tree
Hide file tree
Showing 16 changed files with 101 additions and 94 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ jobs:

- name: Run python tests
env:
DCC_NEW_TMP_EMAIL: ${{ secrets.DCC_NEW_TMP_EMAIL }}
CHATMAIL_DOMAIN: ${{ secrets.CHATMAIL_DOMAIN }}
DCC_RS_TARGET: debug
DCC_RS_DEV: ${{ github.workspace }}
working-directory: python
Expand Down Expand Up @@ -274,6 +274,6 @@ jobs:
- name: Run deltachat-rpc-client tests
env:
DCC_NEW_TMP_EMAIL: ${{ secrets.DCC_NEW_TMP_EMAIL }}
CHATMAIL_DOMAIN: ${{ secrets.CHATMAIL_DOMAIN }}
working-directory: deltachat-rpc-client
run: tox -e py
2 changes: 1 addition & 1 deletion .github/workflows/jsonrpc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
working-directory: deltachat-jsonrpc/typescript
run: npm run test
env:
DCC_NEW_TMP_EMAIL: ${{ secrets.DCC_NEW_TMP_EMAIL }}
CHATMAIL_DOMAIN: ${{ secrets.CHATMAIL_DOMAIN }}
- name: make sure websocket server version still builds
working-directory: deltachat-jsonrpc
run: cargo build --bin deltachat-jsonrpc-server --features webserver
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/node-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,5 @@ jobs:
working-directory: node
run: npm run test
env:
DCC_NEW_TMP_EMAIL: ${{ secrets.DCC_NEW_TMP_EMAIL }}
CHATMAIL_DOMAIN: ${{ secrets.CHATMAIL_DOMAIN }}
NODE_OPTIONS: "--force-node-api-uncaught-exceptions-policy=true"
4 changes: 2 additions & 2 deletions deltachat-jsonrpc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,10 @@ This will build the `deltachat-jsonrpc-server` binary and then run a test suite

The test suite includes some tests that need online connectivity and a way to create test email accounts. To run these tests, talk to DeltaChat developers to get a token for the `testrun.org` service, or use a local instance of [`mailadm`](https://github.com/deltachat/docker-mailadm).

Then, set the `DCC_NEW_TMP_EMAIL` environment variable to your mailadm token before running the tests.
Then, set the `CHATMAIL_DOMAIN` environment variable to your testing email server domain.

```
DCC_NEW_TMP_EMAIL=https://testrun.org/new_email?t=yourtoken npm run test
CHATMAIL_DOMAIN=chat.example.org npm run test
```

#### Test Coverage
Expand Down
10 changes: 5 additions & 5 deletions deltachat-jsonrpc/typescript/test/online.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ describe("online tests", function () {

before(async function () {
this.timeout(60000);
if (!process.env.DCC_NEW_TMP_EMAIL) {
if (!process.env.CHATMAIL_DOMAIN) {
if (process.env.COVERAGE && !process.env.COVERAGE_OFFLINE) {
console.error(
"CAN NOT RUN COVERAGE correctly: Missing DCC_NEW_TMP_EMAIL environment variable!\n\n",
"CAN NOT RUN COVERAGE correctly: Missing CHATMAIL_DOMAIN environment variable!\n\n",
"You can set COVERAGE_OFFLINE=1 to circumvent this check and skip the online tests, but those coverage results will be wrong, because some functions can only be tested in the online test"
);
process.exit(1);
}
console.log(
"Missing DCC_NEW_TMP_EMAIL environment variable!, skip integration tests"
"Missing CHATMAIL_DOMAIN environment variable!, skip integration tests"
);
this.skip();
}
Expand All @@ -33,15 +33,15 @@ describe("online tests", function () {
if (kind !== "Info") console.log(contextId, kind);
});

account1 = await createTempUser(process.env.DCC_NEW_TMP_EMAIL);
account1 = createTempUser(process.env.CHATMAIL_DOMAIN);
if (!account1 || !account1.email || !account1.password) {
console.log(
"We didn't got back an account from the api, skip integration tests"
);
this.skip();
}

account2 = await createTempUser(process.env.DCC_NEW_TMP_EMAIL);
account2 = createTempUser(process.env.CHATMAIL_DOMAIN);
if (!account2 || !account2.email || !account2.password) {
console.log(
"We didn't got back an account2 from the api, skip integration tests"
Expand Down
17 changes: 8 additions & 9 deletions deltachat-jsonrpc/typescript/test/test_base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,14 @@ export async function startServer(): Promise<RpcServerHandle> {
};
}

export async function createTempUser(url: string) {
const response = await fetch(url, {
method: "POST",
headers: {
"cache-control": "no-cache",
},
});
if (!response.ok) throw new Error("Received invalid response");
return response.json();
export function createTempUser(chatmailDomain: String) {
const charset = "2345789acdefghjkmnpqrstuvwxyz";
let user = "ci-";
for (let i = 0; i < 6; i++) {
user += charset[Math.floor(Math.random() * charset.length)];
}
const email = user + "@" + chatmailDomain;
return { email: email, password: user + "$" + user };
}

function getTargetDir(): Promise<string> {
Expand Down
14 changes: 6 additions & 8 deletions deltachat-rpc-client/src/deltachat_rpc_client/pytestplugin.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import json
import os
import urllib.request
import random
from typing import AsyncGenerator, List, Optional

import pytest
Expand All @@ -10,12 +9,11 @@


def get_temp_credentials() -> dict:
url = os.getenv("DCC_NEW_TMP_EMAIL")
assert url, "Failed to get online account, DCC_NEW_TMP_EMAIL is not set"

request = urllib.request.Request(url, method="POST")
with urllib.request.urlopen(request, timeout=60) as f:
return json.load(f)
domain = os.getenv("CHATMAIL_DOMAIN")
username = "ci-" + "".join(random.choice("2345789acdefghjkmnpqrstuvwxyz") for i in range(6))
password = f"{username}${username}"
addr = f"{username}@{domain}"
return {"email": addr, "password": password}


class ACFactory:
Expand Down
2 changes: 1 addition & 1 deletion deltachat-rpc-client/tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ setenv =
# Avoid stack overflow when Rust core is built without optimizations.
RUST_MIN_STACK=8388608
passenv =
DCC_NEW_TMP_EMAIL
CHATMAIL_DOMAIN
deps =
pytest
pytest-timeout
Expand Down
4 changes: 2 additions & 2 deletions node/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,10 +204,10 @@ Running `npm test` ends with showing a code coverage report, which is produced b

The coverage report from `nyc` in the console is rather limited. To get a more detailed coverage report you can run `npm run coverage-html-report`. This will produce a html report from the `nyc` data and display it in a browser on your local machine.

To run the integration tests you need to set the `DCC_NEW_TMP_EMAIL` environment variables. E.g.:
To run the integration tests you need to set the `CHATMAIL_DOMAIN` environment variables. E.g.:

```
$ export DCC_NEW_TMP_EMAIL=https://testrun.org/new_email?t=[token]
$ export CHATMAIL_DOMAIN=chat.example.org
$ npm run test
```

Expand Down
31 changes: 8 additions & 23 deletions node/test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,14 @@ import fetch from 'node-fetch'
chai.use(chaiAsPromised)
chai.config.truncateThreshold = 0 // Do not truncate assertion errors.

async function createTempUser(url) {
async function postData(url = '') {
// Default options are marked with *
const response = await fetch(url, {
method: 'POST', // *GET, POST, PUT, DELETE, etc.
headers: {
'cache-control': 'no-cache',
},
})
if (!response.ok) {
throw new Error('request failed: ' + response.body.read())
}
return response.json() // parses JSON response into native JavaScript objects
function createTempUser(chatmailDomain) {
const charset = "2345789acdefghjkmnpqrstuvwxyz";
let user = "ci-";
for (let i = 0; i < 6; i++) {
user += charset[Math.floor(Math.random() * charset.length)];
}

return await postData(url)
const email = user + "@" + chatmailDomain;
return { email: email, password: user + "$" + user };
}

describe('static tests', function () {
Expand Down Expand Up @@ -768,14 +760,7 @@ describe('Integration tests', function () {
})

this.beforeAll(async function () {
if (!process.env.DCC_NEW_TMP_EMAIL) {
console.log(
'Missing DCC_NEW_TMP_EMAIL environment variable!, skip integration tests'
)
this.skip()
}

account = await createTempUser(process.env.DCC_NEW_TMP_EMAIL)
account = createTempUser(process.env.CHATMAIL_DOMAIN)
if (!account || !account.email || !account.password) {
console.log(
"We didn't got back an account from the api, skip integration tests"
Expand Down
14 changes: 7 additions & 7 deletions python/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,14 @@ end-to-end tests that require accounts on real e-mail servers.
Running "live" tests with temporary accounts
--------------------------------------------

If you want to run live functional tests you can set ``DCC_NEW_TMP_EMAIL`` to a URL that creates e-mail accounts. Most developers use https://testrun.org URLs created and managed by `mailadm <https://mailadm.readthedocs.io/>`_.
If you want to run live functional tests
you can set ``CHATMAIL_DOMAIN`` to a domain of the email server
that creates e-mail accounts like this::

Please feel free to contact us through a github issue or by e-mail and we'll send you a URL that you can then use for functional tests like this::
export CHATMAIL_DOMAIN=nine.testrun.org

export DCC_NEW_TMP_EMAIL=<URL you got from us>

With this account-creation setting, pytest runs create ephemeral e-mail accounts on the http://testrun.org server.
These accounts are removed automatically as they expire.
With this account-creation setting, pytest runs create ephemeral e-mail accounts on the server.
These accounts have the pattern `ci-{6 characters}@{CHATMAIL_DOMAIN}`.
After setting the variable, either rerun `scripts/run-python-test.sh`
or run offline and online tests with `tox` directly::

Expand Down Expand Up @@ -159,6 +159,6 @@ find it with::

This docker image can be used to run tests and build Python wheels for all interpreters::

$ docker run -e DCC_NEW_TMP_EMAIL \
$ docker run -e CHATMAIL_DOMAIN \
--rm -it -v $(pwd):/mnt -w /mnt \
deltachat/coredeps scripts/run_all.sh
57 changes: 35 additions & 22 deletions python/src/deltachat/testplugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
import threading
import time
import weakref
import random
from queue import Queue
from typing import Callable, Dict, List, Optional, Set

import pytest
import requests
from _pytest._code import Source

import deltachat
Expand All @@ -29,6 +29,12 @@ def pytest_addoption(parser):
default=None,
help="a file with >=2 lines where each line contains NAME=VALUE config settings for one account",
)
group.addoption(
"--chatmail",
action="store",
default=None,
help="chatmail server domain name",
)
group.addoption(
"--ignored",
action="store_true",
Expand All @@ -53,10 +59,12 @@ def pytest_addoption(parser):

def pytest_configure(config):
cfg = config.getoption("--liveconfig")

cfg = config.getoption("--chatmail")
if not cfg:
cfg = os.getenv("DCC_NEW_TMP_EMAIL")
cfg = os.getenv("CHATMAIL_DOMAIN")
if cfg:
config.option.liveconfig = cfg
config.option.chatmail = cfg

# Make sure we don't get garbled output because threads keep running
# collect all ever created accounts in a weakref-set (so we don't
Expand Down Expand Up @@ -157,13 +165,29 @@ def get_liveconfig_producer(self):
"""provide live account configs, cached on a per-test-process scope
so that test functions can re-use already known live configs.
Depending on the --liveconfig option this comes from
a HTTP provider or a file with a line specifying each accounts config.
a file with a line specifying each accounts config
or a --chatmail domain.
"""
liveconfig_opt = self.pytestconfig.getoption("--liveconfig")
if not liveconfig_opt:
pytest.skip("specify DCC_NEW_TMP_EMAIL or --liveconfig to provide live accounts")

if not liveconfig_opt.startswith("http"):
chatmail_opt = self.pytestconfig.getoption("--chatmail")
if chatmail_opt:
# Use a chatmail instance.
domain = chatmail_opt
MAX_LIVE_CREATED_ACCOUNTS = 10
for index in range(MAX_LIVE_CREATED_ACCOUNTS):
try:
yield self._configlist[index]
except IndexError:
username = "ci-" + "".join(random.choice("2345789acdefghjkmnpqrstuvwxyz") for i in range(6))
password = f"{username}${username}"
addr = f"{username}@{domain}"
config = {"addr": addr, "mail_pw": password}
print("newtmpuser {}: addr={}".format(index, config["addr"]))
self._configlist.append(config)
yield config
pytest.fail(f"more than {MAX_LIVE_CREATED_ACCOUNTS} live accounts requested.")
elif liveconfig_opt:
# Read a list of accounts from file.
for line in open(liveconfig_opt):
if line.strip() and not line.strip().startswith("#"):
d = {}
Expand All @@ -174,20 +198,9 @@ def get_liveconfig_producer(self):

yield from iter(self._configlist)
else:
MAX_LIVE_CREATED_ACCOUNTS = 10
for index in range(MAX_LIVE_CREATED_ACCOUNTS):
try:
yield self._configlist[index]
except IndexError:
res = requests.post(liveconfig_opt, timeout=60)
if res.status_code != 200:
pytest.fail(f"newtmpuser count={index} code={res.status_code}: '{res.text}'")
d = res.json()
config = {"addr": d["email"], "mail_pw": d["password"]}
print("newtmpuser {}: addr={}".format(index, config["addr"]))
self._configlist.append(config)
yield config
pytest.fail(f"more than {MAX_LIVE_CREATED_ACCOUNTS} live accounts requested.")
pytest.skip(
"specify --liveconfig, CHATMAIL_DOMAIN or --chatmail to provide live accounts",
)

def cache_maybe_retrieve_configured_db_files(self, cache_addr, db_target_path):
db_target_path = pathlib.Path(db_target_path)
Expand Down
28 changes: 20 additions & 8 deletions python/tests/test_1_online.py
Original file line number Diff line number Diff line change
Expand Up @@ -2208,7 +2208,17 @@ def test_delete_multiple_messages(acfactory, lp):

def test_trash_multiple_messages(acfactory, lp):
ac1, ac2 = acfactory.get_online_accounts(2)

# Create the Trash folder on IMAP server
# and recreate the account so Trash folder is configured.
lp.sec("Creating trash folder")
ac2.direct_imap.create_folder("Trash")
lp.sec("Creating new accounts")
ac2 = acfactory.new_online_configuring_account(cloned_from=ac2)
acfactory.bring_accounts_online()

ac2.set_config("delete_to_trash", "1")
assert ac2.get_config("configured_trash_folder")
chat12 = acfactory.get_accepted_chat(ac1, ac2)

lp.sec("ac1: sending 3 messages")
Expand Down Expand Up @@ -2239,13 +2249,15 @@ def test_trash_multiple_messages(acfactory, lp):


def test_configure_error_msgs_wrong_pw(acfactory):
configdict = acfactory.get_next_liveconfig()
ac1 = acfactory.get_unconfigured_account()
ac1.update_config(configdict)
ac1.set_config("mail_pw", "abc") # Wrong mail pw
ac1.configure()
(ac1,) = acfactory.get_online_accounts(1)

ac2 = acfactory.get_unconfigured_account()
ac2.set_config("addr", ac1.get_config("addr"))
ac2.set_config("mail_pw", "abc") # Wrong mail pw
ac2.configure()
while True:
ev = ac1._evtracker.get_matching("DC_EVENT_CONFIGURE_PROGRESS")
ev = ac2._evtracker.get_matching("DC_EVENT_CONFIGURE_PROGRESS")
print(f"Configuration progress: {ev.data1}")
if ev.data1 == 0:
break
# Password is wrong so it definitely has to say something about "password"
Expand Down Expand Up @@ -2548,7 +2560,7 @@ def test_invalid_password(self, acfactory):
def test_invalid_user(self, acfactory):
configdict = acfactory.get_next_liveconfig()
ac1 = acfactory.get_unconfigured_account()
configdict["addr"] = "x" + configdict["addr"]
configdict["addr"] = "$" + configdict["addr"]
ac1.update_config(configdict)
configtracker = ac1.configure()
configtracker.wait_progress(500)
Expand All @@ -2557,7 +2569,7 @@ def test_invalid_user(self, acfactory):
def test_invalid_domain(self, acfactory):
configdict = acfactory.get_next_liveconfig()
ac1 = acfactory.get_unconfigured_account()
configdict["addr"] += "x"
configdict["addr"] += "$"
ac1.update_config(configdict)
configtracker = ac1.configure()
configtracker.wait_progress(500)
Expand Down
2 changes: 1 addition & 1 deletion python/tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ setenv =
passenv =
DCC_RS_DEV
DCC_RS_TARGET
DCC_NEW_TMP_EMAIL
CHATMAIL_DOMAIN
CARGO_TARGET_DIR
RUSTC_WRAPPER
deps =
Expand Down
Loading

0 comments on commit 6aae027

Please sign in to comment.