зеркало из https://github.com/mozilla/gecko-dev.git
650 строки
25 KiB
Python
650 строки
25 KiB
Python
# 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 os
|
|
import os.path
|
|
import re
|
|
import sys
|
|
|
|
BUILD_TYPES = [
|
|
"optimized",
|
|
"isDebugBuild",
|
|
"isCoverageBuild",
|
|
"AddressSanitizer",
|
|
"ThreadSanitizer",
|
|
]
|
|
EQEQ = "=="
|
|
FUZZY_IF_REGEX = r"^fuzzy-if\((.*?),(\d+)-(\d+),(\d+)-(\d+)\)$"
|
|
IMPLICIT = {
|
|
"fission": True,
|
|
"is64Bit": True,
|
|
"useDrawSnapshot": False,
|
|
"swgl": False,
|
|
}
|
|
MARGIN = 0.05 # Increase difference/pixels percentage
|
|
NOT_EQ = "!="
|
|
OSES = ["Android", "cocoaWidget", "appleSilicon", "gtkWidget", "winWidget"]
|
|
PASS = "PASS"
|
|
TEST_TYPES = [EQEQ, NOT_EQ]
|
|
|
|
|
|
class ListManifestParser(object):
|
|
"""
|
|
Meta Manifest Parser is the main class for the lmp program.
|
|
"""
|
|
|
|
errfile = sys.stderr
|
|
outfile = sys.stdout
|
|
verbose = False
|
|
|
|
def __init__(
|
|
self, implicit_vars=False, verbose=False, error=None, warning=None, info=None
|
|
):
|
|
self.implicit_vars = implicit_vars
|
|
self.verbose = verbose
|
|
self._error = error
|
|
self._warning = warning
|
|
self._info = info
|
|
self.parser = None
|
|
self.fuzzy_if_rx = None
|
|
|
|
def error(self, e):
|
|
if self._error is not None:
|
|
self._error(e)
|
|
else:
|
|
print(f"ERROR: {e}", file=sys.stderr, flush=True)
|
|
|
|
def warning(self, e):
|
|
if self._warning is not None:
|
|
self._warning(e)
|
|
else:
|
|
print(f"WARNING: {e}", file=sys.stderr, flush=True)
|
|
|
|
def info(self, e):
|
|
if self._info is not None:
|
|
self._info(e)
|
|
else:
|
|
print(f"INFO: {e}", file=sys.stderr, flush=True)
|
|
|
|
def vinfo(self, e):
|
|
if self.verbose:
|
|
self.info(e)
|
|
|
|
def should_merge(self, condition, fuzzy_if_condition):
|
|
"""
|
|
Return True if existing condition and proposed fuzzy_if
|
|
differ by one dimension (or less)
|
|
"""
|
|
|
|
c_os = None
|
|
os = None
|
|
conditions = condition.split("&&")
|
|
n = len(conditions)
|
|
fuzzy_ifs = fuzzy_if_condition.split("&&")
|
|
m = len(fuzzy_ifs)
|
|
dimensions = {}
|
|
delta = 0 # dimensions of difference
|
|
for i in range(n):
|
|
if conditions[i].find("||") > 0:
|
|
disjunctions = conditions[i][1:-1].split("||")
|
|
if disjunctions[0] in OSES:
|
|
c_os = disjunctions[0]
|
|
for j in range(m):
|
|
if fuzzy_ifs[j] in OSES:
|
|
os = fuzzy_ifs[j]
|
|
if c_os != os:
|
|
return False # do not merge different OSES
|
|
fuzzy_ifs[j] = ""
|
|
break
|
|
conditions[i] = ""
|
|
elif self.implicit_vars and disjunctions[0] in IMPLICIT:
|
|
dimensions[disjunctions[0]] = True
|
|
conditions[i] = ""
|
|
else:
|
|
delta += 1 # OTHER adds a dimension
|
|
elif conditions[i] in OSES:
|
|
c_os = conditions[i]
|
|
for j in range(m):
|
|
if fuzzy_ifs[j] in OSES:
|
|
os = fuzzy_ifs[j]
|
|
if c_os != os:
|
|
return False # do not merge different OSES
|
|
fuzzy_ifs[j] = ""
|
|
break # expect only one os variable
|
|
conditions[i] = ""
|
|
elif conditions[i] in BUILD_TYPES:
|
|
for j in range(m):
|
|
if fuzzy_ifs[j] in BUILD_TYPES:
|
|
if conditions[i] != fuzzy_ifs[j]:
|
|
delta += 1 # BUILD_TYPE different
|
|
fuzzy_ifs[j] = ""
|
|
break # expect at most one build_type
|
|
conditions[i] = "" # handles also if BUILD_TYPE is omitted
|
|
else:
|
|
negated = False
|
|
if conditions[i][0] == "!":
|
|
negated = True
|
|
cond = conditions[i][1:]
|
|
else:
|
|
cond = conditions[i]
|
|
dimensions[cond] = True
|
|
if negated:
|
|
opposite = cond
|
|
else:
|
|
opposite = "!" + cond
|
|
for j in range(m):
|
|
if conditions[i] == fuzzy_ifs[j]: # same
|
|
fuzzy_ifs[j] = ""
|
|
conditions[i] = ""
|
|
break
|
|
elif opposite == fuzzy_ifs[j]: # opposite explicit
|
|
delta += 1 # different
|
|
fuzzy_ifs[j] = ""
|
|
conditions[i] = ""
|
|
break
|
|
elif fuzzy_ifs[j] == "(" + cond + "||!" + cond + ")":
|
|
fuzzy_ifs[j] = ""
|
|
conditions[i] = ""
|
|
break
|
|
if (
|
|
conditions[i]
|
|
and self.implicit_vars
|
|
and not (IMPLICIT[cond] and not negated)
|
|
and not (not IMPLICIT[cond] and negated)
|
|
): # opposite implicit different
|
|
delta += 1
|
|
conditions[i] = ""
|
|
for i in range(n):
|
|
if conditions[i]: # unhandled
|
|
delta += 1 # OTHER adds a dimension
|
|
for j in range(m):
|
|
if fuzzy_ifs[j]: # unhandled
|
|
if fuzzy_ifs[j] in OSES:
|
|
return False # condition doesn't specify OS
|
|
if fuzzy_ifs[j] in BUILD_TYPES:
|
|
continue # does not add a dimension b/c condition doesn't specify
|
|
if fuzzy_ifs[j][0] == "!":
|
|
cond = fuzzy_ifs[j][1:]
|
|
else:
|
|
cond = fuzzy_ifs[j]
|
|
if not cond in dimensions:
|
|
delta += 1 # OTHER adds a dimension
|
|
return delta <= 1
|
|
|
|
def merge(self, condition, fuzzy_if_condition):
|
|
"""
|
|
A. if 2 of the 5 build-types are present -- eliminate ALL build types
|
|
(i.e. the condition will apply to all build types)
|
|
|
|
B. If both the implicit and explicit (non) default value are present, add
|
|
an OR like this (swgl || !swgl) -- that way the condition will match
|
|
any value of swgl. For implicit variables see:
|
|
https://searchfox.org/mozilla-central/source/layout/tools/reftest/manifest.sys.mjs#30
|
|
fission: true,
|
|
is64Bit: true,
|
|
useDrawSnapshot: false,
|
|
swgl: false,
|
|
|
|
C. for other vars if we have A and !A then remove A from the condition
|
|
"""
|
|
|
|
os = ""
|
|
build_type = ""
|
|
conditions = condition.split("&&")
|
|
n = len(conditions)
|
|
fuzzy_ifs = fuzzy_if_condition.split("&&")
|
|
m = len(fuzzy_ifs)
|
|
conds = {}
|
|
for i in range(n):
|
|
if conditions[i].find("||") > 0:
|
|
disjunctions = conditions[i][1:-1].split("||")
|
|
cond = disjunctions[0]
|
|
if cond in OSES:
|
|
for j in range(m):
|
|
if fuzzy_ifs[j] in OSES:
|
|
if fuzzy_ifs[j] not in disjunctions:
|
|
disjunctions.append(fuzzy_ifs[j])
|
|
fuzzy_ifs[j] = ""
|
|
disjunctions = sorted(disjunctions)
|
|
os = "(" + "||".join(disjunctions) + ")"
|
|
conditions[i] = ""
|
|
elif self.implicit_vars and cond in IMPLICIT:
|
|
for j in range(m):
|
|
if not fuzzy_ifs[j]:
|
|
continue
|
|
if (
|
|
fuzzy_ifs[j] == cond
|
|
or fuzzy_ifs[j] == "!" + cond
|
|
or fuzzy_ifs[j] == "(" + cond + "||!" + cond + ")"
|
|
):
|
|
fuzzy_ifs[j] = ""
|
|
break
|
|
conds[cond] = conditions[i]
|
|
conditions[i] = ""
|
|
elif conditions[i] in OSES:
|
|
os = conditions[i]
|
|
conditions[i] = ""
|
|
for j in range(m):
|
|
if fuzzy_ifs[j] in OSES:
|
|
if os < fuzzy_ifs[j]: # add in alpha order
|
|
os = "(" + os + "||" + fuzzy_ifs[j] + ")"
|
|
elif os > fuzzy_ifs[j]:
|
|
os = "(" + fuzzy_ifs[j] + "||" + os + ")"
|
|
fuzzy_ifs[j] = ""
|
|
break # expect only one os variable
|
|
elif conditions[i] in BUILD_TYPES:
|
|
build_type = conditions[i]
|
|
for j in range(m):
|
|
if fuzzy_ifs[j] in BUILD_TYPES:
|
|
if fuzzy_ifs[j] != build_type: # different
|
|
build_type = ""
|
|
fuzzy_ifs[j] = ""
|
|
conditions[i] = ""
|
|
break # expect at most one build_type
|
|
if conditions[i]: # fuzzy_if had build_type _removed_
|
|
build_type = ""
|
|
conditions[i] = ""
|
|
else:
|
|
negated = False
|
|
if conditions[i][0] == "!":
|
|
negated = True
|
|
cond = conditions[i][1:]
|
|
else:
|
|
cond = conditions[i]
|
|
if negated:
|
|
opposite = cond
|
|
else:
|
|
opposite = "!" + cond
|
|
disjunction = ""
|
|
for j in range(m):
|
|
if not fuzzy_ifs[j]:
|
|
continue
|
|
if conditions[i] == fuzzy_ifs[j]: # same
|
|
conds[cond] = conditions[i]
|
|
fuzzy_ifs[j] = ""
|
|
conditions[i] = ""
|
|
break
|
|
if (
|
|
self.implicit_vars
|
|
and cond in IMPLICIT
|
|
and (
|
|
opposite == fuzzy_ifs[j]
|
|
or fuzzy_ifs[j] == "(" + cond + "||!" + cond + ")"
|
|
)
|
|
):
|
|
if negated:
|
|
disjunction = "(" + opposite + "||" + conditions[i] + ")"
|
|
else:
|
|
disjunction = "(" + conditions[i] + "||" + opposite + ")"
|
|
conds[cond] = disjunction
|
|
fuzzy_ifs[j] = ""
|
|
conditions[i] = ""
|
|
break
|
|
if opposite == fuzzy_ifs[j]: # remove
|
|
fuzzy_ifs[j] = ""
|
|
conditions[i] = ""
|
|
break
|
|
if (
|
|
self.implicit_vars
|
|
and conditions[i]
|
|
and not (IMPLICIT[cond] and not negated)
|
|
and not (not IMPLICIT[cond] and negated)
|
|
): # opposite implicit
|
|
if negated:
|
|
disjunction = "(" + opposite + "||" + conditions[i] + ")"
|
|
else:
|
|
disjunction = "(" + conditions[i] + "||" + opposite + ")"
|
|
conds[cond] = disjunction
|
|
conditions[i] = ""
|
|
if not self.implicit_vars and conditions[i]:
|
|
conditions[i] = "" # remove, unspecified in fuzzy_if
|
|
for i in range(n):
|
|
if conditions[i]: # unhandled
|
|
negated = False
|
|
if conditions[i][0] == "!":
|
|
negated = True
|
|
cond = conditions[i][1:]
|
|
else:
|
|
cond = conditions[i]
|
|
if (not (self.implicit_vars and cond in IMPLICIT)) or ( # not implicit
|
|
(IMPLICIT[cond] and negated)
|
|
or (not IMPLICIT[cond] and not negated) # or explicit
|
|
):
|
|
conds[cond] = conditions[i]
|
|
for j in range(m):
|
|
if fuzzy_ifs[j]: # unhandled
|
|
if fuzzy_ifs[j] in OSES:
|
|
os = fuzzy_ifs[j]
|
|
continue
|
|
if fuzzy_ifs[j] in BUILD_TYPES and fuzzy_ifs[j] != build_type:
|
|
build_type = ""
|
|
continue
|
|
negated = False
|
|
if fuzzy_ifs[j][0] == "!":
|
|
negated = True
|
|
cond = fuzzy_ifs[j][1:]
|
|
else:
|
|
cond = fuzzy_ifs[j]
|
|
if not (self.implicit_vars and cond in IMPLICIT): # not implicit
|
|
pass # not present in condition
|
|
elif (IMPLICIT[cond] and negated) or (
|
|
not IMPLICIT[cond] and not negated
|
|
): # or opposite of implicit
|
|
disjunction = ""
|
|
if negated:
|
|
opposite = cond
|
|
else:
|
|
opposite = "!" + cond
|
|
if negated:
|
|
disjunction = "(" + opposite + "||" + fuzzy_ifs[j] + ")"
|
|
else:
|
|
disjunction = "(" + fuzzy_ifs[j] + "||" + opposite + ")"
|
|
conds[cond] = disjunction
|
|
if os:
|
|
merged = os
|
|
else:
|
|
merged = ""
|
|
if build_type:
|
|
if merged:
|
|
merged += "&&"
|
|
merged += build_type
|
|
conds_keys = sorted(list(conds.keys()))
|
|
for cond in conds_keys:
|
|
if os != "winWidget" and conds[cond] == "is64Bit":
|
|
continue # special case: elide is64Bit except on Windows
|
|
if os != "gtkWidget" and cond == "useDrawSnapshot":
|
|
continue # special case: elide useDrawSnapshot except on Linux
|
|
if merged:
|
|
merged += "&&"
|
|
merged += conds[cond]
|
|
return merged
|
|
|
|
def get_os_in_condition(self, condition):
|
|
"""Return reftest os variable for condition (or the empty string)"""
|
|
|
|
os = ""
|
|
conditions = condition.split("&&")
|
|
n = len(conditions)
|
|
for i in range(n):
|
|
if conditions[i].find("||") > 0:
|
|
disjunctions = conditions[i][1:-1].split("||")
|
|
if disjunctions[0] in OSES:
|
|
os = disjunctions[0] # returns ONLY first OS if disjunction
|
|
break
|
|
if conditions[i] in OSES:
|
|
os = conditions[i]
|
|
break
|
|
return os
|
|
|
|
def get_dimensions(self, condition):
|
|
"""Return number of dimensions in condition"""
|
|
|
|
dimensions = []
|
|
conditions = condition.split("&&")
|
|
n = len(conditions)
|
|
for i in range(n):
|
|
if conditions[i].find("||") > 0:
|
|
disjunctions = conditions[i][1:-1].split("||")
|
|
if disjunctions[0] in OSES:
|
|
if "os" not in dimensions:
|
|
dimensions.append("os")
|
|
elif disjunctions[0] not in dimensions:
|
|
dimensions.append(disjunctions[0])
|
|
if conditions[i] in OSES:
|
|
if "os" not in dimensions:
|
|
dimensions.append("os")
|
|
elif conditions[i] in BUILD_TYPES:
|
|
if "build_type" not in dimensions:
|
|
dimensions.append("build_type")
|
|
else:
|
|
if conditions[i][0] == "!":
|
|
cond = conditions[i][1:]
|
|
else:
|
|
cond = conditions[i]
|
|
if cond not in dimensions:
|
|
dimensions.append(cond)
|
|
if self.implicit_vars:
|
|
for cond in IMPLICIT:
|
|
if cond not in dimensions:
|
|
dimensions.append(cond)
|
|
return len(dimensions)
|
|
|
|
def calc_fuzzy_if(
|
|
self, modifiers, j, fuzzy_if_condition, d_min, d_max, p_min, p_max
|
|
):
|
|
"""
|
|
Will analzye modifiers in range(j) and
|
|
- move non fuzzy-if's to the left
|
|
- sort fuzzy-ifs by OS and by dimension
|
|
- merge with an exising fuzzy-if ONLY if differs by one dimension (or less)
|
|
- else add fuzzy-if in dimension order
|
|
Returns additional_comment (if added second or subsequent for this OS)
|
|
"""
|
|
|
|
def fuzzy_if_keyfn(fuzzy_if):
|
|
os = ""
|
|
dimensions = 0
|
|
m = self.fuzzy_if_rx.findall(fuzzy_if)
|
|
if len(m) == 1: # NOT fuzzy-if
|
|
condition = m[0][0]
|
|
os = self.get_os_in_condition(condition)
|
|
dimensions = self.get_dimensions(condition)
|
|
try:
|
|
os_i = OSES.index(os)
|
|
except ValueError:
|
|
os_i = -1
|
|
return [os_i, dimensions]
|
|
|
|
success = True
|
|
additional_comment = ""
|
|
merged = None # index in modifiers of the last merged fuzzy_if
|
|
os = self.get_os_in_condition(fuzzy_if_condition)
|
|
fuzzy_if = f"fuzzy-if({fuzzy_if_condition},{d_min}-{d_max},{p_min}-{p_max})"
|
|
first = j # position of first fuzzy-if
|
|
if self.fuzzy_if_rx is None:
|
|
self.fuzzy_if_rx = re.compile(FUZZY_IF_REGEX)
|
|
i = 0
|
|
while i < j:
|
|
m = self.fuzzy_if_rx.findall(modifiers[i])
|
|
if len(m) != 1: # NOT fuzzy-if
|
|
if i > first: # move before fuzzy-if's
|
|
modifier = modifiers[i]
|
|
del modifiers[i]
|
|
modifiers.insert(first, modifier)
|
|
first += 1
|
|
else: # fuzzy-if
|
|
if i < first:
|
|
first = i
|
|
condition = m[0][0]
|
|
dmin = int(m[0][1])
|
|
dmax = int(m[0][2])
|
|
pmin = int(m[0][3])
|
|
pmax = int(m[0][4])
|
|
this_os = self.get_os_in_condition(condition)
|
|
if this_os == os and (
|
|
condition == fuzzy_if_condition
|
|
or self.should_merge(condition, fuzzy_if_condition)
|
|
):
|
|
self.vinfo(f"CONDITION {i:2d} NOW {modifiers[i]}")
|
|
self.vinfo(f"PROPOSED {fuzzy_if_condition}")
|
|
fuzzy_if_condition = self.merge(condition, fuzzy_if_condition)
|
|
d_min = min(dmin, d_min) # dmin, if zero, is kept
|
|
d_max = max(dmax, d_max)
|
|
p_min = min(pmin, p_min) # pmin, if zero, is kept
|
|
p_max = max(pmax, p_max)
|
|
fuzzy_if = f"fuzzy-if({fuzzy_if_condition},{d_min}-{d_max},{p_min}-{p_max})"
|
|
if (d_min == 0 and d_max == 0) or (p_min == 0 and p_max == 0):
|
|
additional_comment = f"fuzzy-if removed as calculated range is {d_min}-{d_max},{p_min}-{p_max}"
|
|
self.vinfo(f"ABANDONED MERGE {fuzzy_if}")
|
|
del modifiers[i]
|
|
i -= 1
|
|
j -= 1
|
|
continue
|
|
if merged is not None: # delete previous
|
|
self.vinfo(f" Deleting previous: {merged}")
|
|
del modifiers[merged]
|
|
i -= 1
|
|
j -= 1
|
|
modifiers[i] = fuzzy_if
|
|
merged = i
|
|
self.vinfo(f"UPDATED MERGED {fuzzy_if}")
|
|
i += 1
|
|
if (
|
|
success
|
|
and merged is None
|
|
and ((d_min == 0 and d_max == 0) or (p_min == 0 and p_max == 0))
|
|
):
|
|
if not additional_comment: # this is NOT the result of merging to 0-0
|
|
self.vinfo(f"ABANDONED ADD {fuzzy_if}")
|
|
additional_comment = f"fuzzy-if not added as calculated range is {d_min}-{d_max},{p_min}-{p_max}"
|
|
success = False
|
|
else:
|
|
merged = i # avoid adding below
|
|
if success:
|
|
if merged is None:
|
|
self.vinfo(f"UPDATED ADDED {fuzzy_if}")
|
|
modifiers.insert(j, fuzzy_if)
|
|
j += 1
|
|
fuzzy_ifs = modifiers[first:j]
|
|
if len(fuzzy_ifs) > 0:
|
|
fuzzy_ifs = sorted(fuzzy_ifs, key=fuzzy_if_keyfn)
|
|
a = j # first fuzzy_if for os
|
|
b = j # last fuzzy_if for os
|
|
for i in range(len(fuzzy_ifs)):
|
|
modifiers[first + i] = fuzzy_ifs[i]
|
|
if fuzzy_ifs[i].startswith("fuzzy-if(" + os):
|
|
if a == j:
|
|
a = first + i
|
|
b = first + i
|
|
if b > a:
|
|
additional_comment = f"NOTE: more than one fuzzy-if for the OS = {os} ==> may require manual review"
|
|
return success, additional_comment
|
|
|
|
def reftest_add_fuzzy_if(
|
|
self,
|
|
manifest_str,
|
|
filename,
|
|
fuzzy_if,
|
|
differences,
|
|
pixels,
|
|
lineno,
|
|
zero,
|
|
bug_reference,
|
|
):
|
|
"""
|
|
Edits a reftest manifest string to add disabled condition
|
|
Returns additional_comment (if any)
|
|
"""
|
|
|
|
result = ("", "")
|
|
additional_comment = ""
|
|
words = filename.split()
|
|
if len(words) < 3:
|
|
self.error(
|
|
f"Expected filename in the form '[optional conditions] == url url_ref': {filename}"
|
|
)
|
|
return result
|
|
test_type = words[-3]
|
|
url = os.path.basename(words[-2])
|
|
url_ref = os.path.basename(words[-1])
|
|
lines = manifest_str.splitlines()
|
|
if lineno == 0 or lineno > len(lines):
|
|
self.error("cannot determine line to edit in manifest")
|
|
return result
|
|
line = lines[lineno - 1]
|
|
comment = ""
|
|
comment_start = line.find(" #") # MUST NOT match anchors!
|
|
if comment_start > 0:
|
|
comment = line[comment_start + 1 :]
|
|
line = line[0:comment_start].strip()
|
|
words = line.split()
|
|
n = len(words)
|
|
if n < 3:
|
|
self.error(f"line {lineno} does not match: {line}")
|
|
return result
|
|
if os.path.basename(words[n - 1]) != url_ref:
|
|
self.error(f"words[n-1] not url_ref: {words[n-1]} != {url_ref}")
|
|
return result
|
|
if os.path.basename(words[n - 2]) != url:
|
|
self.error(f"words[n-2] not url: {words[n-2]} != {url}")
|
|
return result
|
|
if words[n - 3] != test_type:
|
|
self.error(f"words[n-3] not '{test_type}': {words[n-3]}")
|
|
return result
|
|
d_min = 0
|
|
d_max = 0
|
|
if len(differences) > 0:
|
|
d_min = min(differences)
|
|
d_max = max(differences)
|
|
if d_min == 0 and d_max > 0: # recalc minimum
|
|
i = 0
|
|
n = len(differences)
|
|
while i < n:
|
|
if differences[i] == 0:
|
|
del differences[i]
|
|
n -= 1
|
|
else:
|
|
i += 1
|
|
if n > 0:
|
|
d_min = min(differences)
|
|
p_min = 0
|
|
p_max = 0
|
|
if len(pixels) > 0:
|
|
p_min = min(pixels)
|
|
p_max = max(pixels)
|
|
if p_min == 0 and p_max > 0: # recalc minimum
|
|
i = 0
|
|
n = len(pixels)
|
|
while i < n:
|
|
if pixels[i] == 0:
|
|
del pixels[i]
|
|
n -= 1
|
|
else:
|
|
i += 1
|
|
if n > 0:
|
|
p_min = min(pixels)
|
|
if zero:
|
|
d_min = 0
|
|
p_min = 0
|
|
d_max2 = int((1.0 + MARGIN) * d_max)
|
|
if d_max2 > d_max:
|
|
self.info(
|
|
f"Increased max difference from {d_max} by {int(MARGIN*100)}% to {d_max2}"
|
|
)
|
|
d_max = d_max2
|
|
p_max2 = int((1.0 + MARGIN) * p_max)
|
|
if p_max2 > p_max:
|
|
self.info(
|
|
f"Increased differing pixels from {p_max} by {int(MARGIN*100)}% to {p_max2}"
|
|
)
|
|
p_max = p_max2
|
|
if comment:
|
|
bug = bug_reference.split()
|
|
if comment.find(bug[1]) < 0: # look for bug number only
|
|
comment += ", " + bug_reference
|
|
else:
|
|
comment = "# " + bug_reference
|
|
j = 0
|
|
for i in range(n):
|
|
if words[i].startswith("HTTP") or words[i] == test_type:
|
|
j = i
|
|
break
|
|
success, additional_comment = self.calc_fuzzy_if(
|
|
words, j, fuzzy_if, d_min, d_max, p_min, p_max
|
|
)
|
|
if success:
|
|
words.append(comment)
|
|
lines[lineno - 1] = " ".join(words)
|
|
manifest_str = "\n".join(lines)
|
|
if manifest_str[-1] != "\n":
|
|
manifest_str += "\n"
|
|
else:
|
|
manifest_str = ""
|
|
result = (manifest_str, additional_comment)
|
|
return result
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(ListManifestParser().run())
|