2020-04-05 13:25:47 +00:00
|
|
|
|
__filename__ = "tests.py"
|
|
|
|
|
__author__ = "Bob Mottram"
|
|
|
|
|
__license__ = "AGPL3+"
|
2021-01-26 10:07:42 +00:00
|
|
|
|
__version__ = "1.2.0"
|
2020-04-05 13:25:47 +00:00
|
|
|
|
__maintainer__ = "Bob Mottram"
|
|
|
|
|
__email__ = "bob@freedombone.net"
|
|
|
|
|
__status__ = "Production"
|
|
|
|
|
|
2019-06-30 20:14:03 +00:00
|
|
|
|
import time
|
2020-04-05 13:25:47 +00:00
|
|
|
|
import os
|
2019-06-30 21:20:02 +00:00
|
|
|
|
import shutil
|
2019-08-16 10:36:41 +00:00
|
|
|
|
import json
|
2019-08-15 18:21:43 +00:00
|
|
|
|
from time import gmtime, strftime
|
2019-07-09 14:20:23 +00:00
|
|
|
|
from pprint import pprint
|
2019-06-30 20:14:03 +00:00
|
|
|
|
from httpsig import signPostHeaders
|
|
|
|
|
from httpsig import verifyPostHeaders
|
2019-08-17 10:15:01 +00:00
|
|
|
|
from httpsig import messageContentDigest
|
2019-06-30 20:14:03 +00:00
|
|
|
|
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
|
2020-12-13 19:05:26 +00:00
|
|
|
|
from posts import getMentionedPeople
|
2020-08-25 19:35:55 +00:00
|
|
|
|
from posts import validContentWarning
|
2019-06-30 21:20:02 +00:00
|
|
|
|
from posts import deleteAllPosts
|
|
|
|
|
from posts import createPublicPost
|
2019-06-30 22:56:37 +00:00
|
|
|
|
from posts import sendPost
|
2019-07-05 14:39:24 +00:00
|
|
|
|
from posts import noOfFollowersOnDomain
|
2019-07-08 08:51:33 +00:00
|
|
|
|
from posts import groupFollowersByDomain
|
2019-07-12 22:29:10 +00:00
|
|
|
|
from posts import archivePostsForPerson
|
2019-07-16 10:19:04 +00:00
|
|
|
|
from posts import sendPostViaServer
|
2019-07-01 11:09:09 +00:00
|
|
|
|
from follow import clearFollows
|
|
|
|
|
from follow import clearFollowers
|
2019-07-16 21:38:06 +00:00
|
|
|
|
from follow import sendFollowRequestViaServer
|
2019-07-17 11:54:13 +00:00
|
|
|
|
from follow import sendUnfollowRequestViaServer
|
2021-01-25 12:24:40 +00:00
|
|
|
|
from utils import decodedHost
|
2020-12-16 11:19:16 +00:00
|
|
|
|
from utils import getFullDomain
|
2020-11-24 10:53:10 +00:00
|
|
|
|
from utils import validNickname
|
2020-11-08 11:24:43 +00:00
|
|
|
|
from utils import firstParagraphFromString
|
2020-08-23 11:13:35 +00:00
|
|
|
|
from utils import removeIdEnding
|
2020-06-22 16:55:19 +00:00
|
|
|
|
from utils import siteIsActive
|
2019-11-24 17:40:31 +00:00
|
|
|
|
from utils import updateRecentPostsCache
|
2019-07-06 19:24:52 +00:00
|
|
|
|
from utils import followPerson
|
2019-08-21 16:35:46 +00:00
|
|
|
|
from utils import getNicknameFromActor
|
|
|
|
|
from utils import getDomainFromActor
|
2019-09-29 18:48:34 +00:00
|
|
|
|
from utils import copytree
|
2019-11-23 10:08:00 +00:00
|
|
|
|
from utils import loadJson
|
|
|
|
|
from utils import saveJson
|
2019-10-12 12:45:53 +00:00
|
|
|
|
from utils import getStatusNumber
|
2020-09-25 13:21:56 +00:00
|
|
|
|
from utils import getFollowersOfPerson
|
2020-10-25 12:47:16 +00:00
|
|
|
|
from utils import removeHtml
|
2021-01-31 11:05:17 +00:00
|
|
|
|
from utils import dangerousMarkup
|
2019-06-30 21:20:02 +00:00
|
|
|
|
from follow import followerOfPerson
|
2020-12-22 13:57:24 +00:00
|
|
|
|
from follow import unfollowAccount
|
|
|
|
|
from follow import unfollowerOfAccount
|
2019-07-06 13:49:25 +00:00
|
|
|
|
from follow import sendFollowRequest
|
2019-07-03 10:04:23 +00:00
|
|
|
|
from person import createPerson
|
2019-08-22 18:36:07 +00:00
|
|
|
|
from person import setDisplayNickname
|
2019-07-03 10:04:23 +00:00
|
|
|
|
from person import setBio
|
2020-06-15 12:37:53 +00:00
|
|
|
|
# from person import generateRSAKey
|
2019-07-19 10:01:24 +00:00
|
|
|
|
from skills import setSkillLevel
|
2019-07-18 15:09:23 +00:00
|
|
|
|
from roles import setRole
|
2019-07-18 16:21:26 +00:00
|
|
|
|
from roles import outboxDelegate
|
2020-09-03 18:48:32 +00:00
|
|
|
|
from auth import constantTimeStringCheck
|
2019-07-03 18:24:44 +00:00
|
|
|
|
from auth import createBasicAuthHeader
|
|
|
|
|
from auth import authorizeBasic
|
|
|
|
|
from auth import storeBasicCredentials
|
2019-07-11 12:29:31 +00:00
|
|
|
|
from like import likePost
|
2019-07-18 09:26:47 +00:00
|
|
|
|
from like import sendLikeViaServer
|
2019-07-11 17:55:10 +00:00
|
|
|
|
from announce import announcePublic
|
2019-07-16 19:07:45 +00:00
|
|
|
|
from announce import sendAnnounceViaServer
|
2019-07-12 19:26:54 +00:00
|
|
|
|
from media import getMediaPath
|
2019-08-30 15:50:20 +00:00
|
|
|
|
from media import getAttachmentMediaType
|
2019-07-17 17:16:48 +00:00
|
|
|
|
from delete import sendDeleteViaServer
|
2020-08-21 18:32:16 +00:00
|
|
|
|
from inbox import jsonPostAllowsComments
|
2019-07-18 09:26:47 +00:00
|
|
|
|
from inbox import validInbox
|
2019-07-18 11:35:48 +00:00
|
|
|
|
from inbox import validInboxFilenames
|
2020-12-22 13:57:24 +00:00
|
|
|
|
from categories import guessHashtagCategory
|
2020-09-14 09:33:42 +00:00
|
|
|
|
from content import htmlReplaceEmailQuote
|
2020-08-02 17:01:12 +00:00
|
|
|
|
from content import htmlReplaceQuoteMarks
|
2020-12-13 14:48:45 +00:00
|
|
|
|
from content import dangerousCSS
|
2019-09-01 08:55:05 +00:00
|
|
|
|
from content import addWebLinks
|
2019-09-29 18:48:34 +00:00
|
|
|
|
from content import replaceEmojiFromTags
|
|
|
|
|
from content import addHtmlTags
|
2019-11-04 20:39:14 +00:00
|
|
|
|
from content import removeLongWords
|
2020-05-12 09:34:58 +00:00
|
|
|
|
from content import replaceContentDuplicates
|
2020-06-14 13:25:38 +00:00
|
|
|
|
from content import removeTextFormatting
|
2020-10-11 09:33:31 +00:00
|
|
|
|
from content import removeHtmlTag
|
2019-11-23 13:04:11 +00:00
|
|
|
|
from theme import setCSSparam
|
2021-01-04 19:02:24 +00:00
|
|
|
|
from linked_data_sig import generateJsonSignature
|
|
|
|
|
from linked_data_sig import verifyJsonSignature
|
2020-10-17 12:05:41 +00:00
|
|
|
|
from newsdaemon import hashtagRuleTree
|
2020-10-17 17:36:10 +00:00
|
|
|
|
from newsdaemon import hashtagRuleResolve
|
2020-10-25 10:06:54 +00:00
|
|
|
|
from newswire import getNewswireTags
|
2020-11-22 18:43:01 +00:00
|
|
|
|
from newswire import parseFeedDate
|
2021-01-22 13:32:37 +00:00
|
|
|
|
from mastoapiv1 import getMastoApiV1IdFromNickname
|
|
|
|
|
from mastoapiv1 import getNicknameFromMastoApiV1Id
|
2021-02-02 21:08:33 +00:00
|
|
|
|
from webapp_post import prepareHtmlPostNickname
|
2019-06-30 20:14:03 +00:00
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
testServerAliceRunning = False
|
|
|
|
|
testServerBobRunning = False
|
|
|
|
|
testServerEveRunning = False
|
|
|
|
|
thrAlice = None
|
|
|
|
|
thrBob = None
|
|
|
|
|
thrEve = None
|
|
|
|
|
|
2019-06-30 21:27:25 +00:00
|
|
|
|
|
2020-12-22 18:06:23 +00:00
|
|
|
|
def _testHttpsigBase(withDigest):
|
2019-06-30 20:14:03 +00:00
|
|
|
|
print('testHttpsig(' + str(withDigest) + ')')
|
2019-08-09 09:46:33 +00:00
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
baseDir = os.getcwd()
|
|
|
|
|
path = baseDir + '/.testHttpsigBase'
|
2019-08-09 09:46:33 +00:00
|
|
|
|
if os.path.isdir(path):
|
|
|
|
|
shutil.rmtree(path)
|
|
|
|
|
os.mkdir(path)
|
|
|
|
|
os.chdir(path)
|
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
contentType = 'application/activity+json'
|
|
|
|
|
nickname = 'socrates'
|
|
|
|
|
domain = 'argumentative.social'
|
|
|
|
|
httpPrefix = 'https'
|
|
|
|
|
port = 5576
|
|
|
|
|
password = 'SuperSecretPassword'
|
|
|
|
|
privateKeyPem, publicKeyPem, person, wfEndpoint = \
|
2020-07-12 12:31:28 +00:00
|
|
|
|
createPerson(path, nickname, domain, port, httpPrefix,
|
|
|
|
|
False, False, password)
|
2019-08-09 09:46:33 +00:00
|
|
|
|
assert privateKeyPem
|
2020-04-05 13:25:47 +00:00
|
|
|
|
messageBodyJson = {
|
2020-03-22 20:36:19 +00:00
|
|
|
|
"a key": "a value",
|
|
|
|
|
"another key": "A string",
|
|
|
|
|
"yet another key": "Another string"
|
|
|
|
|
}
|
2020-04-05 13:25:47 +00:00
|
|
|
|
messageBodyJsonStr = json.dumps(messageBodyJson)
|
2019-07-01 09:31:02 +00:00
|
|
|
|
|
2020-12-16 11:19:16 +00:00
|
|
|
|
headersDomain = getFullDomain(domain, port)
|
2019-07-01 09:31:02 +00:00
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
dateStr = strftime("%a, %d %b %Y %H:%M:%S %Z", gmtime())
|
|
|
|
|
boxpath = '/inbox'
|
2019-06-30 20:14:03 +00:00
|
|
|
|
if not withDigest:
|
2020-04-05 13:25:47 +00:00
|
|
|
|
headers = {
|
2020-03-22 20:36:19 +00:00
|
|
|
|
'host': headersDomain,
|
|
|
|
|
'date': dateStr,
|
|
|
|
|
'content-type': 'application/json'
|
|
|
|
|
}
|
2020-04-05 13:25:47 +00:00
|
|
|
|
signatureHeader = \
|
|
|
|
|
signPostHeaders(dateStr, privateKeyPem, nickname,
|
|
|
|
|
domain, port,
|
|
|
|
|
domain, port,
|
2019-08-16 13:47:01 +00:00
|
|
|
|
boxpath, httpPrefix, None)
|
2019-06-30 20:14:03 +00:00
|
|
|
|
else:
|
2020-04-05 13:25:47 +00:00
|
|
|
|
bodyDigest = messageContentDigest(messageBodyJsonStr)
|
|
|
|
|
contentLength = len(messageBodyJsonStr)
|
|
|
|
|
headers = {
|
2020-03-22 20:36:19 +00:00
|
|
|
|
'host': headersDomain,
|
|
|
|
|
'date': dateStr,
|
|
|
|
|
'digest': f'SHA-256={bodyDigest}',
|
|
|
|
|
'content-type': contentType,
|
|
|
|
|
'content-length': str(contentLength)
|
|
|
|
|
}
|
2020-04-05 13:25:47 +00:00
|
|
|
|
signatureHeader = \
|
|
|
|
|
signPostHeaders(dateStr, privateKeyPem, nickname,
|
|
|
|
|
domain, port,
|
|
|
|
|
domain, port,
|
2019-08-17 10:15:01 +00:00
|
|
|
|
boxpath, httpPrefix, messageBodyJsonStr)
|
2019-07-01 09:31:02 +00:00
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
headers['signature'] = signatureHeader
|
|
|
|
|
assert verifyPostHeaders(httpPrefix, publicKeyPem, headers,
|
|
|
|
|
boxpath, False, None,
|
|
|
|
|
messageBodyJsonStr, False)
|
2019-11-12 18:21:52 +00:00
|
|
|
|
if withDigest:
|
|
|
|
|
# everything correct except for content-length
|
2020-04-05 13:25:47 +00:00
|
|
|
|
headers['content-length'] = str(contentLength + 2)
|
|
|
|
|
assert verifyPostHeaders(httpPrefix, publicKeyPem, headers,
|
|
|
|
|
boxpath, False, None,
|
|
|
|
|
messageBodyJsonStr, False) is False
|
|
|
|
|
assert verifyPostHeaders(httpPrefix, publicKeyPem, headers,
|
|
|
|
|
'/parambulator' + boxpath, False, None,
|
|
|
|
|
messageBodyJsonStr, False) is False
|
|
|
|
|
assert verifyPostHeaders(httpPrefix, publicKeyPem, headers,
|
|
|
|
|
boxpath, True, None,
|
|
|
|
|
messageBodyJsonStr, False) is False
|
2019-06-30 20:14:03 +00:00
|
|
|
|
if not withDigest:
|
|
|
|
|
# fake domain
|
2020-04-05 13:25:47 +00:00
|
|
|
|
headers = {
|
2020-03-22 20:36:19 +00:00
|
|
|
|
'host': 'bogon.domain',
|
|
|
|
|
'date': dateStr,
|
|
|
|
|
'content-type': 'application/json'
|
|
|
|
|
}
|
2019-06-30 20:14:03 +00:00
|
|
|
|
else:
|
|
|
|
|
# correct domain but fake message
|
2020-04-05 13:25:47 +00:00
|
|
|
|
messageBodyJsonStr = \
|
|
|
|
|
'{"a key": "a value", "another key": "Fake GNUs", ' + \
|
|
|
|
|
'"yet another key": "More Fake GNUs"}'
|
|
|
|
|
contentLength = len(messageBodyJsonStr)
|
|
|
|
|
bodyDigest = messageContentDigest(messageBodyJsonStr)
|
|
|
|
|
headers = {
|
2020-03-22 20:36:19 +00:00
|
|
|
|
'host': domain,
|
|
|
|
|
'date': dateStr,
|
|
|
|
|
'digest': f'SHA-256={bodyDigest}',
|
|
|
|
|
'content-type': contentType,
|
|
|
|
|
'content-length': str(contentLength)
|
|
|
|
|
}
|
2020-04-05 13:25:47 +00:00
|
|
|
|
headers['signature'] = signatureHeader
|
|
|
|
|
assert verifyPostHeaders(httpPrefix, publicKeyPem, headers,
|
|
|
|
|
boxpath, True, None,
|
|
|
|
|
messageBodyJsonStr, False) is False
|
2019-11-12 18:21:52 +00:00
|
|
|
|
|
2019-08-09 09:46:33 +00:00
|
|
|
|
os.chdir(baseDir)
|
|
|
|
|
shutil.rmtree(path)
|
2019-06-30 20:14:03 +00:00
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
|
2019-06-30 20:14:03 +00:00
|
|
|
|
def testHttpsig():
|
2020-12-22 18:06:23 +00:00
|
|
|
|
_testHttpsigBase(True)
|
|
|
|
|
_testHttpsigBase(False)
|
2019-06-30 20:14:03 +00:00
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
|
2019-06-30 20:14:03 +00:00
|
|
|
|
def testCache():
|
|
|
|
|
print('testCache')
|
2020-04-05 13:25:47 +00:00
|
|
|
|
personUrl = "cat@cardboard.box"
|
|
|
|
|
personJson = {
|
|
|
|
|
"id": 123456,
|
|
|
|
|
"test": "This is a test"
|
|
|
|
|
}
|
|
|
|
|
personCache = {}
|
2020-08-29 10:21:29 +00:00
|
|
|
|
storePersonInCache(None, personUrl, personJson, personCache, True)
|
|
|
|
|
result = getPersonFromCache(None, personUrl, personCache, True)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
assert result['id'] == 123456
|
|
|
|
|
assert result['test'] == 'This is a test'
|
|
|
|
|
|
2019-06-30 20:14:03 +00:00
|
|
|
|
|
|
|
|
|
def testThreadsFunction(param: str):
|
|
|
|
|
for i in range(10000):
|
|
|
|
|
time.sleep(2)
|
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
|
2019-06-30 20:14:03 +00:00
|
|
|
|
def testThreads():
|
|
|
|
|
print('testThreads')
|
2020-04-05 13:25:47 +00:00
|
|
|
|
thr = \
|
|
|
|
|
threadWithTrace(target=testThreadsFunction,
|
|
|
|
|
args=('test',),
|
|
|
|
|
daemon=True)
|
2019-06-30 20:14:03 +00:00
|
|
|
|
thr.start()
|
2020-12-18 15:29:12 +00:00
|
|
|
|
assert thr.is_alive() is True
|
2019-06-30 20:14:03 +00:00
|
|
|
|
time.sleep(1)
|
|
|
|
|
thr.kill()
|
|
|
|
|
thr.join()
|
2020-12-18 15:29:12 +00:00
|
|
|
|
assert thr.is_alive() is False
|
2019-06-30 21:20:02 +00:00
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
|
|
|
|
|
def createServerAlice(path: str, domain: str, port: int,
|
|
|
|
|
bobAddress: str, federationList: [],
|
|
|
|
|
hasFollows: bool, hasPosts: bool,
|
2020-09-27 19:27:24 +00:00
|
|
|
|
sendThreads: []):
|
2020-04-05 13:25:47 +00:00
|
|
|
|
print('Creating test server: Alice on port ' + str(port))
|
2019-06-30 21:20:02 +00:00
|
|
|
|
if os.path.isdir(path):
|
|
|
|
|
shutil.rmtree(path)
|
|
|
|
|
os.mkdir(path)
|
|
|
|
|
os.chdir(path)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
nickname = 'alice'
|
|
|
|
|
httpPrefix = 'http'
|
2020-06-09 11:03:59 +00:00
|
|
|
|
proxyType = None
|
2020-04-05 13:25:47 +00:00
|
|
|
|
password = 'alicepass'
|
|
|
|
|
maxReplies = 64
|
|
|
|
|
domainMaxPostsPerDay = 1000
|
|
|
|
|
accountMaxPostsPerDay = 1000
|
|
|
|
|
allowDeletion = True
|
|
|
|
|
privateKeyPem, publicKeyPem, person, wfEndpoint = \
|
2020-07-12 12:31:28 +00:00
|
|
|
|
createPerson(path, nickname, domain, port, httpPrefix, True,
|
|
|
|
|
False, password)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
deleteAllPosts(path, nickname, domain, 'inbox')
|
|
|
|
|
deleteAllPosts(path, nickname, domain, 'outbox')
|
|
|
|
|
assert setSkillLevel(path, nickname, domain, 'hacking', 90)
|
|
|
|
|
assert setRole(path, nickname, domain, 'someproject', 'guru')
|
2019-07-06 13:49:25 +00:00
|
|
|
|
if hasFollows:
|
2020-04-05 13:25:47 +00:00
|
|
|
|
followPerson(path, nickname, domain, 'bob', bobAddress,
|
|
|
|
|
federationList, False)
|
|
|
|
|
followerOfPerson(path, nickname, domain, 'bob', bobAddress,
|
|
|
|
|
federationList, False)
|
2019-07-06 13:49:25 +00:00
|
|
|
|
if hasPosts:
|
2020-12-22 21:24:46 +00:00
|
|
|
|
testFollowersOnly = False
|
|
|
|
|
testSaveToFile = True
|
2020-12-22 21:27:46 +00:00
|
|
|
|
clientToServer = False
|
2020-12-22 21:24:46 +00:00
|
|
|
|
testCommentsEnabled = True
|
|
|
|
|
testAttachImageFilename = None
|
|
|
|
|
testMediaType = None
|
|
|
|
|
testImageDescription = None
|
2020-04-05 13:25:47 +00:00
|
|
|
|
createPublicPost(path, nickname, domain, port, httpPrefix,
|
|
|
|
|
"No wise fish would go anywhere without a porpoise",
|
2020-12-22 21:24:46 +00:00
|
|
|
|
testFollowersOnly,
|
|
|
|
|
testSaveToFile,
|
|
|
|
|
clientToServer,
|
|
|
|
|
testCommentsEnabled,
|
|
|
|
|
testAttachImageFilename,
|
|
|
|
|
testMediaType,
|
2021-01-07 15:38:55 +00:00
|
|
|
|
testImageDescription)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
createPublicPost(path, nickname, domain, port, httpPrefix,
|
2020-12-22 21:24:46 +00:00
|
|
|
|
"Curiouser and curiouser!",
|
|
|
|
|
testFollowersOnly,
|
|
|
|
|
testSaveToFile,
|
|
|
|
|
clientToServer,
|
|
|
|
|
testCommentsEnabled,
|
|
|
|
|
testAttachImageFilename,
|
|
|
|
|
testMediaType,
|
2021-01-07 15:38:55 +00:00
|
|
|
|
testImageDescription)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
createPublicPost(path, nickname, domain, port, httpPrefix,
|
|
|
|
|
"In the gardens of memory, in the palace " +
|
|
|
|
|
"of dreams, that is where you and I shall meet",
|
2020-12-22 21:24:46 +00:00
|
|
|
|
testFollowersOnly,
|
|
|
|
|
testSaveToFile,
|
|
|
|
|
clientToServer,
|
|
|
|
|
testCommentsEnabled,
|
|
|
|
|
testAttachImageFilename,
|
|
|
|
|
testMediaType,
|
2021-01-07 15:38:55 +00:00
|
|
|
|
testImageDescription)
|
2019-06-30 21:27:25 +00:00
|
|
|
|
global testServerAliceRunning
|
2020-04-05 13:25:47 +00:00
|
|
|
|
testServerAliceRunning = True
|
|
|
|
|
maxMentions = 10
|
|
|
|
|
maxEmoji = 10
|
|
|
|
|
onionDomain = None
|
2020-06-03 17:38:34 +00:00
|
|
|
|
i2pDomain = None
|
2020-11-20 10:58:49 +00:00
|
|
|
|
allowLocalNetworkAccess = True
|
2020-11-22 11:48:53 +00:00
|
|
|
|
maxNewswirePosts = 20
|
2020-12-13 12:44:17 +00:00
|
|
|
|
dormantMonths = 3
|
2020-12-18 11:48:00 +00:00
|
|
|
|
sendThreadsTimeoutMins = 30
|
2020-12-26 10:22:56 +00:00
|
|
|
|
maxFollowers = 10
|
2021-01-05 10:29:37 +00:00
|
|
|
|
verifyAllSignatures = True
|
2019-06-30 21:20:02 +00:00
|
|
|
|
print('Server running: Alice')
|
2021-01-05 10:29:37 +00:00
|
|
|
|
runDaemon(verifyAllSignatures,
|
|
|
|
|
sendThreadsTimeoutMins,
|
2020-12-18 11:48:00 +00:00
|
|
|
|
dormantMonths, maxNewswirePosts,
|
2020-12-13 12:44:17 +00:00
|
|
|
|
allowLocalNetworkAccess,
|
2020-12-26 10:22:56 +00:00
|
|
|
|
2048, False, True, False, False, True, maxFollowers,
|
2020-10-26 20:32:01 +00:00
|
|
|
|
0, 100, 1024, 5, False,
|
2020-10-23 19:18:13 +00:00
|
|
|
|
0, False, 1, False, False, False,
|
2020-10-07 09:10:42 +00:00
|
|
|
|
5, True, True, 'en', __version__,
|
2020-06-03 17:38:34 +00:00
|
|
|
|
"instanceId", False, path, domain,
|
2020-08-02 09:51:20 +00:00
|
|
|
|
onionDomain, i2pDomain, None, port, port,
|
2020-04-05 13:25:47 +00:00
|
|
|
|
httpPrefix, federationList, maxMentions, maxEmoji, False,
|
2020-06-09 11:03:59 +00:00
|
|
|
|
proxyType, maxReplies,
|
2020-04-05 13:25:47 +00:00
|
|
|
|
domainMaxPostsPerDay, accountMaxPostsPerDay,
|
2021-01-07 15:38:55 +00:00
|
|
|
|
allowDeletion, True, True, False, sendThreads,
|
2020-07-12 12:31:28 +00:00
|
|
|
|
False)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def createServerBob(path: str, domain: str, port: int,
|
|
|
|
|
aliceAddress: str, federationList: [],
|
|
|
|
|
hasFollows: bool, hasPosts: bool,
|
2020-09-27 19:27:24 +00:00
|
|
|
|
sendThreads: []):
|
2020-04-05 13:25:47 +00:00
|
|
|
|
print('Creating test server: Bob on port ' + str(port))
|
2019-06-30 21:20:02 +00:00
|
|
|
|
if os.path.isdir(path):
|
|
|
|
|
shutil.rmtree(path)
|
|
|
|
|
os.mkdir(path)
|
|
|
|
|
os.chdir(path)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
nickname = 'bob'
|
|
|
|
|
httpPrefix = 'http'
|
2020-06-09 11:03:59 +00:00
|
|
|
|
proxyType = None
|
2020-04-05 13:25:47 +00:00
|
|
|
|
clientToServer = False
|
|
|
|
|
password = 'bobpass'
|
|
|
|
|
maxReplies = 64
|
|
|
|
|
domainMaxPostsPerDay = 1000
|
|
|
|
|
accountMaxPostsPerDay = 1000
|
|
|
|
|
allowDeletion = True
|
|
|
|
|
privateKeyPem, publicKeyPem, person, wfEndpoint = \
|
2020-07-12 12:31:28 +00:00
|
|
|
|
createPerson(path, nickname, domain, port, httpPrefix, True,
|
|
|
|
|
False, password)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
deleteAllPosts(path, nickname, domain, 'inbox')
|
|
|
|
|
deleteAllPosts(path, nickname, domain, 'outbox')
|
|
|
|
|
assert setRole(path, nickname, domain, 'bandname', 'bass player')
|
|
|
|
|
assert setRole(path, nickname, domain, 'bandname', 'publicist')
|
2019-07-06 13:49:25 +00:00
|
|
|
|
if hasFollows:
|
2020-04-05 13:25:47 +00:00
|
|
|
|
followPerson(path, nickname, domain,
|
|
|
|
|
'alice', aliceAddress, federationList, False)
|
|
|
|
|
followerOfPerson(path, nickname, domain,
|
|
|
|
|
'alice', aliceAddress, federationList, False)
|
2019-07-06 13:49:25 +00:00
|
|
|
|
if hasPosts:
|
2020-12-22 21:24:46 +00:00
|
|
|
|
testFollowersOnly = False
|
|
|
|
|
testSaveToFile = True
|
|
|
|
|
testCommentsEnabled = True
|
|
|
|
|
testAttachImageFilename = None
|
2020-12-22 21:27:46 +00:00
|
|
|
|
testImageDescription = None
|
|
|
|
|
testMediaType = None
|
2020-04-05 13:25:47 +00:00
|
|
|
|
createPublicPost(path, nickname, domain, port, httpPrefix,
|
|
|
|
|
"It's your life, live it your way.",
|
2020-12-22 21:24:46 +00:00
|
|
|
|
testFollowersOnly,
|
|
|
|
|
testSaveToFile,
|
|
|
|
|
clientToServer,
|
|
|
|
|
testCommentsEnabled,
|
|
|
|
|
testAttachImageFilename,
|
|
|
|
|
testMediaType,
|
2021-01-07 15:38:55 +00:00
|
|
|
|
testImageDescription)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
createPublicPost(path, nickname, domain, port, httpPrefix,
|
|
|
|
|
"One of the things I've realised is that " +
|
|
|
|
|
"I am very simple",
|
2020-12-22 21:24:46 +00:00
|
|
|
|
testFollowersOnly,
|
|
|
|
|
testSaveToFile,
|
|
|
|
|
clientToServer,
|
|
|
|
|
testCommentsEnabled,
|
|
|
|
|
testAttachImageFilename,
|
|
|
|
|
testMediaType,
|
2021-01-07 15:38:55 +00:00
|
|
|
|
testImageDescription)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
createPublicPost(path, nickname, domain, port, httpPrefix,
|
|
|
|
|
"Quantum physics is a bit of a passion of mine",
|
2020-12-22 21:24:46 +00:00
|
|
|
|
testFollowersOnly,
|
|
|
|
|
testSaveToFile,
|
|
|
|
|
clientToServer,
|
|
|
|
|
testCommentsEnabled,
|
|
|
|
|
testAttachImageFilename,
|
|
|
|
|
testMediaType,
|
2021-01-07 15:38:55 +00:00
|
|
|
|
testImageDescription)
|
2019-06-30 21:27:25 +00:00
|
|
|
|
global testServerBobRunning
|
2020-04-05 13:25:47 +00:00
|
|
|
|
testServerBobRunning = True
|
|
|
|
|
maxMentions = 10
|
|
|
|
|
maxEmoji = 10
|
|
|
|
|
onionDomain = None
|
2020-06-03 17:38:34 +00:00
|
|
|
|
i2pDomain = None
|
2020-11-20 10:58:49 +00:00
|
|
|
|
allowLocalNetworkAccess = True
|
2020-11-22 11:48:53 +00:00
|
|
|
|
maxNewswirePosts = 20
|
2020-12-13 12:44:17 +00:00
|
|
|
|
dormantMonths = 3
|
2020-12-18 11:48:00 +00:00
|
|
|
|
sendThreadsTimeoutMins = 30
|
2020-12-26 10:22:56 +00:00
|
|
|
|
maxFollowers = 10
|
2021-01-05 10:29:37 +00:00
|
|
|
|
verifyAllSignatures = True
|
2019-06-30 21:20:02 +00:00
|
|
|
|
print('Server running: Bob')
|
2021-01-05 10:29:37 +00:00
|
|
|
|
runDaemon(verifyAllSignatures,
|
|
|
|
|
sendThreadsTimeoutMins,
|
2020-12-18 11:48:00 +00:00
|
|
|
|
dormantMonths, maxNewswirePosts,
|
2020-12-13 12:44:17 +00:00
|
|
|
|
allowLocalNetworkAccess,
|
2020-12-26 10:22:56 +00:00
|
|
|
|
2048, False, True, False, False, True, maxFollowers,
|
2020-10-26 20:32:01 +00:00
|
|
|
|
0, 100, 1024, 5, False, 0,
|
2020-10-23 19:18:13 +00:00
|
|
|
|
False, 1, False, False, False,
|
2020-10-07 09:10:42 +00:00
|
|
|
|
5, True, True, 'en', __version__,
|
2020-06-03 17:38:34 +00:00
|
|
|
|
"instanceId", False, path, domain,
|
2020-08-02 09:51:20 +00:00
|
|
|
|
onionDomain, i2pDomain, None, port, port,
|
2020-04-05 13:25:47 +00:00
|
|
|
|
httpPrefix, federationList, maxMentions, maxEmoji, False,
|
2020-06-09 11:03:59 +00:00
|
|
|
|
proxyType, maxReplies,
|
2020-04-05 13:25:47 +00:00
|
|
|
|
domainMaxPostsPerDay, accountMaxPostsPerDay,
|
2021-01-07 15:38:55 +00:00
|
|
|
|
allowDeletion, True, True, False, sendThreads,
|
2020-07-12 12:31:28 +00:00
|
|
|
|
False)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def createServerEve(path: str, domain: str, port: int, federationList: [],
|
|
|
|
|
hasFollows: bool, hasPosts: bool,
|
2020-09-27 19:27:24 +00:00
|
|
|
|
sendThreads: []):
|
2020-04-05 13:25:47 +00:00
|
|
|
|
print('Creating test server: Eve on port ' + str(port))
|
2019-07-07 19:25:38 +00:00
|
|
|
|
if os.path.isdir(path):
|
|
|
|
|
shutil.rmtree(path)
|
|
|
|
|
os.mkdir(path)
|
|
|
|
|
os.chdir(path)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
nickname = 'eve'
|
|
|
|
|
httpPrefix = 'http'
|
2020-06-09 11:03:59 +00:00
|
|
|
|
proxyType = None
|
2020-04-05 13:25:47 +00:00
|
|
|
|
password = 'evepass'
|
|
|
|
|
maxReplies = 64
|
|
|
|
|
allowDeletion = True
|
|
|
|
|
privateKeyPem, publicKeyPem, person, wfEndpoint = \
|
2020-07-12 12:31:28 +00:00
|
|
|
|
createPerson(path, nickname, domain, port, httpPrefix, True,
|
|
|
|
|
False, password)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
deleteAllPosts(path, nickname, domain, 'inbox')
|
|
|
|
|
deleteAllPosts(path, nickname, domain, 'outbox')
|
2019-07-07 19:25:38 +00:00
|
|
|
|
global testServerEveRunning
|
2020-04-05 13:25:47 +00:00
|
|
|
|
testServerEveRunning = True
|
|
|
|
|
maxMentions = 10
|
|
|
|
|
maxEmoji = 10
|
|
|
|
|
onionDomain = None
|
2020-06-03 17:38:34 +00:00
|
|
|
|
i2pDomain = None
|
2020-11-20 10:58:49 +00:00
|
|
|
|
allowLocalNetworkAccess = True
|
2020-11-22 11:48:53 +00:00
|
|
|
|
maxNewswirePosts = 20
|
2020-12-13 12:44:17 +00:00
|
|
|
|
dormantMonths = 3
|
2020-12-18 11:48:00 +00:00
|
|
|
|
sendThreadsTimeoutMins = 30
|
2020-12-26 10:22:56 +00:00
|
|
|
|
maxFollowers = 10
|
2021-01-05 10:29:37 +00:00
|
|
|
|
verifyAllSignatures = True
|
2019-07-07 19:25:38 +00:00
|
|
|
|
print('Server running: Eve')
|
2021-01-05 10:29:37 +00:00
|
|
|
|
runDaemon(verifyAllSignatures,
|
|
|
|
|
sendThreadsTimeoutMins,
|
2020-12-18 11:48:00 +00:00
|
|
|
|
dormantMonths, maxNewswirePosts,
|
2020-12-13 12:44:17 +00:00
|
|
|
|
allowLocalNetworkAccess,
|
2020-12-26 10:22:56 +00:00
|
|
|
|
2048, False, True, False, False, True, maxFollowers,
|
2020-10-26 20:32:01 +00:00
|
|
|
|
0, 100, 1024, 5, False, 0,
|
2020-10-23 19:18:13 +00:00
|
|
|
|
False, 1, False, False, False,
|
2020-10-07 09:10:42 +00:00
|
|
|
|
5, True, True, 'en', __version__,
|
2020-06-03 17:38:34 +00:00
|
|
|
|
"instanceId", False, path, domain,
|
2020-08-02 09:51:20 +00:00
|
|
|
|
onionDomain, i2pDomain, None, port, port,
|
2020-04-05 13:25:47 +00:00
|
|
|
|
httpPrefix, federationList, maxMentions, maxEmoji, False,
|
2020-06-09 11:03:59 +00:00
|
|
|
|
proxyType, maxReplies, allowDeletion, True, True, False,
|
2021-01-07 15:38:55 +00:00
|
|
|
|
sendThreads, False)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
|
2019-07-07 19:25:38 +00:00
|
|
|
|
|
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
|
2020-04-05 13:25:47 +00:00
|
|
|
|
testServerAliceRunning = False
|
|
|
|
|
testServerBobRunning = False
|
2019-06-30 21:27:25 +00:00
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
httpPrefix = 'http'
|
2020-06-09 11:03:59 +00:00
|
|
|
|
proxyType = None
|
2019-06-30 22:56:37 +00:00
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
baseDir = os.getcwd()
|
|
|
|
|
if os.path.isdir(baseDir + '/.tests'):
|
|
|
|
|
shutil.rmtree(baseDir + '/.tests')
|
|
|
|
|
os.mkdir(baseDir + '/.tests')
|
2019-06-30 21:20:02 +00:00
|
|
|
|
|
|
|
|
|
# create the servers
|
2020-04-05 13:25:47 +00:00
|
|
|
|
aliceDir = baseDir + '/.tests/alice'
|
|
|
|
|
aliceDomain = '127.0.0.50'
|
|
|
|
|
alicePort = 61935
|
|
|
|
|
aliceAddress = aliceDomain + ':' + str(alicePort)
|
|
|
|
|
|
|
|
|
|
bobDir = baseDir + '/.tests/bob'
|
|
|
|
|
bobDomain = '127.0.0.100'
|
|
|
|
|
bobPort = 61936
|
|
|
|
|
federationList = [bobDomain, aliceDomain]
|
|
|
|
|
aliceSendThreads = []
|
|
|
|
|
bobSendThreads = []
|
|
|
|
|
bobAddress = bobDomain + ':' + str(bobPort)
|
2019-07-11 12:29:31 +00:00
|
|
|
|
|
2020-02-19 12:27:21 +00:00
|
|
|
|
global thrAlice
|
|
|
|
|
if thrAlice:
|
2020-12-18 15:29:12 +00:00
|
|
|
|
while thrAlice.is_alive():
|
2020-02-19 12:27:21 +00:00
|
|
|
|
thrAlice.stop()
|
|
|
|
|
time.sleep(1)
|
|
|
|
|
thrAlice.kill()
|
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
thrAlice = \
|
|
|
|
|
threadWithTrace(target=createServerAlice,
|
|
|
|
|
args=(aliceDir, aliceDomain, alicePort, bobAddress,
|
|
|
|
|
federationList, False, False,
|
2020-09-27 19:27:24 +00:00
|
|
|
|
aliceSendThreads),
|
2020-04-05 13:25:47 +00:00
|
|
|
|
daemon=True)
|
2020-02-19 12:27:21 +00:00
|
|
|
|
|
|
|
|
|
global thrBob
|
|
|
|
|
if thrBob:
|
2020-12-18 15:29:12 +00:00
|
|
|
|
while thrBob.is_alive():
|
2020-02-19 12:27:21 +00:00
|
|
|
|
thrBob.stop()
|
|
|
|
|
time.sleep(1)
|
|
|
|
|
thrBob.kill()
|
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
thrBob = \
|
|
|
|
|
threadWithTrace(target=createServerBob,
|
|
|
|
|
args=(bobDir, bobDomain, bobPort, aliceAddress,
|
|
|
|
|
federationList, False, False,
|
2020-09-27 19:27:24 +00:00
|
|
|
|
bobSendThreads),
|
2020-04-05 13:25:47 +00:00
|
|
|
|
daemon=True)
|
2019-07-01 21:01:43 +00:00
|
|
|
|
|
|
|
|
|
thrAlice.start()
|
2019-06-30 21:20:02 +00:00
|
|
|
|
thrBob.start()
|
2020-12-18 15:29:12 +00:00
|
|
|
|
assert thrAlice.is_alive() is True
|
|
|
|
|
assert thrBob.is_alive() is True
|
2019-06-30 21:20:02 +00:00
|
|
|
|
|
2019-06-30 21:27:25 +00:00
|
|
|
|
# wait for both servers to be running
|
|
|
|
|
while not (testServerAliceRunning and testServerBobRunning):
|
|
|
|
|
time.sleep(1)
|
2020-03-22 21:16:02 +00:00
|
|
|
|
|
2019-07-04 20:25:19 +00:00
|
|
|
|
time.sleep(1)
|
2019-06-30 21:20:02 +00:00
|
|
|
|
|
2019-07-11 12:29:31 +00:00
|
|
|
|
print('\n\n*******************************************************')
|
2019-06-30 22:56:37 +00:00
|
|
|
|
print('Alice sends to Bob')
|
|
|
|
|
os.chdir(aliceDir)
|
2020-06-09 11:03:59 +00:00
|
|
|
|
sessionAlice = createSession(proxyType)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
inReplyTo = None
|
|
|
|
|
inReplyToAtomUri = None
|
|
|
|
|
subject = None
|
|
|
|
|
alicePostLog = []
|
|
|
|
|
followersOnly = False
|
|
|
|
|
saveToFile = True
|
|
|
|
|
clientToServer = False
|
|
|
|
|
ccUrl = None
|
|
|
|
|
alicePersonCache = {}
|
|
|
|
|
aliceCachedWebfingers = {}
|
|
|
|
|
attachedImageFilename = baseDir + '/img/logo.png'
|
|
|
|
|
mediaType = getAttachmentMediaType(attachedImageFilename)
|
|
|
|
|
attachedImageDescription = 'Logo'
|
|
|
|
|
isArticle = False
|
2019-07-11 12:29:31 +00:00
|
|
|
|
# nothing in Alice's outbox
|
2020-04-05 13:25:47 +00:00
|
|
|
|
outboxPath = aliceDir + '/accounts/alice@' + aliceDomain + '/outbox'
|
|
|
|
|
assert len([name for name in os.listdir(outboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(outboxPath, name))]) == 0
|
|
|
|
|
|
|
|
|
|
sendResult = \
|
|
|
|
|
sendPost(__version__,
|
|
|
|
|
sessionAlice, aliceDir, 'alice', aliceDomain, alicePort,
|
|
|
|
|
'bob', bobDomain, bobPort, ccUrl, httpPrefix,
|
|
|
|
|
'Why is a mouse when it spins? ' +
|
|
|
|
|
'यह एक परीक्षण है #sillyquestion',
|
|
|
|
|
followersOnly,
|
2020-08-21 17:40:50 +00:00
|
|
|
|
saveToFile, clientToServer, True,
|
|
|
|
|
attachedImageFilename, mediaType,
|
2021-01-07 15:38:55 +00:00
|
|
|
|
attachedImageDescription, federationList,
|
2020-04-05 13:25:47 +00:00
|
|
|
|
aliceSendThreads, alicePostLog, aliceCachedWebfingers,
|
|
|
|
|
alicePersonCache, isArticle, inReplyTo,
|
|
|
|
|
inReplyToAtomUri, subject)
|
|
|
|
|
print('sendResult: ' + str(sendResult))
|
|
|
|
|
|
|
|
|
|
queuePath = bobDir + '/accounts/bob@' + bobDomain + '/queue'
|
|
|
|
|
inboxPath = bobDir + '/accounts/bob@' + bobDomain + '/inbox'
|
|
|
|
|
mPath = getMediaPath()
|
|
|
|
|
mediaPath = aliceDir + '/' + mPath
|
2019-07-07 22:25:22 +00:00
|
|
|
|
for i in range(30):
|
2019-07-04 20:36:12 +00:00
|
|
|
|
if os.path.isdir(inboxPath):
|
2020-04-05 13:25:47 +00:00
|
|
|
|
if len([name for name in os.listdir(inboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(inboxPath, name))]) > 0:
|
|
|
|
|
if len([name for name in os.listdir(outboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(outboxPath,
|
|
|
|
|
name))]) == 1:
|
|
|
|
|
if len([name for name in os.listdir(mediaPath)
|
|
|
|
|
if os.path.isfile(os.path.join(mediaPath,
|
|
|
|
|
name))]) > 0:
|
|
|
|
|
if len([name for name in os.listdir(queuePath)
|
|
|
|
|
if os.path.isfile(os.path.join(queuePath,
|
|
|
|
|
name))]) == 0:
|
2019-10-19 17:50:05 +00:00
|
|
|
|
break
|
2019-07-01 21:01:43 +00:00
|
|
|
|
time.sleep(1)
|
2019-07-09 08:52:53 +00:00
|
|
|
|
|
2020-12-06 15:05:22 +00:00
|
|
|
|
# check that a news account exists
|
|
|
|
|
newsActorDir = aliceDir + '/accounts/news@' + aliceDomain
|
|
|
|
|
print("newsActorDir: " + newsActorDir)
|
|
|
|
|
assert os.path.isdir(newsActorDir)
|
|
|
|
|
newsActorFile = newsActorDir + '.json'
|
|
|
|
|
assert os.path.isfile(newsActorFile)
|
|
|
|
|
newsActorJson = loadJson(newsActorFile)
|
|
|
|
|
assert newsActorJson
|
|
|
|
|
assert newsActorJson.get("id")
|
|
|
|
|
# check the id of the news actor
|
|
|
|
|
print('News actor Id: ' + newsActorJson["id"])
|
|
|
|
|
assert (newsActorJson["id"] ==
|
|
|
|
|
httpPrefix + '://' + aliceAddress + '/users/news')
|
|
|
|
|
|
2019-07-12 19:26:54 +00:00
|
|
|
|
# Image attachment created
|
2020-04-05 13:25:47 +00:00
|
|
|
|
assert len([name for name in os.listdir(mediaPath)
|
|
|
|
|
if os.path.isfile(os.path.join(mediaPath, name))]) > 0
|
2019-07-11 12:29:31 +00:00
|
|
|
|
# inbox item created
|
2020-04-05 13:25:47 +00:00
|
|
|
|
assert len([name for name in os.listdir(inboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(inboxPath, name))]) == 1
|
2019-07-11 12:29:31 +00:00
|
|
|
|
# queue item removed
|
2020-04-05 13:25:47 +00:00
|
|
|
|
testval = len([name for name in os.listdir(queuePath)
|
|
|
|
|
if os.path.isfile(os.path.join(queuePath, name))])
|
|
|
|
|
print('queuePath: ' + queuePath + ' '+str(testval))
|
|
|
|
|
assert testval == 0
|
|
|
|
|
assert validInbox(bobDir, 'bob', bobDomain)
|
|
|
|
|
assert validInboxFilenames(bobDir, 'bob', bobDomain,
|
|
|
|
|
aliceDomain, alicePort)
|
2019-11-09 09:50:58 +00:00
|
|
|
|
print('Check that message received from Alice contains the expected text')
|
|
|
|
|
for name in os.listdir(inboxPath):
|
2020-04-05 13:25:47 +00:00
|
|
|
|
filename = os.path.join(inboxPath, name)
|
2019-11-09 09:50:58 +00:00
|
|
|
|
assert os.path.isfile(filename)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
receivedJson = loadJson(filename, 0)
|
2019-11-23 10:08:00 +00:00
|
|
|
|
if receivedJson:
|
2019-11-09 09:50:58 +00:00
|
|
|
|
pprint(receivedJson['object']['content'])
|
2019-11-09 09:52:09 +00:00
|
|
|
|
assert receivedJson
|
2020-04-05 13:25:47 +00:00
|
|
|
|
assert 'Why is a mouse when it spins?' in \
|
|
|
|
|
receivedJson['object']['content']
|
2019-11-09 09:52:09 +00:00
|
|
|
|
assert 'यह एक परीक्षण है' in receivedJson['object']['content']
|
|
|
|
|
|
2019-07-11 12:59:00 +00:00
|
|
|
|
print('\n\n*******************************************************')
|
|
|
|
|
print("Bob likes Alice's post")
|
|
|
|
|
|
2020-12-22 21:24:46 +00:00
|
|
|
|
aliceDomainStr = aliceDomain + ':' + str(alicePort)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
followerOfPerson(bobDir, 'bob', bobDomain, 'alice',
|
2020-12-22 21:24:46 +00:00
|
|
|
|
aliceDomainStr, federationList, False)
|
|
|
|
|
bobDomainStr = bobDomain + ':' + str(bobPort)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
followPerson(aliceDir, 'alice', aliceDomain, 'bob',
|
2020-12-22 21:24:46 +00:00
|
|
|
|
bobDomainStr, federationList, False)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
|
2020-06-09 11:03:59 +00:00
|
|
|
|
sessionBob = createSession(proxyType)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
bobPostLog = []
|
|
|
|
|
bobPersonCache = {}
|
|
|
|
|
bobCachedWebfingers = {}
|
|
|
|
|
statusNumber = None
|
|
|
|
|
outboxPostFilename = None
|
|
|
|
|
outboxPath = aliceDir + '/accounts/alice@' + aliceDomain + '/outbox'
|
2019-07-11 12:59:00 +00:00
|
|
|
|
for name in os.listdir(outboxPath):
|
|
|
|
|
if '#statuses#' in name:
|
2020-04-05 13:25:47 +00:00
|
|
|
|
statusNumber = \
|
|
|
|
|
int(name.split('#statuses#')[1].replace('.json', ''))
|
|
|
|
|
outboxPostFilename = outboxPath + '/' + name
|
|
|
|
|
assert statusNumber > 0
|
2019-07-11 12:59:00 +00:00
|
|
|
|
assert outboxPostFilename
|
2020-04-05 13:25:47 +00:00
|
|
|
|
assert likePost({}, sessionBob, bobDir, federationList,
|
|
|
|
|
'bob', bobDomain, bobPort, httpPrefix,
|
|
|
|
|
'alice', aliceDomain, alicePort, [],
|
|
|
|
|
statusNumber, False, bobSendThreads, bobPostLog,
|
|
|
|
|
bobPersonCache, bobCachedWebfingers,
|
|
|
|
|
True, __version__)
|
2019-07-11 12:59:00 +00:00
|
|
|
|
|
|
|
|
|
for i in range(20):
|
|
|
|
|
if 'likes' in open(outboxPostFilename).read():
|
|
|
|
|
break
|
|
|
|
|
time.sleep(1)
|
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
alicePostJson = loadJson(outboxPostFilename, 0)
|
2019-11-23 10:08:00 +00:00
|
|
|
|
if alicePostJson:
|
2019-07-11 12:59:00 +00:00
|
|
|
|
pprint(alicePostJson)
|
2020-03-22 21:16:02 +00:00
|
|
|
|
|
2019-07-11 12:59:00 +00:00
|
|
|
|
assert 'likes' in open(outboxPostFilename).read()
|
2019-07-11 17:55:10 +00:00
|
|
|
|
|
|
|
|
|
print('\n\n*******************************************************')
|
|
|
|
|
print("Bob repeats Alice's post")
|
2020-04-05 13:25:47 +00:00
|
|
|
|
objectUrl = \
|
|
|
|
|
httpPrefix + '://' + aliceDomain + ':' + str(alicePort) + \
|
|
|
|
|
'/users/alice/statuses/' + str(statusNumber)
|
|
|
|
|
inboxPath = aliceDir + '/accounts/alice@' + aliceDomain + '/inbox'
|
|
|
|
|
outboxPath = bobDir + '/accounts/bob@' + bobDomain + '/outbox'
|
|
|
|
|
outboxBeforeAnnounceCount = \
|
|
|
|
|
len([name for name in os.listdir(outboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(outboxPath, name))])
|
|
|
|
|
beforeAnnounceCount = \
|
|
|
|
|
len([name for name in os.listdir(inboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(inboxPath, name))])
|
|
|
|
|
print('inbox items before announce: ' + str(beforeAnnounceCount))
|
|
|
|
|
print('outbox items before announce: ' + str(outboxBeforeAnnounceCount))
|
|
|
|
|
assert outboxBeforeAnnounceCount == 0
|
|
|
|
|
assert beforeAnnounceCount == 0
|
|
|
|
|
announcePublic(sessionBob, bobDir, federationList,
|
|
|
|
|
'bob', bobDomain, bobPort, httpPrefix,
|
|
|
|
|
objectUrl,
|
|
|
|
|
False, bobSendThreads, bobPostLog,
|
|
|
|
|
bobPersonCache, bobCachedWebfingers,
|
|
|
|
|
True, __version__)
|
|
|
|
|
announceMessageArrived = False
|
|
|
|
|
outboxMessageArrived = False
|
2019-07-11 19:31:02 +00:00
|
|
|
|
for i in range(10):
|
|
|
|
|
time.sleep(1)
|
2020-03-27 19:54:41 +00:00
|
|
|
|
if not os.path.isdir(inboxPath):
|
|
|
|
|
continue
|
2020-04-05 13:25:47 +00:00
|
|
|
|
if len([name for name in os.listdir(outboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(outboxPath, name))]) > 0:
|
|
|
|
|
outboxMessageArrived = True
|
2020-03-27 19:54:41 +00:00
|
|
|
|
print('Announce created by Bob')
|
2020-04-05 13:25:47 +00:00
|
|
|
|
if len([name for name in os.listdir(inboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(inboxPath, name))]) > 0:
|
|
|
|
|
announceMessageArrived = True
|
2020-03-27 19:54:41 +00:00
|
|
|
|
print('Announce message sent to Alice!')
|
|
|
|
|
if announceMessageArrived and outboxMessageArrived:
|
|
|
|
|
break
|
2020-04-05 13:25:47 +00:00
|
|
|
|
afterAnnounceCount = \
|
|
|
|
|
len([name for name in os.listdir(inboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(inboxPath, name))])
|
|
|
|
|
outboxAfterAnnounceCount = \
|
|
|
|
|
len([name for name in os.listdir(outboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(outboxPath, name))])
|
|
|
|
|
print('inbox items after announce: ' + str(afterAnnounceCount))
|
|
|
|
|
print('outbox items after announce: ' + str(outboxAfterAnnounceCount))
|
|
|
|
|
assert afterAnnounceCount == beforeAnnounceCount+1
|
|
|
|
|
assert outboxAfterAnnounceCount == outboxBeforeAnnounceCount + 1
|
2019-06-30 21:20:02 +00:00
|
|
|
|
# stop the servers
|
|
|
|
|
thrAlice.kill()
|
|
|
|
|
thrAlice.join()
|
2020-12-18 15:29:12 +00:00
|
|
|
|
assert thrAlice.is_alive() is False
|
2019-06-30 21:20:02 +00:00
|
|
|
|
|
|
|
|
|
thrBob.kill()
|
|
|
|
|
thrBob.join()
|
2020-12-18 15:29:12 +00:00
|
|
|
|
assert thrBob.is_alive() is False
|
2019-06-30 21:20:02 +00:00
|
|
|
|
|
2019-07-05 12:35:29 +00:00
|
|
|
|
os.chdir(baseDir)
|
|
|
|
|
shutil.rmtree(aliceDir)
|
|
|
|
|
shutil.rmtree(bobDir)
|
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
|
2019-10-15 09:31:10 +00:00
|
|
|
|
def testFollowBetweenServers():
|
|
|
|
|
print('Testing sending a follow request from one server to another')
|
|
|
|
|
|
|
|
|
|
global testServerAliceRunning
|
|
|
|
|
global testServerBobRunning
|
2020-04-05 13:25:47 +00:00
|
|
|
|
testServerAliceRunning = False
|
|
|
|
|
testServerBobRunning = False
|
2019-10-15 09:31:10 +00:00
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
httpPrefix = 'http'
|
2020-06-09 11:03:59 +00:00
|
|
|
|
proxyType = None
|
2020-04-05 13:25:47 +00:00
|
|
|
|
federationList = []
|
2019-10-15 09:31:10 +00:00
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
baseDir = os.getcwd()
|
|
|
|
|
if os.path.isdir(baseDir + '/.tests'):
|
|
|
|
|
shutil.rmtree(baseDir + '/.tests')
|
|
|
|
|
os.mkdir(baseDir + '/.tests')
|
2019-10-15 09:31:10 +00:00
|
|
|
|
|
|
|
|
|
# create the servers
|
2020-04-05 13:25:47 +00:00
|
|
|
|
aliceDir = baseDir + '/.tests/alice'
|
|
|
|
|
aliceDomain = '127.0.0.47'
|
|
|
|
|
alicePort = 61935
|
|
|
|
|
aliceSendThreads = []
|
|
|
|
|
aliceAddress = aliceDomain + ':' + str(alicePort)
|
|
|
|
|
|
|
|
|
|
bobDir = baseDir + '/.tests/bob'
|
|
|
|
|
bobDomain = '127.0.0.79'
|
|
|
|
|
bobPort = 61936
|
|
|
|
|
bobSendThreads = []
|
|
|
|
|
bobAddress = bobDomain + ':' + str(bobPort)
|
2020-02-19 12:27:21 +00:00
|
|
|
|
|
|
|
|
|
global thrAlice
|
|
|
|
|
if thrAlice:
|
2020-12-18 15:29:12 +00:00
|
|
|
|
while thrAlice.is_alive():
|
2020-02-19 12:27:21 +00:00
|
|
|
|
thrAlice.stop()
|
|
|
|
|
time.sleep(1)
|
|
|
|
|
thrAlice.kill()
|
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
thrAlice = \
|
|
|
|
|
threadWithTrace(target=createServerAlice,
|
|
|
|
|
args=(aliceDir, aliceDomain, alicePort, bobAddress,
|
|
|
|
|
federationList, False, False,
|
2020-09-27 19:27:24 +00:00
|
|
|
|
aliceSendThreads),
|
2020-04-05 13:25:47 +00:00
|
|
|
|
daemon=True)
|
2019-10-15 09:31:10 +00:00
|
|
|
|
|
2020-02-19 12:27:21 +00:00
|
|
|
|
global thrBob
|
|
|
|
|
if thrBob:
|
2020-12-18 15:29:12 +00:00
|
|
|
|
while thrBob.is_alive():
|
2020-02-19 12:27:21 +00:00
|
|
|
|
thrBob.stop()
|
|
|
|
|
time.sleep(1)
|
|
|
|
|
thrBob.kill()
|
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
thrBob = \
|
|
|
|
|
threadWithTrace(target=createServerBob,
|
|
|
|
|
args=(bobDir, bobDomain, bobPort, aliceAddress,
|
|
|
|
|
federationList, False, False,
|
2020-09-27 19:27:24 +00:00
|
|
|
|
bobSendThreads),
|
2020-04-05 13:25:47 +00:00
|
|
|
|
daemon=True)
|
2019-10-15 09:31:10 +00:00
|
|
|
|
|
|
|
|
|
thrAlice.start()
|
|
|
|
|
thrBob.start()
|
2020-12-18 15:29:12 +00:00
|
|
|
|
assert thrAlice.is_alive() is True
|
|
|
|
|
assert thrBob.is_alive() is True
|
2019-10-15 09:31:10 +00:00
|
|
|
|
|
|
|
|
|
# wait for all servers to be running
|
2020-04-05 13:25:47 +00:00
|
|
|
|
ctr = 0
|
2019-10-15 09:31:10 +00:00
|
|
|
|
while not (testServerAliceRunning and testServerBobRunning):
|
|
|
|
|
time.sleep(1)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
ctr += 1
|
|
|
|
|
if ctr > 60:
|
2019-10-15 09:31:10 +00:00
|
|
|
|
break
|
2020-04-05 13:25:47 +00:00
|
|
|
|
print('Alice online: ' + str(testServerAliceRunning))
|
|
|
|
|
print('Bob online: ' + str(testServerBobRunning))
|
|
|
|
|
assert ctr <= 60
|
2019-10-15 09:31:10 +00:00
|
|
|
|
time.sleep(1)
|
|
|
|
|
|
|
|
|
|
# In the beginning all was calm and there were no follows
|
|
|
|
|
|
|
|
|
|
print('*********************************************************')
|
|
|
|
|
print('Alice sends a follow request to Bob')
|
|
|
|
|
os.chdir(aliceDir)
|
2020-06-09 11:03:59 +00:00
|
|
|
|
sessionAlice = createSession(proxyType)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
inReplyTo = None
|
|
|
|
|
inReplyToAtomUri = None
|
|
|
|
|
subject = None
|
|
|
|
|
alicePostLog = []
|
|
|
|
|
followersOnly = False
|
|
|
|
|
saveToFile = True
|
|
|
|
|
clientToServer = False
|
|
|
|
|
ccUrl = None
|
|
|
|
|
alicePersonCache = {}
|
|
|
|
|
aliceCachedWebfingers = {}
|
|
|
|
|
alicePostLog = []
|
|
|
|
|
sendResult = \
|
|
|
|
|
sendFollowRequest(sessionAlice, aliceDir,
|
|
|
|
|
'alice', aliceDomain, alicePort, httpPrefix,
|
|
|
|
|
'bob', bobDomain, bobPort, httpPrefix,
|
|
|
|
|
clientToServer, federationList,
|
|
|
|
|
aliceSendThreads, alicePostLog,
|
|
|
|
|
aliceCachedWebfingers, alicePersonCache,
|
2020-12-26 10:22:56 +00:00
|
|
|
|
True, __version__)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
print('sendResult: ' + str(sendResult))
|
2019-10-15 09:31:10 +00:00
|
|
|
|
|
2020-12-23 10:58:50 +00:00
|
|
|
|
for t in range(16):
|
2020-04-05 13:25:47 +00:00
|
|
|
|
if os.path.isfile(bobDir + '/accounts/bob@' +
|
|
|
|
|
bobDomain + '/followers.txt'):
|
|
|
|
|
if os.path.isfile(aliceDir + '/accounts/alice@' +
|
|
|
|
|
aliceDomain + '/following.txt'):
|
2020-09-03 12:16:24 +00:00
|
|
|
|
if os.path.isfile(aliceDir + '/accounts/alice@' +
|
|
|
|
|
aliceDomain + '/followingCalendar.txt'):
|
|
|
|
|
break
|
2019-10-15 09:31:10 +00:00
|
|
|
|
time.sleep(1)
|
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
assert validInbox(bobDir, 'bob', bobDomain)
|
|
|
|
|
assert validInboxFilenames(bobDir, 'bob', bobDomain,
|
|
|
|
|
aliceDomain, alicePort)
|
2020-09-03 12:16:24 +00:00
|
|
|
|
assert 'alice@' + aliceDomain in open(bobDir + '/accounts/bob@' +
|
|
|
|
|
bobDomain + '/followers.txt').read()
|
|
|
|
|
assert 'bob@' + bobDomain in open(aliceDir + '/accounts/alice@' +
|
|
|
|
|
aliceDomain + '/following.txt').read()
|
|
|
|
|
assert 'bob@' + bobDomain in open(aliceDir + '/accounts/alice@' +
|
|
|
|
|
aliceDomain +
|
|
|
|
|
'/followingCalendar.txt').read()
|
2019-10-15 09:31:10 +00:00
|
|
|
|
|
|
|
|
|
print('\n\n*********************************************************')
|
|
|
|
|
print('Alice sends a message to Bob')
|
2020-04-05 13:25:47 +00:00
|
|
|
|
alicePostLog = []
|
|
|
|
|
alicePersonCache = {}
|
|
|
|
|
aliceCachedWebfingers = {}
|
|
|
|
|
alicePostLog = []
|
|
|
|
|
isArticle = False
|
|
|
|
|
sendResult = \
|
|
|
|
|
sendPost(__version__,
|
|
|
|
|
sessionAlice, aliceDir, 'alice', aliceDomain, alicePort,
|
|
|
|
|
'bob', bobDomain, bobPort, ccUrl,
|
|
|
|
|
httpPrefix, 'Alice message', followersOnly, saveToFile,
|
2020-08-21 17:40:50 +00:00
|
|
|
|
clientToServer, True,
|
2021-01-07 15:38:55 +00:00
|
|
|
|
None, None, None, federationList,
|
2020-04-05 13:25:47 +00:00
|
|
|
|
aliceSendThreads, alicePostLog, aliceCachedWebfingers,
|
|
|
|
|
alicePersonCache, isArticle, inReplyTo,
|
|
|
|
|
inReplyToAtomUri, subject)
|
|
|
|
|
print('sendResult: ' + str(sendResult))
|
|
|
|
|
|
|
|
|
|
queuePath = bobDir + '/accounts/bob@' + bobDomain + '/queue'
|
|
|
|
|
inboxPath = bobDir + '/accounts/bob@' + bobDomain + '/inbox'
|
|
|
|
|
aliceMessageArrived = False
|
2019-10-15 09:31:10 +00:00
|
|
|
|
for i in range(20):
|
|
|
|
|
time.sleep(1)
|
|
|
|
|
if os.path.isdir(inboxPath):
|
2020-04-05 13:25:47 +00:00
|
|
|
|
if len([name for name in os.listdir(inboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(inboxPath, name))]) > 0:
|
|
|
|
|
aliceMessageArrived = True
|
2019-10-15 09:31:10 +00:00
|
|
|
|
print('Alice message sent to Bob!')
|
|
|
|
|
break
|
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
assert aliceMessageArrived is True
|
2019-10-15 09:31:10 +00:00
|
|
|
|
print('Message from Alice to Bob succeeded')
|
|
|
|
|
|
|
|
|
|
# stop the servers
|
|
|
|
|
thrAlice.kill()
|
|
|
|
|
thrAlice.join()
|
2020-12-18 15:29:12 +00:00
|
|
|
|
assert thrAlice.is_alive() is False
|
2019-10-15 09:31:10 +00:00
|
|
|
|
|
|
|
|
|
thrBob.kill()
|
|
|
|
|
thrBob.join()
|
2020-12-18 15:29:12 +00:00
|
|
|
|
assert thrBob.is_alive() is False
|
2020-03-22 21:16:02 +00:00
|
|
|
|
|
2019-07-09 08:52:53 +00:00
|
|
|
|
# queue item removed
|
2019-11-09 21:39:04 +00:00
|
|
|
|
time.sleep(4)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
assert len([name for name in os.listdir(queuePath)
|
|
|
|
|
if os.path.isfile(os.path.join(queuePath, name))]) == 0
|
2020-03-22 21:16:02 +00:00
|
|
|
|
|
2019-07-06 13:49:25 +00:00
|
|
|
|
os.chdir(baseDir)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
shutil.rmtree(baseDir + '/.tests')
|
|
|
|
|
|
2019-07-06 13:49:25 +00:00
|
|
|
|
|
2019-07-05 12:35:29 +00:00
|
|
|
|
def testFollowersOfPerson():
|
|
|
|
|
print('testFollowersOfPerson')
|
2020-04-05 13:25:47 +00:00
|
|
|
|
currDir = os.getcwd()
|
|
|
|
|
nickname = 'mxpop'
|
|
|
|
|
domain = 'diva.domain'
|
|
|
|
|
password = 'birb'
|
|
|
|
|
port = 80
|
|
|
|
|
httpPrefix = 'https'
|
|
|
|
|
federationList = []
|
|
|
|
|
baseDir = currDir + '/.tests_followersofperson'
|
2019-07-05 12:35:29 +00:00
|
|
|
|
if os.path.isdir(baseDir):
|
|
|
|
|
shutil.rmtree(baseDir)
|
|
|
|
|
os.mkdir(baseDir)
|
2020-03-22 21:16:02 +00:00
|
|
|
|
os.chdir(baseDir)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
createPerson(baseDir, nickname, domain, port,
|
2020-07-12 12:31:28 +00:00
|
|
|
|
httpPrefix, True, False, password)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
createPerson(baseDir, 'maxboardroom', domain, port,
|
2020-07-12 12:31:28 +00:00
|
|
|
|
httpPrefix, True, False, password)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
createPerson(baseDir, 'ultrapancake', domain, port,
|
2020-07-12 12:31:28 +00:00
|
|
|
|
httpPrefix, True, False, password)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
createPerson(baseDir, 'drokk', domain, port,
|
2020-07-12 12:31:28 +00:00
|
|
|
|
httpPrefix, True, False, password)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
createPerson(baseDir, 'sausagedog', domain, port,
|
2020-07-12 12:31:28 +00:00
|
|
|
|
httpPrefix, True, False, password)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
|
|
|
|
|
clearFollows(baseDir, nickname, domain)
|
|
|
|
|
followPerson(baseDir, nickname, domain, 'maxboardroom', domain,
|
|
|
|
|
federationList, False)
|
|
|
|
|
followPerson(baseDir, 'drokk', domain, 'ultrapancake', domain,
|
|
|
|
|
federationList, False)
|
2019-07-05 12:35:29 +00:00
|
|
|
|
# deliberate duplication
|
2020-04-05 13:25:47 +00:00
|
|
|
|
followPerson(baseDir, 'drokk', domain, 'ultrapancake', domain,
|
|
|
|
|
federationList, False)
|
|
|
|
|
followPerson(baseDir, 'sausagedog', domain, 'ultrapancake', domain,
|
|
|
|
|
federationList, False)
|
|
|
|
|
followPerson(baseDir, nickname, domain, 'ultrapancake', domain,
|
|
|
|
|
federationList, False)
|
|
|
|
|
followPerson(baseDir, nickname, domain, 'someother', 'randodomain.net',
|
|
|
|
|
federationList, False)
|
|
|
|
|
|
|
|
|
|
followList = getFollowersOfPerson(baseDir, 'ultrapancake', domain)
|
|
|
|
|
assert len(followList) == 3
|
|
|
|
|
assert 'mxpop@' + domain in followList
|
|
|
|
|
assert 'drokk@' + domain in followList
|
|
|
|
|
assert 'sausagedog@' + domain in followList
|
2019-07-05 12:35:29 +00:00
|
|
|
|
os.chdir(currDir)
|
|
|
|
|
shutil.rmtree(baseDir)
|
2019-07-05 14:25:15 +00:00
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
|
2019-07-05 14:25:15 +00:00
|
|
|
|
def testNoOfFollowersOnDomain():
|
|
|
|
|
print('testNoOfFollowersOnDomain')
|
2020-04-05 13:25:47 +00:00
|
|
|
|
currDir = os.getcwd()
|
|
|
|
|
nickname = 'mxpop'
|
|
|
|
|
domain = 'diva.domain'
|
|
|
|
|
otherdomain = 'soup.dragon'
|
|
|
|
|
password = 'birb'
|
|
|
|
|
port = 80
|
|
|
|
|
httpPrefix = 'https'
|
|
|
|
|
federationList = []
|
|
|
|
|
baseDir = currDir + '/.tests_nooffollowersOndomain'
|
2019-07-05 14:25:15 +00:00
|
|
|
|
if os.path.isdir(baseDir):
|
|
|
|
|
shutil.rmtree(baseDir)
|
|
|
|
|
os.mkdir(baseDir)
|
2020-03-22 21:16:02 +00:00
|
|
|
|
os.chdir(baseDir)
|
2020-07-12 12:31:28 +00:00
|
|
|
|
createPerson(baseDir, nickname, domain, port, httpPrefix, True,
|
|
|
|
|
False, password)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
createPerson(baseDir, 'maxboardroom', otherdomain, port,
|
2020-07-12 12:31:28 +00:00
|
|
|
|
httpPrefix, True, False, password)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
createPerson(baseDir, 'ultrapancake', otherdomain, port,
|
2020-07-12 12:31:28 +00:00
|
|
|
|
httpPrefix, True, False, password)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
createPerson(baseDir, 'drokk', otherdomain, port,
|
2020-07-12 12:31:28 +00:00
|
|
|
|
httpPrefix, True, False, password)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
createPerson(baseDir, 'sausagedog', otherdomain, port,
|
2020-07-12 12:31:28 +00:00
|
|
|
|
httpPrefix, True, False, password)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
|
|
|
|
|
followPerson(baseDir, 'drokk', otherdomain, nickname, domain,
|
|
|
|
|
federationList, False)
|
|
|
|
|
followPerson(baseDir, 'sausagedog', otherdomain, nickname, domain,
|
|
|
|
|
federationList, False)
|
|
|
|
|
followPerson(baseDir, 'maxboardroom', otherdomain, nickname, domain,
|
|
|
|
|
federationList, False)
|
|
|
|
|
|
|
|
|
|
followerOfPerson(baseDir, nickname, domain,
|
|
|
|
|
'cucumber', 'sandwiches.party',
|
|
|
|
|
federationList, False)
|
|
|
|
|
followerOfPerson(baseDir, nickname, domain,
|
|
|
|
|
'captainsensible', 'damned.zone',
|
|
|
|
|
federationList, False)
|
|
|
|
|
followerOfPerson(baseDir, nickname, domain, 'pilchard', 'zombies.attack',
|
|
|
|
|
federationList, False)
|
|
|
|
|
followerOfPerson(baseDir, nickname, domain, 'drokk', otherdomain,
|
|
|
|
|
federationList, False)
|
|
|
|
|
followerOfPerson(baseDir, nickname, domain, 'sausagedog', otherdomain,
|
|
|
|
|
federationList, False)
|
|
|
|
|
followerOfPerson(baseDir, nickname, domain, 'maxboardroom', otherdomain,
|
|
|
|
|
federationList, False)
|
|
|
|
|
|
|
|
|
|
followersOnOtherDomain = \
|
|
|
|
|
noOfFollowersOnDomain(baseDir, nickname + '@' + domain, otherdomain)
|
|
|
|
|
assert followersOnOtherDomain == 3
|
|
|
|
|
|
2020-12-22 13:57:24 +00:00
|
|
|
|
unfollowerOfAccount(baseDir, nickname, domain, 'sausagedog', otherdomain)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
followersOnOtherDomain = \
|
|
|
|
|
noOfFollowersOnDomain(baseDir, nickname + '@' + domain, otherdomain)
|
|
|
|
|
assert followersOnOtherDomain == 2
|
2020-03-22 21:16:02 +00:00
|
|
|
|
|
2019-07-05 14:25:15 +00:00
|
|
|
|
os.chdir(currDir)
|
|
|
|
|
shutil.rmtree(baseDir)
|
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
|
2019-07-08 08:51:33 +00:00
|
|
|
|
def testGroupFollowers():
|
|
|
|
|
print('testGroupFollowers')
|
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
currDir = os.getcwd()
|
|
|
|
|
nickname = 'test735'
|
|
|
|
|
domain = 'mydomain.com'
|
|
|
|
|
password = 'somepass'
|
|
|
|
|
port = 80
|
|
|
|
|
httpPrefix = 'https'
|
|
|
|
|
federationList = []
|
|
|
|
|
baseDir = currDir + '/.tests_testgroupfollowers'
|
2019-07-08 08:51:33 +00:00
|
|
|
|
if os.path.isdir(baseDir):
|
|
|
|
|
shutil.rmtree(baseDir)
|
|
|
|
|
os.mkdir(baseDir)
|
2020-03-22 21:16:02 +00:00
|
|
|
|
os.chdir(baseDir)
|
2020-07-12 12:31:28 +00:00
|
|
|
|
createPerson(baseDir, nickname, domain, port, httpPrefix, True,
|
|
|
|
|
False, password)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
|
|
|
|
|
clearFollowers(baseDir, nickname, domain)
|
|
|
|
|
followerOfPerson(baseDir, nickname, domain, 'badger', 'wild.domain',
|
|
|
|
|
federationList, False)
|
|
|
|
|
followerOfPerson(baseDir, nickname, domain, 'squirrel', 'wild.domain',
|
|
|
|
|
federationList, False)
|
|
|
|
|
followerOfPerson(baseDir, nickname, domain, 'rodent', 'wild.domain',
|
|
|
|
|
federationList, False)
|
|
|
|
|
followerOfPerson(baseDir, nickname, domain, 'utterly', 'clutterly.domain',
|
|
|
|
|
federationList, False)
|
|
|
|
|
followerOfPerson(baseDir, nickname, domain, 'zonked', 'zzz.domain',
|
|
|
|
|
federationList, False)
|
|
|
|
|
followerOfPerson(baseDir, nickname, domain, 'nap', 'zzz.domain',
|
|
|
|
|
federationList, False)
|
|
|
|
|
|
|
|
|
|
grouped = groupFollowersByDomain(baseDir, nickname, domain)
|
|
|
|
|
assert len(grouped.items()) == 3
|
2019-07-08 08:51:33 +00:00
|
|
|
|
assert grouped.get('zzz.domain')
|
|
|
|
|
assert grouped.get('clutterly.domain')
|
|
|
|
|
assert grouped.get('wild.domain')
|
2020-04-05 13:25:47 +00:00
|
|
|
|
assert len(grouped['zzz.domain']) == 2
|
|
|
|
|
assert len(grouped['wild.domain']) == 3
|
|
|
|
|
assert len(grouped['clutterly.domain']) == 1
|
2020-03-22 21:16:02 +00:00
|
|
|
|
|
2019-07-08 08:51:33 +00:00
|
|
|
|
os.chdir(currDir)
|
|
|
|
|
shutil.rmtree(baseDir)
|
|
|
|
|
|
2020-03-22 21:16:02 +00:00
|
|
|
|
|
2019-07-03 09:24:55 +00:00
|
|
|
|
def testFollows():
|
2019-07-03 10:04:23 +00:00
|
|
|
|
print('testFollows')
|
2020-04-05 13:25:47 +00:00
|
|
|
|
currDir = os.getcwd()
|
|
|
|
|
nickname = 'test529'
|
|
|
|
|
domain = 'testdomain.com'
|
|
|
|
|
password = 'mypass'
|
|
|
|
|
port = 80
|
|
|
|
|
httpPrefix = 'https'
|
|
|
|
|
federationList = ['wild.com', 'mesh.com']
|
|
|
|
|
baseDir = currDir + '/.tests_testfollows'
|
2019-07-03 09:24:55 +00:00
|
|
|
|
if os.path.isdir(baseDir):
|
|
|
|
|
shutil.rmtree(baseDir)
|
|
|
|
|
os.mkdir(baseDir)
|
2020-03-22 21:16:02 +00:00
|
|
|
|
os.chdir(baseDir)
|
2020-07-12 12:31:28 +00:00
|
|
|
|
createPerson(baseDir, nickname, domain, port, httpPrefix, True,
|
|
|
|
|
False, password)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
|
|
|
|
|
clearFollows(baseDir, nickname, domain)
|
|
|
|
|
followPerson(baseDir, nickname, domain, 'badger', 'wild.com',
|
|
|
|
|
federationList, False)
|
|
|
|
|
followPerson(baseDir, nickname, domain, 'squirrel', 'secret.com',
|
|
|
|
|
federationList, False)
|
|
|
|
|
followPerson(baseDir, nickname, domain, 'rodent', 'drainpipe.com',
|
|
|
|
|
federationList, False)
|
|
|
|
|
followPerson(baseDir, nickname, domain, 'batman', 'mesh.com',
|
|
|
|
|
federationList, False)
|
|
|
|
|
followPerson(baseDir, nickname, domain, 'giraffe', 'trees.com',
|
|
|
|
|
federationList, False)
|
|
|
|
|
|
|
|
|
|
f = open(baseDir + '/accounts/' + nickname + '@' + domain +
|
|
|
|
|
'/following.txt', "r")
|
|
|
|
|
domainFound = False
|
2019-07-03 09:24:55 +00:00
|
|
|
|
for followingDomain in f:
|
2020-05-22 11:32:38 +00:00
|
|
|
|
testDomain = followingDomain.split('@')[1]
|
|
|
|
|
testDomain = testDomain.replace('\n', '').replace('\r', '')
|
2020-04-05 13:25:47 +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)
|
2020-12-22 13:57:24 +00:00
|
|
|
|
unfollowAccount(baseDir, nickname, domain, 'batman', 'mesh.com')
|
2019-07-03 09:33:28 +00:00
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
domainFound = False
|
2019-07-03 09:33:28 +00:00
|
|
|
|
for followingDomain in f:
|
2020-05-22 11:32:38 +00:00
|
|
|
|
testDomain = followingDomain.split('@')[1]
|
|
|
|
|
testDomain = testDomain.replace('\n', '').replace('\r', '')
|
2020-04-05 13:25:47 +00:00
|
|
|
|
if testDomain == 'mesh.com':
|
|
|
|
|
domainFound = True
|
|
|
|
|
assert(domainFound is False)
|
|
|
|
|
|
|
|
|
|
clearFollowers(baseDir, nickname, domain)
|
|
|
|
|
followerOfPerson(baseDir, nickname, domain, 'badger', 'wild.com',
|
|
|
|
|
federationList, False)
|
|
|
|
|
followerOfPerson(baseDir, nickname, domain, 'squirrel', 'secret.com',
|
|
|
|
|
federationList, False)
|
|
|
|
|
followerOfPerson(baseDir, nickname, domain, 'rodent', 'drainpipe.com',
|
|
|
|
|
federationList, False)
|
|
|
|
|
followerOfPerson(baseDir, nickname, domain, 'batman', 'mesh.com',
|
|
|
|
|
federationList, False)
|
|
|
|
|
followerOfPerson(baseDir, nickname, domain, 'giraffe', 'trees.com',
|
|
|
|
|
federationList, False)
|
|
|
|
|
|
|
|
|
|
f = open(baseDir + '/accounts/' + nickname + '@' + domain +
|
|
|
|
|
'/followers.txt', "r")
|
2019-07-03 09:24:55 +00:00
|
|
|
|
for followerDomain in f:
|
2020-05-22 11:32:38 +00:00
|
|
|
|
testDomain = followerDomain.split('@')[1]
|
|
|
|
|
testDomain = testDomain.replace('\n', '').replace('\r', '')
|
2019-07-03 09:24:55 +00:00
|
|
|
|
if testDomain not in federationList:
|
|
|
|
|
print(testDomain)
|
|
|
|
|
assert(False)
|
|
|
|
|
|
|
|
|
|
os.chdir(currDir)
|
|
|
|
|
shutil.rmtree(baseDir)
|
2019-07-03 10:04:23 +00:00
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
|
2019-07-03 10:04:23 +00:00
|
|
|
|
def testCreatePerson():
|
|
|
|
|
print('testCreatePerson')
|
2020-04-05 13:25:47 +00:00
|
|
|
|
currDir = os.getcwd()
|
|
|
|
|
nickname = 'test382'
|
|
|
|
|
domain = 'badgerdomain.com'
|
|
|
|
|
password = 'mypass'
|
|
|
|
|
port = 80
|
|
|
|
|
httpPrefix = 'https'
|
|
|
|
|
clientToServer = False
|
|
|
|
|
baseDir = currDir + '/.tests_createperson'
|
2019-07-03 10:04:23 +00:00
|
|
|
|
if os.path.isdir(baseDir):
|
|
|
|
|
shutil.rmtree(baseDir)
|
|
|
|
|
os.mkdir(baseDir)
|
|
|
|
|
os.chdir(baseDir)
|
2020-03-22 21:16:02 +00:00
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
privateKeyPem, publicKeyPem, person, wfEndpoint = \
|
|
|
|
|
createPerson(baseDir, nickname, domain, port,
|
2020-07-12 12:31:28 +00:00
|
|
|
|
httpPrefix, True, False, password)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
assert os.path.isfile(baseDir + '/accounts/passwords')
|
|
|
|
|
deleteAllPosts(baseDir, nickname, domain, 'inbox')
|
|
|
|
|
deleteAllPosts(baseDir, nickname, domain, 'outbox')
|
|
|
|
|
setDisplayNickname(baseDir, nickname, domain, 'badger')
|
|
|
|
|
setBio(baseDir, nickname, domain, 'Randomly roaming in your backyard')
|
2020-06-24 13:30:50 +00:00
|
|
|
|
archivePostsForPerson(nickname, domain, baseDir, 'inbox', None, {}, 4)
|
|
|
|
|
archivePostsForPerson(nickname, domain, baseDir, 'outbox', None, {}, 4)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
|
|
|
|
|
"G'day world!", False, True, clientToServer,
|
2021-01-07 15:38:55 +00:00
|
|
|
|
True, None, None, None, None,
|
2020-04-05 13:25:47 +00:00
|
|
|
|
'Not suitable for Vogons')
|
2019-07-03 10:04:23 +00:00
|
|
|
|
|
|
|
|
|
os.chdir(currDir)
|
|
|
|
|
shutil.rmtree(baseDir)
|
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
|
2019-07-18 16:21:26 +00:00
|
|
|
|
def testDelegateRoles():
|
|
|
|
|
print('testDelegateRoles')
|
2020-04-05 13:25:47 +00:00
|
|
|
|
currDir = os.getcwd()
|
|
|
|
|
nickname = 'test382'
|
|
|
|
|
nicknameDelegated = 'test383'
|
|
|
|
|
domain = 'badgerdomain.com'
|
|
|
|
|
password = 'mypass'
|
|
|
|
|
port = 80
|
|
|
|
|
httpPrefix = 'https'
|
|
|
|
|
baseDir = currDir + '/.tests_delegaterole'
|
2019-07-18 16:21:26 +00:00
|
|
|
|
if os.path.isdir(baseDir):
|
|
|
|
|
shutil.rmtree(baseDir)
|
|
|
|
|
os.mkdir(baseDir)
|
|
|
|
|
os.chdir(baseDir)
|
2020-03-22 21:16:02 +00:00
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
privateKeyPem, publicKeyPem, person, wfEndpoint = \
|
|
|
|
|
createPerson(baseDir, nickname, domain, port,
|
2020-07-12 12:31:28 +00:00
|
|
|
|
httpPrefix, True, False, password)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
privateKeyPem, publicKeyPem, person, wfEndpoint = \
|
|
|
|
|
createPerson(baseDir, nicknameDelegated, domain, port,
|
2020-07-12 12:31:28 +00:00
|
|
|
|
httpPrefix, True, False, 'insecure')
|
2020-04-05 13:25:47 +00:00
|
|
|
|
|
|
|
|
|
httpPrefix = 'http'
|
|
|
|
|
project = 'artechoke'
|
|
|
|
|
role = 'delegator'
|
|
|
|
|
actorDelegated = \
|
|
|
|
|
httpPrefix + '://' + domain + '/users/' + nicknameDelegated
|
|
|
|
|
newRoleJson = {
|
2019-07-18 16:21:26 +00:00
|
|
|
|
'type': 'Delegate',
|
2020-04-05 13:25:47 +00:00
|
|
|
|
'actor': httpPrefix + '://' + domain + '/users/' + nickname,
|
2019-07-18 16:21:26 +00:00
|
|
|
|
'object': {
|
|
|
|
|
'type': 'Role',
|
2020-04-05 13:25:47 +00:00
|
|
|
|
'actor': actorDelegated,
|
|
|
|
|
'object': project + ';' + role,
|
2019-07-18 16:21:26 +00:00
|
|
|
|
'to': [],
|
2020-03-22 21:16:02 +00:00
|
|
|
|
'cc': []
|
2019-07-18 16:21:26 +00:00
|
|
|
|
},
|
|
|
|
|
'to': [],
|
|
|
|
|
'cc': []
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
assert outboxDelegate(baseDir, nickname, newRoleJson, False)
|
2019-07-18 16:21:26 +00:00
|
|
|
|
# second time delegation has already happened so should return false
|
2020-04-05 13:25:47 +00:00
|
|
|
|
assert outboxDelegate(baseDir, nickname, newRoleJson, False) is False
|
2019-07-18 16:21:26 +00:00
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
assert '"delegator"' in open(baseDir + '/accounts/' + nickname +
|
|
|
|
|
'@' + domain + '.json').read()
|
|
|
|
|
assert '"delegator"' in open(baseDir + '/accounts/' + nicknameDelegated +
|
|
|
|
|
'@' + domain + '.json').read()
|
2020-03-22 21:16:02 +00:00
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
newRoleJson = {
|
2019-07-18 16:21:26 +00:00
|
|
|
|
'type': 'Delegate',
|
2020-04-05 13:25:47 +00:00
|
|
|
|
'actor': httpPrefix + '://' + domain + '/users/' + nicknameDelegated,
|
2019-07-18 16:21:26 +00:00
|
|
|
|
'object': {
|
|
|
|
|
'type': 'Role',
|
2020-04-05 13:25:47 +00:00
|
|
|
|
'actor': httpPrefix + '://' + domain + '/users/' + nickname,
|
2019-07-18 16:21:26 +00:00
|
|
|
|
'object': 'otherproject;otherrole',
|
|
|
|
|
'to': [],
|
2020-03-22 21:16:02 +00:00
|
|
|
|
'cc': []
|
2019-07-18 16:21:26 +00:00
|
|
|
|
},
|
|
|
|
|
'to': [],
|
|
|
|
|
'cc': []
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# non-delegators cannot assign roles
|
2020-04-05 13:25:47 +00:00
|
|
|
|
assert outboxDelegate(baseDir, nicknameDelegated,
|
|
|
|
|
newRoleJson, False) is False
|
|
|
|
|
assert '"otherrole"' not in open(baseDir + '/accounts/' +
|
|
|
|
|
nickname + '@' + domain + '.json').read()
|
2019-07-18 16:21:26 +00:00
|
|
|
|
|
|
|
|
|
os.chdir(currDir)
|
|
|
|
|
shutil.rmtree(baseDir)
|
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
|
2019-07-03 18:24:44 +00:00
|
|
|
|
def testAuthentication():
|
|
|
|
|
print('testAuthentication')
|
2020-04-05 13:25:47 +00:00
|
|
|
|
currDir = os.getcwd()
|
|
|
|
|
nickname = 'test8743'
|
|
|
|
|
password = 'SuperSecretPassword12345'
|
2019-07-03 18:24:44 +00:00
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
baseDir = currDir + '/.tests_authentication'
|
2019-07-03 18:24:44 +00:00
|
|
|
|
if os.path.isdir(baseDir):
|
|
|
|
|
shutil.rmtree(baseDir)
|
|
|
|
|
os.mkdir(baseDir)
|
|
|
|
|
os.chdir(baseDir)
|
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
assert storeBasicCredentials(baseDir, 'othernick', 'otherpass')
|
|
|
|
|
assert storeBasicCredentials(baseDir, 'bad:nick', 'otherpass') is False
|
|
|
|
|
assert storeBasicCredentials(baseDir, 'badnick', 'otherpa:ss') is False
|
|
|
|
|
assert storeBasicCredentials(baseDir, nickname, password)
|
2019-07-03 18:24:44 +00:00
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
authHeader = createBasicAuthHeader(nickname, password)
|
|
|
|
|
assert authorizeBasic(baseDir, '/users/' + nickname + '/inbox',
|
|
|
|
|
authHeader, False)
|
|
|
|
|
assert authorizeBasic(baseDir, '/users/' + nickname,
|
|
|
|
|
authHeader, False) is False
|
|
|
|
|
assert authorizeBasic(baseDir, '/users/othernick/inbox',
|
|
|
|
|
authHeader, False) is False
|
2019-07-03 18:24:44 +00:00
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
authHeader = createBasicAuthHeader(nickname, password + '1')
|
|
|
|
|
assert authorizeBasic(baseDir, '/users/' + nickname + '/inbox',
|
|
|
|
|
authHeader, False) is False
|
2019-07-03 18:24:44 +00:00
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
password = 'someOtherPassword'
|
|
|
|
|
assert storeBasicCredentials(baseDir, nickname, password)
|
2019-07-03 19:13:23 +00:00
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
authHeader = createBasicAuthHeader(nickname, password)
|
|
|
|
|
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-07-16 10:19:04 +00:00
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
|
2019-07-16 10:19:04 +00:00
|
|
|
|
def testClientToServer():
|
|
|
|
|
print('Testing sending a post via c2s')
|
|
|
|
|
|
|
|
|
|
global testServerAliceRunning
|
|
|
|
|
global testServerBobRunning
|
2020-04-05 13:25:47 +00:00
|
|
|
|
testServerAliceRunning = False
|
|
|
|
|
testServerBobRunning = False
|
2019-07-16 10:19:04 +00:00
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
httpPrefix = 'http'
|
2020-06-09 11:03:59 +00:00
|
|
|
|
proxyType = None
|
2020-04-05 13:25:47 +00:00
|
|
|
|
federationList = []
|
2019-07-16 10:19:04 +00:00
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
baseDir = os.getcwd()
|
|
|
|
|
if os.path.isdir(baseDir + '/.tests'):
|
|
|
|
|
shutil.rmtree(baseDir + '/.tests')
|
|
|
|
|
os.mkdir(baseDir + '/.tests')
|
2019-07-16 10:19:04 +00:00
|
|
|
|
|
|
|
|
|
# create the servers
|
2020-04-05 13:25:47 +00:00
|
|
|
|
aliceDir = baseDir + '/.tests/alice'
|
|
|
|
|
aliceDomain = '127.0.0.42'
|
|
|
|
|
alicePort = 61935
|
|
|
|
|
aliceSendThreads = []
|
|
|
|
|
aliceAddress = aliceDomain + ':' + str(alicePort)
|
|
|
|
|
|
|
|
|
|
bobDir = baseDir + '/.tests/bob'
|
|
|
|
|
bobDomain = '127.0.0.64'
|
|
|
|
|
bobPort = 61936
|
|
|
|
|
bobSendThreads = []
|
|
|
|
|
bobAddress = bobDomain + ':' + str(bobPort)
|
2020-02-19 12:27:21 +00:00
|
|
|
|
|
|
|
|
|
global thrAlice
|
|
|
|
|
if thrAlice:
|
2020-12-18 15:29:12 +00:00
|
|
|
|
while thrAlice.is_alive():
|
2020-02-19 12:27:21 +00:00
|
|
|
|
thrAlice.stop()
|
|
|
|
|
time.sleep(1)
|
|
|
|
|
thrAlice.kill()
|
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
thrAlice = \
|
|
|
|
|
threadWithTrace(target=createServerAlice,
|
|
|
|
|
args=(aliceDir, aliceDomain, alicePort, bobAddress,
|
|
|
|
|
federationList, False, False,
|
2020-09-27 19:27:24 +00:00
|
|
|
|
aliceSendThreads),
|
2020-04-05 13:25:47 +00:00
|
|
|
|
daemon=True)
|
2020-03-22 21:16:02 +00:00
|
|
|
|
|
2020-02-19 12:27:21 +00:00
|
|
|
|
global thrBob
|
|
|
|
|
if thrBob:
|
2020-12-18 15:29:12 +00:00
|
|
|
|
while thrBob.is_alive():
|
2020-02-19 12:27:21 +00:00
|
|
|
|
thrBob.stop()
|
|
|
|
|
time.sleep(1)
|
|
|
|
|
thrBob.kill()
|
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
thrBob = \
|
|
|
|
|
threadWithTrace(target=createServerBob,
|
|
|
|
|
args=(bobDir, bobDomain, bobPort, aliceAddress,
|
|
|
|
|
federationList, False, False,
|
2020-09-27 19:27:24 +00:00
|
|
|
|
bobSendThreads),
|
2020-04-05 13:25:47 +00:00
|
|
|
|
daemon=True)
|
2019-07-16 10:19:04 +00:00
|
|
|
|
|
|
|
|
|
thrAlice.start()
|
|
|
|
|
thrBob.start()
|
2020-12-18 15:29:12 +00:00
|
|
|
|
assert thrAlice.is_alive() is True
|
|
|
|
|
assert thrBob.is_alive() is True
|
2019-07-16 10:19:04 +00:00
|
|
|
|
|
|
|
|
|
# wait for both servers to be running
|
2020-04-05 13:25:47 +00:00
|
|
|
|
ctr = 0
|
2019-07-16 10:19:04 +00:00
|
|
|
|
while not (testServerAliceRunning and testServerBobRunning):
|
|
|
|
|
time.sleep(1)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
ctr += 1
|
|
|
|
|
if ctr > 60:
|
2019-07-16 10:19:04 +00:00
|
|
|
|
break
|
2020-04-05 13:25:47 +00:00
|
|
|
|
print('Alice online: ' + str(testServerAliceRunning))
|
|
|
|
|
print('Bob online: ' + str(testServerBobRunning))
|
2019-07-16 10:19:04 +00:00
|
|
|
|
|
|
|
|
|
time.sleep(1)
|
2020-03-22 21:16:02 +00:00
|
|
|
|
|
2019-07-16 10:19:04 +00:00
|
|
|
|
print('\n\n*******************************************************')
|
|
|
|
|
print('Alice sends to Bob via c2s')
|
|
|
|
|
|
2020-06-09 11:03:59 +00:00
|
|
|
|
sessionAlice = createSession(proxyType)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
followersOnly = False
|
|
|
|
|
attachedImageFilename = baseDir+'/img/logo.png'
|
|
|
|
|
mediaType = getAttachmentMediaType(attachedImageFilename)
|
|
|
|
|
attachedImageDescription = 'Logo'
|
|
|
|
|
isArticle = False
|
|
|
|
|
cachedWebfingers = {}
|
|
|
|
|
personCache = {}
|
|
|
|
|
password = 'alicepass'
|
|
|
|
|
outboxPath = aliceDir + '/accounts/alice@' + aliceDomain + '/outbox'
|
|
|
|
|
inboxPath = bobDir + '/accounts/bob@' + bobDomain + '/inbox'
|
|
|
|
|
assert len([name for name in os.listdir(outboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(outboxPath, name))]) == 0
|
|
|
|
|
assert len([name for name in os.listdir(inboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(inboxPath, name))]) == 0
|
|
|
|
|
sendResult = \
|
|
|
|
|
sendPostViaServer(__version__,
|
|
|
|
|
aliceDir, sessionAlice, 'alice', password,
|
|
|
|
|
aliceDomain, alicePort,
|
|
|
|
|
'bob', bobDomain, bobPort, None,
|
|
|
|
|
httpPrefix, 'Sent from my ActivityPub client',
|
2020-08-21 17:40:50 +00:00
|
|
|
|
followersOnly, True,
|
2020-04-05 13:25:47 +00:00
|
|
|
|
attachedImageFilename, mediaType,
|
2021-01-07 15:38:55 +00:00
|
|
|
|
attachedImageDescription,
|
2020-04-05 13:25:47 +00:00
|
|
|
|
cachedWebfingers, personCache, isArticle,
|
|
|
|
|
True, None, None, None)
|
|
|
|
|
print('sendResult: ' + str(sendResult))
|
2019-07-16 10:19:04 +00:00
|
|
|
|
|
|
|
|
|
for i in range(30):
|
|
|
|
|
if os.path.isdir(outboxPath):
|
2020-04-05 13:25:47 +00:00
|
|
|
|
if len([name for name in os.listdir(outboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(outboxPath, name))]) == 1:
|
2019-07-16 10:19:04 +00:00
|
|
|
|
break
|
|
|
|
|
time.sleep(1)
|
2019-07-16 11:33:40 +00:00
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
assert len([name for name in os.listdir(outboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(outboxPath, name))]) == 1
|
2019-07-16 11:33:40 +00:00
|
|
|
|
print(">>> c2s post arrived in Alice's outbox")
|
2020-03-22 21:16:02 +00:00
|
|
|
|
|
2019-07-16 11:33:40 +00:00
|
|
|
|
for i in range(30):
|
|
|
|
|
if os.path.isdir(inboxPath):
|
2020-04-05 13:25:47 +00:00
|
|
|
|
if len([name for name in os.listdir(inboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(inboxPath, name))]) == 1:
|
2019-07-16 11:33:40 +00:00
|
|
|
|
break
|
|
|
|
|
time.sleep(1)
|
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
assert len([name for name in os.listdir(inboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(inboxPath, name))]) == 1
|
2019-07-16 11:33:40 +00:00
|
|
|
|
print(">>> s2s post arrived in Bob's inbox")
|
|
|
|
|
print("c2s send success")
|
|
|
|
|
|
2019-07-16 19:07:45 +00:00
|
|
|
|
print('\n\nGetting message id for the post')
|
2020-04-05 13:25:47 +00:00
|
|
|
|
statusNumber = 0
|
|
|
|
|
outboxPostFilename = None
|
|
|
|
|
outboxPostId = None
|
2019-07-16 19:07:45 +00:00
|
|
|
|
for name in os.listdir(outboxPath):
|
|
|
|
|
if '#statuses#' in name:
|
2020-04-05 13:25:47 +00:00
|
|
|
|
statusNumber = name.split('#statuses#')[1].replace('.json', '')
|
|
|
|
|
statusNumber = int(statusNumber.replace('#activity', ''))
|
|
|
|
|
outboxPostFilename = outboxPath + '/' + name
|
|
|
|
|
postJsonObject = loadJson(outboxPostFilename, 0)
|
2019-11-23 10:08:00 +00:00
|
|
|
|
if postJsonObject:
|
2020-08-23 11:13:35 +00:00
|
|
|
|
outboxPostId = removeIdEnding(postJsonObject['id'])
|
2019-07-16 19:07:45 +00:00
|
|
|
|
assert outboxPostId
|
2020-04-05 13:25:47 +00:00
|
|
|
|
print('message id obtained: ' + outboxPostId)
|
|
|
|
|
assert validInbox(bobDir, 'bob', bobDomain)
|
|
|
|
|
assert validInboxFilenames(bobDir, 'bob', bobDomain,
|
|
|
|
|
aliceDomain, alicePort)
|
2019-07-16 21:38:06 +00:00
|
|
|
|
|
|
|
|
|
print('\n\nAlice follows Bob')
|
2020-04-05 13:25:47 +00:00
|
|
|
|
sendFollowRequestViaServer(aliceDir, sessionAlice,
|
|
|
|
|
'alice', password,
|
|
|
|
|
aliceDomain, alicePort,
|
|
|
|
|
'bob', bobDomain, bobPort,
|
|
|
|
|
httpPrefix,
|
|
|
|
|
cachedWebfingers, personCache,
|
|
|
|
|
True, __version__)
|
2020-11-23 15:07:55 +00:00
|
|
|
|
alicePetnamesFilename = aliceDir + '/accounts/' + \
|
|
|
|
|
'alice@' + aliceDomain + '/petnames.txt'
|
2020-04-05 13:25:47 +00:00
|
|
|
|
aliceFollowingFilename = \
|
|
|
|
|
aliceDir + '/accounts/alice@' + aliceDomain + '/following.txt'
|
|
|
|
|
bobFollowersFilename = \
|
|
|
|
|
bobDir + '/accounts/bob@' + bobDomain + '/followers.txt'
|
2020-03-02 21:28:22 +00:00
|
|
|
|
for t in range(10):
|
|
|
|
|
if os.path.isfile(bobFollowersFilename):
|
2020-04-05 13:25:47 +00:00
|
|
|
|
if 'alice@' + aliceDomain + ':' + str(alicePort) in \
|
|
|
|
|
open(bobFollowersFilename).read():
|
2020-11-23 15:07:55 +00:00
|
|
|
|
if os.path.isfile(aliceFollowingFilename) and \
|
|
|
|
|
os.path.isfile(alicePetnamesFilename):
|
2020-04-05 13:25:47 +00:00
|
|
|
|
if 'bob@' + bobDomain + ':' + str(bobPort) in \
|
|
|
|
|
open(aliceFollowingFilename).read():
|
2019-07-17 11:24:11 +00:00
|
|
|
|
break
|
2019-07-16 21:38:06 +00:00
|
|
|
|
time.sleep(1)
|
|
|
|
|
|
2020-03-02 21:28:22 +00:00
|
|
|
|
assert os.path.isfile(bobFollowersFilename)
|
|
|
|
|
assert os.path.isfile(aliceFollowingFilename)
|
2020-11-23 15:07:55 +00:00
|
|
|
|
assert os.path.isfile(alicePetnamesFilename)
|
|
|
|
|
assert 'bob bob@' + bobDomain in \
|
|
|
|
|
open(alicePetnamesFilename).read()
|
2020-04-05 13:25:47 +00:00
|
|
|
|
print('alice@' + aliceDomain + ':' + str(alicePort) + ' in ' +
|
|
|
|
|
bobFollowersFilename)
|
|
|
|
|
assert 'alice@' + aliceDomain + ':' + str(alicePort) in \
|
|
|
|
|
open(bobFollowersFilename).read()
|
|
|
|
|
print('bob@' + bobDomain + ':' + str(bobPort) + ' in ' +
|
|
|
|
|
aliceFollowingFilename)
|
|
|
|
|
assert 'bob@' + bobDomain + ':' + str(bobPort) in \
|
|
|
|
|
open(aliceFollowingFilename).read()
|
|
|
|
|
assert validInbox(bobDir, 'bob', bobDomain)
|
|
|
|
|
assert validInboxFilenames(bobDir, 'bob', bobDomain,
|
|
|
|
|
aliceDomain, alicePort)
|
2019-07-17 17:16:48 +00:00
|
|
|
|
|
|
|
|
|
print('\n\nBob follows Alice')
|
2020-04-05 13:25:47 +00:00
|
|
|
|
sendFollowRequestViaServer(aliceDir, sessionAlice,
|
|
|
|
|
'bob', 'bobpass',
|
|
|
|
|
bobDomain, bobPort,
|
|
|
|
|
'alice', aliceDomain, alicePort,
|
|
|
|
|
httpPrefix,
|
|
|
|
|
cachedWebfingers, personCache,
|
|
|
|
|
True, __version__)
|
2019-07-17 17:16:48 +00:00
|
|
|
|
for t in range(10):
|
2020-04-05 13:25:47 +00:00
|
|
|
|
if os.path.isfile(aliceDir + '/accounts/alice@' + aliceDomain +
|
|
|
|
|
'/followers.txt'):
|
|
|
|
|
if 'bob@' + bobDomain + ':' + str(bobPort) in \
|
|
|
|
|
open(aliceDir + '/accounts/alice@' + aliceDomain +
|
|
|
|
|
'/followers.txt').read():
|
|
|
|
|
if os.path.isfile(bobDir + '/accounts/bob@' + bobDomain +
|
|
|
|
|
'/following.txt'):
|
2020-07-03 21:56:38 +00:00
|
|
|
|
aliceHandleStr = \
|
|
|
|
|
'alice@' + aliceDomain + ':' + str(alicePort)
|
|
|
|
|
if aliceHandleStr in \
|
2020-04-05 13:25:47 +00:00
|
|
|
|
open(bobDir + '/accounts/bob@' + bobDomain +
|
|
|
|
|
'/following.txt').read():
|
2020-07-03 21:56:38 +00:00
|
|
|
|
if os.path.isfile(bobDir + '/accounts/bob@' +
|
|
|
|
|
bobDomain +
|
|
|
|
|
'/followingCalendar.txt'):
|
|
|
|
|
if aliceHandleStr in \
|
|
|
|
|
open(bobDir + '/accounts/bob@' + bobDomain +
|
|
|
|
|
'/followingCalendar.txt').read():
|
|
|
|
|
break
|
2019-07-17 17:16:48 +00:00
|
|
|
|
time.sleep(1)
|
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
assert os.path.isfile(aliceDir + '/accounts/alice@' + aliceDomain +
|
|
|
|
|
'/followers.txt')
|
|
|
|
|
assert os.path.isfile(bobDir + '/accounts/bob@' + bobDomain +
|
|
|
|
|
'/following.txt')
|
|
|
|
|
assert 'bob@' + bobDomain + ':' + str(bobPort) in \
|
|
|
|
|
open(aliceDir + '/accounts/alice@' + aliceDomain +
|
|
|
|
|
'/followers.txt').read()
|
|
|
|
|
assert 'alice@' + aliceDomain + ':' + str(alicePort) in \
|
|
|
|
|
open(bobDir + '/accounts/bob@' + bobDomain + '/following.txt').read()
|
2019-07-18 09:26:47 +00:00
|
|
|
|
|
|
|
|
|
print('\n\nBob likes the post')
|
2020-06-09 11:03:59 +00:00
|
|
|
|
sessionBob = createSession(proxyType)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
password = 'bobpass'
|
|
|
|
|
outboxPath = bobDir + '/accounts/bob@' + bobDomain + '/outbox'
|
|
|
|
|
inboxPath = aliceDir + '/accounts/alice@' + aliceDomain + '/inbox'
|
|
|
|
|
print(str(len([name for name in os.listdir(outboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(outboxPath, name))])))
|
|
|
|
|
assert len([name for name in os.listdir(outboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(outboxPath, name))]) == 1
|
|
|
|
|
print(str(len([name for name in os.listdir(inboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(inboxPath, name))])))
|
|
|
|
|
assert len([name for name in os.listdir(inboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(inboxPath, name))]) == 1
|
|
|
|
|
sendLikeViaServer(bobDir, sessionBob,
|
|
|
|
|
'bob', 'bobpass',
|
|
|
|
|
bobDomain, bobPort,
|
|
|
|
|
httpPrefix, outboxPostId,
|
|
|
|
|
cachedWebfingers, personCache,
|
|
|
|
|
True, __version__)
|
2019-07-18 09:26:47 +00:00
|
|
|
|
for i in range(20):
|
2020-03-22 21:16:02 +00:00
|
|
|
|
if os.path.isdir(outboxPath) and os.path.isdir(inboxPath):
|
2020-04-05 13:25:47 +00:00
|
|
|
|
if len([name for name in os.listdir(outboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(outboxPath, name))]) == 2:
|
|
|
|
|
test = len([name for name in os.listdir(inboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(inboxPath, name))])
|
|
|
|
|
if test == 1:
|
2019-07-18 09:26:47 +00:00
|
|
|
|
break
|
|
|
|
|
time.sleep(1)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
assert len([name for name in os.listdir(outboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(outboxPath, name))]) == 2
|
|
|
|
|
assert len([name for name in os.listdir(inboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(inboxPath, name))]) == 1
|
2019-07-18 09:26:47 +00:00
|
|
|
|
print('Post liked')
|
2020-03-22 21:16:02 +00:00
|
|
|
|
|
2019-07-18 09:26:47 +00:00
|
|
|
|
print('\n\nBob repeats the post')
|
2020-04-05 13:25:47 +00:00
|
|
|
|
print(str(len([name for name in os.listdir(outboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(outboxPath, name))])))
|
|
|
|
|
assert len([name for name in os.listdir(outboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(outboxPath, name))]) == 2
|
|
|
|
|
print(str(len([name for name in os.listdir(inboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(inboxPath, name))])))
|
|
|
|
|
assert len([name for name in os.listdir(inboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(inboxPath, name))]) == 1
|
|
|
|
|
sendAnnounceViaServer(bobDir, sessionBob, 'bob', password,
|
|
|
|
|
bobDomain, bobPort,
|
|
|
|
|
httpPrefix, outboxPostId,
|
|
|
|
|
cachedWebfingers,
|
|
|
|
|
personCache, True, __version__)
|
2019-07-16 22:57:45 +00:00
|
|
|
|
for i in range(20):
|
2020-03-22 21:16:02 +00:00
|
|
|
|
if os.path.isdir(outboxPath) and os.path.isdir(inboxPath):
|
2020-04-05 13:25:47 +00:00
|
|
|
|
if len([name for name in os.listdir(outboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(outboxPath, name))]) == 3:
|
|
|
|
|
if len([name for name in os.listdir(inboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(inboxPath,
|
|
|
|
|
name))]) == 2:
|
2019-07-16 22:57:45 +00:00
|
|
|
|
break
|
2019-07-16 19:07:45 +00:00
|
|
|
|
time.sleep(1)
|
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
assert len([name for name in os.listdir(outboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(outboxPath, name))]) == 3
|
|
|
|
|
assert len([name for name in os.listdir(inboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(inboxPath, name))]) == 2
|
2019-07-16 19:07:45 +00:00
|
|
|
|
print('Post repeated')
|
2019-07-17 11:54:13 +00:00
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
inboxPath = bobDir + '/accounts/bob@' + bobDomain + '/inbox'
|
|
|
|
|
outboxPath = aliceDir + '/accounts/alice@' + aliceDomain + '/outbox'
|
|
|
|
|
postsBefore = \
|
|
|
|
|
len([name for name in os.listdir(inboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(inboxPath, name))])
|
|
|
|
|
print('\n\nAlice deletes her post: ' + outboxPostId + ' ' +
|
|
|
|
|
str(postsBefore))
|
|
|
|
|
password = 'alicepass'
|
|
|
|
|
sendDeleteViaServer(aliceDir, sessionAlice, 'alice', password,
|
|
|
|
|
aliceDomain, alicePort,
|
|
|
|
|
httpPrefix, outboxPostId,
|
|
|
|
|
cachedWebfingers, personCache,
|
|
|
|
|
True, __version__)
|
2019-07-17 17:16:48 +00:00
|
|
|
|
for i in range(30):
|
|
|
|
|
if os.path.isdir(inboxPath):
|
2020-04-05 13:25:47 +00:00
|
|
|
|
test = len([name for name in os.listdir(inboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(inboxPath, name))])
|
|
|
|
|
if test == postsBefore-1:
|
2019-07-17 17:16:48 +00:00
|
|
|
|
break
|
|
|
|
|
time.sleep(1)
|
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
test = len([name for name in os.listdir(inboxPath)
|
|
|
|
|
if os.path.isfile(os.path.join(inboxPath, name))])
|
|
|
|
|
assert test == postsBefore - 1
|
2019-07-17 17:16:48 +00:00
|
|
|
|
print(">>> post deleted from Alice's outbox and Bob's inbox")
|
2020-04-05 13:25:47 +00:00
|
|
|
|
assert validInbox(bobDir, 'bob', bobDomain)
|
|
|
|
|
assert validInboxFilenames(bobDir, 'bob', bobDomain,
|
|
|
|
|
aliceDomain, alicePort)
|
2020-03-22 21:16:02 +00:00
|
|
|
|
|
2019-07-17 11:54:13 +00:00
|
|
|
|
print('\n\nAlice unfollows Bob')
|
2020-04-05 13:25:47 +00:00
|
|
|
|
password = 'alicepass'
|
|
|
|
|
sendUnfollowRequestViaServer(baseDir, sessionAlice,
|
|
|
|
|
'alice', password,
|
|
|
|
|
aliceDomain, alicePort,
|
|
|
|
|
'bob', bobDomain, bobPort,
|
|
|
|
|
httpPrefix,
|
|
|
|
|
cachedWebfingers, personCache,
|
|
|
|
|
True, __version__)
|
2019-07-17 11:54:13 +00:00
|
|
|
|
for t in range(10):
|
2020-04-05 13:25:47 +00:00
|
|
|
|
if 'alice@' + aliceDomain + ':' + str(alicePort) not in \
|
|
|
|
|
open(bobFollowersFilename).read():
|
|
|
|
|
if 'bob@' + bobDomain + ':' + str(bobPort) not in \
|
|
|
|
|
open(aliceFollowingFilename).read():
|
2019-07-17 11:54:13 +00:00
|
|
|
|
break
|
|
|
|
|
time.sleep(1)
|
|
|
|
|
|
2020-03-02 21:28:22 +00:00
|
|
|
|
assert os.path.isfile(bobFollowersFilename)
|
|
|
|
|
assert os.path.isfile(aliceFollowingFilename)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
assert 'alice@' + aliceDomain + ':' + str(alicePort) \
|
|
|
|
|
not in open(bobFollowersFilename).read()
|
|
|
|
|
assert 'bob@' + bobDomain + ':' + str(bobPort) \
|
|
|
|
|
not in open(aliceFollowingFilename).read()
|
|
|
|
|
assert validInbox(bobDir, 'bob', bobDomain)
|
|
|
|
|
assert validInboxFilenames(bobDir, 'bob', bobDomain,
|
|
|
|
|
aliceDomain, alicePort)
|
|
|
|
|
assert validInbox(aliceDir, 'alice', aliceDomain)
|
|
|
|
|
assert validInboxFilenames(aliceDir, 'alice', aliceDomain,
|
|
|
|
|
bobDomain, bobPort)
|
2019-07-17 11:54:13 +00:00
|
|
|
|
|
2019-07-16 11:33:40 +00:00
|
|
|
|
# stop the servers
|
|
|
|
|
thrAlice.kill()
|
|
|
|
|
thrAlice.join()
|
2020-12-18 15:29:12 +00:00
|
|
|
|
assert thrAlice.is_alive() is False
|
2019-07-16 11:33:40 +00:00
|
|
|
|
|
|
|
|
|
thrBob.kill()
|
|
|
|
|
thrBob.join()
|
2020-12-18 15:29:12 +00:00
|
|
|
|
assert thrBob.is_alive() is False
|
2019-07-16 11:33:40 +00:00
|
|
|
|
|
|
|
|
|
os.chdir(baseDir)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
# shutil.rmtree(aliceDir)
|
|
|
|
|
# shutil.rmtree(bobDir)
|
|
|
|
|
|
2019-07-16 10:19:04 +00:00
|
|
|
|
|
2019-08-21 16:35:46 +00:00
|
|
|
|
def testActorParsing():
|
|
|
|
|
print('testActorParsing')
|
2020-04-05 13:25:47 +00:00
|
|
|
|
actor = 'https://mydomain:72/users/mynick'
|
|
|
|
|
domain, port = getDomainFromActor(actor)
|
|
|
|
|
assert domain == 'mydomain'
|
|
|
|
|
assert port == 72
|
|
|
|
|
nickname = getNicknameFromActor(actor)
|
|
|
|
|
assert nickname == 'mynick'
|
|
|
|
|
|
2020-08-13 16:41:02 +00:00
|
|
|
|
actor = 'https://element/accounts/badger'
|
|
|
|
|
domain, port = getDomainFromActor(actor)
|
|
|
|
|
assert domain == 'element'
|
|
|
|
|
nickname = getNicknameFromActor(actor)
|
|
|
|
|
assert nickname == 'badger'
|
|
|
|
|
|
|
|
|
|
actor = 'egg@chicken.com'
|
|
|
|
|
domain, port = getDomainFromActor(actor)
|
|
|
|
|
assert domain == 'chicken.com'
|
|
|
|
|
nickname = getNicknameFromActor(actor)
|
|
|
|
|
assert nickname == 'egg'
|
|
|
|
|
|
|
|
|
|
actor = '@waffle@cardboard'
|
|
|
|
|
domain, port = getDomainFromActor(actor)
|
|
|
|
|
assert domain == 'cardboard'
|
|
|
|
|
nickname = getNicknameFromActor(actor)
|
|
|
|
|
assert nickname == 'waffle'
|
|
|
|
|
|
|
|
|
|
actor = 'https://astral/channel/sky'
|
|
|
|
|
domain, port = getDomainFromActor(actor)
|
|
|
|
|
assert domain == 'astral'
|
|
|
|
|
nickname = getNicknameFromActor(actor)
|
|
|
|
|
assert nickname == 'sky'
|
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
actor = 'https://randomain/users/rando'
|
|
|
|
|
domain, port = getDomainFromActor(actor)
|
|
|
|
|
assert domain == 'randomain'
|
|
|
|
|
nickname = getNicknameFromActor(actor)
|
|
|
|
|
assert nickname == 'rando'
|
|
|
|
|
|
|
|
|
|
actor = 'https://otherdomain:49/@othernick'
|
|
|
|
|
domain, port = getDomainFromActor(actor)
|
|
|
|
|
assert domain == 'otherdomain'
|
|
|
|
|
assert port == 49
|
|
|
|
|
nickname = getNicknameFromActor(actor)
|
|
|
|
|
assert nickname == 'othernick'
|
|
|
|
|
|
2019-08-21 16:35:46 +00:00
|
|
|
|
|
2019-09-01 08:55:05 +00:00
|
|
|
|
def testWebLinks():
|
2019-09-01 08:57:51 +00:00
|
|
|
|
print('testWebLinks')
|
2020-01-24 10:52:59 +00:00
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
exampleText = \
|
|
|
|
|
'<p><span class=\"h-card\"><a href=\"https://something/@orother' + \
|
|
|
|
|
'\" class=\"u-url mention\">@<span>foo</span></a></span> Some ' + \
|
|
|
|
|
'random text.</p><p>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' + \
|
|
|
|
|
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' + \
|
|
|
|
|
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' + \
|
|
|
|
|
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' + \
|
|
|
|
|
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' + \
|
|
|
|
|
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA</p>'
|
|
|
|
|
resultText = removeLongWords(exampleText, 40, [])
|
|
|
|
|
assert resultText == \
|
|
|
|
|
'<p><span class="h-card"><a href="https://something/@orother"' + \
|
|
|
|
|
' class="u-url mention">@<span>foo</span></a></span> ' + \
|
|
|
|
|
'Some random text.</p>'
|
|
|
|
|
|
|
|
|
|
exampleText = \
|
|
|
|
|
'This post has a web links https://somesite.net\n\nAnd some other text'
|
|
|
|
|
linkedText = addWebLinks(exampleText)
|
|
|
|
|
assert \
|
2020-12-13 11:31:16 +00:00
|
|
|
|
'<a href="https://somesite.net" rel="nofollow noopener noreferrer"' + \
|
2020-04-05 13:25:47 +00:00
|
|
|
|
' target="_blank"><span class="invisible">https://' + \
|
|
|
|
|
'</span><span class="ellipsis">somesite.net</span></a' in linkedText
|
|
|
|
|
|
|
|
|
|
exampleText = \
|
|
|
|
|
'This post has a very long web link\n\nhttp://' + \
|
|
|
|
|
'cbwebewuvfuftdiudbqd33dddbbyuef23fyug3bfhcyu2fct2' + \
|
|
|
|
|
'cuyqbcbucuwvckiwyfgewfvqejbchevbhwevuevwbqebqekve' + \
|
|
|
|
|
'qvuvjfkf.onion\n\nAnd some other text'
|
|
|
|
|
linkedText = addWebLinks(exampleText)
|
2019-10-01 10:36:51 +00:00
|
|
|
|
assert 'ellipsis' in linkedText
|
2020-01-24 10:52:59 +00:00
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
exampleText = \
|
|
|
|
|
'<p>1. HAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAH' + \
|
|
|
|
|
'AHAHAHHAHAHAHAHAHAHAHAHAHAHAHAHHAHAHAHAHAHAHAHAH</p>'
|
|
|
|
|
resultText = removeLongWords(exampleText, 40, [])
|
|
|
|
|
assert resultText == '<p>1. HAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHA</p>'
|
|
|
|
|
|
|
|
|
|
exampleText = \
|
|
|
|
|
'<p>Tox address is 88AB9DED6F9FBEF43E105FB72060A2D89F9B93C74' + \
|
|
|
|
|
'4E8C45AB3C5E42C361C837155AFCFD9D448 </p>'
|
|
|
|
|
resultText = removeLongWords(exampleText, 40, [])
|
|
|
|
|
assert resultText == exampleText
|
|
|
|
|
|
2020-10-31 23:10:38 +00:00
|
|
|
|
exampleText = \
|
|
|
|
|
'some.incredibly.long.and.annoying.word.which.should.be.removed: ' + \
|
|
|
|
|
'The remaining text'
|
|
|
|
|
resultText = removeLongWords(exampleText, 40, [])
|
|
|
|
|
assert resultText == \
|
|
|
|
|
'some.incredibly.long.and.annoying.word.w\n' + \
|
|
|
|
|
'hich.should.be.removed: The remaining text'
|
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
exampleText = \
|
|
|
|
|
'<p>Tox address is 88AB9DED6F9FBEF43E105FB72060A2D89F9B93C74' + \
|
|
|
|
|
'4E8C45AB3C5E42C361C837155AFCFD9D448</p>'
|
|
|
|
|
resultText = removeLongWords(exampleText, 40, [])
|
|
|
|
|
assert resultText == \
|
|
|
|
|
'<p>Tox address is 88AB9DED6F9FBEF43E105FB72060A2D89F9B93C7\n' + \
|
|
|
|
|
'44E8C45AB3C5E42C361C837155AFCFD9D448</p>'
|
|
|
|
|
|
|
|
|
|
exampleText = \
|
|
|
|
|
'<p>ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCA' + \
|
|
|
|
|
'BCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCAB' + \
|
|
|
|
|
'CABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC' + \
|
|
|
|
|
'ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCA' + \
|
|
|
|
|
'BCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCAB' + \
|
|
|
|
|
'CABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC' + \
|
|
|
|
|
'ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCA' + \
|
|
|
|
|
'BCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCAB' + \
|
|
|
|
|
'CABCABCABCABCABCABCABCABC</p>'
|
|
|
|
|
resultText = removeLongWords(exampleText, 40, [])
|
|
|
|
|
assert resultText == r'<p>ABCABCABCABCABCABCABCABCABCABCABCABCABCA<\p>'
|
|
|
|
|
|
|
|
|
|
exampleText = \
|
|
|
|
|
'"the nucleus of mutual-support institutions, habits, and customs ' + \
|
|
|
|
|
'remains alive with the millions; it keeps them together; and ' + \
|
|
|
|
|
'they prefer to cling to their customs, beliefs, and traditions ' + \
|
|
|
|
|
'rather than to accept the teachings of a war of each ' + \
|
|
|
|
|
'against all"\n\n--Peter Kropotkin'
|
2020-12-22 21:24:46 +00:00
|
|
|
|
testFnStr = addWebLinks(exampleText)
|
|
|
|
|
resultText = removeLongWords(testFnStr, 40, [])
|
2020-04-05 13:25:47 +00:00
|
|
|
|
assert resultText == exampleText
|
2020-03-29 10:48:31 +00:00
|
|
|
|
assert 'ellipsis' not in resultText
|
2020-03-29 09:59:54 +00:00
|
|
|
|
|
2020-05-12 09:34:58 +00:00
|
|
|
|
exampleText = \
|
|
|
|
|
'<p>filepopout=' + \
|
2020-05-12 09:42:24 +00:00
|
|
|
|
'TemplateAttachmentRichPopout<<\\p>'
|
2020-05-12 09:34:58 +00:00
|
|
|
|
resultText = replaceContentDuplicates(exampleText)
|
|
|
|
|
assert resultText == \
|
|
|
|
|
'<p>filepopout=' + \
|
|
|
|
|
'TemplateAttachmentRichPopout'
|
|
|
|
|
|
2020-08-07 20:51:34 +00:00
|
|
|
|
exampleText = \
|
2020-08-11 17:18:22 +00:00
|
|
|
|
'<p>Test1 test2 #YetAnotherExcessivelyLongwindedAndBoringHashtag</p>'
|
2020-12-22 21:24:46 +00:00
|
|
|
|
testFnStr = addWebLinks(exampleText)
|
|
|
|
|
resultText = removeLongWords(testFnStr, 40, [])
|
2020-08-07 20:51:34 +00:00
|
|
|
|
assert(resultText ==
|
|
|
|
|
'<p>Test1 test2 '
|
|
|
|
|
'#YetAnotherExcessivelyLongwindedAndBorin\ngHashtag</p>')
|
|
|
|
|
|
2020-12-06 10:18:41 +00:00
|
|
|
|
exampleText = \
|
2020-12-06 14:47:06 +00:00
|
|
|
|
"<p>Don't remove a p2p link " + \
|
|
|
|
|
"rad:git:hwd1yrerc3mcgn8ga9rho3dqi4w33nep7kxmqezss4topyfgmexihp" + \
|
|
|
|
|
"33xcw</p>"
|
2020-12-22 21:24:46 +00:00
|
|
|
|
testFnStr = addWebLinks(exampleText)
|
|
|
|
|
resultText = removeLongWords(testFnStr, 40, [])
|
2020-12-06 10:18:41 +00:00
|
|
|
|
assert resultText == exampleText
|
|
|
|
|
|
2020-01-24 10:52:59 +00:00
|
|
|
|
|
2020-02-21 15:09:31 +00:00
|
|
|
|
def testAddEmoji():
|
|
|
|
|
print('testAddEmoji')
|
2020-04-05 13:25:47 +00:00
|
|
|
|
content = "Emoji :lemon: :strawberry: :banana:"
|
|
|
|
|
httpPrefix = 'http'
|
|
|
|
|
nickname = 'testuser'
|
|
|
|
|
domain = 'testdomain.net'
|
|
|
|
|
port = 3682
|
|
|
|
|
recipients = []
|
|
|
|
|
hashtags = {}
|
|
|
|
|
baseDir = os.getcwd()
|
|
|
|
|
baseDirOriginal = os.getcwd()
|
|
|
|
|
path = baseDir + '/.tests'
|
2019-09-29 18:48:34 +00:00
|
|
|
|
if not os.path.isdir(path):
|
|
|
|
|
os.mkdir(path)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
path = baseDir + '/.tests/emoji'
|
2019-09-29 18:48:34 +00:00
|
|
|
|
if os.path.isdir(path):
|
|
|
|
|
shutil.rmtree(path)
|
2020-03-22 21:16:02 +00:00
|
|
|
|
os.mkdir(path)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
baseDir = path
|
|
|
|
|
path = baseDir + '/emoji'
|
2019-09-29 18:48:34 +00:00
|
|
|
|
if os.path.isdir(path):
|
|
|
|
|
shutil.rmtree(path)
|
2020-03-22 21:16:02 +00:00
|
|
|
|
os.mkdir(path)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
copytree(baseDirOriginal + '/emoji', baseDir + '/emoji')
|
2019-09-29 18:48:34 +00:00
|
|
|
|
os.chdir(baseDir)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
privateKeyPem, publicKeyPem, person, wfEndpoint = \
|
|
|
|
|
createPerson(baseDir, nickname, domain, port,
|
2020-07-12 12:31:28 +00:00
|
|
|
|
httpPrefix, True, False, 'password')
|
2020-04-05 13:25:47 +00:00
|
|
|
|
contentModified = \
|
|
|
|
|
addHtmlTags(baseDir, httpPrefix,
|
|
|
|
|
nickname, domain, content,
|
|
|
|
|
recipients, hashtags, True)
|
2020-02-21 15:09:31 +00:00
|
|
|
|
assert ':lemon:' in contentModified
|
2020-02-21 09:53:36 +00:00
|
|
|
|
assert contentModified.startswith('<p>')
|
|
|
|
|
assert contentModified.endswith('</p>')
|
2020-04-05 13:25:47 +00:00
|
|
|
|
tags = []
|
|
|
|
|
for tagName, tag in hashtags.items():
|
2019-09-29 18:48:34 +00:00
|
|
|
|
tags.append(tag)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
content = contentModified
|
|
|
|
|
contentModified = replaceEmojiFromTags(content, tags, 'content')
|
|
|
|
|
# print('contentModified: '+contentModified)
|
|
|
|
|
assert contentModified == '<p>Emoji 🍋 🍓 🍌</p>'
|
2019-09-29 18:48:34 +00:00
|
|
|
|
|
|
|
|
|
os.chdir(baseDirOriginal)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
shutil.rmtree(baseDirOriginal + '/.tests')
|
|
|
|
|
|
2019-09-29 18:48:34 +00:00
|
|
|
|
|
2019-10-12 12:45:53 +00:00
|
|
|
|
def testGetStatusNumber():
|
|
|
|
|
print('testGetStatusNumber')
|
2020-04-05 13:25:47 +00:00
|
|
|
|
prevStatusNumber = None
|
|
|
|
|
for i in range(1, 20):
|
|
|
|
|
statusNumber, published = getStatusNumber()
|
2019-10-12 12:45:53 +00:00
|
|
|
|
if prevStatusNumber:
|
|
|
|
|
assert len(statusNumber) == 18
|
|
|
|
|
assert int(statusNumber) > prevStatusNumber
|
2020-04-05 13:25:47 +00:00
|
|
|
|
prevStatusNumber = int(statusNumber)
|
|
|
|
|
|
2019-10-12 12:45:53 +00:00
|
|
|
|
|
2020-10-11 12:41:15 +00:00
|
|
|
|
def testJsonString() -> None:
|
|
|
|
|
print('testJsonString')
|
2020-10-11 13:00:26 +00:00
|
|
|
|
filename = '.epicyon_tests_testJsonString.json'
|
2020-04-05 13:25:47 +00:00
|
|
|
|
messageStr = "Crème brûlée यह एक परीक्षण ह"
|
|
|
|
|
testJson = {
|
2019-11-09 12:13:39 +00:00
|
|
|
|
"content": messageStr
|
|
|
|
|
}
|
2020-04-05 13:25:47 +00:00
|
|
|
|
assert saveJson(testJson, filename)
|
|
|
|
|
receivedJson = loadJson(filename, 0)
|
2019-11-09 12:13:39 +00:00
|
|
|
|
assert receivedJson
|
2020-04-05 13:25:47 +00:00
|
|
|
|
assert receivedJson['content'] == messageStr
|
|
|
|
|
encodedStr = json.dumps(testJson, ensure_ascii=False)
|
2019-11-09 12:52:47 +00:00
|
|
|
|
assert messageStr in encodedStr
|
2020-10-11 13:00:26 +00:00
|
|
|
|
os.remove(filename)
|
2019-11-09 12:13:39 +00:00
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
|
2019-11-23 10:13:57 +00:00
|
|
|
|
def testSaveLoadJson():
|
|
|
|
|
print('testSaveLoadJson')
|
2020-04-05 13:25:47 +00:00
|
|
|
|
testJson = {
|
2019-11-23 10:13:57 +00:00
|
|
|
|
"param1": 3,
|
2019-11-23 10:20:30 +00:00
|
|
|
|
"param2": '"Crème brûlée यह एक परीक्षण ह"'
|
2019-11-23 10:13:57 +00:00
|
|
|
|
}
|
2020-10-11 13:03:08 +00:00
|
|
|
|
testFilename = '.epicyon_tests_testSaveLoadJson.json'
|
2019-11-23 10:13:57 +00:00
|
|
|
|
if os.path.isfile(testFilename):
|
|
|
|
|
os.remove(testFilename)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
assert saveJson(testJson, testFilename)
|
2019-11-23 10:13:57 +00:00
|
|
|
|
assert os.path.isfile(testFilename)
|
2020-04-05 13:25:47 +00:00
|
|
|
|
testLoadJson = loadJson(testFilename)
|
2019-11-23 10:13:57 +00:00
|
|
|
|
assert(testLoadJson)
|
|
|
|
|
assert testLoadJson.get('param1')
|
|
|
|
|
assert testLoadJson.get('param2')
|
2020-04-05 13:25:47 +00:00
|
|
|
|
assert testLoadJson['param1'] == 3
|
|
|
|
|
assert testLoadJson['param2'] == '"Crème brûlée यह एक परीक्षण ह"'
|
2019-11-23 10:13:57 +00:00
|
|
|
|
os.remove(testFilename)
|
2019-11-23 13:04:11 +00:00
|
|
|
|
|
2020-04-05 13:25:47 +00:00
|
|
|
|
|
2019-11-23 13:04:11 +00:00
|
|
|
|
def testTheme():
|
|
|
|
|
print('testTheme')
|
2020-04-05 13:25:47 +00:00
|
|
|
|
css = 'somestring --background-value: 24px; --foreground-value: 24px;'
|
|
|
|
|
result = setCSSparam(css, 'background-value', '32px')
|
|
|
|
|
assert result == \
|
|
|
|
|
'somestring --background-value: 32px; --foreground-value: 24px;'
|
|
|
|
|
css = \
|
|
|
|
|
'somestring --background-value: 24px; --foreground-value: 24px; ' + \
|
|
|
|
|
'--background-value: 24px;'
|
|
|
|
|
result = setCSSparam(css, 'background-value', '32px')
|
|
|
|
|
assert result == \
|
|
|
|
|
'somestring --background-value: 32px; --foreground-value: 24px; ' + \
|
|
|
|
|
'--background-value: 32px;'
|
|
|
|
|
css = '--background-value: 24px; --foreground-value: 24px;'
|
|
|
|
|
result = setCSSparam(css, 'background-value', '32px')
|
|
|
|
|
assert result == '--background-value: 32px; --foreground-value: 24px;'
|
|
|
|
|
|
2019-11-23 13:04:11 +00:00
|
|
|
|
|
2019-11-24 11:28:58 +00:00
|
|
|
|
def testRecentPostsCache():
|
|
|
|
|
print('testRecentPostsCache')
|
2020-04-05 13:25:47 +00:00
|
|
|
|
recentPostsCache = {}
|
|
|
|
|
maxRecentPosts = 3
|
|
|
|
|
htmlStr = '<html></html>'
|
2019-11-24 11:28:58 +00:00
|
|
|
|
for i in range(5):
|
2020-04-05 13:25:47 +00:00
|
|
|
|
postJsonObject = {
|
2019-11-24 11:28:58 +00:00
|
|
|
|
"id": "https://somesite.whatever/users/someuser/statuses/"+str(i)
|
|
|
|
|
}
|
2020-04-05 13:25:47 +00:00
|
|
|
|
updateRecentPostsCache(recentPostsCache, maxRecentPosts,
|
|
|
|
|
postJsonObject, htmlStr)
|
|
|
|
|
assert len(recentPostsCache['index']) == maxRecentPosts
|
|
|
|
|
assert len(recentPostsCache['json'].items()) == maxRecentPosts
|
|
|
|
|
assert len(recentPostsCache['html'].items()) == maxRecentPosts
|
|
|
|
|
|
2019-11-24 11:28:58 +00:00
|
|
|
|
|
2020-06-14 13:25:38 +00:00
|
|
|
|
def testRemoveTextFormatting():
|
|
|
|
|
print('testRemoveTextFormatting')
|
|
|
|
|
testStr = '<p>Text without formatting</p>'
|
|
|
|
|
resultStr = removeTextFormatting(testStr)
|
|
|
|
|
assert(resultStr == testStr)
|
|
|
|
|
testStr = '<p>Text <i>with</i> <h3>formatting</h3></p>'
|
|
|
|
|
resultStr = removeTextFormatting(testStr)
|
|
|
|
|
assert(resultStr == '<p>Text with formatting</p>')
|
|
|
|
|
|
|
|
|
|
|
2020-06-15 12:37:53 +00:00
|
|
|
|
def testJsonld():
|
|
|
|
|
print("testJsonld")
|
2021-01-04 19:02:24 +00:00
|
|
|
|
|
2020-06-15 12:37:53 +00:00
|
|
|
|
jldDocument = {
|
2021-01-03 18:20:25 +00:00
|
|
|
|
"@context": "https://www.w3.org/ns/activitystreams",
|
2021-01-04 19:02:24 +00:00
|
|
|
|
"actor": "https://somesite.net/users/gerbil",
|
2020-06-15 12:37:53 +00:00
|
|
|
|
"description": "My json document",
|
|
|
|
|
"numberField": 83582,
|
|
|
|
|
"object": {
|
2021-01-03 14:34:27 +00:00
|
|
|
|
"content": "valid content"
|
2020-06-15 12:37:53 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
# privateKeyPem, publicKeyPem = generateRSAKey()
|
|
|
|
|
privateKeyPem = '-----BEGIN RSA PRIVATE KEY-----\n' \
|
|
|
|
|
'MIIEowIBAAKCAQEAod9iHfIn4ugY/2byFrFjUprrFLkkH5bCrjiBq2/MdHFg99IQ\n' \
|
|
|
|
|
'7li2x2mg5fkBMhU5SJIxlN8kiZMFq7JUXSA97Yo4puhVubqTSHihIh6Xn2mTjTgs\n' \
|
|
|
|
|
'zNo9SBbmN3YiyBPTcr0rF4jGWZAduJ8u6i7Eky2QH+UBKyUNRZrcfoVq+7grHUIA\n' \
|
|
|
|
|
'45pE7vAfEEWtgRiw32Nwlx55N3hayHax0y8gMdKEF/vfYKRLcM7rZgEASMtlCpgy\n' \
|
|
|
|
|
'fsyHwFCDzl/BP8AhP9u3dM+SEundeAvF58AiXx1pKvBpxqttDNAsKWCRQ06/WI/W\n' \
|
|
|
|
|
'2Rwihl9yCjobqRoFsZ/cTEi6FG9AbDAds5YjTwIDAQABAoIBAERL3rbpy8Bl0t43\n' \
|
|
|
|
|
'jh7a+yAIMvVMZBxb3InrV3KAug/LInGNFQ2rKnsaawN8uu9pmwCuhfLc7yqIeJUH\n' \
|
|
|
|
|
'qaadCuPlNJ/fWQQC309tbfbaV3iv78xejjBkSATZfIqb8nLeQpGflMXaNG3na1LQ\n' \
|
|
|
|
|
'/tdZoiDC0ZNTaNnOSTo765oKKqhHUTQkwkGChrwG3Js5jekV4zpPMLhUafXk6ksd\n' \
|
|
|
|
|
'8XLlZdCF3RUnuguXAg2xP/duxMYmTCx3eeGPkXBPQl0pahu8/6OtBoYvBrqNdQcx\n' \
|
|
|
|
|
'jnEtYX9PCqDY3hAXW9GWsxNfu02DKhWigFHFNRUQtMI++438+QIfzXPslE2bTQIt\n' \
|
|
|
|
|
'0OXUlwECgYEAxTKUZ7lwIBb5XKPJq53RQmX66M3ArxI1RzFSKm1+/CmxvYiN0c+5\n' \
|
|
|
|
|
'2Aq62WEIauX6hoZ7yQb4zhdeNRzinLR7rsmBvIcP12FidXG37q9v3Vu70KmHniJE\n' \
|
|
|
|
|
'TPbt5lHQ0bNACFxkar4Ab/JZN4CkMRgJdlcZ5boYNmcGOYCvw9izuM8CgYEA0iQ1\n' \
|
|
|
|
|
'khIFZ6fCiXwVRGvEHmqSnkBmBHz8MY8fczv2Z4Gzfq3Tlh9VxpigK2F2pFt7keWc\n' \
|
|
|
|
|
'53HerYFHFpf5otDhEyRwA1LyIcwbj5HopumxsB2WG+/M2as45lLfWa6KO73OtPpU\n' \
|
|
|
|
|
'wGZYW+i/otdk9eFphceYtw19mxI+3lYoeI8EjYECgYBxOtTKJkmCs45lqkp/d3QT\n' \
|
|
|
|
|
'2zjSempcXGkpQuG6KPtUUaCUgxdj1RISQj792OCbeQh8PDZRvOYaeIKInthkQKIQ\n' \
|
|
|
|
|
'P/Z1yVvIQUvmwfBqZmQmR6k1bFLJ80UiqFr7+BiegH2RD3Q9cnIP1aly3DPrWLD+\n' \
|
|
|
|
|
'OY9OQKfsfQWu+PxzyTeRMwKBgD8Zjlh5PtQ8RKcB8mTkMzSq7bHFRpzsZtH+1wPE\n' \
|
|
|
|
|
'Kp40DRDp41H9wMTsiZPdJUH/EmDh4LaCs8nHuu/m3JfuPtd/pn7pBjntzwzSVFji\n' \
|
|
|
|
|
'bW+jwrJK1Gk8B87pbZXBWlLMEOi5Dn/je37Fqd2c7f0DHauFHq9AxsmsteIPXwGs\n' \
|
|
|
|
|
'eEKBAoGBAIzJX/5yFp3ObkPracIfOJ/U/HF1UdP6Y8qmOJBZOg5s9Y+JAdY76raK\n' \
|
|
|
|
|
'0SbZPsOpuFUdTiRkSI3w/p1IuM5dPxgCGH9MHqjqogU5QwXr3vLF+a/PFhINkn1x\n' \
|
|
|
|
|
'lozRZjDcF1y6xHfExotPC973UZnKEviq9/FqOsovZpvSQkzAYSZF\n' \
|
|
|
|
|
'-----END RSA PRIVATE KEY-----'
|
|
|
|
|
publicKeyPem = '-----BEGIN PUBLIC KEY-----\n' \
|
|
|
|
|
'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAod9iHfIn4ugY/2byFrFj\n' \
|
|
|
|
|
'UprrFLkkH5bCrjiBq2/MdHFg99IQ7li2x2mg5fkBMhU5SJIxlN8kiZMFq7JUXSA9\n' \
|
|
|
|
|
'7Yo4puhVubqTSHihIh6Xn2mTjTgszNo9SBbmN3YiyBPTcr0rF4jGWZAduJ8u6i7E\n' \
|
|
|
|
|
'ky2QH+UBKyUNRZrcfoVq+7grHUIA45pE7vAfEEWtgRiw32Nwlx55N3hayHax0y8g\n' \
|
|
|
|
|
'MdKEF/vfYKRLcM7rZgEASMtlCpgyfsyHwFCDzl/BP8AhP9u3dM+SEundeAvF58Ai\n' \
|
|
|
|
|
'Xx1pKvBpxqttDNAsKWCRQ06/WI/W2Rwihl9yCjobqRoFsZ/cTEi6FG9AbDAds5Yj\n' \
|
|
|
|
|
'TwIDAQAB\n' \
|
|
|
|
|
'-----END PUBLIC KEY-----'
|
|
|
|
|
|
2021-01-04 19:02:24 +00:00
|
|
|
|
signedDocument = jldDocument.copy()
|
|
|
|
|
generateJsonSignature(signedDocument, privateKeyPem)
|
2020-06-15 12:37:53 +00:00
|
|
|
|
assert(signedDocument)
|
2020-06-15 13:35:33 +00:00
|
|
|
|
assert(signedDocument.get('signature'))
|
|
|
|
|
assert(signedDocument['signature'].get('signatureValue'))
|
|
|
|
|
assert(signedDocument['signature'].get('type'))
|
|
|
|
|
assert(len(signedDocument['signature']['signatureValue']) > 50)
|
2021-01-04 19:02:24 +00:00
|
|
|
|
# print(str(signedDocument['signature']))
|
|
|
|
|
assert(signedDocument['signature']['type'] == 'RsaSignature2017')
|
|
|
|
|
assert(verifyJsonSignature(signedDocument, publicKeyPem))
|
|
|
|
|
|
2021-01-03 14:31:35 +00:00
|
|
|
|
# alter the signed document
|
2021-01-03 18:20:25 +00:00
|
|
|
|
signedDocument['object']['content'] = 'forged content'
|
2021-01-04 19:02:24 +00:00
|
|
|
|
assert(not verifyJsonSignature(signedDocument, publicKeyPem))
|
2020-06-15 12:37:53 +00:00
|
|
|
|
|
2021-01-03 15:27:59 +00:00
|
|
|
|
jldDocument2 = {
|
2021-01-03 18:20:25 +00:00
|
|
|
|
"@context": "https://www.w3.org/ns/activitystreams",
|
2021-01-04 19:02:24 +00:00
|
|
|
|
"actor": "https://somesite.net/users/gerbil",
|
2021-01-03 15:27:59 +00:00
|
|
|
|
"description": "Another json document",
|
|
|
|
|
"numberField": 13353,
|
|
|
|
|
"object": {
|
|
|
|
|
"content": "More content"
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-01-04 19:02:24 +00:00
|
|
|
|
signedDocument2 = jldDocument2.copy()
|
|
|
|
|
generateJsonSignature(signedDocument2, privateKeyPem)
|
2021-01-03 15:27:59 +00:00
|
|
|
|
assert(signedDocument2)
|
|
|
|
|
assert(signedDocument2.get('signature'))
|
|
|
|
|
assert(signedDocument2['signature'].get('signatureValue'))
|
|
|
|
|
# changed signature on different document
|
|
|
|
|
if signedDocument['signature']['signatureValue'] == \
|
|
|
|
|
signedDocument2['signature']['signatureValue']:
|
|
|
|
|
print('json signature has not changed for different documents')
|
2021-01-04 19:02:24 +00:00
|
|
|
|
assert '.' not in str(signedDocument['signature']['signatureValue'])
|
|
|
|
|
assert len(str(signedDocument['signature']['signatureValue'])) > 340
|
2021-01-03 18:20:25 +00:00
|
|
|
|
assert(signedDocument['signature']['signatureValue'] !=
|
|
|
|
|
signedDocument2['signature']['signatureValue'])
|
2021-01-03 15:27:59 +00:00
|
|
|
|
|
2020-06-15 12:37:53 +00:00
|
|
|
|
|
2020-06-22 16:55:19 +00:00
|
|
|
|
def testSiteIsActive():
|
|
|
|
|
print('testSiteIsActive')
|
|
|
|
|
assert(siteIsActive('https://mastodon.social'))
|
|
|
|
|
assert(not siteIsActive('https://notarealwebsite.a.b.c'))
|
|
|
|
|
|
|
|
|
|
|
2020-07-07 14:18:02 +00:00
|
|
|
|
def testRemoveHtml():
|
|
|
|
|
print('testRemoveHtml')
|
|
|
|
|
testStr = 'This string has no html.'
|
|
|
|
|
assert(removeHtml(testStr) == testStr)
|
|
|
|
|
testStr = 'This string <a href="1234.567">has html</a>.'
|
|
|
|
|
assert(removeHtml(testStr) == 'This string has html.')
|
|
|
|
|
|
|
|
|
|
|
2020-12-13 14:48:45 +00:00
|
|
|
|
def testDangerousCSS():
|
|
|
|
|
print('testDangerousCSS')
|
|
|
|
|
baseDir = os.getcwd()
|
|
|
|
|
for subdir, dirs, files in os.walk(baseDir):
|
|
|
|
|
for f in files:
|
|
|
|
|
if not f.endswith('.css'):
|
|
|
|
|
continue
|
|
|
|
|
assert not dangerousCSS(baseDir + '/' + f, False)
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
|
2020-07-10 14:15:01 +00:00
|
|
|
|
def testDangerousMarkup():
|
|
|
|
|
print('testDangerousMarkup')
|
2020-11-20 10:58:49 +00:00
|
|
|
|
allowLocalNetworkAccess = False
|
2020-07-10 14:15:01 +00:00
|
|
|
|
content = '<p>This is a valid message</p>'
|
2020-11-20 10:58:49 +00:00
|
|
|
|
assert(not dangerousMarkup(content, allowLocalNetworkAccess))
|
2020-11-11 09:42:48 +00:00
|
|
|
|
|
2020-07-10 14:15:01 +00:00
|
|
|
|
content = 'This is a valid message without markup'
|
2020-11-20 10:58:49 +00:00
|
|
|
|
assert(not dangerousMarkup(content, allowLocalNetworkAccess))
|
2020-11-11 09:42:48 +00:00
|
|
|
|
|
2020-07-10 14:15:01 +00:00
|
|
|
|
content = '<p>This is a valid-looking message. But wait... ' + \
|
|
|
|
|
'<script>document.getElementById("concentrated")' + \
|
|
|
|
|
'.innerHTML = "evil";</script></p>'
|
2020-11-20 10:58:49 +00:00
|
|
|
|
assert(dangerousMarkup(content, allowLocalNetworkAccess))
|
2020-11-11 09:42:48 +00:00
|
|
|
|
|
2020-11-15 10:36:24 +00:00
|
|
|
|
content = '<p>This html contains more than you expected... ' + \
|
|
|
|
|
'<script language="javascript">document.getElementById("abc")' + \
|
|
|
|
|
'.innerHTML = "def";</script></p>'
|
2020-11-20 10:58:49 +00:00
|
|
|
|
assert(dangerousMarkup(content, allowLocalNetworkAccess))
|
2020-11-15 10:36:24 +00:00
|
|
|
|
|
2020-07-10 14:15:01 +00:00
|
|
|
|
content = '<p>This is a valid-looking message. But wait... ' + \
|
|
|
|
|
'<script src="https://evilsite/payload.js" /></p>'
|
2020-11-20 10:58:49 +00:00
|
|
|
|
assert(dangerousMarkup(content, allowLocalNetworkAccess))
|
2020-11-11 09:42:48 +00:00
|
|
|
|
|
2020-07-10 14:15:01 +00:00
|
|
|
|
content = '<p>This message embeds an evil frame.' + \
|
|
|
|
|
'<iframe src="somesite"></iframe></p>'
|
2020-11-20 10:58:49 +00:00
|
|
|
|
assert(dangerousMarkup(content, allowLocalNetworkAccess))
|
2020-11-11 09:42:48 +00:00
|
|
|
|
|
2020-07-10 14:15:01 +00:00
|
|
|
|
content = '<p>This message tries to obfuscate an evil frame.' + \
|
|
|
|
|
'< iframe src = "somesite"></ iframe ></p>'
|
2020-11-20 10:58:49 +00:00
|
|
|
|
assert(dangerousMarkup(content, allowLocalNetworkAccess))
|
2020-11-11 09:42:48 +00:00
|
|
|
|
|
2020-07-10 14:15:01 +00:00
|
|
|
|
content = '<p>This message is not necessarily evil, but annoying.' + \
|
|
|
|
|
'<hr><br><br><br><br><br><br><br><hr><hr></p>'
|
2020-11-20 10:58:49 +00:00
|
|
|
|
assert(dangerousMarkup(content, allowLocalNetworkAccess))
|
2020-11-11 09:42:48 +00:00
|
|
|
|
|
2020-07-10 14:15:01 +00:00
|
|
|
|
content = '<p>This message contans a ' + \
|
|
|
|
|
'<a href="https://validsite/index.html">valid link.</a></p>'
|
2020-11-20 10:58:49 +00:00
|
|
|
|
assert(not dangerousMarkup(content, allowLocalNetworkAccess))
|
2020-11-11 09:42:48 +00:00
|
|
|
|
|
2020-07-10 14:15:01 +00:00
|
|
|
|
content = '<p>This message contans a ' + \
|
|
|
|
|
'<a href="https://validsite/iframe.html">' + \
|
|
|
|
|
'valid link having invalid but harmless name.</a></p>'
|
2020-11-20 10:58:49 +00:00
|
|
|
|
assert(not dangerousMarkup(content, allowLocalNetworkAccess))
|
2020-07-10 14:15:01 +00:00
|
|
|
|
|
2020-11-11 09:42:48 +00:00
|
|
|
|
content = '<p>This message which <a href="127.0.0.1:8736">' + \
|
|
|
|
|
'tries to access the local network</a></p>'
|
2020-11-20 10:58:49 +00:00
|
|
|
|
assert(dangerousMarkup(content, allowLocalNetworkAccess))
|
2020-11-11 09:42:48 +00:00
|
|
|
|
|
|
|
|
|
content = '<p>This message which <a href="http://192.168.5.10:7235">' + \
|
|
|
|
|
'tries to access the local network</a></p>'
|
2020-11-20 10:58:49 +00:00
|
|
|
|
assert(dangerousMarkup(content, allowLocalNetworkAccess))
|
2020-11-11 09:42:48 +00:00
|
|
|
|
|
|
|
|
|
content = '<p>127.0.0.1 This message which does not access ' + \
|
|
|
|
|
'the local network</a></p>'
|
2020-11-20 10:58:49 +00:00
|
|
|
|
assert(not dangerousMarkup(content, allowLocalNetworkAccess))
|
2020-11-11 09:42:48 +00:00
|
|
|
|
|
2020-07-10 14:15:01 +00:00
|
|
|
|
|
2020-08-02 17:01:12 +00:00
|
|
|
|
def runHtmlReplaceQuoteMarks():
|
|
|
|
|
print('htmlReplaceQuoteMarks')
|
|
|
|
|
testStr = 'The "cat" "sat" on the mat'
|
|
|
|
|
result = htmlReplaceQuoteMarks(testStr)
|
2020-08-02 18:09:50 +00:00
|
|
|
|
assert result == 'The “cat” “sat” on the mat'
|
2020-08-02 17:01:12 +00:00
|
|
|
|
|
|
|
|
|
testStr = 'The cat sat on the mat'
|
|
|
|
|
result = htmlReplaceQuoteMarks(testStr)
|
|
|
|
|
assert result == 'The cat sat on the mat'
|
|
|
|
|
|
|
|
|
|
testStr = '"hello"'
|
|
|
|
|
result = htmlReplaceQuoteMarks(testStr)
|
2020-08-02 18:09:50 +00:00
|
|
|
|
assert result == '“hello”'
|
2020-08-02 17:01:12 +00:00
|
|
|
|
|
2020-08-02 19:16:22 +00:00
|
|
|
|
testStr = '"hello" <a href="somesite.html">"test" html</a>'
|
2020-08-02 17:17:51 +00:00
|
|
|
|
result = htmlReplaceQuoteMarks(testStr)
|
2020-08-02 19:16:22 +00:00
|
|
|
|
assert result == '“hello” <a href="somesite.html">“test” html</a>'
|
2020-08-02 17:17:51 +00:00
|
|
|
|
|
2020-08-02 17:01:12 +00:00
|
|
|
|
|
2020-08-21 18:32:16 +00:00
|
|
|
|
def testJsonPostAllowsComments():
|
|
|
|
|
print('testJsonPostAllowsComments')
|
|
|
|
|
postJsonObject = {
|
|
|
|
|
"id": "123"
|
|
|
|
|
}
|
|
|
|
|
assert jsonPostAllowsComments(postJsonObject)
|
|
|
|
|
postJsonObject = {
|
|
|
|
|
"id": "123",
|
|
|
|
|
"commentsEnabled": False
|
|
|
|
|
}
|
|
|
|
|
assert not jsonPostAllowsComments(postJsonObject)
|
|
|
|
|
postJsonObject = {
|
|
|
|
|
"id": "123",
|
|
|
|
|
"commentsEnabled": True
|
|
|
|
|
}
|
|
|
|
|
assert jsonPostAllowsComments(postJsonObject)
|
|
|
|
|
postJsonObject = {
|
|
|
|
|
"id": "123",
|
|
|
|
|
"object": {
|
|
|
|
|
"commentsEnabled": True
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
assert jsonPostAllowsComments(postJsonObject)
|
|
|
|
|
postJsonObject = {
|
|
|
|
|
"id": "123",
|
|
|
|
|
"object": {
|
|
|
|
|
"commentsEnabled": False
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
assert not jsonPostAllowsComments(postJsonObject)
|
|
|
|
|
|
|
|
|
|
|
2020-08-23 11:13:35 +00:00
|
|
|
|
def testRemoveIdEnding():
|
|
|
|
|
print('testRemoveIdEnding')
|
|
|
|
|
testStr = 'https://activitypub.somedomain.net'
|
|
|
|
|
resultStr = removeIdEnding(testStr)
|
|
|
|
|
assert resultStr == 'https://activitypub.somedomain.net'
|
|
|
|
|
|
|
|
|
|
testStr = \
|
|
|
|
|
'https://activitypub.somedomain.net/users/foo/' + \
|
|
|
|
|
'statuses/34544814814/activity'
|
|
|
|
|
resultStr = removeIdEnding(testStr)
|
|
|
|
|
assert resultStr == \
|
|
|
|
|
'https://activitypub.somedomain.net/users/foo/statuses/34544814814'
|
|
|
|
|
|
|
|
|
|
testStr = \
|
|
|
|
|
'https://undo.somedomain.net/users/foo/statuses/34544814814/undo'
|
|
|
|
|
resultStr = removeIdEnding(testStr)
|
|
|
|
|
assert resultStr == \
|
|
|
|
|
'https://undo.somedomain.net/users/foo/statuses/34544814814'
|
|
|
|
|
|
|
|
|
|
testStr = \
|
|
|
|
|
'https://event.somedomain.net/users/foo/statuses/34544814814/event'
|
|
|
|
|
resultStr = removeIdEnding(testStr)
|
|
|
|
|
assert resultStr == \
|
|
|
|
|
'https://event.somedomain.net/users/foo/statuses/34544814814'
|
|
|
|
|
|
|
|
|
|
|
2020-08-25 19:35:55 +00:00
|
|
|
|
def testValidContentWarning():
|
|
|
|
|
print('testValidContentWarning')
|
|
|
|
|
resultStr = validContentWarning('Valid content warning')
|
|
|
|
|
assert resultStr == 'Valid content warning'
|
|
|
|
|
|
|
|
|
|
resultStr = validContentWarning('Invalid #content warning')
|
|
|
|
|
assert resultStr == 'Invalid content warning'
|
|
|
|
|
|
|
|
|
|
resultStr = \
|
|
|
|
|
validContentWarning('Invalid <a href="somesite">content warning</a>')
|
|
|
|
|
assert resultStr == 'Invalid content warning'
|
|
|
|
|
|
|
|
|
|
|
2020-08-26 18:21:57 +00:00
|
|
|
|
def testTranslations():
|
|
|
|
|
print('testTranslations')
|
|
|
|
|
languagesStr = ('ar', 'ca', 'cy', 'de', 'es', 'fr', 'ga',
|
|
|
|
|
'hi', 'it', 'ja', 'oc', 'pt', 'ru', 'zh')
|
|
|
|
|
|
|
|
|
|
# load all translations into a dict
|
|
|
|
|
langDict = {}
|
|
|
|
|
for lang in languagesStr:
|
|
|
|
|
langJson = loadJson('translations/' + lang + '.json')
|
2020-08-29 11:14:19 +00:00
|
|
|
|
if not langJson:
|
|
|
|
|
print('Missing language file ' +
|
|
|
|
|
'translations/' + lang + '.json')
|
2020-08-26 18:21:57 +00:00
|
|
|
|
assert langJson
|
|
|
|
|
langDict[lang] = langJson
|
|
|
|
|
|
|
|
|
|
# load english translations
|
|
|
|
|
translationsJson = loadJson('translations/en.json')
|
|
|
|
|
# test each english string exists in the other language files
|
|
|
|
|
for englishStr, translatedStr in translationsJson.items():
|
|
|
|
|
for lang in languagesStr:
|
|
|
|
|
langJson = langDict[lang]
|
|
|
|
|
if not langJson.get(englishStr):
|
|
|
|
|
print(englishStr + ' is missing from ' + lang + '.json')
|
|
|
|
|
assert langJson.get(englishStr)
|
|
|
|
|
|
2020-09-03 18:13:29 +00:00
|
|
|
|
|
2020-09-03 18:48:32 +00:00
|
|
|
|
def testConstantTimeStringCheck():
|
|
|
|
|
print('testConstantTimeStringCheck')
|
|
|
|
|
assert constantTimeStringCheck('testing', 'testing')
|
|
|
|
|
assert not constantTimeStringCheck('testing', '1234')
|
|
|
|
|
assert not constantTimeStringCheck('testing', '1234567')
|
|
|
|
|
|
|
|
|
|
itterations = 256
|
|
|
|
|
|
|
|
|
|
start = time.time()
|
|
|
|
|
for timingTest in range(itterations):
|
|
|
|
|
constantTimeStringCheck('nnjfbefefbsnjsdnvbcueftqfeuqfbqefnjeniwufgy',
|
|
|
|
|
'nnjfbefefbsnjsdnvbcueftqfeuqfbqefnjeniwufgy')
|
|
|
|
|
end = time.time()
|
|
|
|
|
avTime1 = ((end - start) * 1000000 / itterations)
|
|
|
|
|
|
2020-09-03 18:52:18 +00:00
|
|
|
|
# change a single character and observe timing difference
|
2020-09-03 18:48:32 +00:00
|
|
|
|
start = time.time()
|
|
|
|
|
for timingTest in range(itterations):
|
|
|
|
|
constantTimeStringCheck('nnjfbefefbsnjsdnvbcueftqfeuqfbqefnjeniwufgy',
|
|
|
|
|
'nnjfbefefbsnjsdnvbcueftqfeuqfbqeznjeniwufgy')
|
|
|
|
|
end = time.time()
|
|
|
|
|
avTime2 = ((end - start) * 1000000 / itterations)
|
|
|
|
|
timeDiffMicroseconds = abs(avTime2 - avTime1)
|
|
|
|
|
# time difference should be less than 10uS
|
2020-10-25 10:10:56 +00:00
|
|
|
|
assert int(timeDiffMicroseconds) < 10
|
2020-09-03 18:48:32 +00:00
|
|
|
|
|
2020-09-03 18:52:18 +00:00
|
|
|
|
# change multiple characters and observe timing difference
|
|
|
|
|
start = time.time()
|
|
|
|
|
for timingTest in range(itterations):
|
|
|
|
|
constantTimeStringCheck('nnjfbefefbsnjsdnvbcueftqfeuqfbqefnjeniwufgy',
|
|
|
|
|
'ano1befffbsn7sd3vbluef6qseuqfpqeznjgni9bfgi')
|
|
|
|
|
end = time.time()
|
|
|
|
|
avTime2 = ((end - start) * 1000000 / itterations)
|
|
|
|
|
timeDiffMicroseconds = abs(avTime2 - avTime1)
|
|
|
|
|
# time difference should be less than 10uS
|
2020-10-25 10:10:56 +00:00
|
|
|
|
assert int(timeDiffMicroseconds) < 10
|
2020-09-03 18:52:18 +00:00
|
|
|
|
|
2020-09-03 18:48:32 +00:00
|
|
|
|
|
2020-09-14 09:33:42 +00:00
|
|
|
|
def testReplaceEmailQuote():
|
|
|
|
|
print('testReplaceEmailQuote')
|
2020-09-14 09:41:44 +00:00
|
|
|
|
testStr = '<p>This content has no quote.</p>'
|
2020-09-14 09:33:42 +00:00
|
|
|
|
assert htmlReplaceEmailQuote(testStr) == testStr
|
|
|
|
|
|
2020-09-14 09:41:44 +00:00
|
|
|
|
testStr = '<p>This content has no quote.</p>' + \
|
|
|
|
|
'<p>With multiple</p><p>lines</p>'
|
2020-09-14 09:33:42 +00:00
|
|
|
|
assert htmlReplaceEmailQuote(testStr) == testStr
|
|
|
|
|
|
2020-09-14 11:30:56 +00:00
|
|
|
|
testStr = '<p>"This is a quoted paragraph."</p>'
|
|
|
|
|
assert htmlReplaceEmailQuote(testStr) == \
|
|
|
|
|
'<p><blockquote>This is a quoted paragraph.</blockquote></p>'
|
|
|
|
|
|
2020-09-14 09:33:42 +00:00
|
|
|
|
testStr = "<p><span class=\"h-card\">" + \
|
|
|
|
|
"<a href=\"https://somewebsite/@nickname\" " + \
|
|
|
|
|
"class=\"u-url mention\">@<span>nickname</span></a></span> " + \
|
|
|
|
|
"<br />> This is a quote</p><p>Some other text.</p>"
|
|
|
|
|
expectedStr = "<p><span class=\"h-card\">" + \
|
|
|
|
|
"<a href=\"https://somewebsite/@nickname\" " + \
|
|
|
|
|
"class=\"u-url mention\">@<span>nickname</span></a></span> " + \
|
|
|
|
|
"<br /><blockquote>This is a quote</blockquote></p>" + \
|
|
|
|
|
"<p>Some other text.</p>"
|
|
|
|
|
resultStr = htmlReplaceEmailQuote(testStr)
|
|
|
|
|
if resultStr != expectedStr:
|
2020-09-30 22:52:39 +00:00
|
|
|
|
print('Result: ' + str(resultStr))
|
2020-09-14 09:33:42 +00:00
|
|
|
|
print('Expect: ' + expectedStr)
|
|
|
|
|
assert resultStr == expectedStr
|
|
|
|
|
|
2020-09-14 10:25:12 +00:00
|
|
|
|
testStr = "<p>Some text:</p><p>> first line->second line</p>" + \
|
|
|
|
|
"<p>Some question?</p>"
|
|
|
|
|
expectedStr = "<p>Some text:</p><p><blockquote>first line-<br>" + \
|
|
|
|
|
"second line</blockquote></p><p>Some question?</p>"
|
|
|
|
|
resultStr = htmlReplaceEmailQuote(testStr)
|
|
|
|
|
if resultStr != expectedStr:
|
2020-09-30 22:52:39 +00:00
|
|
|
|
print('Result: ' + str(resultStr))
|
2020-09-14 10:25:12 +00:00
|
|
|
|
print('Expect: ' + expectedStr)
|
|
|
|
|
assert resultStr == expectedStr
|
|
|
|
|
|
2020-09-30 22:22:42 +00:00
|
|
|
|
testStr = "<p><span class=\"h-card\">" + \
|
|
|
|
|
"<a href=\"https://somedomain/@somenick\" " + \
|
|
|
|
|
"class=\"u-url mention\">@<span>somenick</span>" + \
|
|
|
|
|
"</a></span> </p><p>> Text1.<br />> <br />" + \
|
|
|
|
|
"> Text2<br />> <br />> Text3<br />" + \
|
|
|
|
|
"><br />> Text4<br />> <br />> " + \
|
|
|
|
|
"Text5<br />> <br />> Text6</p><p>Text7</p>"
|
2020-09-30 22:55:53 +00:00
|
|
|
|
expectedStr = "<p><span class=\"h-card\">" + \
|
|
|
|
|
"<a href=\"https://somedomain/@somenick\" " + \
|
|
|
|
|
"class=\"u-url mention\">@<span>somenick</span></a>" + \
|
|
|
|
|
"</span> </p><p><blockquote> Text1.<br /><br />" + \
|
|
|
|
|
"Text2<br /><br />Text3<br />><br />Text4<br />" + \
|
|
|
|
|
"<br />Text5<br /><br />Text6</blockquote></p><p>Text7</p>"
|
2020-09-30 22:22:42 +00:00
|
|
|
|
resultStr = htmlReplaceEmailQuote(testStr)
|
|
|
|
|
if resultStr != expectedStr:
|
2020-09-30 22:52:39 +00:00
|
|
|
|
print('Result: ' + str(resultStr))
|
2020-09-30 22:22:42 +00:00
|
|
|
|
print('Expect: ' + expectedStr)
|
|
|
|
|
assert resultStr == expectedStr
|
|
|
|
|
|
2020-09-14 09:33:42 +00:00
|
|
|
|
|
2020-10-11 09:33:31 +00:00
|
|
|
|
def testRemoveHtmlTag():
|
|
|
|
|
print('testRemoveHtmlTag')
|
|
|
|
|
testStr = "<p><img width=\"864\" height=\"486\" " + \
|
|
|
|
|
"src=\"https://somesiteorother.com/image.jpg\"></p>"
|
|
|
|
|
resultStr = removeHtmlTag(testStr, 'width')
|
|
|
|
|
assert resultStr == "<p><img height=\"486\" " + \
|
|
|
|
|
"src=\"https://somesiteorother.com/image.jpg\"></p>"
|
|
|
|
|
|
|
|
|
|
|
2020-10-17 12:05:41 +00:00
|
|
|
|
def testHashtagRuleTree():
|
|
|
|
|
print('testHashtagRuleTree')
|
2020-10-20 17:37:15 +00:00
|
|
|
|
operators = ('not', 'and', 'or', 'xor', 'from', 'contains')
|
2020-10-17 12:05:41 +00:00
|
|
|
|
|
2020-10-20 17:37:15 +00:00
|
|
|
|
url = 'testsite.com'
|
2020-10-18 15:10:36 +00:00
|
|
|
|
moderated = True
|
|
|
|
|
conditionsStr = \
|
|
|
|
|
'contains "Cat" or contains "Corvid" or ' + \
|
|
|
|
|
'contains "Dormouse" or contains "Buzzard"'
|
|
|
|
|
tagsInConditions = []
|
|
|
|
|
tree = hashtagRuleTree(operators, conditionsStr,
|
|
|
|
|
tagsInConditions, moderated)
|
|
|
|
|
assert str(tree) == str(['or', ['contains', ['"Cat"']],
|
|
|
|
|
['contains', ['"Corvid"']],
|
|
|
|
|
['contains', ['"Dormouse"']],
|
|
|
|
|
['contains', ['"Buzzard"']]])
|
|
|
|
|
|
2020-10-17 18:49:43 +00:00
|
|
|
|
content = 'This is a test'
|
2020-10-17 17:36:10 +00:00
|
|
|
|
moderated = True
|
2020-10-17 12:05:41 +00:00
|
|
|
|
conditionsStr = '#foo or #bar'
|
|
|
|
|
tagsInConditions = []
|
2020-10-17 17:36:10 +00:00
|
|
|
|
tree = hashtagRuleTree(operators, conditionsStr,
|
|
|
|
|
tagsInConditions, moderated)
|
2020-10-17 12:05:41 +00:00
|
|
|
|
assert str(tree) == str(['or', ['#foo'], ['#bar']])
|
|
|
|
|
assert str(tagsInConditions) == str(['#foo', '#bar'])
|
|
|
|
|
hashtags = ['#foo']
|
2020-10-20 17:37:15 +00:00
|
|
|
|
assert hashtagRuleResolve(tree, hashtags, moderated, content, url)
|
2020-10-17 12:05:41 +00:00
|
|
|
|
hashtags = ['#carrot', '#stick']
|
2020-10-20 17:37:15 +00:00
|
|
|
|
assert not hashtagRuleResolve(tree, hashtags, moderated, content, url)
|
|
|
|
|
|
|
|
|
|
content = 'This is a test'
|
|
|
|
|
url = 'https://testsite.com/something'
|
|
|
|
|
moderated = True
|
|
|
|
|
conditionsStr = '#foo and from "testsite.com"'
|
|
|
|
|
tagsInConditions = []
|
|
|
|
|
tree = hashtagRuleTree(operators, conditionsStr,
|
|
|
|
|
tagsInConditions, moderated)
|
|
|
|
|
assert str(tree) == str(['and', ['#foo'], ['from', ['"testsite.com"']]])
|
|
|
|
|
assert str(tagsInConditions) == str(['#foo'])
|
|
|
|
|
hashtags = ['#foo']
|
2020-10-21 10:39:09 +00:00
|
|
|
|
assert hashtagRuleResolve(tree, hashtags, moderated, content, url)
|
2020-10-20 17:37:15 +00:00
|
|
|
|
assert not hashtagRuleResolve(tree, hashtags, moderated, content,
|
|
|
|
|
'othersite.net')
|
2020-10-17 18:49:43 +00:00
|
|
|
|
|
|
|
|
|
content = 'This is a test'
|
|
|
|
|
moderated = True
|
|
|
|
|
conditionsStr = 'contains "is a" and #foo or #bar'
|
|
|
|
|
tagsInConditions = []
|
|
|
|
|
tree = hashtagRuleTree(operators, conditionsStr,
|
|
|
|
|
tagsInConditions, moderated)
|
|
|
|
|
assert str(tree) == \
|
|
|
|
|
str(['and', ['contains', ['"is a"']],
|
|
|
|
|
['or', ['#foo'], ['#bar']]])
|
|
|
|
|
assert str(tagsInConditions) == str(['#foo', '#bar'])
|
|
|
|
|
hashtags = ['#foo']
|
2020-10-20 17:37:15 +00:00
|
|
|
|
assert hashtagRuleResolve(tree, hashtags, moderated, content, url)
|
2020-10-17 18:49:43 +00:00
|
|
|
|
hashtags = ['#carrot', '#stick']
|
2020-10-20 17:37:15 +00:00
|
|
|
|
assert not hashtagRuleResolve(tree, hashtags, moderated, content, url)
|
2020-10-17 17:36:10 +00:00
|
|
|
|
|
|
|
|
|
moderated = False
|
|
|
|
|
conditionsStr = 'not moderated and #foo or #bar'
|
|
|
|
|
tagsInConditions = []
|
|
|
|
|
tree = hashtagRuleTree(operators, conditionsStr,
|
|
|
|
|
tagsInConditions, moderated)
|
|
|
|
|
assert str(tree) == \
|
|
|
|
|
str(['not', ['and', ['moderated'], ['or', ['#foo'], ['#bar']]]])
|
|
|
|
|
assert str(tagsInConditions) == str(['#foo', '#bar'])
|
|
|
|
|
hashtags = ['#foo']
|
2020-10-20 17:37:15 +00:00
|
|
|
|
assert hashtagRuleResolve(tree, hashtags, moderated, content, url)
|
2020-10-17 17:36:10 +00:00
|
|
|
|
hashtags = ['#carrot', '#stick']
|
2020-10-20 17:37:15 +00:00
|
|
|
|
assert hashtagRuleResolve(tree, hashtags, moderated, content, url)
|
2020-10-17 17:36:10 +00:00
|
|
|
|
|
|
|
|
|
moderated = True
|
|
|
|
|
conditionsStr = 'moderated and #foo or #bar'
|
|
|
|
|
tagsInConditions = []
|
|
|
|
|
tree = hashtagRuleTree(operators, conditionsStr,
|
|
|
|
|
tagsInConditions, moderated)
|
|
|
|
|
assert str(tree) == \
|
|
|
|
|
str(['and', ['moderated'], ['or', ['#foo'], ['#bar']]])
|
|
|
|
|
assert str(tagsInConditions) == str(['#foo', '#bar'])
|
|
|
|
|
hashtags = ['#foo']
|
2020-10-20 17:37:15 +00:00
|
|
|
|
assert hashtagRuleResolve(tree, hashtags, moderated, content, url)
|
2020-10-17 17:36:10 +00:00
|
|
|
|
hashtags = ['#carrot', '#stick']
|
2020-10-20 17:37:15 +00:00
|
|
|
|
assert not hashtagRuleResolve(tree, hashtags, moderated, content, url)
|
2020-10-17 12:05:41 +00:00
|
|
|
|
|
|
|
|
|
conditionsStr = 'x'
|
|
|
|
|
tagsInConditions = []
|
2020-10-17 17:36:10 +00:00
|
|
|
|
tree = hashtagRuleTree(operators, conditionsStr,
|
|
|
|
|
tagsInConditions, moderated)
|
2020-10-17 12:05:41 +00:00
|
|
|
|
assert tree is None
|
|
|
|
|
assert tagsInConditions == []
|
|
|
|
|
hashtags = ['#foo']
|
2020-10-20 17:37:15 +00:00
|
|
|
|
assert not hashtagRuleResolve(tree, hashtags, moderated, content, url)
|
2020-10-17 12:05:41 +00:00
|
|
|
|
|
|
|
|
|
conditionsStr = '#x'
|
|
|
|
|
tagsInConditions = []
|
2020-10-17 17:36:10 +00:00
|
|
|
|
tree = hashtagRuleTree(operators, conditionsStr,
|
|
|
|
|
tagsInConditions, moderated)
|
2020-10-17 12:05:41 +00:00
|
|
|
|
assert str(tree) == str(['#x'])
|
|
|
|
|
assert str(tagsInConditions) == str(['#x'])
|
|
|
|
|
hashtags = ['#x']
|
2020-10-20 17:37:15 +00:00
|
|
|
|
assert hashtagRuleResolve(tree, hashtags, moderated, content, url)
|
2020-10-17 12:05:41 +00:00
|
|
|
|
hashtags = ['#y', '#z']
|
2020-10-20 17:37:15 +00:00
|
|
|
|
assert not hashtagRuleResolve(tree, hashtags, moderated, content, url)
|
2020-10-17 12:05:41 +00:00
|
|
|
|
|
|
|
|
|
conditionsStr = 'not #b'
|
|
|
|
|
tagsInConditions = []
|
2020-10-17 17:36:10 +00:00
|
|
|
|
tree = hashtagRuleTree(operators, conditionsStr,
|
|
|
|
|
tagsInConditions, moderated)
|
2020-10-17 12:05:41 +00:00
|
|
|
|
assert str(tree) == str(['not', ['#b']])
|
|
|
|
|
assert str(tagsInConditions) == str(['#b'])
|
|
|
|
|
hashtags = ['#y', '#z']
|
2020-10-20 17:37:15 +00:00
|
|
|
|
assert hashtagRuleResolve(tree, hashtags, moderated, content, url)
|
2020-10-17 12:05:41 +00:00
|
|
|
|
hashtags = ['#a', '#b', '#c']
|
2020-10-20 17:37:15 +00:00
|
|
|
|
assert not hashtagRuleResolve(tree, hashtags, moderated, content, url)
|
2020-10-17 12:05:41 +00:00
|
|
|
|
|
|
|
|
|
conditionsStr = '#foo or #bar and #a'
|
|
|
|
|
tagsInConditions = []
|
2020-10-17 17:36:10 +00:00
|
|
|
|
tree = hashtagRuleTree(operators, conditionsStr,
|
|
|
|
|
tagsInConditions, moderated)
|
2020-10-17 12:05:41 +00:00
|
|
|
|
assert str(tree) == str(['and', ['or', ['#foo'], ['#bar']], ['#a']])
|
|
|
|
|
assert str(tagsInConditions) == str(['#foo', '#bar', '#a'])
|
2020-10-18 15:10:36 +00:00
|
|
|
|
hashtags = ['#foo', '#bar', '#a']
|
2020-10-20 17:37:15 +00:00
|
|
|
|
assert hashtagRuleResolve(tree, hashtags, moderated, content, url)
|
2020-10-17 12:05:41 +00:00
|
|
|
|
hashtags = ['#bar', '#a']
|
2020-10-20 17:37:15 +00:00
|
|
|
|
assert hashtagRuleResolve(tree, hashtags, moderated, content, url)
|
2020-10-17 12:05:41 +00:00
|
|
|
|
hashtags = ['#foo', '#a']
|
2020-10-20 17:37:15 +00:00
|
|
|
|
assert hashtagRuleResolve(tree, hashtags, moderated, content, url)
|
2020-10-17 12:05:41 +00:00
|
|
|
|
hashtags = ['#x', '#a']
|
2020-10-20 17:37:15 +00:00
|
|
|
|
assert not hashtagRuleResolve(tree, hashtags, moderated, content, url)
|
2020-10-17 12:05:41 +00:00
|
|
|
|
|
|
|
|
|
|
2020-10-25 10:06:54 +00:00
|
|
|
|
def testGetNewswireTags():
|
|
|
|
|
print('testGetNewswireTags')
|
2020-10-25 10:24:02 +00:00
|
|
|
|
rssDescription = '<img src="https://somesite/someimage.jpg" ' + \
|
2020-10-25 10:08:02 +00:00
|
|
|
|
'class="misc-stuff" alt="#ExcitingHashtag" ' + \
|
|
|
|
|
'srcset="https://somesite/someimage.jpg" ' + \
|
|
|
|
|
'sizes="(max-width: 864px) 100vw, 864px" />' + \
|
|
|
|
|
'Compelling description with #ExcitingHashtag, which is ' + \
|
|
|
|
|
'being posted in #BoringForum'
|
2020-10-25 10:06:54 +00:00
|
|
|
|
tags = getNewswireTags(rssDescription, 10)
|
|
|
|
|
assert len(tags) == 2
|
|
|
|
|
assert '#BoringForum' in tags
|
|
|
|
|
assert '#ExcitingHashtag' in tags
|
|
|
|
|
|
|
|
|
|
|
2020-11-08 11:24:43 +00:00
|
|
|
|
def testFirstParagraphFromString():
|
|
|
|
|
print('testFirstParagraphFromString')
|
|
|
|
|
testStr = \
|
|
|
|
|
'<p><a href="https://somesite.com/somepath">This is a test</a></p>' + \
|
|
|
|
|
'<p>This is another paragraph</p>'
|
|
|
|
|
resultStr = firstParagraphFromString(testStr)
|
|
|
|
|
assert resultStr == 'This is a test'
|
|
|
|
|
|
|
|
|
|
testStr = 'Testing without html'
|
|
|
|
|
resultStr = firstParagraphFromString(testStr)
|
|
|
|
|
assert resultStr == testStr
|
|
|
|
|
|
|
|
|
|
|
2020-11-22 18:43:01 +00:00
|
|
|
|
def testParseFeedDate():
|
|
|
|
|
print('testParseFeedDate')
|
2020-12-09 10:38:09 +00:00
|
|
|
|
|
2020-12-14 15:17:30 +00:00
|
|
|
|
pubDate = "2020-12-14T00:08:06+00:00"
|
|
|
|
|
publishedDate = parseFeedDate(pubDate)
|
|
|
|
|
assert publishedDate == "2020-12-14 00:08:06+00:00"
|
|
|
|
|
|
2020-12-09 10:38:09 +00:00
|
|
|
|
pubDate = "Tue, 08 Dec 2020 06:24:38 -0600"
|
|
|
|
|
publishedDate = parseFeedDate(pubDate)
|
|
|
|
|
assert publishedDate == "2020-12-08 12:24:38+00:00"
|
|
|
|
|
|
2020-11-22 18:43:01 +00:00
|
|
|
|
pubDate = "2020-08-27T16:12:34+00:00"
|
|
|
|
|
publishedDate = parseFeedDate(pubDate)
|
2020-11-22 19:13:41 +00:00
|
|
|
|
assert publishedDate == "2020-08-27 16:12:34+00:00"
|
2020-11-22 19:01:18 +00:00
|
|
|
|
|
|
|
|
|
pubDate = "Sun, 22 Nov 2020 19:51:33 +0100"
|
|
|
|
|
publishedDate = parseFeedDate(pubDate)
|
2020-11-22 20:18:10 +00:00
|
|
|
|
assert publishedDate == "2020-11-22 18:51:33+00:00"
|
2020-11-22 18:43:01 +00:00
|
|
|
|
|
|
|
|
|
|
2020-11-24 10:53:10 +00:00
|
|
|
|
def testValidNickname():
|
|
|
|
|
print('testValidNickname')
|
|
|
|
|
domain = 'somedomain.net'
|
|
|
|
|
|
|
|
|
|
nickname = 'myvalidnick'
|
|
|
|
|
assert validNickname(domain, nickname)
|
|
|
|
|
|
|
|
|
|
nickname = 'my.invalid.nick'
|
|
|
|
|
assert not validNickname(domain, nickname)
|
|
|
|
|
|
|
|
|
|
nickname = 'myinvalidnick?'
|
|
|
|
|
assert not validNickname(domain, nickname)
|
|
|
|
|
|
|
|
|
|
nickname = 'my invalid nick?'
|
|
|
|
|
assert not validNickname(domain, nickname)
|
|
|
|
|
|
|
|
|
|
|
2020-12-05 11:11:32 +00:00
|
|
|
|
def testGuessHashtagCategory() -> None:
|
|
|
|
|
print('testGuessHashtagCategory')
|
|
|
|
|
hashtagCategories = {
|
|
|
|
|
"foo": ["swan", "goose"],
|
|
|
|
|
"bar": ["cat", "mouse"]
|
|
|
|
|
}
|
|
|
|
|
guess = guessHashtagCategory("unspecifiedgoose", hashtagCategories)
|
|
|
|
|
assert guess == "foo"
|
|
|
|
|
|
|
|
|
|
guess = guessHashtagCategory("catpic", hashtagCategories)
|
|
|
|
|
assert guess == "bar"
|
|
|
|
|
|
|
|
|
|
|
2020-12-13 19:05:26 +00:00
|
|
|
|
def testGetMentionedPeople() -> None:
|
|
|
|
|
print('testGetMentionedPeople')
|
|
|
|
|
baseDir = os.getcwd()
|
|
|
|
|
|
|
|
|
|
content = "@dragon@cave.site @bat@cave.site This is a test."
|
|
|
|
|
actors = getMentionedPeople(baseDir, 'https',
|
|
|
|
|
content,
|
|
|
|
|
'mydomain', False)
|
|
|
|
|
assert actors
|
|
|
|
|
assert len(actors) == 2
|
|
|
|
|
assert actors[0] == "https://cave.site/users/dragon"
|
|
|
|
|
assert actors[1] == "https://cave.site/users/bat"
|
|
|
|
|
|
|
|
|
|
|
2020-12-13 19:53:31 +00:00
|
|
|
|
def testReplyToPublicPost() -> None:
|
|
|
|
|
baseDir = os.getcwd()
|
|
|
|
|
nickname = 'test7492362'
|
|
|
|
|
domain = 'other.site'
|
|
|
|
|
port = 443
|
|
|
|
|
httpPrefix = 'https'
|
|
|
|
|
postId = httpPrefix + '://rat.site/users/ninjarodent/statuses/63746173435'
|
|
|
|
|
reply = \
|
|
|
|
|
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
|
|
|
|
|
"@ninjarodent@rat.site This is a test.",
|
|
|
|
|
False, False, False, True,
|
|
|
|
|
None, None, False, postId)
|
2020-12-13 20:07:45 +00:00
|
|
|
|
# print(str(reply))
|
2020-12-13 19:53:31 +00:00
|
|
|
|
assert reply['object']['content'] == \
|
|
|
|
|
'<p><span class=\"h-card\">' + \
|
|
|
|
|
'<a href=\"https://rat.site/@ninjarodent\" ' + \
|
|
|
|
|
'class=\"u-url mention\">@<span>ninjarodent</span>' + \
|
|
|
|
|
'</a></span> This is a test.</p>'
|
|
|
|
|
assert reply['object']['tag'][0]['type'] == 'Mention'
|
|
|
|
|
assert reply['object']['tag'][0]['name'] == '@ninjarodent@rat.site'
|
|
|
|
|
assert reply['object']['tag'][0]['href'] == \
|
|
|
|
|
'https://rat.site/users/ninjarodent'
|
|
|
|
|
assert len(reply['object']['to']) == 1
|
|
|
|
|
assert reply['object']['to'][0].endswith('#Public')
|
|
|
|
|
assert len(reply['object']['cc']) >= 1
|
|
|
|
|
assert reply['object']['cc'][0].endswith(nickname + '/followers')
|
|
|
|
|
assert len(reply['object']['tag']) == 1
|
|
|
|
|
assert len(reply['object']['cc']) == 2
|
|
|
|
|
assert reply['object']['cc'][1] == \
|
|
|
|
|
httpPrefix + '://rat.site/users/ninjarodent'
|
|
|
|
|
|
|
|
|
|
|
2020-12-22 21:24:46 +00:00
|
|
|
|
def getFunctionCallArgs(name: str, lines: [], startLineCtr: int) -> []:
|
|
|
|
|
"""Returns the arguments of a function call given lines
|
|
|
|
|
of source code and a starting line number
|
2020-12-22 21:27:46 +00:00
|
|
|
|
"""
|
2020-12-22 21:24:46 +00:00
|
|
|
|
argsStr = lines[startLineCtr].split(name + '(')[1]
|
|
|
|
|
if ')' in argsStr:
|
|
|
|
|
argsStr = argsStr.split(')')[0].replace(' ', '').split(',')
|
|
|
|
|
return argsStr
|
|
|
|
|
for lineCtr in range(startLineCtr + 1, len(lines)):
|
|
|
|
|
if ')' not in lines[lineCtr]:
|
|
|
|
|
argsStr += lines[lineCtr]
|
|
|
|
|
continue
|
|
|
|
|
else:
|
|
|
|
|
argsStr += lines[lineCtr].split(')')[0]
|
|
|
|
|
break
|
|
|
|
|
return argsStr.replace('\n', '').replace(' ', '').split(',')
|
|
|
|
|
|
|
|
|
|
|
2020-12-22 22:55:45 +00:00
|
|
|
|
def getFunctionCalls(name: str, lines: [], startLineCtr: int,
|
|
|
|
|
functionProperties: {}) -> []:
|
|
|
|
|
"""Returns the functions called by the given one,
|
|
|
|
|
Starting with the given source code at the given line
|
|
|
|
|
"""
|
|
|
|
|
callsFunctions = []
|
|
|
|
|
functionContentStr = ''
|
|
|
|
|
for lineCtr in range(startLineCtr + 1, len(lines)):
|
2020-12-23 12:48:50 +00:00
|
|
|
|
lineStr = lines[lineCtr].strip()
|
|
|
|
|
if lineStr.startswith('def '):
|
2020-12-22 22:55:45 +00:00
|
|
|
|
break
|
2020-12-23 12:48:50 +00:00
|
|
|
|
if lineStr.startswith('class '):
|
2020-12-22 22:55:45 +00:00
|
|
|
|
break
|
|
|
|
|
functionContentStr += lines[lineCtr]
|
|
|
|
|
for funcName, properties in functionProperties.items():
|
|
|
|
|
if funcName + '(' in functionContentStr:
|
|
|
|
|
callsFunctions.append(funcName)
|
|
|
|
|
return callsFunctions
|
|
|
|
|
|
|
|
|
|
|
2020-12-22 21:24:46 +00:00
|
|
|
|
def functionArgsMatch(callArgs: [], funcArgs: []):
|
|
|
|
|
"""Do the function artuments match the function call arguments
|
|
|
|
|
"""
|
|
|
|
|
if len(callArgs) == len(funcArgs):
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
# count non-optional arguments
|
|
|
|
|
callArgsCtr = 0
|
|
|
|
|
for a in callArgs:
|
|
|
|
|
if a == 'self':
|
|
|
|
|
continue
|
2020-12-23 12:48:50 +00:00
|
|
|
|
if '=' not in a or a.startswith("'"):
|
2020-12-22 21:24:46 +00:00
|
|
|
|
callArgsCtr += 1
|
|
|
|
|
|
|
|
|
|
funcArgsCtr = 0
|
|
|
|
|
for a in funcArgs:
|
|
|
|
|
if a == 'self':
|
|
|
|
|
continue
|
2020-12-23 12:48:50 +00:00
|
|
|
|
if '=' not in a or a.startswith("'"):
|
2020-12-22 21:24:46 +00:00
|
|
|
|
funcArgsCtr += 1
|
|
|
|
|
|
|
|
|
|
return callArgsCtr >= funcArgsCtr
|
|
|
|
|
|
|
|
|
|
|
2020-12-22 12:59:46 +00:00
|
|
|
|
def testFunctions():
|
|
|
|
|
print('testFunctions')
|
|
|
|
|
function = {}
|
|
|
|
|
functionProperties = {}
|
2020-12-22 19:28:34 +00:00
|
|
|
|
modules = {}
|
2020-12-22 12:59:46 +00:00
|
|
|
|
|
|
|
|
|
for subdir, dirs, files in os.walk('.'):
|
|
|
|
|
for sourceFile in files:
|
|
|
|
|
if not sourceFile.endswith('.py'):
|
|
|
|
|
continue
|
|
|
|
|
modName = sourceFile.replace('.py', '')
|
2020-12-22 19:28:34 +00:00
|
|
|
|
modules[modName] = {
|
|
|
|
|
'functions': []
|
|
|
|
|
}
|
2020-12-22 12:59:46 +00:00
|
|
|
|
sourceStr = ''
|
|
|
|
|
with open(sourceFile, "r") as f:
|
|
|
|
|
sourceStr = f.read()
|
2020-12-22 19:28:34 +00:00
|
|
|
|
modules[modName]['source'] = sourceStr
|
2020-12-22 12:59:46 +00:00
|
|
|
|
with open(sourceFile, "r") as f:
|
|
|
|
|
lines = f.readlines()
|
2020-12-22 19:28:34 +00:00
|
|
|
|
modules[modName]['lines'] = lines
|
2020-12-22 12:59:46 +00:00
|
|
|
|
for line in lines:
|
2020-12-23 12:48:50 +00:00
|
|
|
|
if not line.strip().startswith('def '):
|
2020-12-22 12:59:46 +00:00
|
|
|
|
continue
|
|
|
|
|
methodName = line.split('def ', 1)[1].split('(')[0]
|
|
|
|
|
methodArgs = \
|
|
|
|
|
sourceStr.split('def ' + methodName + '(')[1]
|
|
|
|
|
methodArgs = methodArgs.split(')')[0]
|
|
|
|
|
methodArgs = methodArgs.replace(' ', '').split(',')
|
|
|
|
|
if function.get(modName):
|
|
|
|
|
function[modName].append(methodName)
|
|
|
|
|
else:
|
|
|
|
|
function[modName] = [methodName]
|
2020-12-22 19:28:34 +00:00
|
|
|
|
if methodName not in modules[modName]['functions']:
|
|
|
|
|
modules[modName]['functions'].append(methodName)
|
2020-12-22 12:59:46 +00:00
|
|
|
|
functionProperties[methodName] = {
|
|
|
|
|
"args": methodArgs,
|
|
|
|
|
"module": modName,
|
|
|
|
|
"calledInModule": []
|
|
|
|
|
}
|
|
|
|
|
break
|
|
|
|
|
|
2020-12-22 21:24:46 +00:00
|
|
|
|
excludeFuncArgs = [
|
|
|
|
|
'pyjsonld'
|
|
|
|
|
]
|
|
|
|
|
excludeFuncs = [
|
2020-12-23 12:48:50 +00:00
|
|
|
|
'link',
|
|
|
|
|
'set',
|
|
|
|
|
'get'
|
2020-12-22 21:24:46 +00:00
|
|
|
|
]
|
2020-12-22 12:59:46 +00:00
|
|
|
|
# which modules is each function used within?
|
2020-12-22 19:28:34 +00:00
|
|
|
|
for modName, modProperties in modules.items():
|
2020-12-22 13:04:49 +00:00
|
|
|
|
print('Module: ' + modName + ' ✓')
|
2020-12-22 19:28:34 +00:00
|
|
|
|
for name, properties in functionProperties.items():
|
2020-12-22 21:24:46 +00:00
|
|
|
|
lineCtr = 0
|
2020-12-22 19:28:34 +00:00
|
|
|
|
for line in modules[modName]['lines']:
|
2020-12-23 12:48:50 +00:00
|
|
|
|
lineStr = line.strip()
|
|
|
|
|
if lineStr.startswith('def '):
|
|
|
|
|
lineCtr += 1
|
|
|
|
|
continue
|
|
|
|
|
if lineStr.startswith('class '):
|
2020-12-22 21:24:46 +00:00
|
|
|
|
lineCtr += 1
|
2020-12-22 19:28:34 +00:00
|
|
|
|
continue
|
|
|
|
|
if name + '(' in line:
|
|
|
|
|
modList = \
|
|
|
|
|
functionProperties[name]['calledInModule']
|
|
|
|
|
if modName not in modList:
|
|
|
|
|
modList.append(modName)
|
2020-12-22 21:24:46 +00:00
|
|
|
|
if modName in excludeFuncArgs:
|
|
|
|
|
lineCtr += 1
|
|
|
|
|
continue
|
|
|
|
|
if name in excludeFuncs:
|
|
|
|
|
lineCtr += 1
|
|
|
|
|
continue
|
|
|
|
|
callArgs = \
|
|
|
|
|
getFunctionCallArgs(name,
|
|
|
|
|
modules[modName]['lines'],
|
|
|
|
|
lineCtr)
|
|
|
|
|
if not functionArgsMatch(callArgs,
|
|
|
|
|
functionProperties[name]['args']):
|
|
|
|
|
print('Call to function ' + name +
|
|
|
|
|
' does not match its arguments')
|
|
|
|
|
print('def args: ' +
|
|
|
|
|
str(len(functionProperties[name]['args'])) +
|
|
|
|
|
'\n' + str(functionProperties[name]['args']))
|
|
|
|
|
print('Call args: ' + str(len(callArgs)) + '\n' +
|
|
|
|
|
str(callArgs))
|
|
|
|
|
print('module ' + modName + ' line ' + str(lineCtr))
|
|
|
|
|
assert False
|
|
|
|
|
lineCtr += 1
|
2020-12-22 12:59:46 +00:00
|
|
|
|
|
|
|
|
|
# don't check these functions, because they are procedurally called
|
|
|
|
|
exclusions = [
|
2020-12-23 12:48:50 +00:00
|
|
|
|
'do_GET',
|
|
|
|
|
'do_POST',
|
|
|
|
|
'do_HEAD',
|
|
|
|
|
'__run',
|
|
|
|
|
'globaltrace',
|
|
|
|
|
'localtrace',
|
|
|
|
|
'kill',
|
|
|
|
|
'clone',
|
|
|
|
|
'unregister_rdf_parser',
|
2020-12-22 12:59:46 +00:00
|
|
|
|
'set_document_loader',
|
2020-12-23 12:48:50 +00:00
|
|
|
|
'has_property',
|
|
|
|
|
'has_value',
|
|
|
|
|
'add_value',
|
|
|
|
|
'get_values',
|
|
|
|
|
'remove_property',
|
|
|
|
|
'remove_value',
|
2020-12-22 12:59:46 +00:00
|
|
|
|
'normalize',
|
|
|
|
|
'get_document_loader',
|
|
|
|
|
'runInboxQueueWatchdog',
|
|
|
|
|
'runInboxQueue',
|
|
|
|
|
'runPostSchedule',
|
|
|
|
|
'runPostScheduleWatchdog',
|
|
|
|
|
'str2bool',
|
|
|
|
|
'runNewswireDaemon',
|
|
|
|
|
'runNewswireWatchdog',
|
|
|
|
|
'threadSendPost',
|
|
|
|
|
'sendToFollowers',
|
|
|
|
|
'expireCache',
|
|
|
|
|
'getMutualsOfPerson',
|
|
|
|
|
'runPostsQueue',
|
|
|
|
|
'runSharesExpire',
|
|
|
|
|
'runPostsWatchdog',
|
|
|
|
|
'runSharesExpireWatchdog',
|
|
|
|
|
'getThisWeeksEvents',
|
|
|
|
|
'getAvailability',
|
|
|
|
|
'testThreadsFunction',
|
|
|
|
|
'createServerAlice',
|
|
|
|
|
'createServerBob',
|
|
|
|
|
'createServerEve',
|
|
|
|
|
'E2EEremoveDevice',
|
|
|
|
|
'setOrganizationScheme'
|
|
|
|
|
]
|
2020-12-22 13:57:24 +00:00
|
|
|
|
excludeImports = [
|
2020-12-23 12:48:50 +00:00
|
|
|
|
'link',
|
|
|
|
|
'start'
|
2020-12-22 13:57:24 +00:00
|
|
|
|
]
|
2020-12-22 18:06:23 +00:00
|
|
|
|
excludeLocal = [
|
|
|
|
|
'pyjsonld',
|
|
|
|
|
'daemon',
|
|
|
|
|
'tests'
|
|
|
|
|
]
|
2020-12-23 12:48:50 +00:00
|
|
|
|
excludeMods = [
|
|
|
|
|
'pyjsonld'
|
|
|
|
|
]
|
2020-12-22 12:59:46 +00:00
|
|
|
|
# check that functions are called somewhere
|
|
|
|
|
for name, properties in functionProperties.items():
|
2020-12-23 12:48:50 +00:00
|
|
|
|
if name.startswith('__'):
|
|
|
|
|
if name.endswith('__'):
|
|
|
|
|
continue
|
2020-12-22 12:59:46 +00:00
|
|
|
|
if name in exclusions:
|
|
|
|
|
continue
|
2020-12-23 12:48:50 +00:00
|
|
|
|
if properties['module'] in excludeMods:
|
|
|
|
|
continue
|
2020-12-22 18:20:32 +00:00
|
|
|
|
isLocalFunction = False
|
2020-12-22 12:59:46 +00:00
|
|
|
|
if not properties['calledInModule']:
|
|
|
|
|
print('function ' + name +
|
|
|
|
|
' in module ' + properties['module'] +
|
|
|
|
|
' is not called anywhere')
|
|
|
|
|
assert properties['calledInModule']
|
2020-12-22 18:06:23 +00:00
|
|
|
|
|
|
|
|
|
if len(properties['calledInModule']) == 1:
|
|
|
|
|
modName = properties['calledInModule'][0]
|
|
|
|
|
if modName not in excludeLocal and \
|
|
|
|
|
modName == properties['module']:
|
2020-12-22 18:20:32 +00:00
|
|
|
|
isLocalFunction = True
|
2020-12-22 18:06:23 +00:00
|
|
|
|
if not name.startswith('_'):
|
|
|
|
|
print('Local function ' + name +
|
2020-12-22 18:16:24 +00:00
|
|
|
|
' in ' + modName + '.py does not begin with _')
|
2020-12-22 18:06:23 +00:00
|
|
|
|
assert False
|
|
|
|
|
|
2020-12-22 13:57:24 +00:00
|
|
|
|
if name not in excludeImports:
|
|
|
|
|
for modName in properties['calledInModule']:
|
|
|
|
|
if modName == properties['module']:
|
|
|
|
|
continue
|
|
|
|
|
importStr = 'from ' + properties['module'] + ' import ' + name
|
2020-12-22 19:28:34 +00:00
|
|
|
|
if importStr not in modules[modName]['source']:
|
2020-12-22 13:57:24 +00:00
|
|
|
|
print(importStr + ' not found in ' + modName + '.py')
|
|
|
|
|
assert False
|
2020-12-22 18:16:24 +00:00
|
|
|
|
|
2020-12-22 18:20:32 +00:00
|
|
|
|
if not isLocalFunction:
|
2020-12-22 18:16:24 +00:00
|
|
|
|
if name.startswith('_'):
|
|
|
|
|
excludePublic = [
|
|
|
|
|
'pyjsonld',
|
|
|
|
|
'daemon',
|
|
|
|
|
'tests'
|
|
|
|
|
]
|
|
|
|
|
modName = properties['module']
|
|
|
|
|
if modName not in excludePublic:
|
|
|
|
|
print('Public function ' + name + ' in ' +
|
|
|
|
|
modName + '.py begins with _')
|
|
|
|
|
assert False
|
2020-12-22 13:04:49 +00:00
|
|
|
|
print('Function: ' + name + ' ✓')
|
2020-12-22 12:59:46 +00:00
|
|
|
|
|
2020-12-23 16:19:18 +00:00
|
|
|
|
print('Constructing function call graph')
|
2020-12-23 18:15:30 +00:00
|
|
|
|
moduleColors = ('red', 'green', 'yellow', 'orange', 'purple', 'cyan',
|
|
|
|
|
'darkgoldenrod3', 'darkolivegreen1', 'darkorange1',
|
|
|
|
|
'darkorchid1', 'darkseagreen', 'darkslategray4',
|
|
|
|
|
'deeppink1', 'deepskyblue1', 'dimgrey', 'gold1',
|
|
|
|
|
'goldenrod', 'burlywood2', 'bisque1', 'brown1',
|
|
|
|
|
'chartreuse2', 'cornsilk', 'darksalmon')
|
2020-12-23 17:56:25 +00:00
|
|
|
|
maxModuleCalls = 1
|
2020-12-23 19:55:51 +00:00
|
|
|
|
maxFunctionCalls = 1
|
2020-12-23 18:15:30 +00:00
|
|
|
|
colorCtr = 0
|
2020-12-22 22:55:45 +00:00
|
|
|
|
for modName, modProperties in modules.items():
|
|
|
|
|
lineCtr = 0
|
2020-12-23 18:15:30 +00:00
|
|
|
|
modules[modName]['color'] = moduleColors[colorCtr]
|
|
|
|
|
colorCtr += 1
|
|
|
|
|
if colorCtr >= len(moduleColors):
|
|
|
|
|
colorCtr = 0
|
2020-12-22 22:55:45 +00:00
|
|
|
|
for line in modules[modName]['lines']:
|
2020-12-23 12:48:50 +00:00
|
|
|
|
if line.strip().startswith('def '):
|
2020-12-22 22:55:45 +00:00
|
|
|
|
name = line.split('def ')[1].split('(')[0]
|
|
|
|
|
callsList = \
|
|
|
|
|
getFunctionCalls(name, modules[modName]['lines'],
|
|
|
|
|
lineCtr, functionProperties)
|
|
|
|
|
functionProperties[name]['calls'] = callsList.copy()
|
2020-12-23 19:55:51 +00:00
|
|
|
|
if len(callsList) > maxFunctionCalls:
|
|
|
|
|
maxFunctionCalls = len(callsList)
|
2020-12-23 16:19:18 +00:00
|
|
|
|
# keep track of which module calls which other module
|
|
|
|
|
for fn in callsList:
|
|
|
|
|
modCall = functionProperties[fn]['module']
|
|
|
|
|
if modCall != modName:
|
|
|
|
|
if modules[modName].get('calls'):
|
|
|
|
|
if modCall not in modules[modName]['calls']:
|
|
|
|
|
modules[modName]['calls'].append(modCall)
|
2020-12-23 17:56:25 +00:00
|
|
|
|
if len(modules[modName]['calls']) > \
|
|
|
|
|
maxModuleCalls:
|
|
|
|
|
maxModuleCalls = \
|
|
|
|
|
len(modules[modName]['calls'])
|
2020-12-23 16:19:18 +00:00
|
|
|
|
else:
|
|
|
|
|
modules[modName]['calls'] = [modCall]
|
2020-12-22 22:55:45 +00:00
|
|
|
|
lineCtr += 1
|
2020-12-23 16:19:18 +00:00
|
|
|
|
callGraphStr = 'digraph EpicyonModules {\n\n'
|
|
|
|
|
callGraphStr += ' graph [fontsize=10 fontname="Verdana" compound=true];\n'
|
|
|
|
|
callGraphStr += ' node [shape=record fontsize=10 fontname="Verdana"];\n\n'
|
2020-12-23 17:56:25 +00:00
|
|
|
|
# colors of modules nodes
|
|
|
|
|
for modName, modProperties in modules.items():
|
|
|
|
|
if not modProperties.get('calls'):
|
|
|
|
|
callGraphStr += ' "' + modName + \
|
2020-12-23 19:55:51 +00:00
|
|
|
|
'" [fillcolor=yellow style=filled];\n'
|
2020-12-23 17:56:25 +00:00
|
|
|
|
continue
|
2020-12-23 19:55:51 +00:00
|
|
|
|
if len(modProperties['calls']) <= int(maxModuleCalls / 8):
|
2020-12-23 17:56:25 +00:00
|
|
|
|
callGraphStr += ' "' + modName + \
|
2020-12-23 19:55:51 +00:00
|
|
|
|
'" [fillcolor=green style=filled];\n'
|
|
|
|
|
elif len(modProperties['calls']) < int(maxModuleCalls / 4):
|
|
|
|
|
callGraphStr += ' "' + modName + \
|
|
|
|
|
'" [fillcolor=orange style=filled];\n'
|
2020-12-23 17:56:25 +00:00
|
|
|
|
else:
|
|
|
|
|
callGraphStr += ' "' + modName + \
|
2020-12-23 19:55:51 +00:00
|
|
|
|
'" [fillcolor=red style=filled];\n'
|
2020-12-23 17:56:25 +00:00
|
|
|
|
callGraphStr += '\n'
|
|
|
|
|
# connections between modules
|
2020-12-23 16:19:18 +00:00
|
|
|
|
for modName, modProperties in modules.items():
|
|
|
|
|
if not modProperties.get('calls'):
|
|
|
|
|
continue
|
|
|
|
|
for modCall in modProperties['calls']:
|
|
|
|
|
callGraphStr += ' "' + modName + '" -> "' + modCall + '";\n'
|
|
|
|
|
callGraphStr += '\n}\n'
|
|
|
|
|
with open('epicyon_modules.dot', 'w+') as fp:
|
|
|
|
|
fp.write(callGraphStr)
|
|
|
|
|
print('Modules call graph saved to epicyon_modules.dot')
|
|
|
|
|
print('Plot using: ' +
|
|
|
|
|
'sfdp -x -Goverlap=false -Goverlap_scaling=2 ' +
|
|
|
|
|
'-Gsep=+100 -Tx11 epicyon_modules.dot')
|
|
|
|
|
|
2020-12-22 22:55:45 +00:00
|
|
|
|
callGraphStr = 'digraph Epicyon {\n\n'
|
2020-12-23 16:19:18 +00:00
|
|
|
|
callGraphStr += ' size="8,6"; ratio=fill;\n'
|
2020-12-22 22:55:45 +00:00
|
|
|
|
callGraphStr += ' graph [fontsize=10 fontname="Verdana" compound=true];\n'
|
|
|
|
|
callGraphStr += ' node [shape=record fontsize=10 fontname="Verdana"];\n\n'
|
|
|
|
|
|
|
|
|
|
for modName, modProperties in modules.items():
|
2020-12-22 23:26:09 +00:00
|
|
|
|
callGraphStr += ' subgraph cluster_' + modName + ' {\n'
|
|
|
|
|
callGraphStr += ' label = "' + modName + '";\n'
|
2020-12-23 19:55:51 +00:00
|
|
|
|
callGraphStr += ' node [style=filled];\n'
|
2020-12-23 13:41:54 +00:00
|
|
|
|
moduleFunctionsStr = ''
|
2020-12-22 22:55:45 +00:00
|
|
|
|
for name in modProperties['functions']:
|
2020-12-23 14:19:06 +00:00
|
|
|
|
if name.startswith('test'):
|
|
|
|
|
continue
|
2020-12-23 13:41:54 +00:00
|
|
|
|
if name not in excludeFuncs:
|
2020-12-23 19:55:51 +00:00
|
|
|
|
if not functionProperties[name]['calls']:
|
|
|
|
|
moduleFunctionsStr += \
|
|
|
|
|
' "' + name + '" [fillcolor=yellow style=filled];\n'
|
|
|
|
|
continue
|
|
|
|
|
noOfCalls = len(functionProperties[name]['calls'])
|
|
|
|
|
if noOfCalls < int(maxFunctionCalls / 4):
|
|
|
|
|
moduleFunctionsStr += ' "' + name + \
|
|
|
|
|
'" [fillcolor=orange style=filled];\n'
|
|
|
|
|
else:
|
|
|
|
|
moduleFunctionsStr += ' "' + name + \
|
|
|
|
|
'" [fillcolor=red style=filled];\n'
|
|
|
|
|
|
2020-12-23 13:41:54 +00:00
|
|
|
|
if moduleFunctionsStr:
|
2020-12-23 19:55:51 +00:00
|
|
|
|
callGraphStr += moduleFunctionsStr + '\n'
|
2020-12-22 22:55:45 +00:00
|
|
|
|
callGraphStr += ' color=blue;\n'
|
|
|
|
|
callGraphStr += ' }\n\n'
|
|
|
|
|
|
|
|
|
|
for name, properties in functionProperties.items():
|
|
|
|
|
if not properties['calls']:
|
|
|
|
|
continue
|
2020-12-23 19:55:51 +00:00
|
|
|
|
noOfCalls = len(properties['calls'])
|
|
|
|
|
if noOfCalls <= int(maxFunctionCalls / 8):
|
|
|
|
|
modColor = 'blue'
|
|
|
|
|
elif noOfCalls < int(maxFunctionCalls / 4):
|
|
|
|
|
modColor = 'green'
|
|
|
|
|
else:
|
|
|
|
|
modColor = 'red'
|
2020-12-22 23:26:09 +00:00
|
|
|
|
for calledFunc in properties['calls']:
|
2020-12-23 14:19:06 +00:00
|
|
|
|
if calledFunc.startswith('test'):
|
|
|
|
|
continue
|
2020-12-23 13:41:54 +00:00
|
|
|
|
if calledFunc not in excludeFuncs:
|
2020-12-23 18:15:30 +00:00
|
|
|
|
callGraphStr += ' "' + name + '" -> "' + calledFunc + \
|
|
|
|
|
'" [color=' + modColor + '];\n'
|
2020-12-22 22:55:45 +00:00
|
|
|
|
|
|
|
|
|
callGraphStr += '\n}\n'
|
|
|
|
|
with open('epicyon.dot', 'w+') as fp:
|
|
|
|
|
fp.write(callGraphStr)
|
|
|
|
|
print('Call graph saved to epicyon.dot')
|
2020-12-23 16:19:18 +00:00
|
|
|
|
print('Plot using: ' +
|
2020-12-23 13:41:54 +00:00
|
|
|
|
'sfdp -x -Goverlap=prism -Goverlap_scaling=8 ' +
|
|
|
|
|
'-Gsep=+120 -Tx11 epicyon.dot')
|
2020-12-22 22:55:45 +00:00
|
|
|
|
|
2020-12-22 12:59:46 +00:00
|
|
|
|
|
2021-01-02 10:37:19 +00:00
|
|
|
|
def testLinksWithinPost() -> None:
|
|
|
|
|
baseDir = os.getcwd()
|
|
|
|
|
nickname = 'test27636'
|
|
|
|
|
domain = 'rando.site'
|
|
|
|
|
port = 443
|
|
|
|
|
httpPrefix = 'https'
|
|
|
|
|
content = 'This is a test post with links.\n\n' + \
|
|
|
|
|
'ftp://ftp.ncdc.noaa.gov/pub/data/ghcn/v4/\n\nhttps://freedombone.net'
|
|
|
|
|
postJsonObject = \
|
|
|
|
|
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
|
|
|
|
|
content,
|
|
|
|
|
False, False, False, True,
|
|
|
|
|
None, None, False, None)
|
|
|
|
|
assert postJsonObject['object']['content'] == \
|
|
|
|
|
'<p>This is a test post with links.<br><br>' + \
|
|
|
|
|
'<a href="ftp://ftp.ncdc.noaa.gov/pub/data/ghcn/v4/" ' + \
|
|
|
|
|
'rel="nofollow noopener noreferrer" target="_blank">' + \
|
|
|
|
|
'<span class="invisible">ftp://</span>' + \
|
|
|
|
|
'<span class="ellipsis">' + \
|
|
|
|
|
'ftp.ncdc.noaa.gov/pub/data/ghcn/v4/</span>' + \
|
|
|
|
|
'</a><br><br><a href="https://freedombone.net" ' + \
|
|
|
|
|
'rel="nofollow noopener noreferrer" target="_blank">' + \
|
|
|
|
|
'<span class="invisible">https://</span>' + \
|
|
|
|
|
'<span class="ellipsis">freedombone.net</span></a></p>'
|
|
|
|
|
|
2021-01-05 23:09:04 +00:00
|
|
|
|
content = "<p>Some text</p><p>Other text</p><p>More text</p>" + \
|
|
|
|
|
"<pre><code>Errno::EOHNOES (No such file or rodent @ " + \
|
|
|
|
|
"ik_right - /tmp/blah.png)<br></code></pre><p>" + \
|
|
|
|
|
"(<a href=\"https://welllookeyhere.maam/error.txt\" " + \
|
|
|
|
|
"rel=\"nofollow noopener noreferrer\" target=\"_blank\">" + \
|
|
|
|
|
"wuh</a>)</p><p>Oh yeah like for sure</p>" + \
|
|
|
|
|
"<p>Ground sloth tin opener</p>" + \
|
|
|
|
|
"<p><a href=\"https://whocodedthis.huh/tags/" + \
|
|
|
|
|
"taggedthing\" class=\"mention hashtag\" rel=\"tag\" " + \
|
|
|
|
|
"target=\"_blank\">#<span>taggedthing</span></a></p>"
|
|
|
|
|
postJsonObject = \
|
|
|
|
|
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
|
|
|
|
|
content,
|
|
|
|
|
False, False, False, True,
|
|
|
|
|
None, None, False, None)
|
|
|
|
|
assert postJsonObject['object']['content'] == content
|
|
|
|
|
|
2021-01-02 10:37:19 +00:00
|
|
|
|
|
2021-01-22 13:32:37 +00:00
|
|
|
|
def testMastoApi():
|
|
|
|
|
print('testMastoApi')
|
|
|
|
|
nickname = 'ThisIsATestNickname'
|
|
|
|
|
mastoId = getMastoApiV1IdFromNickname(nickname)
|
|
|
|
|
assert(mastoId)
|
|
|
|
|
nickname2 = getNicknameFromMastoApiV1Id(mastoId)
|
|
|
|
|
if nickname2 != nickname:
|
|
|
|
|
print(nickname + ' != ' + nickname2)
|
|
|
|
|
assert nickname2 == nickname
|
|
|
|
|
|
|
|
|
|
|
2021-01-25 12:24:40 +00:00
|
|
|
|
def testDomainHandling():
|
|
|
|
|
print('testDomainHandling')
|
|
|
|
|
testDomain = 'localhost'
|
|
|
|
|
assert decodedHost(testDomain) == testDomain
|
|
|
|
|
testDomain = '127.0.0.1:60'
|
|
|
|
|
assert decodedHost(testDomain) == testDomain
|
|
|
|
|
testDomain = '192.168.5.153'
|
|
|
|
|
assert decodedHost(testDomain) == testDomain
|
|
|
|
|
testDomain = 'xn--espaa-rta.icom.museum'
|
|
|
|
|
assert decodedHost(testDomain) == "españa.icom.museum"
|
|
|
|
|
|
|
|
|
|
|
2021-02-02 21:08:33 +00:00
|
|
|
|
def testPrepareHtmlPostNickname():
|
|
|
|
|
print('testPrepareHtmlPostNickname')
|
|
|
|
|
postHtml = '<a class="imageAnchor" href="/users/bob?replyfollowers='
|
|
|
|
|
postHtml += '<a class="imageAnchor" href="/users/bob?repeatprivate='
|
|
|
|
|
result = prepareHtmlPostNickname('alice', postHtml)
|
|
|
|
|
assert result == postHtml.replace('/bob?', '/alice?')
|
|
|
|
|
|
|
|
|
|
postHtml = '<a class="imageAnchor" href="/users/bob?replyfollowers='
|
|
|
|
|
postHtml += '<a class="imageAnchor" href="/users/bob;repeatprivate='
|
|
|
|
|
expectedHtml = '<a class="imageAnchor" href="/users/alice?replyfollowers='
|
|
|
|
|
expectedHtml += '<a class="imageAnchor" href="/users/bob;repeatprivate='
|
|
|
|
|
result = prepareHtmlPostNickname('alice', postHtml)
|
|
|
|
|
assert result == expectedHtml
|
|
|
|
|
|
|
|
|
|
|
2019-06-30 21:20:02 +00:00
|
|
|
|
def runAllTests():
|
|
|
|
|
print('Running tests...')
|
2020-12-22 12:59:46 +00:00
|
|
|
|
testFunctions()
|
2021-02-02 21:08:33 +00:00
|
|
|
|
testPrepareHtmlPostNickname()
|
2021-01-25 12:24:40 +00:00
|
|
|
|
testDomainHandling()
|
2021-01-22 13:32:37 +00:00
|
|
|
|
testMastoApi()
|
2021-01-02 10:37:19 +00:00
|
|
|
|
testLinksWithinPost()
|
2020-12-13 19:53:31 +00:00
|
|
|
|
testReplyToPublicPost()
|
2020-12-13 19:05:26 +00:00
|
|
|
|
testGetMentionedPeople()
|
2020-12-05 11:11:32 +00:00
|
|
|
|
testGuessHashtagCategory()
|
2020-11-24 10:53:10 +00:00
|
|
|
|
testValidNickname()
|
2020-11-22 18:43:01 +00:00
|
|
|
|
testParseFeedDate()
|
2020-11-08 11:24:43 +00:00
|
|
|
|
testFirstParagraphFromString()
|
2020-10-25 10:06:54 +00:00
|
|
|
|
testGetNewswireTags()
|
2020-10-17 12:05:41 +00:00
|
|
|
|
testHashtagRuleTree()
|
2020-10-11 09:33:31 +00:00
|
|
|
|
testRemoveHtmlTag()
|
2020-09-14 09:33:42 +00:00
|
|
|
|
testReplaceEmailQuote()
|
2020-09-03 18:48:32 +00:00
|
|
|
|
testConstantTimeStringCheck()
|
2020-08-26 18:21:57 +00:00
|
|
|
|
testTranslations()
|
2020-08-25 19:35:55 +00:00
|
|
|
|
testValidContentWarning()
|
2020-08-23 11:13:35 +00:00
|
|
|
|
testRemoveIdEnding()
|
2020-08-21 18:32:16 +00:00
|
|
|
|
testJsonPostAllowsComments()
|
2020-08-02 17:01:12 +00:00
|
|
|
|
runHtmlReplaceQuoteMarks()
|
2020-12-13 14:48:45 +00:00
|
|
|
|
testDangerousCSS()
|
2020-07-10 14:15:01 +00:00
|
|
|
|
testDangerousMarkup()
|
2020-07-07 14:18:02 +00:00
|
|
|
|
testRemoveHtml()
|
2020-06-22 16:55:19 +00:00
|
|
|
|
testSiteIsActive()
|
2020-06-15 12:37:53 +00:00
|
|
|
|
testJsonld()
|
2020-06-14 13:25:38 +00:00
|
|
|
|
testRemoveTextFormatting()
|
2020-01-24 11:27:12 +00:00
|
|
|
|
testWebLinks()
|
2019-11-24 11:28:58 +00:00
|
|
|
|
testRecentPostsCache()
|
2019-11-23 13:04:11 +00:00
|
|
|
|
testTheme()
|
2019-11-23 10:13:57 +00:00
|
|
|
|
testSaveLoadJson()
|
2020-10-11 12:41:15 +00:00
|
|
|
|
testJsonString()
|
2019-10-12 12:45:53 +00:00
|
|
|
|
testGetStatusNumber()
|
2020-02-21 15:09:31 +00:00
|
|
|
|
testAddEmoji()
|
2019-08-21 16:35:46 +00:00
|
|
|
|
testActorParsing()
|
2019-06-30 21:20:02 +00:00
|
|
|
|
testHttpsig()
|
|
|
|
|
testCache()
|
|
|
|
|
testThreads()
|
2019-07-03 10:04:23 +00:00
|
|
|
|
testCreatePerson()
|
2019-07-03 18:24:44 +00:00
|
|
|
|
testAuthentication()
|
2019-07-05 12:35:29 +00:00
|
|
|
|
testFollowersOfPerson()
|
2019-07-05 14:25:15 +00:00
|
|
|
|
testNoOfFollowersOnDomain()
|
2019-07-08 08:51:33 +00:00
|
|
|
|
testFollows()
|
|
|
|
|
testGroupFollowers()
|
2019-07-18 16:21:26 +00:00
|
|
|
|
testDelegateRoles()
|
2020-03-22 21:16:02 +00:00
|
|
|
|
print('Tests succeeded\n')
|