]> git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/dashboard/frontend/src/app/shared/components/config-option/config-option.component.spec.ts
import 15.2.0 Octopus source
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / shared / components / config-option / config-option.component.spec.ts
1 import { HttpClientTestingModule } from '@angular/common/http/testing';
2 import { ComponentFixture, TestBed } from '@angular/core/testing';
3 import { ReactiveFormsModule } from '@angular/forms';
4
5 import * as _ from 'lodash';
6 import { PopoverModule } from 'ngx-bootstrap/popover';
7 import { of as observableOf } from 'rxjs';
8
9 import { configureTestBed } from '../../../../testing/unit-test-helper';
10 import { ConfigurationService } from '../../api/configuration.service';
11 import { CdFormGroup } from '../../forms/cd-form-group';
12 import { HelperComponent } from '../helper/helper.component';
13 import { ConfigOptionComponent } from './config-option.component';
14
15 describe('ConfigOptionComponent', () => {
16 let component: ConfigOptionComponent;
17 let fixture: ComponentFixture<ConfigOptionComponent>;
18 let configurationService: ConfigurationService;
19 let oNames: Array<string>;
20
21 configureTestBed({
22 declarations: [ConfigOptionComponent, HelperComponent],
23 imports: [PopoverModule.forRoot(), ReactiveFormsModule, HttpClientTestingModule],
24 providers: [ConfigurationService]
25 });
26
27 beforeEach(() => {
28 fixture = TestBed.createComponent(ConfigOptionComponent);
29 component = fixture.componentInstance;
30 fixture.detectChanges();
31 configurationService = TestBed.get(ConfigurationService);
32
33 const configOptions: Record<string, any> = [
34 {
35 name: 'osd_scrub_auto_repair_num_errors',
36 type: 'uint',
37 level: 'advanced',
38 desc: 'Maximum number of detected errors to automatically repair',
39 long_desc: '',
40 default: 5,
41 daemon_default: '',
42 tags: [],
43 services: [],
44 see_also: ['osd_scrub_auto_repair'],
45 min: '',
46 max: '',
47 can_update_at_runtime: true,
48 flags: []
49 },
50 {
51 name: 'osd_debug_deep_scrub_sleep',
52 type: 'float',
53 level: 'dev',
54 desc:
55 'Inject an expensive sleep during deep scrub IO to make it easier to induce preemption',
56 long_desc: '',
57 default: 0,
58 daemon_default: '',
59 tags: [],
60 services: [],
61 see_also: [],
62 min: '',
63 max: '',
64 can_update_at_runtime: true,
65 flags: []
66 },
67 {
68 name: 'osd_heartbeat_interval',
69 type: 'int',
70 level: 'advanced',
71 desc: 'Interval (in seconds) between peer pings',
72 long_desc: '',
73 default: 6,
74 daemon_default: '',
75 tags: [],
76 services: [],
77 see_also: [],
78 min: 1,
79 max: 86400,
80 can_update_at_runtime: true,
81 flags: [],
82 value: [
83 {
84 section: 'osd',
85 value: 6
86 }
87 ]
88 },
89 {
90 name: 'bluestore_compression_algorithm',
91 type: 'str',
92 level: 'advanced',
93 desc: 'Default compression algorithm to use when writing object data',
94 long_desc:
95 'This controls the default compressor to use (if any) if the ' +
96 'per-pool property is not set. Note that zstd is *not* recommended for ' +
97 'bluestore due to high CPU overhead when compressing small amounts of data.',
98 default: 'snappy',
99 daemon_default: '',
100 tags: [],
101 services: [],
102 see_also: [],
103 enum_values: ['', 'snappy', 'zlib', 'zstd', 'lz4'],
104 min: '',
105 max: '',
106 can_update_at_runtime: true,
107 flags: ['runtime']
108 },
109 {
110 name: 'rbd_discard_on_zeroed_write_same',
111 type: 'bool',
112 level: 'advanced',
113 desc: 'discard data on zeroed write same instead of writing zero',
114 long_desc: '',
115 default: true,
116 daemon_default: '',
117 tags: [],
118 services: ['rbd'],
119 see_also: [],
120 min: '',
121 max: '',
122 can_update_at_runtime: true,
123 flags: []
124 },
125 {
126 name: 'rbd_journal_max_payload_bytes',
127 type: 'size',
128 level: 'advanced',
129 desc: 'maximum journal payload size before splitting',
130 long_desc: '',
131 daemon_default: '',
132 tags: [],
133 services: ['rbd'],
134 see_also: [],
135 min: '',
136 max: '',
137 can_update_at_runtime: true,
138 flags: [],
139 default: '16384'
140 },
141 {
142 name: 'cluster_addr',
143 type: 'addr',
144 level: 'basic',
145 desc: 'cluster-facing address to bind to',
146 long_desc: '',
147 daemon_default: '',
148 tags: ['network'],
149 services: ['osd'],
150 see_also: [],
151 min: '',
152 max: '',
153 can_update_at_runtime: false,
154 flags: [],
155 default: '-'
156 },
157 {
158 name: 'fsid',
159 type: 'uuid',
160 level: 'basic',
161 desc: 'cluster fsid (uuid)',
162 long_desc: '',
163 daemon_default: '',
164 tags: ['service'],
165 services: ['common'],
166 see_also: [],
167 min: '',
168 max: '',
169 can_update_at_runtime: false,
170 flags: ['no_mon_update'],
171 default: '00000000-0000-0000-0000-000000000000'
172 },
173 {
174 name: 'mgr_tick_period',
175 type: 'secs',
176 level: 'advanced',
177 desc: 'Period in seconds of beacon messages to monitor',
178 long_desc: '',
179 daemon_default: '',
180 tags: [],
181 services: ['mgr'],
182 see_also: [],
183 min: '',
184 max: '',
185 can_update_at_runtime: true,
186 flags: [],
187 default: '2'
188 }
189 ];
190
191 spyOn(configurationService, 'filter').and.returnValue(observableOf(configOptions));
192 oNames = _.map(configOptions, 'name');
193 component.optionNames = oNames;
194 component.optionsForm = new CdFormGroup({});
195 component.optionsFormGroupName = 'testFormGroupName';
196 component.ngOnInit();
197 });
198
199 it('should create', () => {
200 expect(component).toBeTruthy();
201 });
202
203 describe('optionNameToText', () => {
204 it('should format config option names correctly', () => {
205 const configOptionNames = {
206 osd_scrub_auto_repair_num_errors: 'Scrub Auto Repair Num Errors',
207 osd_debug_deep_scrub_sleep: 'Debug Deep Scrub Sleep',
208 osd_heartbeat_interval: 'Heartbeat Interval',
209 bluestore_compression_algorithm: 'Bluestore Compression Algorithm',
210 rbd_discard_on_zeroed_write_same: 'Rbd Discard On Zeroed Write Same',
211 rbd_journal_max_payload_bytes: 'Rbd Journal Max Payload Bytes',
212 cluster_addr: 'Cluster Addr',
213 fsid: 'Fsid',
214 mgr_tick_period: 'Tick Period'
215 };
216
217 component.options.forEach((option) => {
218 expect(option.text).toEqual(configOptionNames[option.name]);
219 });
220 });
221 });
222
223 describe('createForm', () => {
224 it('should set the optionsFormGroupName correctly', () => {
225 expect(component.optionsFormGroupName).toEqual('testFormGroupName');
226 });
227
228 it('should create a FormControl for every config option', () => {
229 component.options.forEach((option) => {
230 expect(Object.keys(component.optionsFormGroup.controls)).toContain(option.name);
231 });
232 });
233 });
234
235 describe('loadStorageData', () => {
236 it('should create a list of config options by names', () => {
237 expect(component.options.length).toEqual(9);
238
239 component.options.forEach((option) => {
240 expect(oNames).toContain(option.name);
241 });
242 });
243
244 it('should add all needed attributes to every config option', () => {
245 component.options.forEach((option) => {
246 const optionKeys = Object.keys(option);
247 expect(optionKeys).toContain('text');
248 expect(optionKeys).toContain('additionalTypeInfo');
249 expect(optionKeys).toContain('value');
250
251 if (option.type !== 'bool' && option.type !== 'str') {
252 expect(optionKeys).toContain('patternHelpText');
253 }
254
255 if (option.name === 'osd_heartbeat_interval') {
256 expect(optionKeys).toContain('maxValue');
257 expect(optionKeys).toContain('minValue');
258 }
259 });
260 });
261
262 it('should set minValue and maxValue correctly', () => {
263 component.options.forEach((option) => {
264 if (option.name === 'osd_heartbeat_interval') {
265 expect(option.minValue).toEqual(1);
266 expect(option.maxValue).toEqual(86400);
267 }
268 });
269 });
270
271 it('should set the value attribute correctly', () => {
272 component.options.forEach((option) => {
273 if (option.name === 'osd_heartbeat_interval') {
274 const value = option.value;
275 expect(value).toBeDefined();
276 expect(value).toEqual({ section: 'osd', value: 6 });
277 } else {
278 expect(option.value).toBeUndefined();
279 }
280 });
281 });
282
283 it('should set the FormControl value correctly', () => {
284 component.options.forEach((option) => {
285 const value = component.optionsFormGroup.getValue(option.name);
286 if (option.name === 'osd_heartbeat_interval') {
287 expect(value).toBeDefined();
288 expect(value).toEqual(6);
289 } else {
290 expect(value).toBeNull();
291 }
292 });
293 });
294 });
295 });