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
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:
raise RuntimeError('invalid port range')
while True:
@ -27,7 +27,7 @@ def getAvailablePort(rangeStart: int = 41952, rangeEnd: int = 65535) -> int: #
if checkPortStatus(port):
logging.debug('get new port -> %i' % 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

4
Basis/Logger.py

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

88
Tester/Shadowsocks.py

@ -4,6 +4,7 @@
import os
import json
import base64
import itertools
from Builder import Shadowsocks
from Basis.Logger import logging
from Basis.Process import Process
@ -82,75 +83,74 @@ def ssPythonLegacy(proxyInfo: dict, isUdp: bool) -> tuple[dict, list]:
def loadPassword(method: str) -> str:
b64 = lambda x: base64.b64encode(x.encode(encoding = 'utf-8')).decode(encoding = 'utf-8')
if not method.startswith('2022-blake3-'):
b64 = lambda x: base64.b64encode(x.encode(encoding = 'utf-8')).decode(encoding = 'utf-8') # base64 encode
if not method.startswith('2022-blake3-'): # normal method
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 = 32)) # three other 2022-blake3-* methods use 32 byte length password
def testConnection(serverType: str, clientType: str, method: str) -> dict:
proxyInfo = {
'server': settings['serverBind'],
'port': getAvailablePort(),
'method': method,
'passwd': loadPassword(method),
'plugin': None
}
socksInfo = {
'addr': settings['clientBind'],
'port': getAvailablePort()
}
ssClientLoad = {
def loadClient(ssType: str, configFile: str, proxyInfo: dict, socksInfo: dict) -> Process:
ssConfig, ssClient = { # generate client start command and its config file
'ss-rust': Shadowsocks.ssRust,
'ss-libev': Shadowsocks.ssLibev,
'ss-python': Shadowsocks.ssPython,
'ss-python-legacy': Shadowsocks.ssPythonLegacy
}[clientType]
ssConfig, ssClient = ssClientLoad(proxyInfo, socksInfo, isUdp = False)
clientFile = os.path.join(settings['workDir'], '%s_%s_%s' % (serverType, clientType, method) + '_client.json')
client = Process(settings['workDir'], cmd = ssClient + ['-c', clientFile], file = {
}[ssType](proxyInfo, socksInfo, isUdp = False)
clientFile = os.path.join(settings['workDir'], configFile)
return Process(settings['workDir'], cmd = ssClient + ['-c', clientFile], file = { # load client process
'path': clientFile,
'content': json.dumps(ssConfig)
}, 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-libev': ssLibev,
'ss-python': ssPython,
'ss-python-legacy': ssPythonLegacy
}[serverType]
ssConfig, ssServer = ssServerLoad(proxyInfo, isUdp = False)
serverFile = os.path.join(settings['workDir'], '%s_%s_%s' % (serverType, clientType, method) + '_server.json')
server = Process(settings['workDir'], cmd = ssServer + ['-c', serverFile], file = {
}[ssType](proxyInfo, isUdp = False)
serverFile = os.path.join(settings['workDir'], configFile)
return Process(settings['workDir'], cmd = ssServer + ['-c', serverFile], file = { # load server process
'path': serverFile,
'content': json.dumps(ssConfig)
}, 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),
'socks': socksInfo,
'client': client,
'server': server,
'client': loadClient(clientType, configName + '_client.json', proxyInfo, socksInfo),
'server': loadServer(serverType, configName + '_server.json', proxyInfo),
'socks': socksInfo, # exposed socks5 interface
}
logging.debug('New shadowsocks test connection -> %s' % testInfo)
return testInfo
def load(isExtra: bool = False) -> list:
result = []
if isExtra:
for ssServer in ssMethods:
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:
def load(isExtra: bool = False):
if not isExtra: # just test basic connection
for method in ssAllMethods: # test every method for once
for ssType in ssMethods: # found the client which support this method
if method not in ssMethods[ssType]: continue
result.append(testConnection(ssType, ssType, method))
break
return result
yield loadTest(ssType, ssType, method) # ssType <-- method --> ssType
break # don't need other client
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 requests
from threading import Thread
from Tester import Shadowsocks
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:
logging.warning(testObj['title'])
logging.debug('network status -> %s' % networkStatus())
testObj['client'].start()
testObj['server'].start()
time.sleep(1)
time.sleep(testDelay)
errFlag = False
try:
request = requests.get(
'http://baidu.com',
'http://iserv.scutbot.cn',
proxies = {
'http': '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()
if errFlag:
logging.warning('client info')
logging.error('command -> ' + str(testObj['client'].cmd))
logging.error('envVar -> ' + str(testObj['client'].env))
logging.error('file -> ' + str(testObj['client'].file))
logging.error('command -> %s' % testObj['client'].cmd)
logging.error('envVar -> %s' % testObj['client'].env)
logging.error('file -> %s' % testObj['client'].file)
logging.warning('client capture output')
logging.error('\n' + str(testObj['client'].output))
logging.warning('server info')
logging.error('command -> ' + str(testObj['server'].cmd))
logging.error('envVar -> ' + str(testObj['server'].env))
logging.error('file -> ' + str(testObj['server'].file))
logging.error('command -> %s' % testObj['server'].cmd)
logging.error('envVar -> %s' % testObj['server'].env)
logging.error('file -> %s' % testObj['server'].file)
logging.warning('server capture output')
logging.error('\n' + str(testObj['server'].output))
testList = Shadowsocks.load(isExtra = True)
for testObject in testList:
test(testObject)
threads = []
ss = Shadowsocks.load(isExtra = True)
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