abinit/tests/pymods/test_fldiff.py

300 lines
9.8 KiB
Python
Executable File

from __future__ import print_function, division, unicode_literals
import pytest
from .fldiff import (
Differ,
LineCountDifference,
# MetaCharDifference,
FloatDifference,
TextDifference,
ForcedDifference,
)
from .data_extractor import DataExtractor
from .yaml_tools.errors import NoIteratorDefinedError, UntaggedDocumentError
from .yaml_tools.structures.commons import GenericMap
class TestDiffer:
lines1 = [
' Here are some regular lines of numbers : 0.4546\n',
' 5.8787 44.537e+056\n',
' .7856 5.0\n',
'- This lines should be ignored\n',
'+ This line appears in output but is not counted as errorneous\n',
': This line is always compared as characters 0.457896321545\n',
'. This one too but it will never be counted a errorneous 2.4354364\n',
'% This line have a fixed tolerance of 1.01e-2: 2.043643 5.5473684\n',
'P P and , lines are handled according to parameters as + or - lines\n'
]
lines2 = [ # numerical differences
' Here are some regular lines of numbers : 0.4546\n',
' 5.8707 44.535e+056\n',
' .7856 8.0\n',
'- This lines should be ignored\n',
'+ This line appears in output but is not counted as errorneous\n',
': This line is always compared as characters 0.457896321545\n',
'. This one too but it will never be counted a errorneous 2.4354364\n',
'% This line have a fixed tolerance of 1.01e-2: 2.043644 5.4\n',
'P P and , lines are handled according to parameters as + or - lines\n'
]
lines3 = [ # text differences
' Here are some regular lines of floats : 0.4546\n',
' 5.8787 44.537e+056\n',
' .7856 5.0\n',
'- Should this line be ignored ?\n',
'+ This line appears in output but is not counted as errorneous\n',
': This line is always compared as characters 0.457896321546\n',
'. This one too but it will never be counted a errorneous 2.4354360\n',
'% This line have a fixed tolerance of 1.01e-2: 2.043643 5.5473684\n',
'P , and P lines are handled according to parameters as + or - lines\n'
]
lines4 = [ # line number differences but not significant
'- We can append as much ignored lines as we want\n',
'P It should not change the result\n',
' Here are some regular lines of numbers : 0.4546\n',
' 5.8787 44.537e+056\n',
' .7856 5.0\n',
'- This lines should be ignored\n',
'+ This line appears in output but is not counted as errorneous\n',
'- Ignored lines are everywhere\n',
': This line is always compared as characters 0.457896321545\n',
'. This one too but it will never be counted a errorneous 2.4354364\n',
'% This line have a fixed tolerance of 1.01e-2: 2.043643 5.5473684\n',
'P P and , lines are handled according to parameters as + or - lines\n'
]
lines5 = [ # line number differences significant
' Here are some regular lines of numbers : 0.4546\n',
' 78.73687 98.5763\n',
' 5.8787 44.537e+056\n',
' .7856 5.0\n',
'- This lines should be ignored\n',
'+ This line appears in output but is not counted as errorneous\n',
': This line is always compared as characters 0.457896321545\n',
'. This one too but it will never be counted a errorneous 2.4354364\n',
'% This line have a fixed tolerance of 1.01e-2: 2.043643 5.5473684\n',
'P P and , lines are handled according to parameters as + or - lines\n'
]
def test_default(self):
diff = Differ()
assert diff.options['tolerance_abs'] == 1.01e-10
assert diff.options['tolerance_rel'] == 1.01e-10
assert diff.options['ignore']
assert diff.options['ignoreP']
def test_diff_lines_same(self):
diff = Differ()
differences = diff._diff_lines(self.lines1, self.lines1)[0]
assert len(differences) == 1
assert isinstance(differences[0], ForcedDifference)
def test_diff_lines_float(self):
diff = Differ()
differences = diff._diff_lines(self.lines1, self.lines2)[0]
print(differences)
assert len(differences) == 5
d3 = differences.pop(3)
assert isinstance(d3, ForcedDifference)
assert all(isinstance(d, FloatDifference) for d in differences)
def test_diff_lines_text(self):
diff = Differ()
differences = diff._diff_lines(self.lines1, self.lines3)[0]
assert len(differences) == 4
d2 = differences.pop(1)
assert isinstance(d2, ForcedDifference)
assert all(isinstance(d, TextDifference) for d in differences)
d4 = differences.pop(2)
assert d4.silent
assert not any(d.silent for d in differences)
def test_diff_lines_number_not_significant(self):
diff = Differ()
differences = diff._diff_lines(self.lines1, self.lines4)[0]
assert len(differences) == 1
assert isinstance(differences[0], ForcedDifference)
def test_diff_lines_number_significant(self):
diff = Differ()
differences = diff._diff_lines(self.lines1, self.lines5)[0]
assert len(differences) == 1
assert isinstance(differences[0], LineCountDifference)
assert differences[0].more == 'file 2'
def test_diff_lines_float_format(self):
diff = Differ()
differences = diff._diff_lines(
[' .0007 564.5e-3 7000.0\n'],
[' 7.0e-4 5.645D-1 7.0f3\n']
)[0]
assert len(differences) == 0
def test_diff_ignore_blanks(self):
diff = Differ()
differences = diff._diff_lines(
[
' One normal line\n',
'.One messy dot \t line\n',
':A colon line.\n',
' And a last line\n'
],
[
' One \tnormal line\n\r',
'.One messy\tdot line \n',
':A colon \t line.\n\r',
' And a last line'
]
)[0]
assert len(differences) == 0
class TestResult:
'''
Result only exists to reproduce the historical fldiff.pl so
the fact that all tests pass is enough.
It may be removed in the future.
'''
pass
class TestDataExtractor:
def test_default(self):
dext = DataExtractor(True)
assert dext.ignore
assert dext.ignoreP
assert not dext.xml_mode
def test_get_metachar(self):
dext = DataExtractor(True)
assert dext._get_metachar('-truc') == '-'
assert dext._get_metachar('+truc') == '+'
assert dext._get_metachar(' truc') == ' '
assert dext._get_metachar('.truc') == '.'
# ignore blank and empty lines
assert dext._get_metachar(' \t\n') == '-'
assert dext._get_metachar('') == '-'
assert dext._get_metachar('Ptruc') == '-'
assert dext._get_metachar(',truc') == '-'
dext = DataExtractor(True, ignore=False)
assert dext._get_metachar(',truc') == '+'
dext = DataExtractor(True, ignoreP=False)
assert dext._get_metachar('Ptruc') == '+'
def test_extract_ignore_minus_meta(self):
dext = DataExtractor(True)
lines = [
'- first',
'P second',
' \t \n',
''
]
linesres, _, ignored = dext.extract(lines)
assert linesres == []
assert ignored == [(i, line) for i, line in enumerate(lines)]
def test_extract_keep_all_non_minus(self):
dext = DataExtractor(True, ignore=False, ignoreP=False)
lines = [
'+ first',
'P second',
', third',
' fourth',
'. fifth',
]
linesres, _, ignored = dext.extract(lines)
assert linesres == [
(0, '+', '+ first'),
(1, '+', 'P second'),
(2, '+', ', third'),
(3, ' ', ' fourth'),
(4, '.', '. fifth'),
]
assert ignored == []
def test_extract_require_iterstart(self):
dext = DataExtractor(True)
dext.iterators_state = {'dtset': 1}
lines = '''\
--- !GenericMap
a field: 58
another: 78
a list of strings:
- "a string"
- "two strings"
- "..."
...'''
lines = [line + '\n' for line in lines.split('\n')]
with pytest.raises(NoIteratorDefinedError):
_, documents, _ = dext.extract(lines)
print(documents)
def test_extract_require_label(self):
dext = DataExtractor(True)
dext.iterators_state = {'dtset': 1}
lines = '''\
--- !IterStart
dtset: 1
...
---
a field: 58
another: 78
a list of strings:
- "a string"
- "two strings"
- "..."
...'''
lines = [line + '\n' for line in lines.split('\n')]
with pytest.raises(UntaggedDocumentError):
_, documents, _ = dext.extract(lines)
assert len(documents) == 1
print(*(doc.obj for doc in documents))
def test_extract_find_yaml_doc(self):
dext = DataExtractor(True)
dext.iterators_state = {'dtset': 1}
lines = '''\
--- !IterStart
dtset: 1
...
Garbage here
--- !GenericMap
a field: 58
another: 78
a list of strings:
- "a string"
- "two strings"
- "..."
...'''
lines = [line + '\n' for line in lines.split('\n')]
_, documents, _ = dext.extract(lines)
# IterStart documents should not be in the document list
assert len(documents) == 1
assert documents['dtset=1 GenericMap'].iterators == {'dtset': 1}
assert documents['dtset=1 GenericMap'].start == 6
assert documents['dtset=1 GenericMap'].end == 13
assert documents['dtset=1 GenericMap'].lines == lines[6:]
assert documents['dtset=1 GenericMap'].obj == GenericMap.from_map({
'a field': 58,
'another': 78,
'a list of strings': ['a string', 'two strings', '...']
})