2016-09-13 11:56:42 +03:00
|
|
|
import sys, subprocess, json
|
|
|
|
|
|
|
|
termwidth = 150
|
|
|
|
|
|
|
|
print_communication = True
|
|
|
|
|
|
|
|
def ordered(obj):
|
|
|
|
if isinstance(obj, dict):
|
|
|
|
return sorted((k, ordered(v)) for k, v in obj.items())
|
|
|
|
if isinstance(obj, list):
|
|
|
|
return sorted(ordered(x) for x in obj)
|
|
|
|
else:
|
|
|
|
return obj
|
|
|
|
|
|
|
|
def col_print(title, array):
|
|
|
|
print
|
|
|
|
print
|
|
|
|
print(title)
|
|
|
|
|
|
|
|
indentwidth = 4
|
|
|
|
indent = " " * indentwidth
|
|
|
|
|
|
|
|
if not array:
|
|
|
|
print(indent + "<None>")
|
|
|
|
return
|
|
|
|
|
|
|
|
padwidth = 2
|
|
|
|
|
|
|
|
maxitemwidth = len(max(array, key=len))
|
|
|
|
|
|
|
|
numCols = max(1, int((termwidth - indentwidth + padwidth) / (maxitemwidth + padwidth)))
|
|
|
|
|
|
|
|
numRows = len(array) // numCols + 1
|
|
|
|
|
|
|
|
pad = " " * padwidth
|
|
|
|
|
|
|
|
for index in range(numRows):
|
|
|
|
print(indent + pad.join(item.ljust(maxitemwidth) for item in array[index::numRows]))
|
|
|
|
|
|
|
|
def waitForRawMessage(cmakeCommand):
|
|
|
|
stdoutdata = ""
|
|
|
|
payload = ""
|
|
|
|
while not cmakeCommand.poll():
|
|
|
|
stdoutdataLine = cmakeCommand.stdout.readline()
|
|
|
|
if stdoutdataLine:
|
|
|
|
stdoutdata += stdoutdataLine.decode('utf-8')
|
|
|
|
else:
|
|
|
|
break
|
|
|
|
begin = stdoutdata.find("[== CMake Server ==[\n")
|
|
|
|
end = stdoutdata.find("]== CMake Server ==]")
|
|
|
|
|
|
|
|
if (begin != -1 and end != -1):
|
|
|
|
begin += len("[== CMake Server ==[\n")
|
|
|
|
payload = stdoutdata[begin:end]
|
|
|
|
if print_communication:
|
|
|
|
print("\nSERVER>", json.loads(payload), "\n")
|
|
|
|
return json.loads(payload)
|
|
|
|
|
|
|
|
def writeRawData(cmakeCommand, content):
|
|
|
|
writeRawData.counter += 1
|
|
|
|
payload = """
|
|
|
|
[== CMake Server ==[
|
|
|
|
%s
|
|
|
|
]== CMake Server ==]
|
|
|
|
""" % content
|
|
|
|
|
|
|
|
rn = ( writeRawData.counter % 2 ) == 0
|
|
|
|
|
|
|
|
if rn:
|
|
|
|
payload = payload.replace('\n', '\r\n')
|
|
|
|
|
|
|
|
if print_communication:
|
|
|
|
print("\nCLIENT>", content, "(Use \\r\\n:", rn, ")\n")
|
|
|
|
cmakeCommand.stdin.write(payload.encode('utf-8'))
|
|
|
|
cmakeCommand.stdin.flush()
|
|
|
|
writeRawData.counter = 0
|
|
|
|
|
|
|
|
def writePayload(cmakeCommand, obj):
|
|
|
|
writeRawData(cmakeCommand, json.dumps(obj))
|
|
|
|
|
|
|
|
def initProc(cmakeCommand):
|
2016-09-09 11:01:44 +03:00
|
|
|
cmakeCommand = subprocess.Popen([cmakeCommand, "-E", "server", "--experimental", "--debug"],
|
2016-09-13 11:56:42 +03:00
|
|
|
stdin=subprocess.PIPE,
|
|
|
|
stdout=subprocess.PIPE)
|
|
|
|
|
|
|
|
packet = waitForRawMessage(cmakeCommand)
|
|
|
|
if packet == None:
|
|
|
|
print("Not in server mode")
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
if packet['type'] != 'hello':
|
|
|
|
print("No hello message")
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
return cmakeCommand
|
|
|
|
|
|
|
|
def waitForMessage(cmakeCommand, expected):
|
|
|
|
data = ordered(expected)
|
|
|
|
packet = ordered(waitForRawMessage(cmakeCommand))
|
|
|
|
|
|
|
|
if packet != data:
|
|
|
|
sys.exit(-1)
|
|
|
|
return packet
|
|
|
|
|
2016-09-27 22:29:20 +03:00
|
|
|
def waitForReply(cmakeCommand, originalType, cookie, skipProgress):
|
|
|
|
gotResult = False
|
|
|
|
while True:
|
|
|
|
packet = waitForRawMessage(cmakeCommand)
|
|
|
|
t = packet['type']
|
|
|
|
if packet['cookie'] != cookie or packet['inReplyTo'] != originalType:
|
|
|
|
sys.exit(1)
|
|
|
|
if t == 'message' or t == 'progress':
|
|
|
|
if skipProgress:
|
|
|
|
continue
|
|
|
|
if t == 'reply':
|
|
|
|
break
|
2016-09-13 11:56:42 +03:00
|
|
|
sys.exit(1)
|
2016-09-27 22:29:20 +03:00
|
|
|
|
2016-09-09 11:01:45 +03:00
|
|
|
return packet
|
2016-09-13 11:56:42 +03:00
|
|
|
|
|
|
|
def waitForError(cmakeCommand, originalType, cookie, message):
|
|
|
|
packet = waitForRawMessage(cmakeCommand)
|
|
|
|
if packet['cookie'] != cookie or packet['type'] != 'error' or packet['inReplyTo'] != originalType or packet['errorMessage'] != message:
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
def waitForProgress(cmakeCommand, originalType, cookie, current, message):
|
|
|
|
packet = waitForRawMessage(cmakeCommand)
|
|
|
|
if packet['cookie'] != cookie or packet['type'] != 'progress' or packet['inReplyTo'] != originalType or packet['progressCurrent'] != current or packet['progressMessage'] != message:
|
|
|
|
sys.exit(1)
|
|
|
|
|
2016-09-09 11:01:45 +03:00
|
|
|
def handshake(cmakeCommand, major, minor, source, build, generator, extraGenerator):
|
2016-09-13 11:56:42 +03:00
|
|
|
version = { 'major': major }
|
|
|
|
if minor >= 0:
|
|
|
|
version['minor'] = minor
|
|
|
|
|
2016-09-09 11:01:45 +03:00
|
|
|
writePayload(cmakeCommand, { 'type': 'handshake', 'protocolVersion': version,
|
|
|
|
'cookie': 'TEST_HANDSHAKE', 'sourceDirectory': source, 'buildDirectory': build,
|
|
|
|
'generator': generator, 'extraGenerator': extraGenerator })
|
2016-09-27 22:29:20 +03:00
|
|
|
waitForReply(cmakeCommand, 'handshake', 'TEST_HANDSHAKE', False)
|
2016-09-09 11:01:45 +03:00
|
|
|
|
|
|
|
def validateGlobalSettings(cmakeCommand, cmakeCommandPath, data):
|
2016-09-27 22:29:20 +03:00
|
|
|
packet = waitForReply(cmakeCommand, 'globalSettings', '', False)
|
2016-09-09 11:01:45 +03:00
|
|
|
|
|
|
|
capabilities = packet['capabilities']
|
|
|
|
|
|
|
|
# validate version:
|
|
|
|
cmakeoutput = subprocess.check_output([ cmakeCommandPath, "--version" ], universal_newlines=True)
|
|
|
|
cmakeVersion = cmakeoutput.splitlines()[0][14:]
|
|
|
|
|
|
|
|
version = capabilities['version']
|
|
|
|
versionString = version['string']
|
|
|
|
vs = str(version['major']) + '.' + str(version['minor']) + '.' + str(version['patch'])
|
|
|
|
if (versionString != vs and not versionString.startswith(vs + '-')):
|
|
|
|
sys.exit(1)
|
|
|
|
if (versionString != cmakeVersion):
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
# validate generators:
|
|
|
|
generatorObjects = capabilities['generators']
|
|
|
|
|
|
|
|
cmakeoutput = subprocess.check_output([ cmakeCommandPath, "--help" ], universal_newlines=True)
|
|
|
|
index = cmakeoutput.index('\nGenerators\n\n')
|
|
|
|
cmakeGenerators = []
|
|
|
|
for line in cmakeoutput[index + 12:].splitlines():
|
|
|
|
if not line.startswith(' '):
|
|
|
|
continue
|
2016-09-09 11:01:45 +03:00
|
|
|
if line.startswith(' '):
|
|
|
|
continue
|
2016-09-09 11:01:45 +03:00
|
|
|
equalPos = line.find('=')
|
|
|
|
tmp = ''
|
|
|
|
if (equalPos > 0):
|
|
|
|
tmp = line[2:equalPos].strip()
|
|
|
|
else:
|
|
|
|
tmp = line.strip()
|
2016-09-09 11:01:45 +03:00
|
|
|
if tmp.endswith(" [arch]"):
|
|
|
|
tmp = tmp[0:len(tmp) - 7]
|
2016-09-09 11:01:45 +03:00
|
|
|
if (len(tmp) > 0) and (" - " not in tmp) and (tmp != 'KDevelop3'):
|
|
|
|
cmakeGenerators.append(tmp)
|
|
|
|
|
|
|
|
generators = []
|
|
|
|
for genObj in generatorObjects:
|
|
|
|
generators.append(genObj['name'])
|
|
|
|
|
|
|
|
generators.sort()
|
|
|
|
cmakeGenerators.sort()
|
|
|
|
|
2016-09-09 11:01:45 +03:00
|
|
|
for gen in cmakeGenerators:
|
|
|
|
if (not gen in generators):
|
|
|
|
sys.exit(1)
|
2016-09-09 11:01:45 +03:00
|
|
|
|
|
|
|
gen = packet['generator']
|
|
|
|
if (gen != '' and not (gen in generators)):
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
for i in data:
|
|
|
|
print("Validating", i)
|
|
|
|
if (packet[i] != data[i]):
|
|
|
|
sys.exit(1)
|