swittest
swittest
is a a full EMV functional test automation system.
Key concepts
Info
swittest
uses JSON format for its test files.
Test suites
A test suite is a document that regroups a certain number of tests together usually under a common criteria, such as:
- Certification level (EMV Level 2 / EMV Level 3)
- Scheme (Visa, Mastercard, Amex, ...)
- Specification version
- Test environment version
Format
{
"name": "MCL v3.1.4 TAL2-Testing Env Dec2021",
"version": "0.2.0",
"date": "2024-10-05",
"environment": {
...
},
"tests": [
...
]
}
With:
name
: The name of the test suite. It should more or less contain the same details as theenv
section.version
: The version of the file.date
: The date when the file was generated.environment
: The test suite details (see Environment).tests
: The list of tests to execute (see Test).
Environment
The environment
section contains information about the test suite usage. The content of the section is described below:
{
...
"environment": {
"type": "TA L2",
"scheme": "Mastercard",
"spec_version": "v3.1.4",
"test_plan_version": "v1.0.1",
"test_env": "Dec 2021"
},
...
}
With:
type
: The type of testing this test suite covers (for ex "TA L2" or "TA L3").scheme
: The payment scheme (for ex "Mastercard" or "Visa").spec_version
: The corresponding specification version.test_plan_version
: The test plan version.test_env
: The test environment version.
Test
The tests
section contains a list of tests to be run as part of the test suite identified by their file name. The content is described below:
{
...
"tests": [
"3B02-0001_first-trx-5-mutualappls",
"3B02-0002_first-trx-4-mutualappls",
...
],
...
}
Test files are is JSON format. No need to specify the file extension in the tests list.
Note
The tool will look for the test files under a strict hierarchy of folders defined as follows: <project_root>/${type}/${scheme}/${spec_version}/${test_plan_version}/${test_env}/tests
, with each of the ${xxx}
parameters belonging to the environment
section.
Test suite data organization
The test suite data follow a very scrict orgnization:
- The test suite(s) must be at the root of the directory.
- The test suite
environment
description is an exact representation of the folder structure:<project_root>/${type}/${scheme}/${spec_version}/${test_plan_version}/${test_env}
- At the end of the
environment
folder structure should be thecapks
,crs
,emvs
andtests
directories, holding the corresponding data.
Below an example of what it could look like:
.
├── L2
│ └── Mastercard
│ └── v3.1.4
│ └── v1.0.1
│ └── Dec 2021
│ ├── capks
│ │ └── CAPK_MCL_1.json
│ ├── crs
│ │ └── CR_MCL_1.json
│ ├── emvs
│ │ └── PPS_MChip_1.json
│ └── tests
│ ├── 3B02-0001_first-trx-5-mutualappls.json
│ └── 3B02-0002_first-trx-4-mutualappls.json
└── L2-Mastercard-v3.1.4-v1.0.1-dec_2021.json
Full example
Below is a full example of what a test suite file could look like:
{
"name": "MCL v3.1.4 TAL2-Testing Env Dec2021",
"version": "0.2.0",
"date": "2024-10-05",
"environment": {
"type": "TA L2",
"scheme": "Mastercard",
"spec_version": "v3.1.4",
"test_plan_version": "v1.0.1",
"test_env": "Dec 2021"
},
"tests": [
"3B02-0001_first-trx-5-mutualappls",
"3B02-0002_first-trx-4-mutualappls",
]
}
Test
A test file is a document that describes the inputs and expected outputs of a perticular transaction (or group of transactions).
Format
{
"name": "3B02-0001_first-trx-5-mutualappls",
"version": "0.2.0",
"date": "2024-10-05",
"environment": {
...
},
"description": "...",
"card": "my-test-card",
"poi_config": {
...
},
"payments": [
...
]
}
With:
name
: The name of the test suite. It should more or less contain the same details as theenv
section.version
: The version of the file.date
: The date when the file was generated.environment
: The test suite details (see Environment).description
: Optional information about the test (conditions, goal, etc...).card
: The virtual card to be used.poi_config
: The EMV configuration to be used for the test (see POIConfig).payments
: The payment(s) to trigger and their expected results (see Payment).
Environment
The environment
section contains information about the test suite usage. The content of the section is described below:
{
...
"environment": {
"type": "TA L2",
"scheme": "Mastercard",
"spec_version": "v3.1.4",
"test_plan_version": "v1.0.1",
"test_env": "Dec 2021"
},
...
}
With:
type
: The type of testing this test suite covers (for ex "TA L2" or "TA L3").scheme
: The payment scheme (for ex "Mastercard" or "Visa").spec_version
: The corresponding specification version.test_plan_version
: The test plan version.test_env
: The test environment version.
POIConfig
The poi_config
section gathers the different pieces of configuration to be used for the test. These pieces are references to other files only. The content of the section is described below:
{
...
"poi_config": {
"name": "POI_Config_1",
"emv_config": "PPS_MChip_1",
"capk_list": "CAPK_MCL_1",
"cr_list": "CR_MCL_1",
},
...
}
With:
name
: The name of the POI Config.emv_config
: The complete EMV config file (e.g. supported combinations or AIDs).capk_list
: Set of CAPKs to be allowed for the test (optional).cr_list
: Set of revoked certificates to be used for the test (optional).
Payment
A test can hold one or several consecutive payments (e.g. transactions) with expected results (e.g. information to check) for each of them. The payments are gathered into a payments
list. Each payment should then be described as below:
{
...
"payments": [
{
"randoms": ["AABBCCDD", "BBCCDDEE"],
"trd": {
"9C": "00",
"9F02": "000000001500",
"5F2A": "0978",
"5F36": "02",
"9A": "241015",
"9F21": "000000",
"9F53": "46",
"9F7C": "1122334455667788990011223344556677889900"
},
"authorization_response": "",
"expectations": {
...
}
},
...
]
}
With:
randoms
: A list of randoms to use for the transaction(s) (optional).trd
: A list of tags corresponding to the Transaction Related Data. Only the following tags are supported: 9C, 9F02, 5F2A, 5F36, 9A, 9F21, 9F53, 9F7C (mandatory).authorization_response
: Authorization response to provide when the cards requires an authorization (optional).expectations
: A list of objects, tags, etc... to be verified for each payment (see Expectations).
Expectations
Expectations are a set of payment related data that must be checked in order for a test to be considered 'pass' or 'fail'. The content of the section is described below:
{
...
"payments": [
{
...
"expectations": {
"restart": {
"error_indication": "0003006A85FF",
"outcome_parameter_set": "5020F0F018F0FF00"
},
"authorization": {
"user_interface_request_data": "1B00000000656E646566720000",
"data_record": {
"tags": {
"9F39": "07",
"9F02": "000000001500",
"9F26": "AC123456789ABCDE",
"5F24": "491231",
"82": "020080",
"50": "4D617374657243617264",
"5A": "5413339000001513",
"9F36": "0002",
"9F09": "0002",
"9F27": "80",
"9F34": "3F0000",
"84": "A0000000041010",
"9F1E": "3132333435363738",
"9F10": "0110000000020000DAC00000000000000000",
"9F11": "01",
"9F33": "006000",
"9F1A": "0056",
"9F35": "22",
"95": "8000000001",
"9F53": "46",
"9F15": "0130",
"5F2A": "0978",
"9A": "241015",
"9C": "00",
"9F37": "AABBCCDD"
},
"tags_present": [],
"tags_not_present": []
},
"discretionary_data": {
"tags": {
"9F5D":"000400",
"DF810E": "00",
"DF810F": "00",
"DF8115": "060000000000FF"
},
"tags_present": [],
"tags_not_present": []
},
"outcome_parameter_set": "30F0F000B8F00D00"
},
"completion": {
... (same as authorization)
}
}
}
]
}
With:
restart
: An expected 'restart' signal to be found in the list of signals provided by the kernel (optional).authorization
: Kernel data provided to perform an authorization request (optional).completion
: Kernel data provided to perform the transaction completion (optional).
Note: Though authorization
and completion
are individually optional, there must at least be one of them in the test expectations.
The authorization
and completion
objects hold the below sub-objects (all of which are optional):
* user_interface_request_data
(full TLV value).
* data_record
(list of tags which value or presence should be checked).
* discretionary_data
(list of tags which value or presence should be checked).
* outcome_parameter_set
(full TLV value).
Note on data_record
and discretionary_data
These objects contains at most 3 sub-objects (all of which are optional):
* tags
: Holds a list of tags (keys) and their expected values (values).
* tags_present
: Holds a list of tags which presence should be confirmed (whatever the value).
* tags_not_present
: Holds a list of tags which absence should be confirmed.
Notes
See below the tags corresponding to the authorization
and completion
sub-objects:
* user_interface_request_data
: DF8116
* data_record
: FF8105
* discretionary_data
: FF8106
* outcome_parameter_set
: DF8129
Full example
Below is a full example of what a test suite file could look like:
{
"name": "3B02-0001_first-trx-5-mutualappls",
"version": "0.2.0",
"date": "2024-10-05",
"environment": {
"type": "TA L2",
"scheme": "Mastercard",
"spec_version": "v3.1.4",
"test_plan_version": "v1.0.1",
"test_env": "Dec 2021"
},
"card": "my-test-card",
"poi_config": {
"name": "POI_Config_1",
"emv_config": "PPS_MChip_1",
"capk_list": "CAPK_MCL_1",
"cr_list": "CR_MCL_1"
},
"payments": [
{
"randoms": ["AABBCCDD", "BBCCDDEE"],
"trd": {
"9C": "00",
"9F02": "000000001500",
"5F2A": "0978",
"5F36": "02",
"9A": "241015",
"9F21": "000000",
"9F53": "46",
"9F7C": "1122334455667788990011223344556677889900"
},
"authorization_response": "3030",
"expectations": {
"restart": {
"error_indication": "0003006A85FF",
"outcome_parameter_set": "5020F0F018F0FF00"
},
"authorization": {
"user_interface_request_data": "1B00000000656E646566720000",
"data_record": {
"tags": {
"9F39": "07",
"9F02": "000000001500",
"9F26": "AC123456789ABCDE",
"5F24": "491231",
"82": "020080",
"50": "4D617374657243617264",
"5A": "5413339000001513",
"9F36": "0002",
"9F09": "0002",
"9F27": "80",
"9F34": "3F0000",
"84": "A0000000041010",
"9F1E": "3132333435363738",
"9F10": "0110000000020000DAC00000000000000000",
"9F11": "01",
"9F33": "006000",
"9F1A": "0056",
"9F35": "22",
"95": "8000000001",
"9F53": "46",
"9F15": "0130",
"5F2A": "0978",
"9A": "241015",
"9C": "00",
"9F37": "AABBCCDD"
},
"tags_present": [],
"tags_not_present": []
},
"discretionary_data": {
"tags": {
"9F5D":"000400",
"DF810E": "00",
"DF810F": "00",
"DF8115": "060000000000FF"
},
"tags_present": [],
"tags_not_present": []
},
"outcome_parameter_set": "30F0F000B8F00D00"
}
}
},
{
"trd": {
"9C": "00",
"9F02": "000000001500",
"5F2A": "0978",
"5F36": "02",
"9A": "241015",
"9F21": "000000",
"9F53": "46",
"9F7C": "1122334455667788990011223344556677889900"
},
"expectations": {
"authorization": {
"user_interface_request_data": "1B00000000656E646566720000",
"data_record": {
"tags": {
"9F39": "07",
"9F02": "000000001500",
"9F26": "AC123456789ABCDE",
"5F24": "491231",
"82": "020080",
"50": "4D617374657243617264",
"5A": "5413339000001513",
"9F36": "0002",
"9F09": "0002",
"9F27": "80",
"9F34": "3F0000",
"84": "A0000000041010",
"9F1E": "3132333435363738",
"9F10": "0110000000020000DAC00000000000000000",
"9F11": "01",
"9F33": "006000",
"9F1A": "0056",
"9F35": "22",
"95": "8000000001",
"9F53": "46",
"9F15": "0130",
"5F2A": "0978",
"9A": "241015",
"9C": "00",
"9F37": "AABBCCDD"
}
},
"discretionary_data": {
"tags": {
"9F5D":"000400",
"DF810E": "00",
"DF810F": "00",
"DF8115": "060000000000FF"
}
},
"outcome_parameter_set": "30F0F000B8F00D00"
}
}
}
]
}
POI Config
A POI Config, in switstack's terminology is a set of files representing different layers of an EMV transaction's configuration.
Those layers are:
- The EMV configuation which holds the supported applications and their respective configurations (TLVs).
- The list of CA keys which is a list of all supported/authorized CA public keys used during card authentication.
- The list of revoked certificates which is a list of CA public keys identifiers that must not be used anymore.
EMV Config
The EMV config is a file, that holds a set of applications to be supported by a kernel with their respective configuration. The contents of the file is described just below:
{
"emvs": {
"EMV Contactless Visa 1": {
"technology_type": "CONTACTLESS",
"kernel": "03",
"aid": "A0000000031010",
"transaction_type": "00",
"asf": true,
"tlv": "E15EDF810C01039F0607A00000000310109C0100DFA0100101E2459F6604270040009F1B04000027109F820D060000000002009F820E06000000010000DFA02006000000000400DFA0140101DFA0150101DFA0160101DFA01701019F1A020840"
},
"EMV Contactless Visa 2": {
"technology_type": "CONTACTLESS",
"kernel": "03",
"aid": "A0000000032010",
"transaction_type": "00",
"asf": true,
"tlv": "E15EDF810C01039F0607A00000000310109C0100DFA0100101E2459F6604270040009F1B04000027109F820D060000000002009F820E06000000010000DFA02006000000000400DFA0140101DFA0150101DFA0160101DFA01701019F1A020840"
}
},
"emv_lists": {
"EMVList Contactless Visa 1" : {
"name": "EMVList Contactless Visa 1",
"emvs": ["EMV Contactless Visa 1", "EMV Contactless Visa 2"]
}
},
"emv_config": {
"name": "EMVConfig Contactless Visa 1",
"emv_nominal_list": "EMVList Contactless Visa 1",
"emv_failsafe_list": "EMVList Contactless Visa 1"
}
}
With:
emvs
: List of individualemv
(e.g. combinations or configurations) for a specific quadruplet (technology_type
,kernel
,aid
andtransaction_type
). Eachemv
must contain the following elements:technology_type
: EitherCONTACT
orCONTACTLESS
.kernel
: The kernel ID (see kernels specifications).aid
: The Application IDentifier.transaction_type
: The type of transaction00
for Purchase.01
for Cash.09
for Purchase with Cashback.20
for Refund.
asf
: The Application Selection Flag.tlv
: The actual TLV configuration.
emv_lists
: List ofemv_list
to group combinations together. Anemv_list
is represented as follows:name
: Name of the list.emvs
: List ofemv
.
emv_config
: The global config item. It is composed of:name
: The config name (for ex PPS_MChip_1).emv_nominal_list
: The list of combinations to use in nominal cases (e.g. most of the time).emv_failsafe_list
: The list of combinations to use in specific conditions (for ex prolongated offline mode).
CAPK List
The CAPK list is a file, that holds a list of EMV CA public keys to be used by the kernel(s) to perform card authentication. The contents of the file is described just below:
{
"capks": {
"mastercard_01": {
"rid": "A000000004",
"index": "01",
"hash_type": "UNDEFINED",
"algorithm_type": "RSA",
"modulus": "AABBCCDDEEFF...",
"exponent": "03",
"hash": "000...00",
"expires_at": "2024-12-31"
},
"mastercard_02": {
"rid": "A000000004",
"index": "02",
"hash_type": "UNDEFINED",
"algorithm_type": "RSA",
"modulus": "AABBCCDDEEFF...",
"exponent": "03",
"hash": "000...00",
"expires_at": "2024-12-31"
},
...
},
"capk_list": {
"name": "My CAPK List",
"capks": ["mastercard_01", "mastercard_02"]
}
}
With:
capks
: A list of individual CAPK objects defined by a name and the following attributes:rid
: The RID.index
: The key index.hash_type
: The key checksum/hash type (UNDEFINED
for now).algorithm_type
: The key algorithm (RSA
for now).moduls
: The key modulus.exponent
: The key exponent.hash
: The key checksum / hash.expires_at
: The key expiration date.
capk_list
: The list of CAPKs. It is composed of:name
: The list name.capks
: A list of CAPKs defined above in the document identified by their name.
CR List
The CR list is a file, that holds a list of revoked EMV CA public keys that cannot be used by the kernel(s) anymore to perform card authentication. The contents of the file is described just below:
{
"crs": {
"mastercard_01": {
"rid": "A000000004",
"index": "01",
"serial_number": "AABBCC"
},
"mastercard_02": {
"rid": "A000000004",
"index": "02",
"serial_number": "AABBCC"
},
...
},
"cr_list": {
"name": "My CR List",
"crs": ["mastercard_01", "mastercard_02"]
}
}
With:
crs
: A list of individual CR objects defined by a name and the following attributes:rid
: The RID.index
: The key index.serial_number
: The key serial number (6 hex digits).
cr_list
: The list of CRs. It is composed of:name
: The list name.crs
: A list of CRs defined above in the document identified by their name.
Virtual cards
Automated testing relies on virtual cards or, to be more exact, expected exchanges between a terminal and a card. The so called virtual cards can hold one or several transactions and for each of those transactions the full set of C-APDUs/R-APDUs expected to be exchanged between a terminal and what would be the equivalent card.
Info
Virtual card files should end up with a .vcard
extension.
Format
<poll>
00A404000E325041592E5359532E444446303100
6F59840E325041592E5359532E4444463031A547BF0C44610C4F07A0000000041010870101610C4F07A0000000043060870103610A4F05B012345678870109610C4F07B0123456781020870108610C4F07B01234567810308701079000
00A4040007A000000004101000
6F3B8407A0000000041010A530870101500A4D6173746572436172645F2D06656E646566729F1101019F38089F02069F33039C01BF0C069F5D030004009000
80A800000C830A0000000015000000080000
770A820200809404100101009000
00B2011400
70485F24034912315A0854133390000015138C0E95059F02069F34039F33039F37048E0A000000000000000000009F0D0500000000009F0E0500000000009F0F0500000000009F4A01829000
80AE40001580000000010000000015003F0000006000D04F877600
77299F2701809F360200029F2608AC123456789ABCDE9F10120110000000020000DAC000000000000000009000
<poll>
00A404000E325041592E5359532E444446303100
6F31840E325041592E5359532E4444463031A51FBF0C1C610C4F07A0000000041010870101610C4F07A00000000430608701039000
00A4040007A000000004101000
6F3B8407A0000000041010A530870101500A4D6173746572436172645F2D06656E646566729F1101019F38089F02069F33039C01BF0C069F5D030004009000
80A800000C830A0000000015000000080000
770A820200809404100101006A85
00A4040007A000000004306000
6F1BA51987010350074D61657374726F5F2D06656E646566729F1101019000
Settings
For the service to run, swittest needs a certain number of settings:
- Organization admin credentials to create/delete configuration files in switcloud.
- Machine basic user credentials as well as a POI ID to create/update/read Payment data.
- The system under test's (terminal) IP address and port to communicate with it.
These will all be passed to the CLI application through environment variable.
Please define, wherever suits you, the following variables:
ST_ORG_ADMIN_EMAIL=<the Org Admin email>
ST_ORG_ADMIN_PASSWORD=<the Org Admin password>
ST_USER_MACHINE_CLIENT_ID=<the machine user client ID>
ST_USER_MACHINE_CLIENT_SECRET=<the machine user client secret>
ST_TARGET_URL=<the target IP address> (port included, ex: 192.168.1.10:1234)
ST_SWITCLOUD_URL=<the switcloud service URL> (port included, ex: https://prod.switcloud.io:8000)
ST_POI_ID=<the POI ID>