#!/usr/bin/env python3
# This file is part of the LibreOffice project.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import re
import os
from subprocess
import Popen, DEVNULL, PIPE
import logging
import sys
def start_logger():
rootLogger = logging.getLogger()
rootLogger.setLevel(os.environ.get(
"LOGLEVEL",
"INFO"))
logFormatter = logging.Formatter(
"%(asctime)s - %(message)s")
fileHandler = logging.FileHandler(
"log.txt")
fileHandler.setFormatter(logFormatter)
rootLogger.addHandler(fileHandler)
streamHandler = logging.StreamHandler(sys.stdout)
rootLogger.addHandler(streamHandler)
return rootLogger
def checkout_file(repoPath, filePath):
p = Popen([
'git',
'-C', repoPath,
'checkout', repoPath + filePath],
stdout=DEVNULL, stderr=DEVNULL)
p.communicate()
def execute_make_and_parse_output(fileName, makeName):
os.environ[
"CPPUNITTRACE"] =
"gdb -ex=run -ex=quit --args"
p = Popen([
'make', makeName],
stdout=DEVNULL, stderr=PIPE)
logger.info(
'Executing ' + makeName)
err =
""
while True:
errout = p.stderr.readline().decode(
'utf-8').strip()
if errout.startswith(
'debug:'):
info = errout.split(
': ')[1]
err += info +
'\n'
logger.info(info)
if errout ==
'' or p.poll():
break
logger.info(
'Parsing output from ' + makeName)
results = {}
for line
in err.strip().split(
'\n'):
if not line:
continue
splitLine = line.split(
' - ')
typeCheck = splitLine[0]
testName = splitLine[1]
importNumber = splitLine[2]
exportNumber = splitLine[3].strip()
if importNumber != exportNumber:
logger.info(
"WARNING: " + testName +
" has different number of " + typeCheck +
". Import: " + \
importNumber +
" Export: " + exportNumber)
else:
if testName.endswith(
'.odt')
or testName.endswith(
'.ott'):
if testName
not in results:
results[testName] = {
'pages': 0,
'checkPages':
False,
'index': 0,
'shapes': 0,
'checkShapes':
False}
if typeCheck ==
'PAGES':
results[testName][
'pages'] = importNumber
elif typeCheck ==
'SHAPES':
results[testName][
'shapes'] = importNumber
cxxFile = open(fileName,
'r')
lines = cxxFile.readlines()
cxxFile.close()
for i
in range(len(lines)):
line = lines[i]
if line.startswith(
'DECLARE'):
try:
testName = re.findall(
'"([^"]*)"', line)[0]
except Exception:
#check in the next line when line is broken into 2 lines
testName = re.findall(
'"([^"]*)"', lines[i + 1])[0]
if testName
in results:
results[testName][
'index'] = i
elif 'getPages' in line:
if testName
in results:
results[testName][
'checkPages'] =
True
elif 'getShapes' in line:
if testName
in results:
results[testName][
'checkShapes'] =
True
total = 0
for i
in results.values():
if not i[
'checkPages']
and int(i[
'pages']) >= 1:
total += 1
lines.insert(i[
'index'] + 2,
" CPPUNIT_ASSERT_EQUAL(" + str(i[
'pages']) +
", getPages());\n")
if not i[
'checkShapes']
and int(i[
'shapes']) >= 1:
total += 1
lines.insert(i[
'index'] + 2,
" CPPUNIT_ASSERT_EQUAL(" + str(i[
'shapes']) +
", getShapes());\n")
logger.info(str(total) +
' missing asserts added in ' + fileName)
cxxFile = open(fileName,
"w")
cxxFile.write(
"".join(lines))
cxxFile.close()
def insert_code_in_sw_model(repoPath, modelTestRelPath):
modelTestPath = repoPath + modelTestRelPath
modelTestFile = open(modelTestPath,
'r')
modelTestLines = modelTestFile.readlines()
modelTestFile.close()
addText =
False
# Add code to check import and export pages
for i
in range(len(modelTestLines)):
line = modelTestLines[i]
if line.strip().startswith(
'void'):
if 'executeLoadVerifyReloadVerify' in line
or \
'executeLoadReloadVerify' in line:
addText =
True
else:
addText =
False
if addText
and 'reload' in line:
modelTestLines.insert( i - 1,
'int nImportPages = getPages();int nImportShapes = getShapes();\n')
modelTestLines.insert( i + 2,
'int nExportPages = getPages();int nExportShapes = getShapes();SAL_' + \
'DEBUG("PAGES - " << filename << " - " << nImportPages << " - " << nExportPages);SAL_' + \
'DEBUG("SHAPES - " << filename << " - " << nImportShapes << " - " << nExportShapes);\n')
addText =
False
modelTestFile = open(modelTestPath,
'w')
modelTestFile.write(
"".join(modelTestLines))
modelTestFile.close()
def check_sw(repoPath):
modelTestRelPath =
'/sw/qa/unit/swmodeltestbase.cxx'
checkout_file(repoPath, modelTestRelPath)
insert_code_in_sw_model(repoPath, modelTestRelPath)
os.chdir(repoPath)
qaDir = os.path.join(repoPath,
'sw/qa/extras/')
for dirName
in os.listdir(qaDir):
subdirName = os.path.join(qaDir, dirName)
if not os.path.isdir(subdirName):
continue
for fileName
in os.listdir(subdirName):
if 'export' in fileName
and fileName.endswith(
'.cxx'):
fileNamePath = os.path.join(subdirName, fileName)
p = Popen([
'git',
'-C', repoPath,
'diff', fileNamePath],
stdout=PIPE, stderr=DEVNULL)
stdout = p.communicate()[0]
if stdout != b
'':
logger.info( fileNamePath +
" has unstaged changes. Ignoring...")
continue
makeName =
'CppunitTest_sw_' + os.path.basename(fileNamePath).split(
'.')[0]
execute_make_and_parse_output(fileNamePath, makeName)
checkout_file(repoPath, modelTestRelPath)
if __name__ ==
'__main__':
logger = start_logger()
repoPath = os.path.dirname(os.path.abspath(__file__)) +
'/..'
check_sw(repoPath)