1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
# Pylint doesn't play well with fixtures and dependency injection from pytest
# pylint: disable=redefined-outer-name
from contextlib import contextmanager
import os
import tempfile
import pytest
from ruamel import yaml
from tests.testutils import generate_junction, create_element_size
from buildstream.plugintestutils import cli
from buildstream import _yaml
from buildstream._yamlcache import YamlCache
from buildstream._project import Project
from buildstream._context import Context
def generate_project(tmpdir, ref_storage, with_junction, name="test"):
if with_junction == 'junction':
subproject_dir = generate_project(
tmpdir, ref_storage,
'no-junction', name='test-subproject'
)
project_dir = os.path.join(tmpdir, name)
os.makedirs(project_dir)
# project.conf
project_conf_path = os.path.join(project_dir, 'project.conf')
elements_path = 'elements'
project_conf = {
'name': name,
'element-path': elements_path,
'ref-storage': ref_storage,
}
_yaml.dump(project_conf, project_conf_path)
# elements
if with_junction == 'junction':
junction_name = 'junction.bst'
junction_dir = os.path.join(project_dir, elements_path)
junction_path = os.path.join(project_dir, elements_path, junction_name)
os.makedirs(junction_dir)
generate_junction(tmpdir, subproject_dir, junction_path)
element_depends = [{'junction': junction_name, 'filename': 'test.bst'}]
else:
element_depends = []
element_name = 'test.bst'
create_element_size(element_name, project_dir, elements_path, element_depends, 1)
return project_dir
@contextmanager
def with_yamlcache(project_dir):
context = Context()
project = Project(project_dir, context)
cache_file = YamlCache.get_cache_file(project_dir)
with YamlCache.open(context, cache_file) as yamlcache:
yield yamlcache, project
def yamlcache_key(yamlcache, in_file, copy_tree=False):
with open(in_file) as f:
key = yamlcache._calculate_key(f.read(), copy_tree)
return key
def modified_file(input_file, tmpdir):
with open(input_file) as f:
data = f.read()
assert 'variables' not in data
data += '\nvariables: {modified: True}\n'
_, temppath = tempfile.mkstemp(dir=tmpdir, text=True)
with open(temppath, 'w') as f:
f.write(data)
return temppath
@pytest.mark.parametrize('ref_storage', ['inline', 'project.refs'])
@pytest.mark.parametrize('with_junction', ['no-junction', 'junction'])
@pytest.mark.parametrize('move_project', ['move', 'no-move'])
def test_yamlcache_used(cli, tmpdir, ref_storage, with_junction, move_project):
# Generate the project
project = generate_project(str(tmpdir), ref_storage, with_junction)
if with_junction == 'junction':
result = cli.run(project=project, args=['source', 'fetch', '--track', 'junction.bst'])
result.assert_success()
# bst show to put it in the cache
result = cli.run(project=project, args=['show', 'test.bst'])
result.assert_success()
element_path = os.path.join(project, 'elements', 'test.bst')
with with_yamlcache(project) as (yc, prj):
# Check that it's in the cache
assert yc.is_cached(prj, element_path)
# *Absolutely* horrible cache corruption to check it's being used
# Modifying the data from the cache is fraught with danger,
# so instead I'll load a modified version of the original file
temppath = modified_file(element_path, str(tmpdir))
contents = _yaml.load(temppath, copy_tree=False, project=prj)
key = yamlcache_key(yc, element_path)
yc.put_from_key(prj, element_path, key, contents)
# Show that a variable has been added
result = cli.run(project=project, args=['show', '--deps', 'none', '--format', '%{vars}', 'test.bst'])
result.assert_success()
data = yaml.safe_load(result.output)
assert 'modified' in data
assert data['modified'] == 'True'
@pytest.mark.parametrize('ref_storage', ['inline', 'project.refs'])
@pytest.mark.parametrize('with_junction', ['junction', 'no-junction'])
def test_yamlcache_changed_file(cli, tmpdir, ref_storage, with_junction):
# i.e. a file is cached, the file is changed, loading the file (with cache) returns new data
# inline and junction can only be changed by opening a workspace
# Generate the project
project = generate_project(str(tmpdir), ref_storage, with_junction)
if with_junction == 'junction':
result = cli.run(project=project, args=['source', 'fetch', '--track', 'junction.bst'])
result.assert_success()
# bst show to put it in the cache
result = cli.run(project=project, args=['show', 'test.bst'])
result.assert_success()
element_path = os.path.join(project, 'elements', 'test.bst')
with with_yamlcache(project) as (yc, prj):
# Check that it's in the cache then modify
assert yc.is_cached(prj, element_path)
with open(element_path, "a") as f:
f.write('\nvariables: {modified: True}\n')
# Load modified yaml cache file into cache
_yaml.load(element_path, copy_tree=False, project=prj, yaml_cache=yc)
# Show that a variable has been added
result = cli.run(project=project, args=['show', '--deps', 'none', '--format', '%{vars}', 'test.bst'])
result.assert_success()
data = yaml.safe_load(result.output)
assert 'modified' in data
assert data['modified'] == 'True'
|