epicyon/tests.py

407 lines
15 KiB
Python
Raw Normal View History

2019-06-30 20:14:03 +00:00
__filename__ = "tests.py"
__author__ = "Bob Mottram"
__license__ = "AGPL3+"
__version__ = "0.0.1"
__maintainer__ = "Bob Mottram"
__email__ = "bob@freedombone.net"
__status__ = "Production"
import base64
import time
2019-07-04 20:36:12 +00:00
import os, os.path
2019-06-30 21:20:02 +00:00
import shutil
2019-06-30 20:14:03 +00:00
from person import createPerson
from Crypto.Hash import SHA256
from httpsig import signPostHeaders
from httpsig import verifyPostHeaders
from cache import storePersonInCache
from cache import getPersonFromCache
from threads import threadWithTrace
2019-06-30 21:20:02 +00:00
from daemon import runDaemon
from session import createSession
from posts import deleteAllPosts
from posts import createPublicPost
2019-06-30 22:56:37 +00:00
from posts import sendPost
2019-07-03 10:09:24 +00:00
from posts import archivePosts
2019-07-01 11:09:09 +00:00
from follow import clearFollows
from follow import clearFollowers
2019-06-30 21:20:02 +00:00
from follow import followPerson
from follow import followerOfPerson
2019-07-01 11:09:09 +00:00
from follow import unfollowPerson
from follow import unfollowerOfPerson
from follow import getFollowersOfPerson
2019-07-03 10:04:23 +00:00
from person import createPerson
from person import setPreferredNickname
from person import setBio
2019-07-03 18:24:44 +00:00
from auth import createBasicAuthHeader
from auth import authorizeBasic
from auth import storeBasicCredentials
2019-06-30 20:14:03 +00:00
2019-06-30 21:27:25 +00:00
testServerAliceRunning = False
testServerBobRunning = False
2019-06-30 20:14:03 +00:00
def testHttpsigBase(withDigest):
print('testHttpsig(' + str(withDigest) + ')')
2019-07-03 09:40:27 +00:00
nickname='socrates'
2019-06-30 20:14:03 +00:00
domain='argumentative.social'
2019-07-03 19:00:03 +00:00
httpPrefix='https'
2019-07-01 09:31:02 +00:00
port=5576
2019-06-30 22:56:37 +00:00
baseDir=os.getcwd()
2019-07-04 19:09:48 +00:00
password='SuperSecretPassword'
privateKeyPem,publicKeyPem,person,wfEndpoint=createPerson(baseDir,nickname,domain,port,httpPrefix,False,password)
2019-07-01 09:31:02 +00:00
messageBodyJsonStr = '{"a key": "a value", "another key": "A string"}'
headersDomain=domain
if port!=80 and port !=443:
headersDomain=domain+':'+str(port)
2019-06-30 20:14:03 +00:00
if not withDigest:
2019-07-01 09:31:02 +00:00
headers = {'host': headersDomain}
2019-06-30 20:14:03 +00:00
else:
2019-07-01 09:31:02 +00:00
bodyDigest = base64.b64encode(SHA256.new(messageBodyJsonStr.encode()).digest())
headers = {'host': headersDomain, 'digest': f'SHA-256={bodyDigest}'}
2019-06-30 20:14:03 +00:00
path='/inbox'
2019-07-03 19:00:03 +00:00
signatureHeader = signPostHeaders(privateKeyPem, nickname, domain, port, path, httpPrefix, None)
2019-06-30 20:14:03 +00:00
headers['signature'] = signatureHeader
2019-07-03 19:00:03 +00:00
assert verifyPostHeaders(httpPrefix, publicKeyPem, headers, '/inbox' ,False, messageBodyJsonStr)
assert verifyPostHeaders(httpPrefix, publicKeyPem, headers, '/parambulator/inbox', False , messageBodyJsonStr) == False
assert verifyPostHeaders(httpPrefix, publicKeyPem, headers, '/inbox', True, messageBodyJsonStr) == False
2019-06-30 20:14:03 +00:00
if not withDigest:
# fake domain
headers = {'host': 'bogon.domain'}
else:
# correct domain but fake message
2019-07-01 09:31:02 +00:00
messageBodyJsonStr = '{"a key": "a value", "another key": "Fake GNUs"}'
bodyDigest = base64.b64encode(SHA256.new(messageBodyJsonStr.encode()).digest())
2019-06-30 20:14:03 +00:00
headers = {'host': domain, 'digest': f'SHA-256={bodyDigest}'}
headers['signature'] = signatureHeader
2019-07-03 19:00:03 +00:00
assert verifyPostHeaders(httpPrefix, publicKeyPem, headers, '/inbox', True, messageBodyJsonStr) == False
2019-06-30 20:14:03 +00:00
def testHttpsig():
testHttpsigBase(False)
testHttpsigBase(True)
def testCache():
print('testCache')
personUrl="cat@cardboard.box"
personJson={ "id": 123456, "test": "This is a test" }
2019-07-01 14:30:48 +00:00
personCache={}
storePersonInCache(personUrl,personJson,personCache)
result=getPersonFromCache(personUrl,personCache)
2019-06-30 20:14:03 +00:00
assert result['id']==123456
assert result['test']=='This is a test'
def testThreadsFunction(param: str):
for i in range(10000):
time.sleep(2)
def testThreads():
print('testThreads')
thr = threadWithTrace(target=testThreadsFunction,args=('test',),daemon=True)
thr.start()
assert thr.isAlive()==True
time.sleep(1)
thr.kill()
thr.join()
assert thr.isAlive()==False
2019-06-30 21:20:02 +00:00
2019-07-01 21:01:43 +00:00
def createServerAlice(path: str,domain: str,port: int,federationList: []):
2019-06-30 21:20:02 +00:00
print('Creating test server: Alice on port '+str(port))
if os.path.isdir(path):
shutil.rmtree(path)
os.mkdir(path)
os.chdir(path)
2019-07-03 09:40:27 +00:00
nickname='alice'
2019-07-04 14:36:29 +00:00
httpPrefix='http'
2019-06-30 21:20:02 +00:00
useTor=False
2019-07-03 15:10:18 +00:00
clientToServer=False
2019-07-04 19:09:48 +00:00
password='alicepass'
privateKeyPem,publicKeyPem,person,wfEndpoint=createPerson(path,nickname,domain,port,httpPrefix,True,password)
2019-07-04 16:24:23 +00:00
deleteAllPosts(path,nickname,domain,'inbox')
deleteAllPosts(path,nickname,domain,'outbox')
2019-07-03 09:40:27 +00:00
followPerson(path,nickname,domain,'bob','127.0.0.100:61936',federationList)
followerOfPerson(path,nickname,domain,'bob','127.0.0.100:61936',federationList)
2019-07-03 19:00:03 +00:00
createPublicPost(path,nickname, domain, port,httpPrefix, "No wise fish would go anywhere without a porpoise", False, True, clientToServer)
createPublicPost(path,nickname, domain, port,httpPrefix, "Curiouser and curiouser!", False, True, clientToServer)
createPublicPost(path,nickname, domain, port,httpPrefix, "In the gardens of memory, in the palace of dreams, that is where you and I shall meet", False, True, clientToServer)
2019-06-30 21:27:25 +00:00
global testServerAliceRunning
testServerAliceRunning = True
2019-06-30 21:20:02 +00:00
print('Server running: Alice')
2019-07-04 14:36:29 +00:00
runDaemon(path,domain,port,httpPrefix,federationList,useTor,True)
2019-06-30 21:20:02 +00:00
2019-07-01 21:01:43 +00:00
def createServerBob(path: str,domain: str,port: int,federationList: []):
2019-06-30 21:20:02 +00:00
print('Creating test server: Bob on port '+str(port))
if os.path.isdir(path):
shutil.rmtree(path)
os.mkdir(path)
os.chdir(path)
2019-07-03 09:40:27 +00:00
nickname='bob'
2019-07-03 19:00:03 +00:00
httpPrefix='http'
2019-06-30 21:20:02 +00:00
useTor=False
2019-07-03 15:10:18 +00:00
clientToServer=False
2019-07-04 19:09:48 +00:00
password='bobpass'
privateKeyPem,publicKeyPem,person,wfEndpoint=createPerson(path,nickname,domain,port,httpPrefix,True,password)
2019-07-04 16:24:23 +00:00
deleteAllPosts(path,nickname,domain,'inbox')
deleteAllPosts(path,nickname,domain,'outbox')
2019-07-03 09:40:27 +00:00
followPerson(path,nickname,domain,'alice','127.0.0.50:61935',federationList)
followerOfPerson(path,nickname,domain,'alice','127.0.0.50:61935',federationList)
2019-07-03 19:00:03 +00:00
createPublicPost(path,nickname, domain, port,httpPrefix, "It's your life, live it your way.", False, True, clientToServer)
createPublicPost(path,nickname, domain, port,httpPrefix, "One of the things I've realised is that I am very simple", False, True, clientToServer)
createPublicPost(path,nickname, domain, port,httpPrefix, "Quantum physics is a bit of a passion of mine", False, True, clientToServer)
2019-06-30 21:27:25 +00:00
global testServerBobRunning
testServerBobRunning = True
2019-06-30 21:20:02 +00:00
print('Server running: Bob')
2019-07-04 14:36:29 +00:00
runDaemon(path,domain,port,httpPrefix,federationList,useTor,True)
2019-06-30 21:20:02 +00:00
def testPostMessageBetweenServers():
print('Testing sending message from one server to the inbox of another')
2019-06-30 21:27:25 +00:00
global testServerAliceRunning
global testServerBobRunning
testServerAliceRunning = False
testServerBobRunning = False
2019-07-03 19:00:03 +00:00
httpPrefix='http'
2019-06-30 22:56:37 +00:00
useTor=False
2019-07-02 09:25:29 +00:00
federationList=['127.0.0.50','127.0.0.100']
2019-06-30 22:56:37 +00:00
2019-06-30 21:20:02 +00:00
baseDir=os.getcwd()
if not os.path.isdir(baseDir+'/.tests'):
os.mkdir(baseDir+'/.tests')
# create the servers
2019-06-30 22:56:37 +00:00
aliceDir=baseDir+'/.tests/alice'
2019-07-02 09:25:29 +00:00
aliceDomain='127.0.0.50'
2019-06-30 22:56:37 +00:00
alicePort=61935
2019-07-01 21:01:43 +00:00
thrAlice = threadWithTrace(target=createServerAlice,args=(aliceDir,aliceDomain,alicePort,federationList),daemon=True)
2019-06-30 21:20:02 +00:00
2019-06-30 22:56:37 +00:00
bobDir=baseDir+'/.tests/bob'
2019-07-02 09:25:29 +00:00
bobDomain='127.0.0.100'
2019-06-30 22:56:37 +00:00
bobPort=61936
2019-07-01 21:01:43 +00:00
thrBob = threadWithTrace(target=createServerBob,args=(bobDir,bobDomain,bobPort,federationList),daemon=True)
thrAlice.start()
2019-06-30 21:20:02 +00:00
thrBob.start()
2019-07-01 21:01:43 +00:00
assert thrAlice.isAlive()==True
2019-06-30 21:20:02 +00:00
assert thrBob.isAlive()==True
2019-06-30 21:27:25 +00:00
# wait for both servers to be running
while not (testServerAliceRunning and testServerBobRunning):
time.sleep(1)
2019-07-04 20:25:19 +00:00
time.sleep(1)
2019-06-30 21:20:02 +00:00
2019-06-30 22:56:37 +00:00
print('Alice sends to Bob')
os.chdir(aliceDir)
2019-07-02 09:25:29 +00:00
sessionAlice = createSession(aliceDomain,alicePort,useTor)
2019-06-30 22:56:37 +00:00
inReplyTo=None
inReplyToAtomUri=None
subject=None
aliceSendThreads = []
alicePostLog = []
2019-07-01 12:51:55 +00:00
followersOnly=False
saveToFile=True
2019-07-03 15:10:18 +00:00
clientToServer=False
2019-07-01 12:51:55 +00:00
ccUrl=None
2019-07-01 14:30:48 +00:00
alicePersonCache={}
aliceCachedWebfingers={}
2019-07-03 19:00:03 +00:00
sendResult = sendPost(sessionAlice,aliceDir,'alice', aliceDomain, alicePort, 'bob', bobDomain, bobPort, ccUrl, httpPrefix, 'Why is a mouse when it spins?', followersOnly, saveToFile, clientToServer, federationList, aliceSendThreads, alicePostLog, aliceCachedWebfingers,alicePersonCache,inReplyTo, inReplyToAtomUri, subject)
2019-06-30 22:56:37 +00:00
print('sendResult: '+str(sendResult))
2019-07-04 20:36:12 +00:00
queuePath=bobDir+'/accounts/bob@'+bobDomain+'/queue'
inboxPath=bobDir+'/accounts/bob@'+bobDomain+'/inbox'
for i in range(10):
if os.path.isdir(inboxPath):
if len([name for name in os.listdir(inboxPath) if os.path.isfile(os.path.join(inboxPath, name))])>0:
break
2019-07-01 21:01:43 +00:00
time.sleep(1)
2019-06-30 22:56:37 +00:00
2019-06-30 21:20:02 +00:00
# stop the servers
thrAlice.kill()
thrAlice.join()
assert thrAlice.isAlive()==False
thrBob.kill()
thrBob.join()
assert thrBob.isAlive()==False
2019-07-04 20:36:12 +00:00
# inbox item created
assert len([name for name in os.listdir(inboxPath) if os.path.isfile(os.path.join(inboxPath, name))])==1
# queue item removed
assert len([name for name in os.listdir(queuePath) if os.path.isfile(os.path.join(queuePath, name))])==0
os.chdir(baseDir)
shutil.rmtree(aliceDir)
shutil.rmtree(bobDir)
def testFollowersOfPerson():
print('testFollowersOfPerson')
currDir=os.getcwd()
nickname='mxpop'
domain='diva.domain'
password='birb'
port=80
httpPrefix='https'
federationList=[]
baseDir=currDir+'/.tests_followersofperson'
if os.path.isdir(baseDir):
shutil.rmtree(baseDir)
os.mkdir(baseDir)
os.chdir(baseDir)
createPerson(baseDir,nickname,domain,port,httpPrefix,True,password)
createPerson(baseDir,'maxboardroom',domain,port,httpPrefix,True,password)
createPerson(baseDir,'ultrapancake',domain,port,httpPrefix,True,password)
createPerson(baseDir,'drokk',domain,port,httpPrefix,True,password)
createPerson(baseDir,'sausagedog',domain,port,httpPrefix,True,password)
clearFollows(baseDir,nickname,domain)
followPerson(baseDir,nickname,domain,'maxboardroom',domain,federationList)
followPerson(baseDir,'drokk',domain,'ultrapancake',domain,federationList)
# deliberate duplication
followPerson(baseDir,'drokk',domain,'ultrapancake',domain,federationList)
followPerson(baseDir,'sausagedog',domain,'ultrapancake',domain,federationList)
followPerson(baseDir,nickname,domain,'ultrapancake',domain,federationList)
followPerson(baseDir,nickname,domain,'someother','randodomain.net',federationList)
followList=getFollowersOfPerson(baseDir,'ultrapancake',domain)
assert len(followList)==3
assert 'mxpop@'+domain in followList
assert 'drokk@'+domain in followList
assert 'sausagedog@'+domain in followList
os.chdir(currDir)
shutil.rmtree(baseDir)
2019-07-03 09:24:55 +00:00
def testFollows():
2019-07-03 10:04:23 +00:00
print('testFollows')
2019-07-03 09:24:55 +00:00
currDir=os.getcwd()
2019-07-03 09:40:27 +00:00
nickname='test529'
2019-07-03 09:24:55 +00:00
domain='testdomain.com'
2019-07-04 19:09:48 +00:00
password='mypass'
2019-07-03 09:24:55 +00:00
port=80
2019-07-03 19:00:03 +00:00
httpPrefix='https'
2019-07-03 09:24:55 +00:00
federationList=['wild.com','mesh.com']
baseDir=currDir+'/.tests_testfollows'
if os.path.isdir(baseDir):
shutil.rmtree(baseDir)
os.mkdir(baseDir)
2019-07-04 19:09:48 +00:00
os.chdir(baseDir)
createPerson(baseDir,nickname,domain,port,httpPrefix,True,password)
2019-07-03 09:24:55 +00:00
2019-07-03 09:40:27 +00:00
clearFollows(baseDir,nickname,domain)
followPerson(baseDir,nickname,domain,'badger','wild.com',federationList)
followPerson(baseDir,nickname,domain,'squirrel','secret.com',federationList)
followPerson(baseDir,nickname,domain,'rodent','drainpipe.com',federationList)
followPerson(baseDir,nickname,domain,'batman','mesh.com',federationList)
followPerson(baseDir,nickname,domain,'giraffe','trees.com',federationList)
2019-07-03 09:24:55 +00:00
2019-07-03 09:40:27 +00:00
f = open(baseDir+'/accounts/'+nickname+'@'+domain+'/following.txt', "r")
2019-07-03 09:33:28 +00:00
domainFound=False
2019-07-03 09:24:55 +00:00
for followingDomain in f:
testDomain=followingDomain.split('@')[1].replace('\n','')
2019-07-03 09:33:28 +00:00
if testDomain=='mesh.com':
domainFound=True
2019-07-03 09:24:55 +00:00
if testDomain not in federationList:
print(testDomain)
assert(False)
2019-07-03 09:33:28 +00:00
assert(domainFound)
2019-07-03 09:40:27 +00:00
unfollowPerson(baseDir,nickname,domain,'batman','mesh.com')
2019-07-03 09:33:28 +00:00
domainFound=False
for followingDomain in f:
testDomain=followingDomain.split('@')[1].replace('\n','')
if testDomain=='mesh.com':
domainFound=True
assert(domainFound==False)
2019-07-03 09:40:27 +00:00
clearFollowers(baseDir,nickname,domain)
followerOfPerson(baseDir,nickname,domain,'badger','wild.com',federationList)
followerOfPerson(baseDir,nickname,domain,'squirrel','secret.com',federationList)
followerOfPerson(baseDir,nickname,domain,'rodent','drainpipe.com',federationList)
followerOfPerson(baseDir,nickname,domain,'batman','mesh.com',federationList)
followerOfPerson(baseDir,nickname,domain,'giraffe','trees.com',federationList)
2019-07-03 09:24:55 +00:00
2019-07-03 09:40:27 +00:00
f = open(baseDir+'/accounts/'+nickname+'@'+domain+'/followers.txt', "r")
2019-07-03 09:24:55 +00:00
for followerDomain in f:
testDomain=followerDomain.split('@')[1].replace('\n','')
if testDomain not in federationList:
print(testDomain)
assert(False)
os.chdir(currDir)
shutil.rmtree(baseDir)
2019-07-03 10:04:23 +00:00
def testCreatePerson():
print('testCreatePerson')
currDir=os.getcwd()
nickname='test382'
domain='badgerdomain.com'
2019-07-04 19:09:48 +00:00
password='mypass'
2019-07-03 10:04:23 +00:00
port=80
2019-07-03 19:00:03 +00:00
httpPrefix='https'
2019-07-03 15:10:18 +00:00
clientToServer=False
2019-07-03 10:04:23 +00:00
baseDir=currDir+'/.tests_createperson'
if os.path.isdir(baseDir):
shutil.rmtree(baseDir)
os.mkdir(baseDir)
os.chdir(baseDir)
2019-07-03 09:24:55 +00:00
2019-07-04 19:09:48 +00:00
privateKeyPem,publicKeyPem,person,wfEndpoint=createPerson(baseDir,nickname,domain,port,httpPrefix,True,password)
assert os.path.isfile(baseDir+'/accounts/passwords')
2019-07-04 16:24:23 +00:00
deleteAllPosts(baseDir,nickname,domain,'inbox')
deleteAllPosts(baseDir,nickname,domain,'outbox')
2019-07-03 10:04:23 +00:00
setPreferredNickname(baseDir,nickname,domain,'badger')
setBio(baseDir,nickname,domain,'Randomly roaming in your backyard')
2019-07-04 16:24:23 +00:00
archivePosts(nickname,domain,baseDir,'inbox',4)
archivePosts(nickname,domain,baseDir,'outbox',4)
2019-07-03 19:00:03 +00:00
createPublicPost(baseDir,nickname, domain, port,httpPrefix, "G'day world!", False, True, clientToServer, None, None, 'Not suitable for Vogons')
2019-07-03 10:04:23 +00:00
os.chdir(currDir)
shutil.rmtree(baseDir)
2019-07-03 18:24:44 +00:00
def testAuthentication():
print('testAuthentication')
currDir=os.getcwd()
nickname='test8743'
password='SuperSecretPassword12345'
baseDir=currDir+'/.tests_authentication'
if os.path.isdir(baseDir):
shutil.rmtree(baseDir)
os.mkdir(baseDir)
os.chdir(baseDir)
assert storeBasicCredentials(baseDir,'othernick','otherpass')
assert storeBasicCredentials(baseDir,'bad:nick','otherpass')==False
assert storeBasicCredentials(baseDir,'badnick','otherpa:ss')==False
assert storeBasicCredentials(baseDir,nickname,password)
authHeader=createBasicAuthHeader(nickname,password)
2019-07-04 08:56:15 +00:00
assert authorizeBasic(baseDir,'/users/'+nickname+'/inbox',authHeader,False)
assert authorizeBasic(baseDir,'/users/'+nickname,authHeader,False)==False
assert authorizeBasic(baseDir,'/users/othernick/inbox',authHeader,False)==False
2019-07-03 18:24:44 +00:00
authHeader=createBasicAuthHeader(nickname,password+'1')
2019-07-04 08:56:15 +00:00
assert authorizeBasic(baseDir,'/users/'+nickname+'/inbox',authHeader,False)==False
2019-07-03 18:24:44 +00:00
2019-07-03 19:13:23 +00:00
password='someOtherPassword'
assert storeBasicCredentials(baseDir,nickname,password)
authHeader=createBasicAuthHeader(nickname,password)
2019-07-04 08:56:15 +00:00
assert authorizeBasic(baseDir,'/users/'+nickname+'/inbox',authHeader,False)
2019-07-03 19:13:23 +00:00
2019-07-03 18:24:44 +00:00
os.chdir(currDir)
shutil.rmtree(baseDir)
2019-06-30 21:20:02 +00:00
def runAllTests():
print('Running tests...')
testHttpsig()
testCache()
testThreads()
2019-07-03 10:04:23 +00:00
testCreatePerson()
2019-07-03 18:24:44 +00:00
testAuthentication()
testFollowersOfPerson()
testFollows()
2019-07-03 18:24:44 +00:00
print('Tests succeeded\n')