Browse Source

update: enhance test process

master
dnomd343 2 years ago
parent
commit
f5f4745e71
  1. 4
      Basis/Functions.py
  2. 4
      Basis/Logger.py
  3. 88
      Tester/Shadowsocks.py
  4. 45
      test.py

4
Basis/Functions.py

@ -19,7 +19,7 @@ def genFlag(length: int = 12) -> str: # generate random task flag
return flag return flag
def getAvailablePort(rangeStart: int = 41952, rangeEnd: int = 65535) -> int: # get a available port def getAvailablePort(rangeStart: int = 1024, rangeEnd: int = 65535, waitTime: int = 10) -> int: # get available port
if rangeStart > rangeEnd or rangeStart < 1 or rangeEnd > 65535: if rangeStart > rangeEnd or rangeStart < 1 or rangeEnd > 65535:
raise RuntimeError('invalid port range') raise RuntimeError('invalid port range')
while True: while True:
@ -27,7 +27,7 @@ def getAvailablePort(rangeStart: int = 41952, rangeEnd: int = 65535) -> int: #
if checkPortStatus(port): if checkPortStatus(port):
logging.debug('get new port -> %i' % port) logging.debug('get new port -> %i' % port)
return port return port
time.sleep(0.1) # wait for 100ms time.sleep(waitTime / 1000) # ms -> s (default 10ms)
def checkPortStatus(port: int) -> bool: # check if the port is occupied def checkPortStatus(port: int) -> bool: # check if the port is occupied

4
Basis/Logger.py

