add a unit test for reading non existent values (to check for #10030)
[wxWidgets.git] / tests / config / fileconf.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: tests/fileconf/fileconf.cpp
3 // Purpose: wxFileConf unit test
4 // Author: Vadim Zeitlin
5 // Created: 2004-09-19
6 // RCS-ID: $Id$
7 // Copyright: (c) 2004 Vadim Zeitlin
8 ///////////////////////////////////////////////////////////////////////////////
9
10 // ----------------------------------------------------------------------------
11 // headers
12 // ----------------------------------------------------------------------------
13
14 #include "testprec.h"
15
16 #ifdef __BORLANDC__
17 #pragma hdrstop
18 #endif
19
20 #if wxUSE_FILECONFIG
21
22 #ifndef WX_PRECOMP
23 #endif // WX_PRECOMP
24
25 #include "wx/fileconf.h"
26 #include "wx/sstream.h"
27 #include "wx/log.h"
28
29 static const wxChar *testconfig =
30 _T("[root]\n")
31 _T("entry=value\n")
32 _T("[root/group1]\n")
33 _T("[root/group1/subgroup]\n")
34 _T("subentry=subvalue\n")
35 _T("subentry2=subvalue2\n")
36 _T("[root/group2]\n")
37 ;
38
39 // ----------------------------------------------------------------------------
40 // local functions
41 // ----------------------------------------------------------------------------
42
43 static wxString Dump(wxFileConfig& fc)
44 {
45 wxStringOutputStream sos;
46 fc.Save(sos);
47 return wxTextFile::Translate(sos.GetString(), wxTextFileType_Unix);
48 }
49
50 // helper macro to test wxFileConfig contents
51 #define wxVERIFY_FILECONFIG(t, fc) CPPUNIT_ASSERT_EQUAL(wxString(t), Dump(fc))
52
53 // ----------------------------------------------------------------------------
54 // test class
55 // ----------------------------------------------------------------------------
56
57 class FileConfigTestCase : public CppUnit::TestCase
58 {
59 public:
60 FileConfigTestCase() { }
61
62 private:
63 CPPUNIT_TEST_SUITE( FileConfigTestCase );
64 CPPUNIT_TEST( Path );
65 CPPUNIT_TEST( AddEntries );
66 CPPUNIT_TEST( GetEntries );
67 CPPUNIT_TEST( GetGroups );
68 CPPUNIT_TEST( HasEntry );
69 CPPUNIT_TEST( HasGroup );
70 CPPUNIT_TEST( Binary );
71 CPPUNIT_TEST( Save );
72 CPPUNIT_TEST( DeleteEntry );
73 CPPUNIT_TEST( DeleteAndWriteEntry );
74 CPPUNIT_TEST( DeleteGroup );
75 CPPUNIT_TEST( DeleteAll );
76 CPPUNIT_TEST( RenameEntry );
77 CPPUNIT_TEST( RenameGroup );
78 CPPUNIT_TEST( CreateEntriesAndSubgroup );
79 CPPUNIT_TEST( CreateSubgroupAndEntries );
80 CPPUNIT_TEST( DeleteLastGroup );
81 CPPUNIT_TEST( DeleteAndRecreateGroup );
82 CPPUNIT_TEST( AddToExistingRoot );
83 CPPUNIT_TEST( ReadNonExistent );
84 CPPUNIT_TEST_SUITE_END();
85
86 void Path();
87 void AddEntries();
88 void GetEntries();
89 void GetGroups();
90 void HasEntry();
91 void HasGroup();
92 void Binary();
93 void Save();
94 void DeleteEntry();
95 void DeleteAndWriteEntry();
96 void DeleteGroup();
97 void DeleteAll();
98 void RenameEntry();
99 void RenameGroup();
100 void CreateEntriesAndSubgroup();
101 void CreateSubgroupAndEntries();
102 void DeleteLastGroup();
103 void DeleteAndRecreateGroup();
104 void AddToExistingRoot();
105 void ReadNonExistent();
106
107
108 static wxString ChangePath(wxFileConfig& fc, const wxChar *path)
109 {
110 fc.SetPath(path);
111
112 return fc.GetPath();
113 }
114
115 void CheckGroupEntries(const wxFileConfig& fc,
116 const wxChar *path,
117 size_t nEntries,
118 ...);
119 void CheckGroupSubgroups(const wxFileConfig& fc,
120 const wxChar *path,
121 size_t nGroups,
122 ...);
123
124 DECLARE_NO_COPY_CLASS(FileConfigTestCase)
125 };
126
127 // register in the unnamed registry so that these tests are run by default
128 CPPUNIT_TEST_SUITE_REGISTRATION( FileConfigTestCase );
129
130 // also include in it's own registry so that these tests can be run alone
131 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( FileConfigTestCase, "FileConfigTestCase" );
132
133 void FileConfigTestCase::Path()
134 {
135 wxStringInputStream sis(testconfig);
136 wxFileConfig fc(sis);
137
138 CPPUNIT_ASSERT( ChangePath(fc, _T("")) == _T("") );
139 CPPUNIT_ASSERT( ChangePath(fc, _T("/")) == _T("") );
140 CPPUNIT_ASSERT( ChangePath(fc, _T("root")) == _T("/root") );
141 CPPUNIT_ASSERT( ChangePath(fc, _T("/root")) == _T("/root") );
142 CPPUNIT_ASSERT( ChangePath(fc, _T("/root/group1/subgroup")) == _T("/root/group1/subgroup") );
143 CPPUNIT_ASSERT( ChangePath(fc, _T("/root/group2")) == _T("/root/group2") );
144 }
145
146 void FileConfigTestCase::AddEntries()
147 {
148 wxFileConfig fc;
149
150 wxVERIFY_FILECONFIG( _T(""), fc );
151
152 fc.Write(_T("/Foo"), _T("foo"));
153 wxVERIFY_FILECONFIG( _T("Foo=foo\n"), fc );
154
155 fc.Write(_T("/Bar/Baz"), _T("baz"));
156 wxVERIFY_FILECONFIG( _T("Foo=foo\n[Bar]\nBaz=baz\n"), fc );
157
158 fc.DeleteAll();
159 wxVERIFY_FILECONFIG( _T(""), fc );
160
161 fc.Write(_T("/Bar/Baz"), _T("baz"));
162 wxVERIFY_FILECONFIG( _T("[Bar]\nBaz=baz\n"), fc );
163
164 fc.Write(_T("/Foo"), _T("foo"));
165 wxVERIFY_FILECONFIG( _T("Foo=foo\n[Bar]\nBaz=baz\n"), fc );
166 }
167
168 void
169 FileConfigTestCase::CheckGroupEntries(const wxFileConfig& fc,
170 const wxChar *path,
171 size_t nEntries,
172 ...)
173 {
174 wxConfigPathChanger change(&fc, wxString(path) + _T("/"));
175
176 CPPUNIT_ASSERT( fc.GetNumberOfEntries() == nEntries );
177
178 va_list ap;
179 va_start(ap, nEntries);
180
181 long cookie;
182 wxString name;
183 for ( bool cont = fc.GetFirstEntry(name, cookie);
184 cont;
185 cont = fc.GetNextEntry(name, cookie), nEntries-- )
186 {
187 CPPUNIT_ASSERT( name == va_arg(ap, wxChar *) );
188 }
189
190 CPPUNIT_ASSERT( nEntries == 0 );
191
192 va_end(ap);
193 }
194
195 void
196 FileConfigTestCase::CheckGroupSubgroups(const wxFileConfig& fc,
197 const wxChar *path,
198 size_t nGroups,
199 ...)
200 {
201 wxConfigPathChanger change(&fc, wxString(path) + _T("/"));
202
203 CPPUNIT_ASSERT( fc.GetNumberOfGroups() == nGroups );
204
205 va_list ap;
206 va_start(ap, nGroups);
207
208 long cookie;
209 wxString name;
210 for ( bool cont = fc.GetFirstGroup(name, cookie);
211 cont;
212 cont = fc.GetNextGroup(name, cookie), nGroups-- )
213 {
214 CPPUNIT_ASSERT( name == va_arg(ap, wxChar *) );
215 }
216
217 CPPUNIT_ASSERT( nGroups == 0 );
218
219 va_end(ap);
220 }
221
222 void FileConfigTestCase::GetEntries()
223 {
224 wxStringInputStream sis(testconfig);
225 wxFileConfig fc(sis);
226
227 CheckGroupEntries(fc, _T(""), 0);
228 CheckGroupEntries(fc, _T("/root"), 1, _T("entry"));
229 CheckGroupEntries(fc, _T("/root/group1"), 0);
230 CheckGroupEntries(fc, _T("/root/group1/subgroup"),
231 2, _T("subentry"), _T("subentry2"));
232 }
233
234 void FileConfigTestCase::GetGroups()
235 {
236 wxStringInputStream sis(testconfig);
237 wxFileConfig fc(sis);
238
239 CheckGroupSubgroups(fc, _T(""), 1, _T("root"));
240 CheckGroupSubgroups(fc, _T("/root"), 2, _T("group1"), _T("group2"));
241 CheckGroupSubgroups(fc, _T("/root/group1"), 1, _T("subgroup"));
242 CheckGroupSubgroups(fc, _T("/root/group2"), 0);
243 }
244
245 void FileConfigTestCase::HasEntry()
246 {
247 wxStringInputStream sis(testconfig);
248 wxFileConfig fc(sis);
249
250 CPPUNIT_ASSERT( !fc.HasEntry(_T("root")) );
251 CPPUNIT_ASSERT( fc.HasEntry(_T("root/entry")) );
252 CPPUNIT_ASSERT( fc.HasEntry(_T("/root/entry")) );
253 CPPUNIT_ASSERT( fc.HasEntry(_T("root/group1/subgroup/subentry")) );
254 CPPUNIT_ASSERT( !fc.HasEntry(_T("")) );
255 CPPUNIT_ASSERT( !fc.HasEntry(_T("root/group1")) );
256 CPPUNIT_ASSERT( !fc.HasEntry(_T("subgroup/subentry")) );
257 CPPUNIT_ASSERT( !fc.HasEntry(_T("/root/no_such_group/entry")) );
258 CPPUNIT_ASSERT( !fc.HasGroup(_T("/root/no_such_group")) );
259 }
260
261 void FileConfigTestCase::HasGroup()
262 {
263 wxStringInputStream sis(testconfig);
264 wxFileConfig fc(sis);
265
266 CPPUNIT_ASSERT( fc.HasGroup(_T("root")) );
267 CPPUNIT_ASSERT( fc.HasGroup(_T("root/group1")) );
268 CPPUNIT_ASSERT( fc.HasGroup(_T("root/group1/subgroup")) );
269 CPPUNIT_ASSERT( fc.HasGroup(_T("root/group2")) );
270 CPPUNIT_ASSERT( !fc.HasGroup(_T("")) );
271 CPPUNIT_ASSERT( !fc.HasGroup(_T("root/group")) );
272 CPPUNIT_ASSERT( !fc.HasGroup(_T("root//subgroup")) );
273 CPPUNIT_ASSERT( !fc.HasGroup(_T("foot/subgroup")) );
274 CPPUNIT_ASSERT( !fc.HasGroup(_T("foot")) );
275 }
276
277 void FileConfigTestCase::Binary()
278 {
279 wxStringInputStream sis(
280 "[root]\n"
281 "binary=Zm9vCg==\n"
282 );
283 wxFileConfig fc(sis);
284
285 wxMemoryBuffer buf;
286 fc.Read("/root/binary", &buf);
287
288 CPPUNIT_ASSERT( memcmp("foo\n", buf.GetData(), buf.GetDataLen()) == 0 );
289
290 buf.SetDataLen(0);
291 buf.AppendData("\0\1\2", 3);
292 fc.Write("/root/012", buf);
293 wxVERIFY_FILECONFIG(
294 "[root]\n"
295 "binary=Zm9vCg==\n"
296 "012=AAEC\n",
297 fc
298 );
299 }
300
301 void FileConfigTestCase::Save()
302 {
303 wxStringInputStream sis(testconfig);
304 wxFileConfig fc(sis);
305 wxVERIFY_FILECONFIG( testconfig, fc );
306 }
307
308 void FileConfigTestCase::DeleteEntry()
309 {
310 wxStringInputStream sis(testconfig);
311 wxFileConfig fc(sis);
312
313 CPPUNIT_ASSERT( !fc.DeleteEntry(_T("foo")) );
314
315 CPPUNIT_ASSERT( fc.DeleteEntry(_T("root/group1/subgroup/subentry")) );
316 wxVERIFY_FILECONFIG( _T("[root]\n")
317 _T("entry=value\n")
318 _T("[root/group1]\n")
319 _T("[root/group1/subgroup]\n")
320 _T("subentry2=subvalue2\n")
321 _T("[root/group2]\n"),
322 fc );
323
324 // group should be deleted now as well as it became empty
325 wxConfigPathChanger change(&fc, _T("root/group1/subgroup/subentry2"));
326 CPPUNIT_ASSERT( fc.DeleteEntry(_T("subentry2")) );
327 wxVERIFY_FILECONFIG( _T("[root]\n")
328 _T("entry=value\n")
329 _T("[root/group1]\n")
330 _T("[root/group2]\n"),
331 fc );
332 }
333
334 void FileConfigTestCase::DeleteAndWriteEntry()
335 {
336 wxStringInputStream sis(
337 "[root/group1]\n"
338 "subentry=subvalue\n"
339 "subentry2=subvalue2\n"
340 "subentry3=subvalue3\n"
341 );
342
343 wxFileConfig fc(sis);
344
345 fc.DeleteEntry("/root/group1/subentry2");
346 fc.Write("/root/group1/subentry2", "testvalue");
347 fc.DeleteEntry("/root/group2/subentry2");
348 fc.Write("/root/group2/subentry2", "testvalue2");
349 fc.DeleteEntry("/root/group1/subentry2");
350 fc.Write("/root/group1/subentry2", "testvalue");
351 fc.DeleteEntry("/root/group2/subentry2");
352 fc.Write("/root/group2/subentry2", "testvalue2");
353
354 wxVERIFY_FILECONFIG( "[root/group1]\n"
355 "subentry=subvalue\n"
356 "subentry3=subvalue3\n"
357 "subentry2=testvalue\n"
358 "[root/group2]\n"
359 "subentry2=testvalue2\n",
360 fc );
361
362 fc.DeleteEntry("/root/group2/subentry2");
363 wxVERIFY_FILECONFIG( "[root/group1]\n"
364 "subentry=subvalue\n"
365 "subentry3=subvalue3\n"
366 "subentry2=testvalue\n",
367 fc );
368
369 fc.DeleteEntry("/root/group1/subentry2");
370 fc.DeleteEntry("/root/group1/subentry");
371 fc.DeleteEntry("/root/group1/subentry3");
372 wxVERIFY_FILECONFIG( "", fc );
373 }
374
375 void FileConfigTestCase::DeleteGroup()
376 {
377 wxStringInputStream sis(testconfig);
378 wxFileConfig fc(sis);
379
380 CPPUNIT_ASSERT( !fc.DeleteGroup(_T("foo")) );
381
382 CPPUNIT_ASSERT( fc.DeleteGroup(_T("root/group1")) );
383 wxVERIFY_FILECONFIG( _T("[root]\n")
384 _T("entry=value\n")
385 _T("[root/group2]\n"),
386 fc );
387
388 // notice trailing slash: it should be ignored
389 CPPUNIT_ASSERT( fc.DeleteGroup(_T("root/group2/")) );
390 wxVERIFY_FILECONFIG( _T("[root]\n")
391 _T("entry=value\n"),
392 fc );
393
394 CPPUNIT_ASSERT( fc.DeleteGroup(_T("root")) );
395 CPPUNIT_ASSERT( Dump(fc).empty() );
396 }
397
398 void FileConfigTestCase::DeleteAll()
399 {
400 wxStringInputStream sis(testconfig);
401 wxFileConfig fc(sis);
402
403 CPPUNIT_ASSERT( fc.DeleteAll() );
404 CPPUNIT_ASSERT( Dump(fc).empty() );
405 }
406
407 void FileConfigTestCase::RenameEntry()
408 {
409 wxStringInputStream sis(testconfig);
410 wxFileConfig fc(sis);
411
412 fc.SetPath(_T("root"));
413 CPPUNIT_ASSERT( fc.RenameEntry(_T("entry"), _T("newname")) );
414 wxVERIFY_FILECONFIG( _T("[root]\n")
415 _T("newname=value\n")
416 _T("[root/group1]\n")
417 _T("[root/group1/subgroup]\n")
418 _T("subentry=subvalue\n")
419 _T("subentry2=subvalue2\n")
420 _T("[root/group2]\n"),
421 fc );
422
423 fc.SetPath(_T("group1/subgroup"));
424 CPPUNIT_ASSERT( !fc.RenameEntry(_T("entry"), _T("newname")) );
425 CPPUNIT_ASSERT( !fc.RenameEntry(_T("subentry"), _T("subentry2")) );
426
427 CPPUNIT_ASSERT( fc.RenameEntry(_T("subentry"), _T("subentry1")) );
428 wxVERIFY_FILECONFIG( _T("[root]\n")
429 _T("newname=value\n")
430 _T("[root/group1]\n")
431 _T("[root/group1/subgroup]\n")
432 _T("subentry2=subvalue2\n")
433 _T("subentry1=subvalue\n")
434 _T("[root/group2]\n"),
435 fc );
436 }
437
438 void FileConfigTestCase::RenameGroup()
439 {
440 wxStringInputStream sis(testconfig);
441 wxFileConfig fc(sis);
442
443 CPPUNIT_ASSERT( fc.RenameGroup(_T("root"), _T("foot")) );
444 wxVERIFY_FILECONFIG( _T("[foot]\n")
445 _T("entry=value\n")
446 _T("[foot/group1]\n")
447 _T("[foot/group1/subgroup]\n")
448 _T("subentry=subvalue\n")
449 _T("subentry2=subvalue2\n")
450 _T("[foot/group2]\n"),
451 fc );
452
453 // renaming a path doesn't work, it must be the immediate group
454 CPPUNIT_ASSERT( !fc.RenameGroup(_T("foot/group1"), _T("group2")) );
455
456
457 fc.SetPath(_T("foot"));
458
459 // renaming to a name of existing group doesn't work
460 CPPUNIT_ASSERT( !fc.RenameGroup(_T("group1"), _T("group2")) );
461
462 // try exchanging the groups names and then restore them back
463 CPPUNIT_ASSERT( fc.RenameGroup(_T("group1"), _T("groupTmp")) );
464 wxVERIFY_FILECONFIG( _T("[foot]\n")
465 _T("entry=value\n")
466 _T("[foot/groupTmp]\n")
467 _T("[foot/groupTmp/subgroup]\n")
468 _T("subentry=subvalue\n")
469 _T("subentry2=subvalue2\n")
470 _T("[foot/group2]\n"),
471 fc );
472
473 CPPUNIT_ASSERT( fc.RenameGroup(_T("group2"), _T("group1")) );
474 wxVERIFY_FILECONFIG( _T("[foot]\n")
475 _T("entry=value\n")
476 _T("[foot/groupTmp]\n")
477 _T("[foot/groupTmp/subgroup]\n")
478 _T("subentry=subvalue\n")
479 _T("subentry2=subvalue2\n")
480 _T("[foot/group1]\n"),
481 fc );
482
483 CPPUNIT_ASSERT( fc.RenameGroup(_T("groupTmp"), _T("group2")) );
484 wxVERIFY_FILECONFIG( _T("[foot]\n")
485 _T("entry=value\n")
486 _T("[foot/group2]\n")
487 _T("[foot/group2/subgroup]\n")
488 _T("subentry=subvalue\n")
489 _T("subentry2=subvalue2\n")
490 _T("[foot/group1]\n"),
491 fc );
492
493 CPPUNIT_ASSERT( fc.RenameGroup(_T("group1"), _T("groupTmp")) );
494 wxVERIFY_FILECONFIG( _T("[foot]\n")
495 _T("entry=value\n")
496 _T("[foot/group2]\n")
497 _T("[foot/group2/subgroup]\n")
498 _T("subentry=subvalue\n")
499 _T("subentry2=subvalue2\n")
500 _T("[foot/groupTmp]\n"),
501 fc );
502
503 CPPUNIT_ASSERT( fc.RenameGroup(_T("group2"), _T("group1")) );
504 wxVERIFY_FILECONFIG( _T("[foot]\n")
505 _T("entry=value\n")
506 _T("[foot/group1]\n")
507 _T("[foot/group1/subgroup]\n")
508 _T("subentry=subvalue\n")
509 _T("subentry2=subvalue2\n")
510 _T("[foot/groupTmp]\n"),
511 fc );
512
513 CPPUNIT_ASSERT( fc.RenameGroup(_T("groupTmp"), _T("group2")) );
514 wxVERIFY_FILECONFIG( _T("[foot]\n")
515 _T("entry=value\n")
516 _T("[foot/group1]\n")
517 _T("[foot/group1/subgroup]\n")
518 _T("subentry=subvalue\n")
519 _T("subentry2=subvalue2\n")
520 _T("[foot/group2]\n"),
521 fc );
522 }
523
524 void FileConfigTestCase::CreateSubgroupAndEntries()
525 {
526 wxFileConfig fc;
527 fc.Write(_T("sub/sub_first"), _T("sub_one"));
528 fc.Write(_T("first"), _T("one"));
529
530 wxVERIFY_FILECONFIG( _T("first=one\n")
531 _T("[sub]\n")
532 _T("sub_first=sub_one\n"),
533 fc );
534 }
535
536 void FileConfigTestCase::CreateEntriesAndSubgroup()
537 {
538 wxFileConfig fc;
539 fc.Write(_T("first"), _T("one"));
540 fc.Write(_T("second"), _T("two"));
541 fc.Write(_T("sub/sub_first"), _T("sub_one"));
542
543 wxVERIFY_FILECONFIG( _T("first=one\n")
544 _T("second=two\n")
545 _T("[sub]\n")
546 _T("sub_first=sub_one\n"),
547 fc );
548 }
549
550 static void EmptyConfigAndWriteKey()
551 {
552 wxFileConfig fc(_T("deleteconftest"));
553
554 const wxString groupPath = _T("/root");
555
556 if ( fc.Exists(groupPath) )
557 {
558 // using DeleteGroup exposes the problem, using DeleteAll doesn't
559 CPPUNIT_ASSERT( fc.DeleteGroup(groupPath) );
560 }
561
562 // the config must be empty for the problem to arise
563 CPPUNIT_ASSERT( !fc.GetNumberOfEntries(true) );
564 CPPUNIT_ASSERT( !fc.GetNumberOfGroups(true) );
565
566
567 // this crashes on second call of this function
568 CPPUNIT_ASSERT( fc.Write(groupPath + _T("/entry"), _T("value")) );
569 }
570
571 void FileConfigTestCase::DeleteLastGroup()
572 {
573 /*
574 We make 2 of the same calls, first to create a file config with a single
575 group and key...
576 */
577 ::EmptyConfigAndWriteKey();
578
579 /*
580 ... then the same but this time the key's group is deleted before the
581 key is written again. This causes a crash.
582 */
583 ::EmptyConfigAndWriteKey();
584
585
586 // clean up
587 wxLogNull noLogging;
588 (void) ::wxRemoveFile(wxFileConfig::GetLocalFileName(_T("deleteconftest")));
589 }
590
591 void FileConfigTestCase::DeleteAndRecreateGroup()
592 {
593 static const wxChar *confInitial =
594 _T("[First]\n")
595 _T("Value1=Foo\n")
596 _T("[Second]\n")
597 _T("Value2=Bar\n");
598
599 wxStringInputStream sis(confInitial);
600 wxFileConfig fc(sis);
601
602 fc.DeleteGroup(_T("Second"));
603 wxVERIFY_FILECONFIG( _T("[First]\n")
604 _T("Value1=Foo\n"),
605 fc );
606
607 fc.Write(_T("Second/Value2"), _T("New"));
608 wxVERIFY_FILECONFIG( _T("[First]\n")
609 _T("Value1=Foo\n")
610 _T("[Second]\n")
611 _T("Value2=New\n"),
612 fc );
613 }
614
615 void FileConfigTestCase::AddToExistingRoot()
616 {
617 static const wxChar *confInitial =
618 _T("[Group]\n")
619 _T("value1=foo\n");
620
621 wxStringInputStream sis(confInitial);
622 wxFileConfig fc(sis);
623
624 fc.Write(_T("/value1"), _T("bar"));
625 wxVERIFY_FILECONFIG(
626 _T("value1=bar\n")
627 _T("[Group]\n")
628 _T("value1=foo\n"),
629 fc
630 );
631 }
632
633 void FileConfigTestCase::ReadNonExistent()
634 {
635 static const char *confTest =
636 "community=censored\n"
637 "[City1]\n"
638 "URL=www.fake1.na\n"
639 "[City1/A1]\n"
640 "[City1/A1/1]\n"
641 "IP=192.168.1.66\n"
642 "URL=www.fake2.na\n"
643 ;
644
645 wxStringInputStream sis(confTest);
646 wxFileConfig fc(sis);
647
648 wxString url;
649 CPPUNIT_ASSERT( !fc.Read("URL", &url) );
650 }
651
652 #endif // wxUSE_FILECONFIG
653