# -*- coding: utf-8 -*- """ Tests checkers functions @brief Test of GRASS Python testing framework checkers (C) 2014 by the GRASS Development Team This program is free software under the GNU General Public License (>=v2). Read the file COPYING that comes with GRASS for details. @author Vaclav Petras """ from grass.script.utils import parse_key_val, try_remove from grass.gunittest.case import TestCase from grass.gunittest.main import test from grass.gunittest.checkers import ( values_equal, text_to_keyvalue, keyvalue_equals, proj_info_equals, proj_units_equals, file_md5, text_file_md5) class TestValuesEqual(TestCase): def test_floats(self): self.assertTrue(values_equal(5.0, 5.0)) self.assertTrue(values_equal(5.1, 5.19, precision=0.1)) self.assertTrue(values_equal(5.00005, 5.000059, precision=0.00001)) self.assertFalse(values_equal(5.125, 5.280)) self.assertFalse(values_equal(5.00005, 5.00006, precision=0.00001)) self.assertFalse(values_equal(2.5, 15.5, precision=5)) def test_ints(self): self.assertTrue(values_equal(5, 5, precision=0.01)) self.assertFalse(values_equal(5, 6, precision=0.01)) self.assertTrue(values_equal(5, 8, precision=3)) self.assertFalse(values_equal(3600, 3623, precision=20)) self.assertTrue(values_equal(5, 5)) self.assertFalse(values_equal(5, 6)) def test_floats_and_ints(self): self.assertTrue(values_equal(5.1, 5, precision=0.2)) self.assertFalse(values_equal(5.1, 5, precision=0.01)) def test_strings(self): self.assertTrue(values_equal('hello', 'hello')) self.assertFalse(values_equal('Hello', 'hello')) def test_lists(self): self.assertTrue(values_equal([1, 2, 3], [1, 2, 3])) self.assertTrue(values_equal([1.1, 2.0, 3.9], [1.1, 1.95, 4.0], precision=0.2)) self.assertFalse(values_equal([1, 2, 3, 4, 5], [1, 22, 3, 4, 5], precision=1)) def test_mixed_lists(self): self.assertTrue(values_equal([1, 'abc', 8], [1, 'abc', 8.2], precision=0.5)) def test_recursive_lists(self): self.assertTrue(values_equal([1, 'abc', [5, 9.6, 9.0]], [1, 'abc', [4.9, 9.2, 9.3]], precision=0.5)) KEYVAL_TEXT = '''s: Hello str: Hello world! f: 1.0 l: 1,2,3,4,5 mixed: hello,8,-25,world!,4-1,5:2,0.1,-9.6 ''' # file location/PERMANENT/PROJ_INFO PROJ_INFO_TEXT_1 = """name: Lambert Conformal Conic proj: lcc datum: nad83 a: 6378137.0 es: 0.006694380022900787 lat_1: 36.16666666666666 lat_2: 34.33333333333334 lat_0: 33.75 lon_0: -79 x_0: 609601.22 y_0: 0 no_defs: defined """ # file location/PERMANENT/PROJ_UNITS PROJ_UNITS_TEXT_1 = """unit: Meter units: Meters meters: 1 """ PROJ_INFO_TEXT_2 = """name: Lambert Conformal Conic proj: lcc datum: nad83 a: 6378137.0000000002 es: 0.006694380022900787 lat_1: 36.166666667 lat_2: 34.333333333 lat_0: 33.75 lon_0: -79 x_0: 609601.22 y_0: 0 no_defs: defined """ PROJ_UNITS_TEXT_2 = """unit: Metre units: Meters meters: 1 """ # what about keys and lower/upper case letters class TestTextToKeyValue(TestCase): def test_conversion(self): keyvals = text_to_keyvalue(KEYVAL_TEXT, sep=':', val_sep=',') expected = {'s': 'Hello', 'str': 'Hello world!', 'f': 1.0, 'l': [1, 2, 3, 4, 5], 'mixed': ['hello', 8, -25, 'world!', '4-1', '5:2', 0.1, -9.6]} self.assertDictEqual(expected, keyvals) def test_single_values(self): keyvals = text_to_keyvalue("a: 1.5", sep=':') self.assertDictEqual({'a': 1.5}, keyvals) keyvals = text_to_keyvalue("abc=1", sep='=') self.assertDictEqual({'abc': 1}, keyvals) keyvals = text_to_keyvalue("abc=hello", sep='=') self.assertDictEqual({'abc': 'hello'}, keyvals) def test_strip(self): keyvals = text_to_keyvalue("a: 2.8 ", sep=':') self.assertDictEqual({'a': 2.8}, keyvals) keyvals = text_to_keyvalue("a: 2 ; 2.8 ; ab cd ", sep=':', val_sep=';') self.assertDictEqual({'a': [2, 2.8, 'ab cd']}, keyvals) keyvals = text_to_keyvalue("a : 2 ; 2.8", sep=':', val_sep=';') self.assertDictEqual({'a': [2, 2.8]}, keyvals) keyvals = text_to_keyvalue("a : \t 2 ;\t2.8", sep=':', val_sep=';') self.assertDictEqual({'a': [2, 2.8]}, keyvals) def test_empty_list_item(self): keyvals = text_to_keyvalue("a: 1, ,5,,", sep=':', val_sep=',') self.assertDictEqual({'a': [1, '', 5, '', '']}, keyvals) def test_empty_value(self): keyvals = text_to_keyvalue("a: ", sep=':') self.assertDictEqual({'a': ''}, keyvals) keyvals = text_to_keyvalue("a:", sep=':') self.assertDictEqual({'a': ''}, keyvals) def test_wrong_lines(self): # we consider no key-value separator as invalid line # and we silently ignore these keyvals = text_to_keyvalue("a", sep=':', skip_invalid=True, skip_empty=False) self.assertDictEqual({}, keyvals) self.assertRaises(ValueError, text_to_keyvalue, "a", sep=':', skip_invalid=False, skip_empty=False) # text_to_keyvalue considers the empty string as valid input keyvals = text_to_keyvalue("", sep=':', skip_invalid=False, skip_empty=False) self.assertDictEqual({}, keyvals) self.assertRaises(ValueError, text_to_keyvalue, "\n", sep=':', skip_invalid=True, skip_empty=False) keyvals = text_to_keyvalue("a\n\n", sep=':', skip_invalid=True, skip_empty=True) self.assertDictEqual({}, keyvals) def test_separators(self): keyvals = text_to_keyvalue("a=a;b;c", sep='=', val_sep=';') self.assertDictEqual({'a': ['a', 'b', 'c']}, keyvals) keyvals = text_to_keyvalue("a 1;2;3", sep=' ', val_sep=';') self.assertDictEqual({'a': [1, 2, 3]}, keyvals) # spaces as key-value separator and values separators # this should work (e.g. because of : in DMS), # although it does not support stripping (we don't merge separators) keyvals = text_to_keyvalue("a 1 2 3", sep=' ', val_sep=' ') self.assertDictEqual({'a': [1, 2, 3]}, keyvals) #def test_projection_files(self): # obtained by r.univar elevation -g # floats removed R_UNIVAR_KEYVAL = """n=2025000 null_cells=57995100 cells=60020100 min=55.5787925720215 max=156.329864501953 range=100.751071929932 mean=110.375440275606 mean_of_abs=110.375440275606 stddev=20.3153233205981 variance=412.712361620436 coeff_var=18.4056555243368 sum=223510266.558102 """ # obtained by r.univar elevation -g # floats removed R_UNIVAR_KEYVAL_INT = """n=2025000 null_cells=57995100 cells=60020100 """ R_UNIVAR_KEYVAL_INT_DICT = {'n': 2025000, 'null_cells': 57995100, 'cells': 60020100} class TestComapreProjections(TestCase): def test_compare_proj_info(self): self.assertTrue(proj_info_equals(PROJ_INFO_TEXT_1, PROJ_INFO_TEXT_2)) self.assertTrue(proj_units_equals(PROJ_UNITS_TEXT_1, PROJ_UNITS_TEXT_2)) class TestParseKeyvalue(TestCase): def test_shell_script_style(self): self.assertDictEqual(parse_key_val(R_UNIVAR_KEYVAL_INT, val_type=int), R_UNIVAR_KEYVAL_INT_DICT) R_UNIVAR_ELEVATION = """n=2025000 null_cells=57995100 cells=60020100 min=55.5787925720215 max=156.329864501953 range=100.751071929932 mean=110.375440275606 mean_of_abs=110.375440275606 stddev=20.3153233205981 variance=412.712361620436 coeff_var=18.4056555243368 sum=223510266.558102 first_quartile=94.79 median=108.88 third_quartile=126.792 percentile_90=138.66 """ R_UNIVAR_ELEVATION_ROUNDED = """n=2025000 null_cells=57995100 cells=60020100 min=55.5788 max=156.33 range=100.751 mean=110.375 mean_of_abs=110.375 stddev=20.3153 variance=412.712 coeff_var=18.4057 sum=223510266.558 first_quartile=94.79 median=108.88 third_quartile=126.792 percentile_90=138.66 """ R_UNIVAR_ELEVATION_SUBSET = """n=2025000 null_cells=57995100 cells=60020100 min=55.5787925720215 max=156.329864501953 """ class TestRasterMapComparisons(TestCase): def test_compare_univars(self): self.assertTrue(keyvalue_equals(text_to_keyvalue(R_UNIVAR_ELEVATION, sep='='), text_to_keyvalue(R_UNIVAR_ELEVATION, sep='='), precision=0)) self.assertFalse(keyvalue_equals(text_to_keyvalue(R_UNIVAR_ELEVATION, sep='='), text_to_keyvalue(R_UNIVAR_ELEVATION_SUBSET, sep='='), precision=0)) def test_compare_univars_subset(self): self.assertTrue(keyvalue_equals(text_to_keyvalue(R_UNIVAR_ELEVATION_SUBSET, sep='='), text_to_keyvalue(R_UNIVAR_ELEVATION, sep='='), a_is_subset=True, precision=0)) self.assertFalse(keyvalue_equals(text_to_keyvalue(R_UNIVAR_ELEVATION, sep='='), text_to_keyvalue(R_UNIVAR_ELEVATION_SUBSET, sep='='), a_is_subset=True, precision=0)) def test_compare_univars_rounded(self): self.assertTrue(keyvalue_equals(text_to_keyvalue(R_UNIVAR_ELEVATION, sep='='), text_to_keyvalue(R_UNIVAR_ELEVATION_ROUNDED, sep='='), precision=0.001)) CORRECT_LINES = [ "null_cells=57995100", "cells=60020100", "min=55.5787925720215", "max=156.329864501953" ] INCORRECT_LINES = [ "null_cells=579951", "cells=60020100", "min=5.5787925720215", "max=156.329864501953" ] class TestMd5Sums(TestCase): r""" To create MD5 which is used for testing use: .. code: sh $ cat > test.txt << EOF null_cells=57995100 cells=60020100 min=55.5787925720215 max=156.329864501953 EOF $ md5sum test.txt 9dd6c4bb9d2cf6051b12f4b5f9d70523 test.txt """ correct_md5sum = '9dd6c4bb9d2cf6051b12f4b5f9d70523' correct_file_name_platform_nl = 'md5_sum_correct_file_platform_nl' correct_file_name_unix_nl = 'md5_sum_correct_file_unix_nl' wrong_file_name = 'md5_sum_wrong_file' @classmethod def setUpClass(cls): with open(cls.correct_file_name_platform_nl, 'w') as f: for line in CORRECT_LINES: # \n should be converted to platform newline f.write(line + '\n') with open(cls.correct_file_name_unix_nl, 'wb') as f: for line in CORRECT_LINES: # binary mode will write pure \n f.write(line + '\n') with open(cls.wrong_file_name, 'w') as f: for line in INCORRECT_LINES: # \n should be converted to platform newline f.write(line + '\n') @classmethod def tearDownClass(cls): try_remove(cls.correct_file_name_platform_nl) try_remove(cls.correct_file_name_unix_nl) try_remove(cls.wrong_file_name) def test_text_file_binary(self): r"""File with ``\n`` (LF) newlines as binary (MD5 has ``\n``).""" self.assertEqual(file_md5(self.correct_file_name_unix_nl), self.correct_md5sum, msg="MD5 sums different") def test_text_file_platfrom(self): r"""Text file with platform dependent newlines""" self.assertEqual(text_file_md5(self.correct_file_name_platform_nl), self.correct_md5sum, msg="MD5 sums different") def test_text_file_unix(self): r"""Text file with ``\n`` (LF) newlines""" self.assertEqual(text_file_md5(self.correct_file_name_unix_nl), self.correct_md5sum, msg="MD5 sums different") def test_text_file_different(self): r"""Text file with ``\n`` (LF) newlines""" self.assertNotEqual(text_file_md5(self.wrong_file_name), self.correct_md5sum, msg="MD5 sums must be different") if __name__ == '__main__': test()