@ -6,8 +6,8 @@ import logging
from colorlog import ColoredFormatter from colorlog import ColoredFormatter
logFile = 'runtime.log' logFile = 'runtime.log'
logLevel = logging.DEBUG # logLevel = logging.DEBUG
# logLevel = logging.WARNING logLevel = logging.WARNING
dateFormat = '%Y-%m-%d %H:%M:%S' dateFormat = '%Y-%m-%d %H:%M:%S'
logFormat = '[%(asctime)s] [%(levelname)s] %(message)s (%(module)s.%(funcName)s)' logFormat = '[%(asctime)s] [%(levelname)s] %(message)s (%(module)s.%(funcName)s)'
logging.basicConfig( logging.basicConfig(

88
Tester/Shadowsocks.py

@ -4,6 +4,7 @@
import os import os
import json import json
import base64 import base64
import itertools
from Builder import Shadowsocks from Builder import Shadowsocks
from Basis.Logger import logging from Basis.Logger import logging
from Basis.Process import Process from Basis.Process import Process
@ -82,75 +83,74 @@ def ssPythonLegacy(proxyInfo: dict, isUdp: bool) -> tuple[dict, list]:
def loadPassword(method: str) -> str: def loadPassword(method: str) -> str:
b64 = lambda x: base64.b64encode(x.encode(encoding = 'utf-8')).decode(encoding = 'utf-8') b64 = lambda x: base64.b64encode(x.encode(encoding = 'utf-8')).decode(encoding = 'utf-8') # base64 encode
if not method.startswith('2022-blake3-'): if not method.startswith('2022-blake3-'): # normal method
return genFlag(length = 8) return genFlag(length = 8)
if method == '2022-blake3-aes-128-gcm': if method == '2022-blake3-aes-128-gcm': # 2022-blake3-aes-128-gcm use 16 byte length password
return b64(genFlag(length = 16)) return b64(genFlag(length = 16))
return b64(genFlag(length = 32)) # three other 2022-blake3-* methods use 32 byte length password return b64(genFlag(length = 32)) # three other 2022-blake3-* methods use 32 byte length password
def testConnection(serverType: str, clientType: str, method: str) -> dict: def loadClient(ssType: str, configFile: str, proxyInfo: dict, socksInfo: dict) -> Process:
proxyInfo = { ssConfig, ssClient = { # generate client start command and its config file
'server': settings['serverBind'],
'port': getAvailablePort(),
'method': method,
'passwd': loadPassword(method),
'plugin': None
}
socksInfo = {
'addr': settings['clientBind'],
'port': getAvailablePort()
}
ssClientLoad = {
'ss-rust': Shadowsocks.ssRust, 'ss-rust': Shadowsocks.ssRust,
'ss-libev': Shadowsocks.ssLibev, 'ss-libev': Shadowsocks.ssLibev,
'ss-python': Shadowsocks.ssPython, 'ss-python': Shadowsocks.ssPython,
'ss-python-legacy': Shadowsocks.ssPythonLegacy 'ss-python-legacy': Shadowsocks.ssPythonLegacy
}[clientType] }[ssType](proxyInfo, socksInfo, isUdp = False)
ssConfig, ssClient = ssClientLoad(proxyInfo, socksInfo, isUdp = False) clientFile = os.path.join(settings['workDir'], configFile)
clientFile = os.path.join(settings['workDir'], '%s_%s_%s' % (serverType, clientType, method) + '_client.json') return Process(settings['workDir'], cmd = ssClient + ['-c', clientFile], file = { # load client process
client = Process(settings['workDir'], cmd = ssClient + ['-c', clientFile], file = {
'path': clientFile, 'path': clientFile,
'content': json.dumps(ssConfig) 'content': json.dumps(ssConfig)
}, isStart = False) }, isStart = False)
ssServerLoad = {
def loadServer(ssType: str, configFile: str, proxyInfo: dict) -> Process:
ssConfig, ssServer = { # generate server start command and its config file
'ss-rust': ssRust, 'ss-rust': ssRust,
'ss-libev': ssLibev, 'ss-libev': ssLibev,
'ss-python': ssPython, 'ss-python': ssPython,
'ss-python-legacy': ssPythonLegacy 'ss-python-legacy': ssPythonLegacy
}[serverType] }[ssType](proxyInfo, isUdp = False)
ssConfig, ssServer = ssServerLoad(proxyInfo, isUdp = False) serverFile = os.path.join(settings['workDir'], configFile)
serverFile = os.path.join(settings['workDir'], '%s_%s_%s' % (serverType, clientType, method) + '_server.json') return Process(settings['workDir'], cmd = ssServer + ['-c', serverFile], file = { # load server process
server = Process(settings['workDir'], cmd = ssServer + ['-c', serverFile], file = {
'path': serverFile, 'path': serverFile,
'content': json.dumps(ssConfig) 'content': json.dumps(ssConfig)
}, isStart = False) }, isStart = False)
testInfo = {
def loadTest(serverType: str, clientType: str, method: str) -> dict:
proxyInfo = { # connection info
'server': settings['serverBind'],
'port': getAvailablePort(),
'method': method,
'passwd': loadPassword(method),
'plugin': None
}
socksInfo = { # socks5 interface for test
'addr': settings['clientBind'],
'port': getAvailablePort()
}
configName = '%s_%s_%s' % (serverType, clientType, method) # prefix of config file name
testInfo = { # release test info
'title': 'Shadowsocks test: {%s <- %s -> %s}' % (serverType, method, clientType), 'title': 'Shadowsocks test: {%s <- %s -> %s}' % (serverType, method, clientType),
'socks': socksInfo, 'client': loadClient(clientType, configName + '_client.json', proxyInfo, socksInfo),
'client': client, 'server': loadServer(serverType, configName + '_server.json', proxyInfo),
'server': server, 'socks': socksInfo, # exposed socks5 interface
} }
logging.debug('New shadowsocks test connection -> %s' % testInfo) logging.debug('New shadowsocks test connection -> %s' % testInfo)
return testInfo return testInfo
def load(isExtra: bool = False) -> list: def load(isExtra: bool = False):
result = [] if not isExtra: # just test basic connection
if isExtra: for method in ssAllMethods: # test every method for once
for ssServer in ssMethods: for ssType in ssMethods: # found the client which support this method
for method in ssMethods[ssServer]:
for ssClient in ssMethods:
if method not in ssMethods[ssClient]: continue
result.append(testConnection(ssServer, ssClient, method))
else:
for method in ssAllMethods:
for ssType in ssMethods:
if method not in ssMethods[ssType]: continue if method not in ssMethods[ssType]: continue
result.append(testConnection(ssType, ssType, method)) yield loadTest(ssType, ssType, method) # ssType <-- method --> ssType
break break # don't need other client
return result return
for ssServer in ssMethods: # traverse all shadowsocks type as server
for method, ssClient in itertools.product(ssMethods[ssServer], ssMethods): # supported methods and clients
if method not in ssMethods[ssClient]: continue
yield loadTest(ssServer, ssClient, method) # ssServer <-- method --> ssClient

45
test.py

@ -3,22 +3,22 @@
import time import time
import requests import requests
from threading import Thread
from Tester import Shadowsocks from Tester import Shadowsocks
from Basis.Logger import logging from Basis.Logger import logging
from Basis.Functions import networkStatus
testDelay = 1 # wait 1s before request test
threadNum = 128 # thread number
def test(testObj: dict) -> None: def test(testObj: dict) -> None:
logging.warning(testObj['title']) logging.warning(testObj['title'])
logging.debug('network status -> %s' % networkStatus())
testObj['client'].start() testObj['client'].start()
testObj['server'].start() testObj['server'].start()
time.sleep(testDelay)
time.sleep(1)
errFlag = False errFlag = False
try: try:
request = requests.get( request = requests.get(
'http://baidu.com', 'http://iserv.scutbot.cn',
proxies = { proxies = {
'http': 'socks5://127.0.0.1:%i' % testObj['socks']['port'], 'http': 'socks5://127.0.0.1:%i' % testObj['socks']['port'],
'https': 'socks5://127.0.0.1:%i' % testObj['socks']['port'], 'https': 'socks5://127.0.0.1:%i' % testObj['socks']['port'],
@ -36,19 +36,34 @@ def test(testObj: dict) -> None:
testObj['server'].quit() testObj['server'].quit()
if errFlag: if errFlag:
logging.warning('client info') logging.warning('client info')
logging.error('command -> ' + str(testObj['client'].cmd)) logging.error('command -> %s' % testObj['client'].cmd)
logging.error('envVar -> ' + str(testObj['client'].env)) logging.error('envVar -> %s' % testObj['client'].env)
logging.error('file -> ' + str(testObj['client'].file)) logging.error('file -> %s' % testObj['client'].file)
logging.warning('client capture output') logging.warning('client capture output')
logging.error('\n' + str(testObj['client'].output)) logging.error('\n' + str(testObj['client'].output))
logging.warning('server info') logging.warning('server info')
logging.error('command -> ' + str(testObj['server'].cmd)) logging.error('command -> %s' % testObj['server'].cmd)
logging.error('envVar -> ' + str(testObj['server'].env)) logging.error('envVar -> %s' % testObj['server'].env)
logging.error('file -> ' + str(testObj['server'].file)) logging.error('file -> %s' % testObj['server'].file)
logging.warning('server capture output') logging.warning('server capture output')
logging.error('\n' + str(testObj['server'].output)) logging.error('\n' + str(testObj['server'].output))
testList = Shadowsocks.load(isExtra = True) threads = []
for testObject in testList: ss = Shadowsocks.load(isExtra = True)
test(testObject)
while True:
try:
for i in range(threadNum):
thread = Thread(target = test, args = (next(ss),))
thread.start()
threads.append(thread)
for thread in threads:
thread.join()
threads.clear()
except StopIteration:
break
for thread in threads:
thread.join()
logging.critical('test complete')

Loading…
Cancel
Save