Merged in feature/INFRA-236 (pull request #8)

selectel cdn smoke tests

Approved-by: Anatoly Bogatyrev <anatoly@nspcc.ru>
This commit is contained in:
Anastasia Prasolova 2020-11-30 13:40:54 +00:00 committed by Anatoly Bogatyrev
commit 84310cbd8e
10 changed files with 309 additions and 163 deletions

View file

@ -54,6 +54,21 @@
export BUILD_NEOFS_NODE=<commit or branch>
```
### Запуск smoke-тестов
Есть сьют со smoke-тестами для CDN-гейтов `robot/testsuites/smoke/selectelcdn_smoke.robot`.
Ему требуются отдельные переменные, в отличие от сьютов NeoFS, которые запускаются на
девэнве. Чтобы библиотеки кейвордов их использовали, нужно установить переменную
окружения
```
export ROBOT_PROFILE=selectel_smoke
```
По умолчанию кейворды используют переменные из файла `robot/resources/lib/neofs_int_vars.py`.
```
robot --outputdir artifacts/ robot/testsuites/smoke/selectelcdn_smoke.robot
```
### Генерация документации
Для генерации документации по шагам:

View file

@ -0,0 +1,41 @@
#!/usr/bin/python3
import logging
import os
import requests
from robot.api.deco import keyword
from robot.api import logger
import robot.errors
from robot.libraries.BuiltIn import BuiltIn
ROBOT_AUTO_KEYWORDS = False
if os.getenv('ROBOT_PROFILE') == 'selectel_smoke':
from selectelcdn_smoke_vars import (NEOGO_CLI_PREFIX, NEO_MAINNET_ENDPOINT,
NEOFS_NEO_API_ENDPOINT, NEOFS_ENDPOINT, HTTP_GATE)
else:
from neofs_int_vars import (NEOGO_CLI_PREFIX, NEO_MAINNET_ENDPOINT,
NEOFS_NEO_API_ENDPOINT, NEOFS_ENDPOINT, HTTP_GATE)
@keyword('Get via HTTP Gate')
def get_via_http_gate(cid: str, oid: str):
"""
This function gets given object from HTTP gate
:param cid: CID to get object from
:param oid: object OID
"""
resp = requests.get(f'{HTTP_GATE}/get/{cid}/{oid}')
if not resp.ok:
logger.info(f"""Failed to get object via HTTP gate:
request: {resp.request.path_url},
response: {resp.text},
status code: {resp.status_code} {resp.reason}""")
return
filename = os.path.curdir + f"/{cid}_{oid}"
with open(filename, "w+") as f:
f.write(resp.text)
return filename

View file

@ -10,10 +10,15 @@ from robot.api.deco import keyword
from robot.api import logger
import random
if os.getenv('ROBOT_PROFILE') == 'selectel_smoke':
from selectelcdn_smoke_vars import (NEOGO_CLI_PREFIX, NEO_MAINNET_ENDPOINT,
NEOFS_NEO_API_ENDPOINT, NEOFS_ENDPOINT)
else:
from neofs_int_vars import (NEOGO_CLI_PREFIX, NEO_MAINNET_ENDPOINT,
NEOFS_NEO_API_ENDPOINT, NEOFS_ENDPOINT)
ROBOT_AUTO_KEYWORDS = False
NEOFS_ENDPOINT = "s01.neofs.devenv:8080"
CLI_PREFIX = ""
@keyword('Form WIF from String')
@ -569,7 +574,7 @@ def generate_file_of_bytes(size):
fout.write(os.urandom(size))
logger.info("Random binary file with size %s bytes has been generated." % str(size))
return filename
return os.path.abspath(os.getcwd()) + '/' + filename
@keyword('Search object')
@ -623,10 +628,7 @@ def verify_head_tombstone(private_key: str, cid: str, oid: str):
except subprocess.CalledProcessError as e:
raise Exception("command '{}' return with error (code {}): {}".format(e.cmd, e.returncode, e.output))
'''
'''
@keyword('Verify linked objects')
def verify_linked_objects(private_key: bytes, cid: str, oid: str, payload_size: float):
@ -770,7 +772,6 @@ def parse_object_system_header(header: str):
result_header['OwnerID'] = m.group(1)
else:
raise Exception("no OwnerID was parsed from object header: \t%s" % output)
# PayloadLength
m = re.search(r'Size: (\d+)', header)
if m.start() != m.end(): # e.g., if match found something
@ -795,7 +796,6 @@ def parse_object_system_header(header: str):
logger.info("Result: %s" % result_header)
return result_header
@keyword('Delete object')
def delete_object(private_key: str, cid: str, oid: str, bearer: str):
@ -826,35 +826,6 @@ def verify_file_hash(filename, expected_hash):
else:
raise Exception("File hash '{}' is not equal to {}".format(file_hash, expected_hash))
'''
@keyword('Create storage group')
def create_storage_group(private_key: bytes, cid: str, *objects_list):
objects = ""
for oid in objects_list:
objects = f'{objects} --oid {oid}'
ObjectCmd = f'{CLI_PREFIX}neofs-cli --host {NEOFS_ENDPOINT} --key {binascii.hexlify(private_key).decode()} sg put --cid {cid} {objects}'
complProc = subprocess.run(ObjectCmd, check=True, universal_newlines=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=15, shell=True)
logger.info("Output: %s" % complProc.stdout)
sgid = _parse_oid(complProc.stdout)
return sgid
@keyword('Get storage group')
def get_storage_group(private_key: bytes, cid: str, sgid: str):
ObjectCmd = f'{CLI_PREFIX}neofs-cli --host {NEOFS_ENDPOINT} --key {binascii.hexlify(private_key).decode()} sg get --cid {cid} --sgid {sgid}'
logger.info("Cmd: %s" % ObjectCmd)
try:
complProc = subprocess.run(ObjectCmd, check=True, universal_newlines=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=15, shell=True)
logger.info("Output: %s" % complProc.stdout)
except subprocess.CalledProcessError as e:
raise Exception("command '{}' return with error (code {}): {}".format(e.cmd, e.returncode, e.output))
'''
@keyword('Cleanup File')
# remove temp files
def cleanup_file(filename: str):
@ -909,7 +880,6 @@ def get_range_hash(private_key: str, cid: str, oid: str, bearer_token: str, rang
except subprocess.CalledProcessError as e:
raise Exception("command '{}' return with error (code {}): {}".format(e.cmd, e.returncode, e.output))
@keyword('Get object from NeoFS')
def get_object(private_key: str, cid: str, oid: str, bearer_token: str, read_object: str):

View file

@ -0,0 +1,9 @@
#!/usr/bin/python3
import os
NEOFS_ENDPOINT = "s01.neofs.devenv:8080"
NEOGO_CLI_PREFIX = "docker exec -it main_chain neo-go"
NEO_MAINNET_ENDPOINT = "main_chain.neofs.devenv:30333"
NEOFS_NEO_API_ENDPOINT = 'http://main_chain.neofs.devenv:30333'
HTTP_GATE = ''

View file

@ -4,24 +4,27 @@ import subprocess
import pexpect
import re
import uuid
import logging
import requests
import json
import os
from robot.api.deco import keyword
from robot.api import logger
import logging
import robot.errors
import requests
import json
from robot.libraries.BuiltIn import BuiltIn
ROBOT_AUTO_KEYWORDS = False
if os.getenv('ROBOT_PROFILE') == 'selectel_smoke':
from selectelcdn_smoke_vars import (NEOGO_CLI_PREFIX, NEO_MAINNET_ENDPOINT,
NEOFS_NEO_API_ENDPOINT, NEOFS_ENDPOINT)
else:
from neofs_int_vars import (NEOGO_CLI_PREFIX, NEO_MAINNET_ENDPOINT,
NEOFS_NEO_API_ENDPOINT, NEOFS_ENDPOINT)
NEOFS_CONTRACT = "5f490fbd8010fd716754073ee960067d28549b7d"
NEOGO_CLI_PREFIX = "docker exec -it main_chain neo-go"
NEO_MAINNET_ENDPOINT = "main_chain.neofs.devenv:30333"
@keyword('Init wallet')
def init_wallet():
@ -76,7 +79,6 @@ def dump_privkey(wallet: str, address: str):
return out
@keyword('Transfer Mainnet Gas')
def transfer_mainnet_gas(wallet: str, address: str, address_to: str, amount: int):
cmd = ( f"{NEOGO_CLI_PREFIX} wallet nep5 transfer -w {wallet} -r http://main_chain.neofs.devenv:30333 --from {address} "
@ -108,7 +110,6 @@ def withdraw_mainnet_gas(wallet: str, address: str, scripthash: str, amount: int
return tx
@keyword('Mainnet Balance')
def mainnet_balance(address: str):
request = 'curl -X POST '+NEO_MAINNET_ENDPOINT+' --cacert ca/nspcc-ca.pem -H \'Content-Type: application/json\' -d \'{ "jsonrpc": "2.0", "id": 5, "method": "getnep5balances", "params": [\"'+address+'\"] }\''
@ -131,7 +132,6 @@ def mainnet_balance(address: str):
@keyword('Expexted Mainnet Balance')
def expected_mainnet_balance(address: str, expected: float):
amount = mainnet_balance(address)
if float(amount) != float(expected):
@ -139,15 +139,14 @@ def expected_mainnet_balance(address: str, expected: float):
return True
@keyword('NeoFS Deposit')
def neofs_deposit(wallet: str, address: str, scripthash: str, amount: int):
def neofs_deposit(wallet: str, address: str, scripthash: str, amount: int, wallet_pass:str=''):
cmd = ( f"{NEOGO_CLI_PREFIX} contract invokefunction -w {wallet} -a {address} "
f"-r http://main_chain.neofs.devenv:30333 {NEOFS_CONTRACT} "
f"-r {NEOFS_NEO_API_ENDPOINT} {NEOFS_CONTRACT} "
f"deposit {scripthash} int:{amount} bytes: -- {scripthash}")
logger.info(f"Executing command: {cmd}")
out = _run_sh_with_passwd('', cmd)
out = _run_sh_with_passwd(wallet_pass, cmd)
logger.info(f"Command completed with output: {out}")
m = re.match(r'^Sent invocation transaction (\w{64})$', out)
@ -158,7 +157,6 @@ def neofs_deposit(wallet: str, address: str, scripthash: str, amount: int):
return tx
@keyword('Transaction accepted in block')
def transaction_accepted_in_block(tx_id):
"""
@ -174,7 +172,6 @@ def transaction_accepted_in_block(tx_id):
logger.info(f"Executing command: {TX_request}")
complProc = subprocess.run(TX_request, check=True, universal_newlines=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=15, shell=True)
logger.info(complProc.stdout)
@ -186,7 +183,6 @@ def transaction_accepted_in_block(tx_id):
logger.info("Transaction has been found in the block %s." % response['result'] )
return response['result']
@keyword('Get Transaction')
def get_transaction(tx_id: str):
"""
@ -200,8 +196,6 @@ def get_transaction(tx_id: str):
stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=15, shell=True)
logger.info(complProc.stdout)
@keyword('Get Balance')
def get_balance(privkey: str):
"""
@ -232,12 +226,11 @@ def expected_balance(privkey: str, init_amount: float, deposit_size: float):
return deposit_change
def _get_balance_request(privkey: str):
'''
Internal method.
'''
Cmd = f'neofs-cli --key {privkey} --rpc-endpoint s01.neofs.devenv:8080 accounting balance'
Cmd = f'neofs-cli --key {privkey} --rpc-endpoint {NEOFS_ENDPOINT} accounting balance'
logger.info("Cmd: %s" % Cmd)
complProc = subprocess.run(Cmd, check=True, universal_newlines=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=150, shell=True)
@ -254,7 +247,6 @@ def _get_balance_request(privkey: str):
return balance
def _run_sh(args):
complProc = subprocess.run(args, check=True, universal_newlines=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
@ -264,7 +256,6 @@ def _run_sh(args):
return errors
return output
def _run_sh_with_passwd(passwd, cmd):
p = pexpect.spawn(cmd)
p.expect(".*")

View file

@ -0,0 +1,9 @@
#!/usr/bin/python3
NEOFS_ENDPOINT = "92.53.71.51:18080"
NEOGO_CLI_PREFIX = "neo-go"
NEO_MAINNET_ENDPOINT = "http://92.53.71.51:20332"
# selectel main chain on lobachevsky-1
NEOFS_NEO_API_ENDPOINT = "http://92.53.71.51:20332"
HTTP_GATE = 'http://92.53.71.51:38080'

View file

@ -0,0 +1,33 @@
# -*- coding: robot -*-
*** Settings ***
Variables ../../variables/common.py
Variables ../../variables/selectelcdn_smoke.py
Library ${RESOURCES}/neofs.py
Library ${RESOURCES}/payment_neogo.py
Library ${RESOURCES}/gates.py
*** Test cases ***
NeoFS Storage Smoke
[Documentation] Creates container and does PUT, GET and LIST on it via CLI and via HTTP Gate
[Timeout] 5 min
${TX_DEPOSIT} = NeoFS Deposit ${WALLET} ${ADDR} ${SCRIPT_HASH} 50 one
Wait Until Keyword Succeeds 1 min 15 sec
... Transaction accepted in block ${TX_DEPOSIT}
Get Transaction ${TX_DEPOSIT}
${CID} = Create container ${PRIV_KEY} public
Wait Until Keyword Succeeds 2 min 30 sec
... Container Existing ${PRIV_KEY} ${CID}
${FILE} = Generate file of bytes 1024
${S_OID} = Put object to NeoFS ${PRIV_KEY} ${FILE} ${CID} ${EMPTY} ${EMPTY}
Get object from NeoFS ${PRIV_KEY} ${CID} ${S_OID} ${EMPTY} s_file_read
${FILEPATH} = Get via HTTP Gate ${CID} ${S_OID}

View file

@ -12,8 +12,6 @@ ABSOLUTE_FILE_PATH="/robot/testsuites/integration"
JF_TOKEN = os.getenv('JF_TOKEN')
REG_USR = os.getenv('REG_USR')
REG_PWD = os.getenv('REG_PWD')
NEOFS_ENDPOINT = "s01.fs.localtest.nspcc.ru:8080"
NEOFS_NEO_API_ENDPOINT = "https://fs.localtest.nspcc.ru/neo_rpc/"
MORPH_BLOCK_TIMEOUT = "10sec"
NEOFS_EPOCH_TIMEOUT = "30sec"

View file

@ -0,0 +1,8 @@
#!/usr/bin/python3
# wallet that has assets in selectel mainnet
WALLET = 'wallets/selectel_mainnet_wallet.json'
# address from this wallet anf its representations
ADDR = 'NbTiM6h8r99kpRtb428XcsUk1TzKed2gTc'
SCRIPT_HASH = 'eb88a496178256213f674eb302e44f9d85cf8aaa'
PRIV_KEY = 'KxyjQ8eUa4FHt3Gvioyt1Wz29cTUrE4eTqX3yFSk1YFCsPL8uNsY'

View file

@ -0,0 +1,72 @@
{
"version": "3.0",
"accounts": [
{
"address": "NbTiM6h8r99kpRtb428XcsUk1TzKed2gTc",
"key": "6PYN7LvaWqBNw7Xb7a52LSbPnP91kyuzYi3HncGvQwQoYAY2W8DncTgpux",
"label": "",
"contract": {
"script": "DCECs2Ir9AF73+MXxYrtX0x1PyBrfbiWBG+n13S7xL9/jcILQZVEDXg=",
"parameters": [
{
"name": "parameter0",
"type": "Signature"
}
],
"deployed": false
},
"lock": false,
"isdefault": false
},
{
"address": "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY",
"key": "6PYN7LvaWqBNw7Xb7a52LSbPnP91kyuzYi3HncGvQwQoYAY2W8DncTgpux",
"label": "",
"contract": {
"script": "EwwhAhA6f33QFlWFl/eWDSfFFqQ5T9loueZRVetLAT5AQEBuDCECp7xV/oaE4BGXaNEEujB5W9zIZhnoZK3SYVZyPtGFzWIMIQKzYiv0AXvf4xfFiu1fTHU/IGt9uJYEb6fXdLvEv3+NwgwhA9kMB99j5pDOd5EuEKtRrMlEtmhgI3tgjE+PgwnnHuaZFAtBE43vrw==",
"parameters": [
{
"name": "parameter0",
"type": "Signature"
},
{
"name": "parameter1",
"type": "Signature"
},
{
"name": "parameter2",
"type": "Signature"
}
],
"deployed": false
},
"lock": false,
"isdefault": false
},
{
"address": "NVNvVRW5Q5naSx2k2iZm7xRgtRNGuZppAK",
"key": "6PYN7LvaWqBNw7Xb7a52LSbPnP91kyuzYi3HncGvQwQoYAY2W8DncTgpux",
"label": "",
"contract": {
"script": "EQwhArNiK/QBe9/jF8WK7V9MdT8ga324lgRvp9d0u8S/f43CEQtBE43vrw==",
"parameters": [
{
"name": "parameter0",
"type": "Signature"
}
],
"deployed": false
},
"lock": false,
"isdefault": false
}
],
"scrypt": {
"n": 16384,
"r": 8,
"p": 8
},
"extra": {
"Tokens": null
}
}