test_parsing.py 7.08 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Copyright 2018 Markus Scheidgen
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an"AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

15
import os
16
17
18
from io import StringIO
import json
import pytest
19
20
21

from nomadcore.local_meta_info import loadJsonFile

22
from nomad.parsing import JSONStreamWriter, parser_dict
23
from nomad.parsing import LocalBackend, BadContextURI
24

25
parser_examples = [
26
    ('parsers/random', 'test/data/parsers/random_0'),
27
    ('parsers/template', 'tests/data/parsers/template.json'),
28
29
30
31
32
33
    ('parsers/exciting', '.dependencies/parsers/exciting/test/examples/Ag/INFO.OUT'),
    ('parsers/exciting', '.dependencies/parsers/exciting/test/examples/GW/INFO.OUT'),
    ('parsers/vasp', '.dependencies/parsers/vasp/test/examples/xml/perovskite.xml'),
    ('parsers/fhi-aims', 'tests/data/parsers/aims.out')
]

34
35
36
37
38
39
40
41
42
43
44
45
46

class TestLocalBackend(object):

    @pytest.fixture(scope='session')
    def meta_info(self):
        path = '.dependencies/nomad-meta-info/meta_info/nomad_meta_info/all.nomadmetainfo.json'
        meta_info, _ = loadJsonFile(path)
        return meta_info

    @pytest.fixture(scope='function')
    def backend(self, meta_info):
        return LocalBackend(meta_info, debug=True)

47
    def test_meta_info(self, meta_info, no_warn):
48
49
        assert 'section_topology' in meta_info

50
    def test_section(self, backend, no_warn):
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
        g_index = backend.openSection('section_run')
        assert g_index == 0
        backend.addValue('program_name', 't0')
        backend.closeSection('section_run', 0)

        g_index = backend.openSection('section_run')
        assert g_index == 1

        g_index = backend.openSection('section_run')
        assert g_index == 2

        backend.addValue('program_name', 't1', 1)
        backend.addValue('program_name', 't2', 2)

        backend.closeSection('section_run', 1)
        backend.closeSection('section_run', 2)

        assert backend.get_sections('section_run') == [0, 1, 2]
        for i in range(0, 3):
            assert backend.get_value('program_name', i) == 't%d' % i

72
    def test_subsection(self, backend: LocalBackend, no_warn):
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
        backend.openSection('section_run')
        backend.openSection('section_method')
        backend.closeSection('section_method', -1)

        backend.openSection('section_method')
        backend.closeSection('section_method', -1)

        backend.openSection('section_run')
        backend.closeSection('section_run', 0)
        backend.closeSection('section_run', 1)

        backend.openSection('section_method')
        backend.closeSection('section_method', -1)

        runs = backend.data['section_run']
        assert len(runs) == 2
        assert len(runs[0]['section_method']) == 2
        assert len(runs[1]['section_method']) == 1

92
    def test_context(self, backend: LocalBackend, no_warn):
93
94
95
96
97
        backend.openSection('section_run')
        backend.openSection('section_method')
        backend.closeSection('section_method', -1)
        backend.closeSection('section_run', -1)

98
99
        backend.openSection('section_run')
        backend.closeSection('section_run', -1)
100

101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
        backend.openContext('/section_run/0')
        backend.addValue('program_name', 't1')
        backend.closeContext('/section_run/0')

        backend.openContext('/section_run/1')
        backend.addValue('program_name', 't2')
        backend.closeContext('/section_run/1')

        backend.openContext('/section_run/0/section_method/0')
        backend.closeContext('/section_run/0/section_method/0')

        runs = backend.data['section_run']
        assert runs[0]['program_name'] == 't1'
        assert runs[1]['program_name'] == 't2'

116
    def test_multi_context(self, backend: LocalBackend, no_warn):
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
        backend.openSection('section_run')
        backend.closeSection('section_run', -1)

        backend.openContext('/section_run/0')
        backend.openSection('section_method')
        backend.closeSection('section_method', -1)
        backend.closeContext('/section_run/0')

        backend.openContext('/section_run/0')
        backend.openSection('section_method')
        backend.closeSection('section_method', -1)
        backend.closeContext('/section_run/0')

        assert len(backend.data['section_method']) == 1

132
    def test_bad_context(self, backend: LocalBackend, no_warn):
133
134
135
136
137
138
139
140
141
142
143
144
        try:
            backend.openContext('section_run/0')
            assert False
        except BadContextURI:
            pass

        try:
            backend.openContext('dsfds')
            assert False
        except BadContextURI:
            pass

145
146
147
148
149
150
151
152
153

def create_reference(data, pretty):
    if (pretty):
        return json.dumps(data, indent=2)
    else:
        return json.dumps(data, separators=(',', ':'))


@pytest.mark.parametrize("pretty", [False, True])
154
def test_stream_generator(pretty, no_warn):
155
156
157
158
159
160
161
162
163
164
165
166
167
    example_data = [
        {
            'key1': 'value',
            'key2': 1
        },
        {
            'key': {
                'key': 'value'
            }
        }
    ]

    out = StringIO()
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
    writer = JSONStreamWriter(out, pretty=pretty)
    writer.open_array()
    writer.open_object()
    writer.key('key1')
    writer.value('value')
    writer.key('key2')
    writer.value(1)
    writer.close_object()
    writer.open_object()
    writer.key('key')
    writer.open_object()
    writer.key('key')
    writer.value('value')
    writer.close_object()
    writer.close_object()
    writer.close_array()
    writer.close()
185
186
187

    assert create_reference(example_data, pretty) == out.getvalue()

188

189
190
def assert_parser_result(backend):
    status, errors = backend.status
191
192
    assert status == 'ParseSuccess'
    assert errors is None or len(errors) == 0
193
194


195
196
197
def run_parser(parser_name, mainfile):
    parser = parser_dict[parser_name]
    return parser.run(mainfile)
Markus Scheidgen's avatar
Markus Scheidgen committed
198
199


200
201
202
203
@pytest.fixture
def parsed_vasp_example() -> LocalBackend:
    return run_parser(
        'parsers/vasp', '.dependencies/parsers/vasp/test/examples/xml/perovskite.xml')
Markus Scheidgen's avatar
Markus Scheidgen committed
204
205


206
207
208
209
210
211
@pytest.fixture
def parsed_template_example() -> LocalBackend:
    return run_parser(
        'parsers/template', 'tests/data/parsers/template.json')


212
213
214
215
216
217
@pytest.fixture(params=parser_examples, ids=lambda spec: '%s-%s' % spec)
def parsed_example(request) -> LocalBackend:
    parser_name, mainfile = request.param
    return run_parser(parser_name, mainfile)


218
def test_parser(parsed_example, no_warn):
219
    assert_parser_result(parsed_example)
Markus Scheidgen's avatar
Markus Scheidgen committed
220
221


222
def test_match(no_warn):
Markus Scheidgen's avatar
Markus Scheidgen committed
223
    directory = 'tests/data/proc/match'
224
225
226
227
228

    count = 0
    for dirpath, _, filenames in os.walk(directory):
        for filename in filenames:
            fullname = os.path.join(dirpath, filename)
Markus Scheidgen's avatar
Markus Scheidgen committed
229
230
231
            for parser in parser_dict.values():
                if parser.is_mainfile(fullname, lambda fn: open(fn)):
                    count += 1
232

Markus Scheidgen's avatar
Markus Scheidgen committed
233
    assert count == 6