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> 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 from robot.api import logger
import random 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 ROBOT_AUTO_KEYWORDS = False
NEOFS_ENDPOINT = "s01.neofs.devenv:8080"
CLI_PREFIX = "" CLI_PREFIX = ""
@keyword('Form WIF from String') @keyword('Form WIF from String')
@ -569,7 +574,7 @@ def generate_file_of_bytes(size):
fout.write(os.urandom(size)) fout.write(os.urandom(size))
logger.info("Random binary file with size %s bytes has been generated." % str(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') @keyword('Search object')
@ -623,10 +628,7 @@ def verify_head_tombstone(private_key: str, cid: str, oid: str):
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
raise Exception("command '{}' return with error (code {}): {}".format(e.cmd, e.returncode, e.output)) raise Exception("command '{}' return with error (code {}): {}".format(e.cmd, e.returncode, e.output))
'''
'''
@keyword('Verify linked objects') @keyword('Verify linked objects')
def verify_linked_objects(private_key: bytes, cid: str, oid: str, payload_size: float): 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) result_header['OwnerID'] = m.group(1)
else: else:
raise Exception("no OwnerID was parsed from object header: \t%s" % output) raise Exception("no OwnerID was parsed from object header: \t%s" % output)
# PayloadLength # PayloadLength
m = re.search(r'Size: (\d+)', header) m = re.search(r'Size: (\d+)', header)
if m.start() != m.end(): # e.g., if match found something 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) logger.info("Result: %s" % result_header)
return result_header return result_header
@keyword('Delete object') @keyword('Delete object')
def delete_object(private_key: str, cid: str, oid: str, bearer: str): def delete_object(private_key: str, cid: str, oid: str, bearer: str):
@ -826,35 +826,6 @@ def verify_file_hash(filename, expected_hash):
else: else:
raise Exception("File hash '{}' is not equal to {}".format(file_hash, expected_hash)) 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') @keyword('Cleanup File')
# remove temp files # remove temp files
def cleanup_file(filename: str): 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: except subprocess.CalledProcessError as e:
raise Exception("command '{}' return with error (code {}): {}".format(e.cmd, e.returncode, e.output)) raise Exception("command '{}' return with error (code {}): {}".format(e.cmd, e.returncode, e.output))
@keyword('Get object from NeoFS') @keyword('Get object from NeoFS')
def get_object(private_key: str, cid: str, oid: str, bearer_token: str, read_object: str): 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 pexpect
import re import re
import uuid import uuid
import logging
import requests
import json
import os
from robot.api.deco import keyword from robot.api.deco import keyword
from robot.api import logger from robot.api import logger
import logging
import robot.errors import robot.errors
import requests
import json
from robot.libraries.BuiltIn import BuiltIn from robot.libraries.BuiltIn import BuiltIn
ROBOT_AUTO_KEYWORDS = False 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" NEOFS_CONTRACT = "5f490fbd8010fd716754073ee960067d28549b7d"
NEOGO_CLI_PREFIX = "docker exec -it main_chain neo-go"
NEO_MAINNET_ENDPOINT = "main_chain.neofs.devenv:30333"
@keyword('Init wallet') @keyword('Init wallet')
def init_wallet(): def init_wallet():
@ -76,7 +79,6 @@ def dump_privkey(wallet: str, address: str):
return out return out
@keyword('Transfer Mainnet Gas') @keyword('Transfer Mainnet Gas')
def transfer_mainnet_gas(wallet: str, address: str, address_to: str, amount: int): 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} " 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 return tx
@keyword('Mainnet Balance') @keyword('Mainnet Balance')
def mainnet_balance(address: str): 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+'\"] }\'' 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') @keyword('Expexted Mainnet Balance')
def expected_mainnet_balance(address: str, expected: float): def expected_mainnet_balance(address: str, expected: float):
amount = mainnet_balance(address) amount = mainnet_balance(address)
if float(amount) != float(expected): if float(amount) != float(expected):
@ -139,15 +139,14 @@ def expected_mainnet_balance(address: str, expected: float):
return True return True
@keyword('NeoFS Deposit') @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} " 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}") f"deposit {scripthash} int:{amount} bytes: -- {scripthash}")
logger.info(f"Executing command: {cmd}") 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}") logger.info(f"Command completed with output: {out}")
m = re.match(r'^Sent invocation transaction (\w{64})$', 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 return tx
@keyword('Transaction accepted in block') @keyword('Transaction accepted in block')
def transaction_accepted_in_block(tx_id): 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}") logger.info(f"Executing command: {TX_request}")
complProc = subprocess.run(TX_request, check=True, universal_newlines=True, complProc = subprocess.run(TX_request, check=True, universal_newlines=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=15, shell=True) stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=15, shell=True)
logger.info(complProc.stdout) 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'] ) logger.info("Transaction has been found in the block %s." % response['result'] )
return response['result'] return response['result']
@keyword('Get Transaction') @keyword('Get Transaction')
def get_transaction(tx_id: str): 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) stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=15, shell=True)
logger.info(complProc.stdout) logger.info(complProc.stdout)
@keyword('Get Balance') @keyword('Get Balance')
def get_balance(privkey: str): def get_balance(privkey: str):
""" """
@ -232,12 +226,11 @@ def expected_balance(privkey: str, init_amount: float, deposit_size: float):
return deposit_change return deposit_change
def _get_balance_request(privkey: str): def _get_balance_request(privkey: str):
''' '''
Internal method. 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) logger.info("Cmd: %s" % Cmd)
complProc = subprocess.run(Cmd, check=True, universal_newlines=True, complProc = subprocess.run(Cmd, check=True, universal_newlines=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=150, shell=True) stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=150, shell=True)
@ -254,7 +247,6 @@ def _get_balance_request(privkey: str):
return balance return balance
def _run_sh(args): def _run_sh(args):
complProc = subprocess.run(args, check=True, universal_newlines=True, complProc = subprocess.run(args, check=True, universal_newlines=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
@ -264,7 +256,6 @@ def _run_sh(args):
return errors return errors
return output return output
def _run_sh_with_passwd(passwd, cmd): def _run_sh_with_passwd(passwd, cmd):
p = pexpect.spawn(cmd) p = pexpect.spawn(cmd)
p.expect(".*") 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') JF_TOKEN = os.getenv('JF_TOKEN')
REG_USR = os.getenv('REG_USR') REG_USR = os.getenv('REG_USR')
REG_PWD = os.getenv('REG_PWD') 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" MORPH_BLOCK_TIMEOUT = "10sec"
NEOFS_EPOCH_TIMEOUT = "30sec" 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
}
}