INFRA-236 selectel cdn smoke tests

This commit is contained in:
anastasia prasolova 2020-11-30 13:33:05 +03:00
parent 1498089c1f
commit 0c4a035e22
9 changed files with 253 additions and 148 deletions

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

@ -9,10 +9,15 @@ import hashlib
from robot.api.deco import keyword from robot.api.deco import keyword
from robot.api import logger from robot.api import logger
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')
@ -26,7 +31,7 @@ def form_wif_from_string(private_key: str):
logger.info("Output: %s" % output) logger.info("Output: %s" % output)
m = re.search(r'WIF\s+(\w+)', output) m = re.search(r'WIF\s+(\w+)', output)
if m.start() != m.end(): if m.start() != m.end():
wif = m.group(1) wif = m.group(1)
else: else:
raise Exception("Can not get WIF.") raise Exception("Can not get WIF.")
@ -46,7 +51,7 @@ def get_scripthash(privkey: str):
# ScriptHash3.0 00284fc88f8ac31f8e56c03301bfab0757e3f212 # ScriptHash3.0 00284fc88f8ac31f8e56c03301bfab0757e3f212
m = re.search(r'ScriptHash3.0 (\w+)', output) m = re.search(r'ScriptHash3.0 (\w+)', output)
if m.start() != m.end(): if m.start() != m.end():
scripthash = m.group(1) scripthash = m.group(1)
else: else:
raise Exception("Can not get ScriptHash.") raise Exception("Can not get ScriptHash.")
@ -141,7 +146,7 @@ def conver_str_to_hex(string_convert: str):
@keyword('Set custom eACL') @keyword('Set custom eACL')
def set_custom_eacl(private_key: bytes, cid: str, eacl_prefix: str, eacl_slice: str, eacl_postfix: str): def set_custom_eacl(private_key: bytes, cid: str, eacl_prefix: str, eacl_slice: str, eacl_postfix: str):
logger.info(str(eacl_prefix)) logger.info(str(eacl_prefix))
logger.info(str(eacl_slice)) logger.info(str(eacl_slice))
logger.info(str(eacl_postfix)) logger.info(str(eacl_postfix))
@ -170,9 +175,9 @@ def set_eacl(private_key: bytes, cid: str, eacl: str):
def get_range(private_key: str, cid: str, oid: str, bearer: str, range_cut: str): def get_range(private_key: str, cid: str, oid: str, bearer: str, range_cut: str):
bearer_token = "" bearer_token = ""
if bearer: if bearer:
bearer_token = f"--bearer {bearer}" bearer_token = f"--bearer {bearer}"
Cmd = f'neofs-cli --rpc-endpoint {NEOFS_ENDPOINT} --key {binascii.hexlify(private_key).decode()} object get-range --cid {cid} --oid {oid} {bearer_token} {range_cut} ' Cmd = f'neofs-cli --rpc-endpoint {NEOFS_ENDPOINT} --key {binascii.hexlify(private_key).decode()} object get-range --cid {cid} --oid {oid} {bearer_token} {range_cut} '
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,
@ -183,10 +188,10 @@ def get_range(private_key: str, cid: str, oid: str, bearer: str, range_cut: str)
@keyword('Create container') @keyword('Create container')
def create_container(private_key: str, basic_acl:str="", rule:str="REP 2 IN X CBF 1 SELECT 2 FROM * AS X"): def create_container(private_key: str, basic_acl:str="", rule:str="REP 2 IN X CBF 1 SELECT 2 FROM * AS X"):
if basic_acl != "": if basic_acl != "":
basic_acl = "--basic-acl " + basic_acl basic_acl = "--basic-acl " + basic_acl
createContainerCmd = f'neofs-cli --rpc-endpoint {NEOFS_ENDPOINT} --key {private_key} container create --policy "{rule}" {basic_acl} --await' createContainerCmd = f'neofs-cli --rpc-endpoint {NEOFS_ENDPOINT} --key {private_key} container create --policy "{rule}" {basic_acl} --await'
logger.info("Cmd: %s" % createContainerCmd) logger.info("Cmd: %s" % createContainerCmd)
complProc = subprocess.run(createContainerCmd, check=True, universal_newlines=True, complProc = subprocess.run(createContainerCmd, check=True, universal_newlines=True,
@ -210,7 +215,7 @@ def container_existing(private_key: str, cid: str):
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=15, shell=True) stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=15, shell=True)
logger.info("Output: %s" % complProc.stdout) logger.info("Output: %s" % complProc.stdout)
_find_cid(complProc.stdout, cid) _find_cid(complProc.stdout, cid)
return return
@ -230,14 +235,14 @@ 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')
def search_object(private_key: str, cid: str, keys: str, bearer: str, filters: str, *expected_objects_list ): def search_object(private_key: str, cid: str, keys: str, bearer: str, filters: str, *expected_objects_list ):
bearer_token = "" bearer_token = ""
if bearer: if bearer:
bearer_token = f"--bearer {bearer}" bearer_token = f"--bearer {bearer}"
@ -255,7 +260,7 @@ def search_object(private_key: str, cid: str, keys: str, bearer: str, filters: s
if expected_objects_list: if expected_objects_list:
found_objects = re.findall(r'(\w{43,44})', complProc.stdout) found_objects = re.findall(r'(\w{43,44})', complProc.stdout)
if sorted(found_objects) == sorted(expected_objects_list): if sorted(found_objects) == sorted(expected_objects_list):
logger.info("Found objects list '{}' is equal for expected list '{}'".format(found_objects, expected_objects_list)) logger.info("Found objects list '{}' is equal for expected list '{}'".format(found_objects, expected_objects_list))
else: else:
@ -264,7 +269,7 @@ def search_object(private_key: str, cid: str, keys: str, bearer: str, filters: s
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 Head Tombstone') @keyword('Verify Head Tombstone')
@ -281,7 +286,7 @@ def verify_head_tombstone(private_key: str, cid: str, oid: str):
logger.info("Tombstone header 'Type=Tombstone Value=MARKED' was parsed from command output") logger.info("Tombstone header 'Type=Tombstone Value=MARKED' was parsed from command output")
else: else:
raise Exception("Tombstone header 'Type=Tombstone Value=MARKED' was not found in the command output: \t%s" % (complProc.stdout)) raise Exception("Tombstone header 'Type=Tombstone Value=MARKED' was not found in the command output: \t%s" % (complProc.stdout))
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))
@ -300,20 +305,20 @@ def _exec_cli_cmd(private_key: bytes, postfix: 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))
return complProc.stdout return complProc.stdout
@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):
payload_size = int(float(payload_size)) payload_size = int(float(payload_size))
# Get linked objects from first # Get linked objects from first
postfix = f'object head --cid {cid} --oid {oid} --full-headers' postfix = f'object head --cid {cid} --oid {oid} --full-headers'
output = _exec_cli_cmd(private_key, postfix) output = _exec_cli_cmd(private_key, postfix)
child_obj_list = [] child_obj_list = []
for m in re.finditer(r'Type=Child ID=([\w-]+)', output): for m in re.finditer(r'Type=Child ID=([\w-]+)', output):
child_obj_list.append(m.group(1)) child_obj_list.append(m.group(1))
@ -324,7 +329,7 @@ def verify_linked_objects(private_key: bytes, cid: str, oid: str, payload_size:
raise Exception("Child objects was not found.") raise Exception("Child objects was not found.")
else: else:
logger.info("Child objects: %s" % child_obj_list) logger.info("Child objects: %s" % child_obj_list)
# HEAD and validate each child object: # HEAD and validate each child object:
payload = 0 payload = 0
parent_id = "00000000-0000-0000-0000-000000000000" parent_id = "00000000-0000-0000-0000-000000000000"
@ -342,7 +347,7 @@ def verify_linked_objects(private_key: bytes, cid: str, oid: str, payload_size:
if not first_obj: if not first_obj:
raise Exception("Can not find first object with zero Parent ID.") raise Exception("Can not find first object with zero Parent ID.")
else: else:
_check_linked_object(first_obj, child_obj_list_headers, payload_size, payload, parent_id) _check_linked_object(first_obj, child_obj_list_headers, payload_size, payload, parent_id)
return child_obj_list_headers.keys() return child_obj_list_headers.keys()
@ -358,11 +363,11 @@ def _check_linked_object(obj:str, child_obj_list_headers:dict, payload_size:int,
logger.info("Previous ID is equal for expected: %s" % parent_id) logger.info("Previous ID is equal for expected: %s" % parent_id)
m = re.search(r'PayloadLength=(\d+)', output) m = re.search(r'PayloadLength=(\d+)', output)
if m.start() != m.end(): if m.start() != m.end():
payload += int(m.group(1)) payload += int(m.group(1))
else: else:
raise Exception("Can not get payload for the object %s." % obj) raise Exception("Can not get payload for the object %s." % obj)
if payload > payload_size: if payload > payload_size:
raise Exception("Payload exceeds expected total payload %s." % payload_size) raise Exception("Payload exceeds expected total payload %s." % payload_size)
@ -371,10 +376,10 @@ def _check_linked_object(obj:str, child_obj_list_headers:dict, payload_size:int,
raise Exception("Incorrect previos ID in the last child object %s." % obj) raise Exception("Incorrect previos ID in the last child object %s." % obj)
else: else:
logger.info("Next ID is correct for the final child object: %s" % obj) logger.info("Next ID is correct for the final child object: %s" % obj)
else: else:
m = re.search(r'Type=Next ID=([\w-]+)', output) m = re.search(r'Type=Next ID=([\w-]+)', output)
if m: if m:
# next object should be in the expected list # next object should be in the expected list
logger.info(m.group(1)) logger.info(m.group(1))
if m.group(1) not in child_obj_list_headers.keys(): if m.group(1) not in child_obj_list_headers.keys():
@ -409,13 +414,13 @@ def head_object(private_key: str, cid: str, oid: str, bearer: str, user_headers:
logger.info("User header %s was parsed from command output" % key) logger.info("User header %s was parsed from command output" % key)
else: else:
raise Exception("User header %s was not found in the command output: \t%s" % (key, complProc.stdout)) raise Exception("User header %s was not found in the command output: \t%s" % (key, complProc.stdout))
return complProc.stdout return complProc.stdout
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('Parse Object System Header') @keyword('Parse Object System Header')
@ -444,7 +449,7 @@ 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)
# Version # Version
m = re.search(r'- Version=(\d+)', header) m = re.search(r'- Version=(\d+)', header)
if m.start() != m.end(): # e.g., if match found something if m.start() != m.end(): # e.g., if match found something
@ -461,7 +466,7 @@ def parse_object_system_header(header: str):
raise Exception("no PayloadLength was parsed from object header: \t%s" % output) raise Exception("no PayloadLength was parsed from object header: \t%s" % output)
# CreatedAtUnixTime # CreatedAtUnixTime
m = re.search(r'- CreatedAt={UnixTime=(\d+)', header) m = re.search(r'- CreatedAt={UnixTime=(\d+)', header)
if m.start() != m.end(): # e.g., if match found something if m.start() != m.end(): # e.g., if match found something
@ -479,26 +484,26 @@ 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('Parse Object Extended Header') @keyword('Parse Object Extended Header')
def parse_object_extended_header(header: str): def parse_object_extended_header(header: str):
result_header = dict() result_header = dict()
pattern = re.compile(r'- Type=(\w+)\n.+Value=(.+)\n') pattern = re.compile(r'- Type=(\w+)\n.+Value=(.+)\n')
for (f_type, f_val) in re.findall(pattern, header): for (f_type, f_val) in re.findall(pattern, header):
logger.info("found: %s - %s" % (f_type, f_val)) logger.info("found: %s - %s" % (f_type, f_val))
if f_type not in result_header.keys(): if f_type not in result_header.keys():
result_header[f_type] = [] result_header[f_type] = []
result_header[f_type].append(f_val) result_header[f_type].append(f_val)
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):
@ -513,7 +518,7 @@ def delete_object(private_key: str, cid: str, oid: str, bearer: str):
stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=15, shell=True) stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=15, shell=True)
logger.info("Output: %s" % complProc.stdout) logger.info("Output: %s" % complProc.stdout)
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 file hash') @keyword('Get file hash')
@ -556,7 +561,7 @@ def get_storage_group(private_key: bytes, cid: str, sgid: str):
logger.info("Output: %s" % complProc.stdout) logger.info("Output: %s" % complProc.stdout)
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('Cleanup File') @keyword('Cleanup File')
# remove temp files # remove temp files
@ -564,11 +569,11 @@ def cleanup_file(filename: str):
if os.path.isfile(filename): if os.path.isfile(filename):
try: try:
os.remove(filename) os.remove(filename)
except OSError as e: except OSError as e:
raise Exception("Error: '%s' - %s." % (e.filename, e.strerror)) raise Exception("Error: '%s' - %s." % (e.filename, e.strerror))
else: else:
raise Exception("Error: '%s' file not found" % filename) raise Exception("Error: '%s' file not found" % filename)
logger.info("File '%s' has been deleted." % filename) logger.info("File '%s' has been deleted." % filename)
@ -593,10 +598,10 @@ def put_object(private_key: str, path: str, cid: str, bearer: str, user_headers:
@keyword('Get Range Hash') @keyword('Get Range Hash')
def get_range_hash(private_key: str, cid: str, oid: str, bearer_token: str, range_cut: str): def get_range_hash(private_key: str, cid: str, oid: str, bearer_token: str, range_cut: str):
if bearer_token: if bearer_token:
bearer_token = f"--bearer {bearer}" bearer_token = f"--bearer {bearer}"
ObjectCmd = f'neofs-cli --rpc-endpoint {NEOFS_ENDPOINT} --key {private_key} object hash --cid {cid} --oid {oid} --range {range_cut} {bearer_token}' ObjectCmd = f'neofs-cli --rpc-endpoint {NEOFS_ENDPOINT} --key {private_key} object hash --cid {cid} --oid {oid} --range {range_cut} {bearer_token}'
logger.info("Cmd: %s" % ObjectCmd) logger.info("Cmd: %s" % ObjectCmd)
@ -607,7 +612,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):
@ -659,7 +663,7 @@ def _parse_oid(output: str):
oid = m.group(1) oid = m.group(1)
else: else:
raise Exception("no OID was parsed from command output: \t%s" % output) raise Exception("no OID was parsed from command output: \t%s" % output)
return oid return oid
def _parse_cid(output: str): def _parse_cid(output: str):
@ -672,7 +676,7 @@ def _parse_cid(output: str):
if not m.start() != m.end(): # e.g., if match found something if not m.start() != m.end(): # e.g., if match found something
raise Exception("no CID was parsed from command output: \t%s" % (output)) raise Exception("no CID was parsed from command output: \t%s" % (output))
cid = m.group(1) cid = m.group(1)
return cid return cid
def _get_storage_nodes(private_key: bytes): def _get_storage_nodes(private_key: bytes):
@ -684,7 +688,7 @@ def _get_storage_nodes(private_key: bytes):
#logger.info("Netmap: %s" % output) #logger.info("Netmap: %s" % output)
#for m in re.finditer(r'"address":"/ip4/(\d+\.\d+\.\d+\.\d+)/tcp/(\d+)"', output): #for m in re.finditer(r'"address":"/ip4/(\d+\.\d+\.\d+\.\d+)/tcp/(\d+)"', output):
# storage_nodes.append(m.group(1)+":"+m.group(2)) # storage_nodes.append(m.group(1)+":"+m.group(2))
#if not storage_nodes: #if not storage_nodes:
# raise Exception("Storage nodes was not found.") # raise Exception("Storage nodes was not found.")
@ -718,4 +722,4 @@ def _search_object(node:str, private_key: str, cid:str, oid: str):
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))

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,15 +4,14 @@ 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
from neocore.KeyPair import KeyPair from neocore.KeyPair import KeyPair
@ -20,11 +19,15 @@ from Crypto import Random
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():
@ -33,7 +36,7 @@ def init_wallet():
cmd = ( f"{NEOGO_CLI_PREFIX} wallet init -w {filename}" ) cmd = ( f"{NEOGO_CLI_PREFIX} wallet init -w {filename}" )
logger.info(f"Executing shell command: {cmd}") logger.info(f"Executing shell command: {cmd}")
out = run_sh(cmd) out = run_sh(cmd)
logger.info(f"Command completed with output: {out}") logger.info(f"Command completed with output: {out}")
return filename return filename
@ -59,11 +62,11 @@ def dump_address(wallet: str):
cmd = ( f"{NEOGO_CLI_PREFIX} wallet dump -w {wallet}" ) cmd = ( f"{NEOGO_CLI_PREFIX} wallet dump -w {wallet}" )
logger.info(f"Executing command: {cmd}") logger.info(f"Executing command: {cmd}")
out = run_sh(cmd) out = run_sh(cmd)
logger.info(f"Command completed with output: {out}") logger.info(f"Command completed with output: {out}")
m = re.search(r'"address": "(\w+)"', out) m = re.search(r'"address": "(\w+)"', out)
if m.start() != m.end(): if m.start() != m.end():
address = m.group(1) address = m.group(1)
else: else:
raise Exception("Can not get address.") raise Exception("Can not get address.")
@ -80,10 +83,7 @@ def dump_privkey(wallet: str, address: str):
return out return out
@keyword('Transfer Mainnet Gas')
@keyword('Transfer Mainnet Gas')
# docker cp wallets/wallet.json main_chain:/wallets/
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} "
f"--to {address_to} --token gas --amount {amount}" ) f"--to {address_to} --token gas --amount {amount}" )
@ -97,9 +97,7 @@ def transfer_mainnet_gas(wallet: str, address: str, address_to: str, amount: int
return out return out
@keyword('Withdraw Mainnet Gas') @keyword('Withdraw Mainnet Gas')
# docker cp wallets/wallet.json main_chain:/wallets/
def withdraw_mainnet_gas(wallet: str, address: str, scripthash: str, amount: int): def withdraw_mainnet_gas(wallet: str, address: str, scripthash: str, amount: int):
cmd = ( f"{NEOGO_CLI_PREFIX} contract invokefunction -w {wallet} -a {address} -r http://main_chain.neofs.devenv:30333 " cmd = ( f"{NEOGO_CLI_PREFIX} contract invokefunction -w {wallet} -a {address} -r http://main_chain.neofs.devenv:30333 "
f"{NEOFS_CONTRACT} withdraw {scripthash} int:{amount} -- {scripthash}" ) f"{NEOFS_CONTRACT} withdraw {scripthash} int:{amount} -- {scripthash}" )
@ -113,10 +111,6 @@ def withdraw_mainnet_gas(wallet: str, address: str, scripthash: str, amount: int
return out return out
# neo-go contract invokefunction -w wallets/deploy_wallet.json -a NTrezR3C4X8aMLVg7vozt5wguyNfFhwuFx -r http://main_chain.neofs.devenv:30333
# 5f490fbd8010fd716754073ee960067d28549b7d withdraw 12b97a2206ae4b10c7e0194b7b655c32cc912057 int:10 -- 12b97a2206ae4b10c7e0194b7b655c32cc912057
@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+'\"] }\''
@ -129,37 +123,31 @@ def mainnet_balance(address: str):
logger.info(out) logger.info(out)
m = re.search(r'"668e0c1f9d7b70a99dd9e06eadd4c784d641afbc","amount":"([\d\.]+)"', out) m = re.search(r'"668e0c1f9d7b70a99dd9e06eadd4c784d641afbc","amount":"([\d\.]+)"', out)
if not m.start() != m.end(): if not m.start() != m.end():
raise Exception("Can not get mainnet gas balance.") raise Exception("Can not get mainnet gas balance.")
amount = m.group(1) amount = m.group(1)
return amount return amount
@keyword('Expexted Mainnet Balance') @keyword('Expexted Mainnet Balance')
def expected_mainnet_balance(address: str, expected: int): def expected_mainnet_balance(address: str, expected: int):
amount = mainnet_balance(address) amount = mainnet_balance(address)
if float(amount) != float(expected): if float(amount) != float(expected):
raise Exception(f"Expected amount ({expected}) of GAS has not been found. Found {amount}.") raise Exception(f"Expected amount ({expected}) of GAS has not been found. Found {amount}.")
return True return True
# balance":[{"assethash":"668e0c1f9d7b70a99dd9e06eadd4c784d641afbc","amount":"50"
#curl -d '{ "jsonrpc": "2.0", "id": 1, "method": "getnep5balances", "params": ["NTrezR3C4X8aMLVg7vozt5wguyNfFhwuFx"] }' main_chain.neofs.devenv:30333
#{"id":1,"jsonrpc":"2.0","result":{"balance":[{"assethash":"668e0c1f9d7b70a99dd9e06eadd4c784d641afbc","amount":"9237.47595500","lastupdatedblock":158}],"address":"NTrezR3C4X8aMLVg7vozt5wguyNfFhwuFx"}}
@keyword('NeoFS Deposit')
def neofs_deposit(wallet: str, address: str, scripthash: str, amount: int, wallet_pass:str=''):
@keyword('NeoFS Deposit')
def neofs_deposit(wallet: str, address: str, scripthash: str, amount: int):
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)
@ -172,32 +160,6 @@ def neofs_deposit(wallet: str, address: str, scripthash: str, amount: int):
return tx return tx
#docker exec -it main_chain \
# neo-go contract invokefunction \
# -w wallets/wallet.json \
# -a NTrezR3C4X8aMLVg7vozt5wguyNfFhwuFx \
# -r http://main_chain.${LOCAL_DOMAIN}:30333 \
# ${NEOFS_CONTRACT_MAINCHAIN} \
# deposit \
# 12b97a2206ae4b10c7e0194b7b655c32cc912057 \
# int:500 \
# bytes: \
# -- 12b97a2206ae4b10c7e0194b7b655c32cc912057
#neo-go contract invokefunction -w wallets/wallet.json -a NTrezR3C4X8aMLVg7vozt5wguyNfFhwuFx
#-r <http://main_chain.neofs.devenv:30333> af5dc5f7e6a6efc64d679098f328027591a2e518
#deposit 12b97a2206ae4b10c7e0194b7b655c32cc912057 int:60 bytes: --
#12b97a2206ae4b10c7e0194b7b655c32cc912057
# wallet nep5 transfer -w wallets/wallet.json -r http://main_chain.neofs.devenv:30333 --from NTrezR3C4X8aMLVg7vozt5wguyNfFhwuFx
# --to NULwe3UAHckN2fzNdcVg31tDiaYtMDwANt --token gas --amount 50
@keyword('Transaction accepted in block') @keyword('Transaction accepted in block')
def transaction_accepted_in_block(tx_id): def transaction_accepted_in_block(tx_id):
""" """
@ -208,14 +170,10 @@ def transaction_accepted_in_block(tx_id):
""" """
logger.info("Transaction id: %s" % tx_id) logger.info("Transaction id: %s" % tx_id)
# curl -d '{ "jsonrpc": "2.0", "id": 1, "method": "getnep5transfers", "params": ["NULwe3UAHckN2fzNdcVg31tDiaYtMDwANt"] }' main_chain.neofs.devenv:30333
TX_request = 'curl -X POST '+NEO_MAINNET_ENDPOINT+' --cacert ca/nspcc-ca.pem -H \'Content-Type: application/json\' -d \'{ "jsonrpc": "2.0", "id": 5, "method": "gettransactionheight", "params": [\"'+ tx_id +'\"] }\'' TX_request = 'curl -X POST '+NEO_MAINNET_ENDPOINT+' --cacert ca/nspcc-ca.pem -H \'Content-Type: application/json\' -d \'{ "jsonrpc": "2.0", "id": 5, "method": "gettransactionheight", "params": [\"'+ 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)
@ -227,7 +185,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):
@ -241,15 +198,6 @@ def get_transaction(tx_id: str):
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)
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,
@ -301,13 +249,6 @@ def run_sh_with_passwd(passwd, cmd):
logger.info("Output: %s" % output) logger.info("Output: %s" % output)
#from subprocess import Popen, PIPE
#p = Popen(['python test_enter.py'], stdin=PIPE, shell=True)
#p.communicate(input='\n')
@keyword('Request NeoFS Deposit') @keyword('Request NeoFS Deposit')
def request_neofs_deposit(public_key: str): def request_neofs_deposit(public_key: str):
""" """
@ -315,8 +256,8 @@ def request_neofs_deposit(public_key: str):
:param public_key: neo public key :param public_key: neo public key
""" """
response = requests.get('https://fs.localtest.nspcc.ru/api/deposit/'+str(public_key), verify='ca/nspcc-ca.pem') response = requests.get('https://fs.localtest.nspcc.ru/api/deposit/'+str(public_key), verify='ca/nspcc-ca.pem')
if response.status_code != 200: if response.status_code != 200:
BuiltIn().fatal_error('Can not run Deposit to {} with error: {}'.format(public_key, response.text)) BuiltIn().fatal_error('Can not run Deposit to {} with error: {}'.format(public_key, response.text))
else: else:
@ -354,19 +295,18 @@ 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)
output = complProc.stdout output = complProc.stdout
logger.info("Output: %s" % output) logger.info("Output: %s" % output)
m = re.match(r'(-?[\d.\.?\d*]+)', output ) m = re.match(r'(-?[\d.\.?\d*]+)', output )
if m is None: if m is None:
BuiltIn().fatal_error('Can not parse balance: "%s"' % output) BuiltIn().fatal_error('Can not parse balance: "%s"' % output)
@ -375,12 +315,3 @@ def _get_balance_request(privkey: str):
logger.info("Balance for '%s' is '%s'" % (privkey, balance) ) logger.info("Balance for '%s' is '%s'" % (privkey, balance) )
return balance return balance
# {"id":5,"jsonrpc":"2.0","result":{"txid":"0x02c178803258a9dbbcce80acfece2f6abb4f51c122e7ce2ddcad332d6a810e5f","trigger":"Application",
# !!!!!!!!!!!
#"vmstate":"FAULT"
# !!!!!!!!!!!
#,"gasconsumed":"11328110","stack":[],"notifications":[]}}

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

@ -9,11 +9,9 @@ CERT="%s/../../ca" % ROOT
# in case when test is run from root in docker # in case when test is run from root in docker
ABSOLUTE_FILE_PATH="/robot/testsuites/integration" 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
}
}