Adding test scripts
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
7
tests/build-in-docker.sh
Executable file
7
tests/build-in-docker.sh
Executable file
@@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/bash -eu
|
||||||
|
|
||||||
|
source tests/docker_env.sh
|
||||||
|
#run_in_docker rm -rf CMakeFiles
|
||||||
|
run_in_docker mkdir -p build_in_docker
|
||||||
|
run_in_docker -w "$PWD/build_in_docker" cmake -DENABLE_EMULATION=1 ..
|
||||||
|
run_in_docker -w "$PWD/build_in_docker" make -j ${NUM_PROC}
|
||||||
31
tests/docker/bullseye/Dockerfile
Normal file
31
tests/docker/bullseye/Dockerfile
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
FROM debian:bullseye
|
||||||
|
|
||||||
|
ARG DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
|
RUN apt update && apt upgrade -y
|
||||||
|
RUN apt install -y apt-utils
|
||||||
|
RUN apt install -y libccid \
|
||||||
|
libpcsclite-dev \
|
||||||
|
git \
|
||||||
|
autoconf \
|
||||||
|
pkg-config \
|
||||||
|
libtool \
|
||||||
|
help2man \
|
||||||
|
automake \
|
||||||
|
gcc \
|
||||||
|
make \
|
||||||
|
build-essential \
|
||||||
|
opensc \
|
||||||
|
python3 \
|
||||||
|
python3-pip \
|
||||||
|
swig \
|
||||||
|
cmake \
|
||||||
|
libfuse-dev \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
RUN pip3 install pytest pycvc cryptography pyscard fido2 inputimeout
|
||||||
|
RUN git clone https://github.com/frankmorgner/vsmartcard.git
|
||||||
|
WORKDIR /vsmartcard/virtualsmartcard
|
||||||
|
RUN autoreconf --verbose --install
|
||||||
|
RUN ./configure --sysconfdir=/etc
|
||||||
|
RUN make && make install
|
||||||
|
WORKDIR /
|
||||||
269
tests/docker/fido2/__init__.py
Normal file
269
tests/docker/fido2/__init__.py
Normal file
@@ -0,0 +1,269 @@
|
|||||||
|
# Copyright (c) 2020 Yubico AB
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or
|
||||||
|
# without modification, are permitted provided that the following
|
||||||
|
# conditions are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above
|
||||||
|
# copyright notice, this list of conditions and the following
|
||||||
|
# disclaimer in the documentation and/or other materials provided
|
||||||
|
# with the distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from .base import HidDescriptor
|
||||||
|
from ..ctap import CtapDevice, CtapError, STATUS
|
||||||
|
from ..utils import LOG_LEVEL_TRAFFIC
|
||||||
|
from threading import Event
|
||||||
|
from enum import IntEnum, IntFlag, unique
|
||||||
|
from typing import Tuple, Optional, Callable, Iterator
|
||||||
|
import struct
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
if sys.platform.startswith("linux"):
|
||||||
|
from . import linux as backend
|
||||||
|
elif sys.platform.startswith("win32"):
|
||||||
|
from . import windows as backend
|
||||||
|
elif sys.platform.startswith("darwin"):
|
||||||
|
from . import macos as backend
|
||||||
|
elif sys.platform.startswith("freebsd"):
|
||||||
|
from . import freebsd as backend
|
||||||
|
elif sys.platform.startswith("openbsd"):
|
||||||
|
from . import openbsd as backend
|
||||||
|
else:
|
||||||
|
raise Exception("Unsupported platform")
|
||||||
|
from . import emulation as backend
|
||||||
|
|
||||||
|
|
||||||
|
list_descriptors = backend.list_descriptors
|
||||||
|
get_descriptor = backend.get_descriptor
|
||||||
|
open_connection = backend.open_connection
|
||||||
|
|
||||||
|
|
||||||
|
@unique
|
||||||
|
class CTAPHID(IntEnum):
|
||||||
|
PING = 0x01
|
||||||
|
MSG = 0x03
|
||||||
|
LOCK = 0x04
|
||||||
|
INIT = 0x06
|
||||||
|
WINK = 0x08
|
||||||
|
CBOR = 0x10
|
||||||
|
CANCEL = 0x11
|
||||||
|
|
||||||
|
ERROR = 0x3F
|
||||||
|
KEEPALIVE = 0x3B
|
||||||
|
|
||||||
|
VENDOR_FIRST = 0x40
|
||||||
|
|
||||||
|
|
||||||
|
@unique
|
||||||
|
class CAPABILITY(IntFlag):
|
||||||
|
WINK = 0x01
|
||||||
|
LOCK = 0x02 # Not used
|
||||||
|
CBOR = 0x04
|
||||||
|
NMSG = 0x08
|
||||||
|
|
||||||
|
def supported(self, flags: CAPABILITY) -> bool:
|
||||||
|
return bool(flags & self)
|
||||||
|
|
||||||
|
|
||||||
|
TYPE_INIT = 0x80
|
||||||
|
|
||||||
|
|
||||||
|
class CtapHidDevice(CtapDevice):
|
||||||
|
"""
|
||||||
|
CtapDevice implementation using the HID transport.
|
||||||
|
|
||||||
|
:cvar descriptor: Device descriptor.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, descriptor: HidDescriptor, connection):
|
||||||
|
self.descriptor = descriptor
|
||||||
|
self._packet_size = descriptor.report_size_out
|
||||||
|
self._connection = connection
|
||||||
|
|
||||||
|
nonce = os.urandom(8)
|
||||||
|
self._channel_id = 0xFFFFFFFF
|
||||||
|
response = self.call(CTAPHID.INIT, nonce)
|
||||||
|
r_nonce, response = response[:8], response[8:]
|
||||||
|
if r_nonce != nonce:
|
||||||
|
raise Exception("Wrong nonce")
|
||||||
|
(
|
||||||
|
self._channel_id,
|
||||||
|
self._u2fhid_version,
|
||||||
|
v1,
|
||||||
|
v2,
|
||||||
|
v3,
|
||||||
|
self._capabilities,
|
||||||
|
) = struct.unpack_from(">IBBBBB", response)
|
||||||
|
self._device_version = (v1, v2, v3)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"CtapHidDevice({self.descriptor.path!r})"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def version(self) -> int:
|
||||||
|
"""CTAP HID protocol version."""
|
||||||
|
return self._u2fhid_version
|
||||||
|
|
||||||
|
@property
|
||||||
|
def device_version(self) -> Tuple[int, int, int]:
|
||||||
|
"""Device version number."""
|
||||||
|
return self._device_version
|
||||||
|
|
||||||
|
@property
|
||||||
|
def capabilities(self) -> int:
|
||||||
|
"""Capabilities supported by the device."""
|
||||||
|
return self._capabilities
|
||||||
|
|
||||||
|
@property
|
||||||
|
def product_name(self) -> Optional[str]:
|
||||||
|
"""Product name of device."""
|
||||||
|
return self.descriptor.product_name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def serial_number(self) -> Optional[str]:
|
||||||
|
"""Serial number of device."""
|
||||||
|
return self.descriptor.serial_number
|
||||||
|
|
||||||
|
def _send_cancel(self):
|
||||||
|
packet = struct.pack(">IB", self._channel_id, TYPE_INIT | CTAPHID.CANCEL).ljust(
|
||||||
|
self._packet_size, b"\0"
|
||||||
|
)
|
||||||
|
logger.log(LOG_LEVEL_TRAFFIC, "SEND: %s", packet.hex())
|
||||||
|
self._connection.write_packet(packet)
|
||||||
|
|
||||||
|
def call(
|
||||||
|
self,
|
||||||
|
cmd: int,
|
||||||
|
data: bytes = b"",
|
||||||
|
event: Optional[Event] = None,
|
||||||
|
on_keepalive: Optional[Callable[[int], None]] = None,
|
||||||
|
) -> bytes:
|
||||||
|
event = event or Event()
|
||||||
|
remaining = data
|
||||||
|
seq = 0
|
||||||
|
|
||||||
|
# Send request
|
||||||
|
header = struct.pack(">IBH", self._channel_id, TYPE_INIT | cmd, len(remaining))
|
||||||
|
while remaining or seq == 0:
|
||||||
|
size = min(len(remaining), self._packet_size - len(header))
|
||||||
|
body, remaining = remaining[:size], remaining[size:]
|
||||||
|
packet = header + body
|
||||||
|
logger.log(LOG_LEVEL_TRAFFIC, "SEND: %s", packet.hex())
|
||||||
|
self._connection.write_packet(packet.ljust(self._packet_size, b"\0"))
|
||||||
|
header = struct.pack(">IB", self._channel_id, 0x7F & seq)
|
||||||
|
seq += 1
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Read response
|
||||||
|
seq = 0
|
||||||
|
response = b""
|
||||||
|
last_ka = None
|
||||||
|
while True:
|
||||||
|
if event.is_set():
|
||||||
|
# Cancel
|
||||||
|
logger.debug("Sending cancel...")
|
||||||
|
self._send_cancel()
|
||||||
|
|
||||||
|
recv = self._connection.read_packet()
|
||||||
|
logger.log(LOG_LEVEL_TRAFFIC, "RECV: %s", recv.hex())
|
||||||
|
|
||||||
|
r_channel = struct.unpack_from(">I", recv)[0]
|
||||||
|
recv = recv[4:]
|
||||||
|
if r_channel != self._channel_id:
|
||||||
|
raise Exception("Wrong channel")
|
||||||
|
|
||||||
|
if not response: # Initialization packet
|
||||||
|
r_cmd, r_len = struct.unpack_from(">BH", recv)
|
||||||
|
recv = recv[3:]
|
||||||
|
if r_cmd == TYPE_INIT | cmd:
|
||||||
|
pass # first data packet
|
||||||
|
elif r_cmd == TYPE_INIT | CTAPHID.KEEPALIVE:
|
||||||
|
ka_status = struct.unpack_from(">B", recv)[0]
|
||||||
|
logger.debug(f"Got keepalive status: {ka_status:02x}")
|
||||||
|
if on_keepalive and ka_status != last_ka:
|
||||||
|
try:
|
||||||
|
ka_status = STATUS(ka_status)
|
||||||
|
except ValueError:
|
||||||
|
pass # Unknown status value
|
||||||
|
last_ka = ka_status
|
||||||
|
on_keepalive(ka_status)
|
||||||
|
continue
|
||||||
|
elif r_cmd == TYPE_INIT | CTAPHID.ERROR:
|
||||||
|
raise CtapError(struct.unpack_from(">B", recv)[0])
|
||||||
|
else:
|
||||||
|
raise CtapError(CtapError.ERR.INVALID_COMMAND)
|
||||||
|
else: # Continuation packet
|
||||||
|
r_seq = struct.unpack_from(">B", recv)[0]
|
||||||
|
recv = recv[1:]
|
||||||
|
if r_seq != seq:
|
||||||
|
raise Exception("Wrong sequence number")
|
||||||
|
seq += 1
|
||||||
|
|
||||||
|
response += recv
|
||||||
|
if len(response) >= r_len:
|
||||||
|
break
|
||||||
|
|
||||||
|
return response[:r_len]
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
logger.debug("Keyboard interrupt, cancelling...")
|
||||||
|
self._send_cancel()
|
||||||
|
|
||||||
|
raise
|
||||||
|
|
||||||
|
def wink(self) -> None:
|
||||||
|
"""Causes the authenticator to blink."""
|
||||||
|
self.call(CTAPHID.WINK)
|
||||||
|
|
||||||
|
def ping(self, msg: bytes = b"Hello FIDO") -> bytes:
|
||||||
|
"""Sends data to the authenticator, which echoes it back.
|
||||||
|
|
||||||
|
:param msg: The data to send.
|
||||||
|
:return: The response from the authenticator.
|
||||||
|
"""
|
||||||
|
return self.call(CTAPHID.PING, msg)
|
||||||
|
|
||||||
|
def lock(self, lock_time: int = 10) -> None:
|
||||||
|
"""Locks the channel."""
|
||||||
|
self.call(CTAPHID.LOCK, struct.pack(">B", lock_time))
|
||||||
|
|
||||||
|
def close(self) -> None:
|
||||||
|
if self._connection:
|
||||||
|
self._connection.close()
|
||||||
|
self._connection = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def list_devices(cls) -> Iterator[CtapHidDevice]:
|
||||||
|
for d in list_descriptors():
|
||||||
|
yield cls(d, open_connection(d))
|
||||||
|
|
||||||
|
|
||||||
|
def list_devices() -> Iterator[CtapHidDevice]:
|
||||||
|
return CtapHidDevice.list_devices()
|
||||||
|
|
||||||
|
|
||||||
|
def open_device(path) -> CtapHidDevice:
|
||||||
|
descriptor = get_descriptor(path)
|
||||||
|
return CtapHidDevice(descriptor, open_connection(descriptor))
|
||||||
79
tests/docker/fido2/emulation.py
Normal file
79
tests/docker/fido2/emulation.py
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
# Original work Copyright 2016 Google Inc. All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
# Modified work Copyright 2020 Yubico AB. All Rights Reserved.
|
||||||
|
# This file, with modifications, is licensed under the above Apache License.
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from .base import HidDescriptor, CtapHidConnection
|
||||||
|
|
||||||
|
import socket
|
||||||
|
from typing import Set
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import sys
|
||||||
|
|
||||||
|
HOST = '127.0.0.1'
|
||||||
|
PORT = 35962
|
||||||
|
|
||||||
|
# Don't typecheck this file on Windows
|
||||||
|
assert sys.platform != "win32" # nosec
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class EmulationCtapHidConnection(CtapHidConnection):
|
||||||
|
def __init__(self, descriptor):
|
||||||
|
self.descriptor = descriptor
|
||||||
|
self.handle = descriptor.path
|
||||||
|
self.handle.connect((HOST, PORT))
|
||||||
|
|
||||||
|
def write_packet(self, packet):
|
||||||
|
if (self.handle.send(len(packet).to_bytes(2, 'big')) != 2):
|
||||||
|
raise OSError("write_packet sending size failed")
|
||||||
|
if (self.handle.send(packet) != len(packet)):
|
||||||
|
raise OSError("write_packet sending packet failed")
|
||||||
|
|
||||||
|
def read_packet(self):
|
||||||
|
bts = self.handle.recv(2)
|
||||||
|
if (len(bts) != 2):
|
||||||
|
raise OSError("read_packet failed reading size")
|
||||||
|
size = int.from_bytes(bts, 'big')
|
||||||
|
data = self.handle.recv(size)
|
||||||
|
if (len(data) != size):
|
||||||
|
raise OSError("read_packet failed reading packet")
|
||||||
|
return data
|
||||||
|
|
||||||
|
def close(self) -> None:
|
||||||
|
return self.handle.close()
|
||||||
|
|
||||||
|
|
||||||
|
def open_connection(descriptor):
|
||||||
|
return EmulationCtapHidConnection(descriptor)
|
||||||
|
|
||||||
|
|
||||||
|
def get_descriptor(_):
|
||||||
|
HOST = 'localhost' # The remote host
|
||||||
|
PORT = 35962 # The same port as used by the server
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
return HidDescriptor(s, 0x00, 0x00, 64, 64, "Pico-Fido", "AAAAAA")
|
||||||
|
|
||||||
|
def list_descriptors():
|
||||||
|
devices = []
|
||||||
|
try:
|
||||||
|
devices.append(get_descriptor(None))
|
||||||
|
except ValueError:
|
||||||
|
pass # Not a CTAP device, ignore.
|
||||||
|
|
||||||
|
return devices
|
||||||
107
tests/docker_env.sh
Normal file
107
tests/docker_env.sh
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
#!/bin/bash -eu
|
||||||
|
|
||||||
|
# Taken from Mbed-TLS project
|
||||||
|
# https://github.com/Mbed-TLS/mbedtls/blob/master/tests/scripts/docker_env.sh
|
||||||
|
#
|
||||||
|
# docker_env.sh
|
||||||
|
#
|
||||||
|
# Purpose
|
||||||
|
# -------
|
||||||
|
#
|
||||||
|
# This is a helper script to enable running tests under a Docker container,
|
||||||
|
# thus making it easier to get set up as well as isolating test dependencies
|
||||||
|
# (which include legacy/insecure configurations of openssl and gnutls).
|
||||||
|
#
|
||||||
|
# WARNING: the Dockerfile used by this script is no longer maintained! See
|
||||||
|
# https://github.com/Mbed-TLS/mbedtls-test/blob/master/README.md#quick-start
|
||||||
|
# for the set of Docker images we use on the CI.
|
||||||
|
#
|
||||||
|
# Notes for users
|
||||||
|
# ---------------
|
||||||
|
# This script expects a Linux x86_64 system with a recent version of Docker
|
||||||
|
# installed and available for use, as well as http/https access. If a proxy
|
||||||
|
# server must be used, invoke this script with the usual environment variables
|
||||||
|
# (http_proxy and https_proxy) set appropriately. If an alternate Docker
|
||||||
|
# registry is needed, specify MBEDTLS_DOCKER_REGISTRY to point at the
|
||||||
|
# host name.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Running this script directly will check for Docker availability and set up
|
||||||
|
# the Docker image.
|
||||||
|
|
||||||
|
# Copyright The Mbed TLS Contributors
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
|
||||||
|
# default values, can be overridden by the environment
|
||||||
|
: ${MBEDTLS_DOCKER_GUEST:=bullseye}
|
||||||
|
|
||||||
|
|
||||||
|
DOCKER_IMAGE_TAG="pico-hsm-test:${MBEDTLS_DOCKER_GUEST}"
|
||||||
|
|
||||||
|
# Make sure docker is available
|
||||||
|
if ! which docker > /dev/null; then
|
||||||
|
echo "Docker is required but doesn't seem to be installed. See https://www.docker.com/ to get started"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Figure out if we need to 'sudo docker'
|
||||||
|
if groups | grep docker > /dev/null; then
|
||||||
|
DOCKER="docker"
|
||||||
|
else
|
||||||
|
echo "Using sudo to invoke docker since you're not a member of the docker group..."
|
||||||
|
DOCKER="docker"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Figure out the number of processors available
|
||||||
|
if [ "$(uname)" == "Darwin" ]; then
|
||||||
|
NUM_PROC="$(sysctl -n hw.logicalcpu)"
|
||||||
|
else
|
||||||
|
NUM_PROC="$(nproc)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build the Docker image
|
||||||
|
echo "Getting docker image up to date (this may take a few minutes)..."
|
||||||
|
${DOCKER} image build \
|
||||||
|
-t ${DOCKER_IMAGE_TAG} \
|
||||||
|
--cache-from=${DOCKER_IMAGE_TAG} \
|
||||||
|
--network host \
|
||||||
|
--build-arg MAKEFLAGS_PARALLEL="-j ${NUM_PROC}" \
|
||||||
|
tests/docker/${MBEDTLS_DOCKER_GUEST}
|
||||||
|
|
||||||
|
run_in_docker()
|
||||||
|
{
|
||||||
|
ENV_ARGS=""
|
||||||
|
while [ "$1" == "-e" ]; do
|
||||||
|
ENV_ARGS="${ENV_ARGS} $1 $2"
|
||||||
|
shift 2
|
||||||
|
done
|
||||||
|
|
||||||
|
WORKDIR="${PWD}"
|
||||||
|
if [ "$1" == '-w' ]; then
|
||||||
|
WORKDIR="$2"
|
||||||
|
shift 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
${DOCKER} container run --rm \
|
||||||
|
--cap-add ALL \
|
||||||
|
--privileged \
|
||||||
|
--volume $PWD:$PWD \
|
||||||
|
--workdir ${WORKDIR} \
|
||||||
|
-e MAKEFLAGS \
|
||||||
|
${ENV_ARGS} \
|
||||||
|
${DOCKER_IMAGE_TAG} \
|
||||||
|
$@
|
||||||
|
}
|
||||||
5
tests/run-test-in-docker.sh
Executable file
5
tests/run-test-in-docker.sh
Executable file
@@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/bash -eu
|
||||||
|
|
||||||
|
source tests/docker_env.sh
|
||||||
|
run_in_docker ./tests/start-up-and-test.sh
|
||||||
|
|
||||||
8
tests/start-up-and-test.sh
Executable file
8
tests/start-up-and-test.sh
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/bash -eu
|
||||||
|
|
||||||
|
/usr/sbin/pcscd &
|
||||||
|
sleep 2
|
||||||
|
rm -f memory.flash
|
||||||
|
cp -R tests/Docker/fido2/* /usr/local/lib/python3.9/dist-packages/fido2/hid
|
||||||
|
./build_in_docker/pico_fido > /dev/null &
|
||||||
|
pytest tests
|
||||||
Reference in New Issue
Block a user