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 + "") 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): cmakeCommand = subprocess.Popen([cmakeCommand, "-E", "server", "--experimental", "--debug"], 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 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 sys.exit(1) return packet 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) def handshake(cmakeCommand, major, minor, source, build, generator, extraGenerator): version = { 'major': major } if minor >= 0: version['minor'] = minor writePayload(cmakeCommand, { 'type': 'handshake', 'protocolVersion': version, 'cookie': 'TEST_HANDSHAKE', 'sourceDirectory': source, 'buildDirectory': build, 'generator': generator, 'extraGenerator': extraGenerator }) waitForReply(cmakeCommand, 'handshake', 'TEST_HANDSHAKE', False) def validateGlobalSettings(cmakeCommand, cmakeCommandPath, data): packet = waitForReply(cmakeCommand, 'globalSettings', '', False) 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 if line.startswith(' '): continue equalPos = line.find('=') tmp = '' if (equalPos > 0): tmp = line[2:equalPos].strip() else: tmp = line.strip() if tmp.endswith(" [arch]"): tmp = tmp[0:len(tmp) - 7] 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() for gen in cmakeGenerators: if (not gen in generators): sys.exit(1) 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)