1 // Boost.Range MFC Extension
2 //
3 // Copyright Shunsuke Sogame 2005-2006.
4 // Distributed under the Boost Software License, Version 1.0.
5 // (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 
8 
9 #include <afx.h> // must be here
10 
11 // #include <pstade/vodka/drink.hpp>
12 
13 #include <boost/test/test_tools.hpp>
14 #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS
15 #define _ATL_NO_AUTOMATIC_NAMESPACE
16 
17 #define BOOST_LIB_NAME boost_test_exec_monitor
18 #include <boost/config/auto_link.hpp>
19 
20 #define BOOST_RANGE_DETAIL_MICROSOFT_TEST
21 #include <boost/range/mfc.hpp> // can be placed first
22 
23 
24 #include <map>
25 #include <boost/concept_check.hpp>
26 // #include <boost/foreach.hpp>
27 #include <boost/range/begin.hpp>
28 #include <boost/range/concepts.hpp>
29 #include <boost/range/end.hpp>
30 #include <boost/static_assert.hpp>
31 #include <boost/algorithm/string.hpp>
32 
33 
34 #include <afx.h>
35 #include <afxcoll.h>
36 #include <afxtempl.h>
37 
38 #if !(_ATL_VER < 0x0700)
39     #include <cstringt.h>
40     #include <atlsimpstr.h>
41     #include <atlstr.h>
42 #endif
43 
44 
45 namespace brdm = boost::range_detail_microsoft;
46 
47 
48 // helpers
49 //
50 
51 template< class MfcMapT, class MapT >
test_mfc_map(MfcMapT & map,const MapT & sample)52 bool test_mfc_map(MfcMapT& map, const MapT& sample)
53 {
54     typedef typename boost::range_iterator<MfcMapT>::type iter_t;
55     typedef typename boost::range_const_iterator<MapT>::type siter_t;
56 
57     bool result = true;
58 
59     result = result && (boost::distance(map) == boost::distance(sample));
60     if (!result)
61         return false;
62 
63     {
64         for (iter_t it = boost::begin(map), last = boost::end(map); it != last; ++it) {
65             result = result && brdm::test_find_key_and_mapped(sample, *it);
66         }
67     }
68 
69     {
70         for (siter_t it = boost::begin(sample), last = boost::end(sample); it != last; ++it) {
71             result = result && (map[it->first] == it->second);
72         }
73     }
74 
75     return result;
76 }
77 
78 
79 template< class MfcMapT, class MapT >
test_mfc_cpair_map(MfcMapT & map,const MapT & sample)80 bool test_mfc_cpair_map(MfcMapT& map, const MapT& sample)
81 {
82     typedef typename boost::range_iterator<MfcMapT>::type iter_t;
83     typedef typename boost::range_const_iterator<MapT>::type siter_t;
84 
85     bool result = true;
86 
87     result = result && (boost::distance(map) == boost::distance(sample));
88     if (!result)
89         return false;
90 
91     {
92         for (iter_t it = boost::begin(map), last = boost::end(map); it != last; ++it) {
93             result = result && brdm::test_find_key_and_mapped(sample, std::make_pair(it->key, it->value));
94         }
95     }
96 
97     {
98         for (siter_t it = boost::begin(sample), last = boost::end(sample); it != last; ++it) {
99             result = result && (map[it->first] == it->second);
100         }
101     }
102 
103     return result;
104 }
105 
106 
107 // arrays
108 //
109 template< class Range >
test_CByteArray(const Range & sample)110 void test_CByteArray(const Range& sample)
111 {
112     typedef typename boost::range_value<Range>::type val_t;
113 
114     typedef ::CByteArray rng_t;
115     BOOST_STATIC_ASSERT(( brdm::test_mutable_iter<rng_t, BYTE *>::value ));
116     BOOST_STATIC_ASSERT(( brdm::test_const_iter  <rng_t, BYTE const*>::value ));
117 
118     rng_t rng;
119     BOOST_CHECK( brdm::test_init_array(rng, sample) );
120     BOOST_CHECK( brdm::test_random_access(rng) );
121     BOOST_CHECK( brdm::test_emptiness(rng) );
122 }
123 
124 
125 template< class Range >
test_CDWordArray(const Range & sample)126 void test_CDWordArray(const Range& sample)
127 {
128     typedef typename boost::range_value<Range>::type val_t;
129 
130     typedef ::CDWordArray rng_t;
131     BOOST_STATIC_ASSERT(( brdm::test_mutable_iter<rng_t, DWORD *>::value ));
132     BOOST_STATIC_ASSERT(( brdm::test_const_iter  <rng_t, DWORD const*>::value ));
133 
134     rng_t rng;
135     BOOST_CHECK( brdm::test_init_array(rng, sample) );
136     BOOST_CHECK( brdm::test_random_access(rng) );
137     BOOST_CHECK( brdm::test_emptiness(rng) );
138 }
139 
140 
141 template< class Range >
test_CObArray(const Range & sample)142 void test_CObArray(const Range& sample)
143 {
144     typedef typename boost::range_value<Range>::type val_t;
145 
146     typedef ::CObArray rng_t;
147     BOOST_STATIC_ASSERT(( brdm::test_mutable_iter<rng_t, brdm::mfc_ptr_array_iterator<rng_t, ::CObject *> >::value ));
148     BOOST_STATIC_ASSERT(( brdm::test_const_iter  <rng_t, brdm::mfc_ptr_array_iterator<const rng_t, const ::CObject *> >::value ));
149 
150     rng_t rng;
151     BOOST_CHECK( brdm::test_init_array(rng, sample) );
152     BOOST_CHECK( brdm::test_random_access(rng) );
153     BOOST_CHECK( brdm::test_emptiness(rng) );
154 }
155 
156 
157 template< class Range >
test_CPtrArray(const Range & sample)158 void test_CPtrArray(const Range& sample)
159 {
160     typedef typename boost::range_value<Range>::type val_t;
161 
162     typedef ::CPtrArray rng_t;
163     BOOST_STATIC_ASSERT(( brdm::test_mutable_iter<rng_t, brdm::mfc_ptr_array_iterator<rng_t, void *> >::value ));
164     BOOST_STATIC_ASSERT(( brdm::test_const_iter  <rng_t, brdm::mfc_ptr_array_iterator<const rng_t, const void *> >::value ));
165 
166     rng_t rng;
167     BOOST_CHECK( brdm::test_init_array(rng, sample) );
168     BOOST_CHECK( brdm::test_random_access(rng) );
169     BOOST_CHECK( brdm::test_emptiness(rng) );
170 }
171 
172 
173 template< class Range >
test_CStringArray(const Range & sample)174 void test_CStringArray(const Range& sample)
175 {
176     typedef typename boost::range_value<Range>::type val_t;
177 
178     typedef ::CStringArray rng_t;
179     BOOST_STATIC_ASSERT(( brdm::test_mutable_iter<rng_t, ::CString *>::value ));
180     BOOST_STATIC_ASSERT(( brdm::test_const_iter  <rng_t, ::CString const *>::value ));
181 
182     rng_t rng;
183     BOOST_CHECK( brdm::test_init_array(rng, sample) );
184     BOOST_CHECK( brdm::test_random_access(rng) );
185     BOOST_CHECK( brdm::test_emptiness(rng) );
186 }
187 
188 
189 template< class Range >
test_CUIntArray(const Range & sample)190 void test_CUIntArray(const Range& sample)
191 {
192     typedef typename boost::range_value<Range>::type val_t;
193 
194     typedef ::CUIntArray rng_t;
195     BOOST_STATIC_ASSERT(( brdm::test_mutable_iter<rng_t, UINT *>::value ));
196     BOOST_STATIC_ASSERT(( brdm::test_const_iter  <rng_t, UINT const *>::value ));
197 
198     rng_t rng;
199     BOOST_CHECK( brdm::test_init_array(rng, sample) );
200     BOOST_CHECK( brdm::test_random_access(rng) );
201     BOOST_CHECK( brdm::test_emptiness(rng) );
202 }
203 
204 
205 template< class Range >
test_CWordArray(const Range & sample)206 void test_CWordArray(const Range& sample)
207 {
208     typedef typename boost::range_value<Range>::type val_t;
209 
210     typedef ::CWordArray rng_t;
211     BOOST_STATIC_ASSERT(( brdm::test_mutable_iter<rng_t, WORD *>::value ));
212     BOOST_STATIC_ASSERT(( brdm::test_const_iter  <rng_t, WORD const *>::value ));
213 
214     rng_t rng;
215     BOOST_CHECK( brdm::test_init_array(rng, sample) );
216     BOOST_CHECK( brdm::test_random_access(rng) );
217     BOOST_CHECK( brdm::test_emptiness(rng) );
218 }
219 
220 
221 // lists
222 //
223 
224 template< class Range >
test_CObList(const Range & sample)225 void test_CObList(const Range& sample)
226 {
227     typedef typename boost::range_value<Range>::type val_t;
228 
229     typedef ::CObList rng_t;
230 
231     BOOST_STATIC_ASSERT(( brdm::test_mutable_iter< rng_t, brdm::list_iterator<rng_t,       ::CObject *> >::value ));
232 #if !defined(BOOST_RANGE_MFC_CONST_COL_RETURNS_NON_REF)
233     BOOST_STATIC_ASSERT(( brdm::test_const_iter  < rng_t, brdm::list_iterator<rng_t const, ::CObject const *> >::value ));
234 #else
235     BOOST_STATIC_ASSERT(( brdm::test_const_iter  < rng_t, brdm::list_iterator<rng_t const, ::CObject const * const, ::CObject const * const> >::value ));
236 #endif
237 
238     rng_t rng;
239     BOOST_CHECK( brdm::test_init_list(rng, sample) );
240     BOOST_CHECK( brdm::test_bidirectional(rng) );
241     BOOST_CHECK( brdm::test_emptiness(rng) );
242 }
243 
244 
245 template< class Range >
test_CPtrList(const Range & sample)246 void test_CPtrList(const Range& sample)
247 {
248     typedef typename boost::range_value<Range>::type val_t;
249 
250     typedef ::CPtrList rng_t;
251 
252     BOOST_STATIC_ASSERT(( brdm::test_mutable_iter< rng_t, brdm::list_iterator<rng_t,       void *> >::value ));
253 #if !defined(BOOST_RANGE_MFC_CONST_COL_RETURNS_NON_REF)
254     BOOST_STATIC_ASSERT(( brdm::test_const_iter  < rng_t, brdm::list_iterator<rng_t const, void const *> >::value ));
255 #else
256     BOOST_STATIC_ASSERT(( brdm::test_const_iter  < rng_t, brdm::list_iterator<rng_t const, void const * const, void const * const> >::value ));
257 #endif
258 
259     rng_t rng;
260     BOOST_CHECK( brdm::test_init_list(rng, sample) );
261     BOOST_CHECK( brdm::test_bidirectional(rng) );
262     BOOST_CHECK( brdm::test_emptiness(rng) );
263 }
264 
265 
266 template< class Range >
test_CStringList(const Range & sample)267 void test_CStringList(const Range& sample)
268 {
269     typedef typename boost::range_value<Range>::type val_t;
270 
271     typedef ::CStringList rng_t;
272 
273     BOOST_STATIC_ASSERT(( brdm::test_mutable_iter< rng_t, brdm::list_iterator<rng_t,       ::CString> >::value ));
274 #if !defined(BOOST_RANGE_MFC_CONST_COL_RETURNS_NON_REF)
275     BOOST_STATIC_ASSERT(( brdm::test_const_iter  < rng_t, brdm::list_iterator<rng_t const, ::CString const> >::value ));
276 #else
277     BOOST_STATIC_ASSERT(( brdm::test_const_iter  < rng_t, brdm::list_iterator<rng_t const, ::CString const, ::CString const> >::value ));
278 #endif
279 
280     rng_t rng;
281     BOOST_CHECK( brdm::test_init_list(rng, sample) );
282     BOOST_CHECK( brdm::test_bidirectional(rng) );
283     BOOST_CHECK( brdm::test_emptiness(rng) );
284 }
285 
286 
287 // maps
288 //
289 
290 template< class MapT >
test_CMapPtrToWord(const MapT & sample)291 void test_CMapPtrToWord(const MapT& sample)
292 {
293     typedef ::CMapPtrToWord rng_t;
294 
295     rng_t rng;
296     boost::function_requires< boost::ForwardRangeConcept<rng_t> >();
297     BOOST_CHECK( brdm::test_init_map(rng, sample) );
298     BOOST_CHECK( ::test_mfc_map(rng, sample) );
299     BOOST_CHECK( brdm::test_emptiness(rng) );
300 }
301 
302 
303 template< class MapT >
test_CMapPtrToPtr(const MapT & sample)304 void test_CMapPtrToPtr(const MapT& sample)
305 {
306     typedef ::CMapPtrToPtr rng_t;
307 
308     rng_t rng;
309     boost::function_requires< boost::ForwardRangeConcept<rng_t> >();
310     BOOST_CHECK( brdm::test_init_map(rng, sample) );
311     BOOST_CHECK( ::test_mfc_map(rng, sample) );
312     BOOST_CHECK( brdm::test_emptiness(rng) );
313 }
314 
315 
316 template< class MapT >
test_CMapStringToOb(const MapT & sample)317 void test_CMapStringToOb(const MapT& sample)
318 {
319     typedef ::CMapStringToOb rng_t;
320 
321     rng_t rng;
322     boost::function_requires< boost::ForwardRangeConcept<rng_t> >();
323     BOOST_CHECK( brdm::test_init_map(rng, sample) );
324     BOOST_CHECK( ::test_mfc_map(rng, sample) );
325     BOOST_CHECK( brdm::test_emptiness(rng) );
326 }
327 
328 
329 template< class MapT >
test_CMapStringToPtr(const MapT & sample)330 void test_CMapStringToPtr(const MapT& sample)
331 {
332     typedef ::CMapStringToPtr rng_t;
333 
334     rng_t rng;
335     boost::function_requires< boost::ForwardRangeConcept<rng_t> >();
336     BOOST_CHECK( brdm::test_init_map(rng, sample) );
337     BOOST_CHECK( ::test_mfc_map(rng, sample) );
338     BOOST_CHECK( brdm::test_emptiness(rng) );
339 }
340 
341 
342 template< class MapT >
test_CMapStringToString(const MapT & sample)343 void test_CMapStringToString(const MapT& sample)
344 {
345     typedef ::CMapStringToString rng_t;
346 
347     rng_t rng;
348     boost::function_requires< boost::ForwardRangeConcept<rng_t> >();
349     BOOST_CHECK( brdm::test_init_map(rng, sample) );
350 #if !defined(BOOST_RANGE_MFC_NO_CPAIR)
351     BOOST_CHECK( ::test_mfc_cpair_map(rng, sample) );
352 #endif
353     BOOST_CHECK( brdm::test_emptiness(rng) );
354 }
355 
356 
357 template< class MapT >
test_CMapWordToOb(const MapT & sample)358 void test_CMapWordToOb(const MapT& sample)
359 {
360     typedef ::CMapWordToOb rng_t;
361 
362     rng_t rng;
363     boost::function_requires< boost::ForwardRangeConcept<rng_t> >();
364     BOOST_CHECK( brdm::test_init_map(rng, sample) );
365     BOOST_CHECK( ::test_mfc_map(rng, sample) );
366     BOOST_CHECK( brdm::test_emptiness(rng) );
367 }
368 
369 
370 template< class MapT >
test_CMapWordToPtr(const MapT & sample)371 void test_CMapWordToPtr(const MapT& sample)
372 {
373     typedef ::CMapWordToPtr rng_t;
374 
375     rng_t rng;
376     boost::function_requires< boost::ForwardRangeConcept<rng_t> >();
377     BOOST_CHECK( brdm::test_init_map(rng, sample) );
378     BOOST_CHECK( ::test_mfc_map(rng, sample) );
379     BOOST_CHECK( brdm::test_emptiness(rng) );
380 }
381 
382 
383 // templates
384 //
385 
386 template< class Range >
test_CArray(const Range & sample)387 void test_CArray(const Range& sample)
388 {
389     typedef typename boost::range_value<Range>::type val_t;
390 
391     typedef ::CArray<val_t, const val_t&> rng_t; // An old MFC needs the second template argument.
392     BOOST_STATIC_ASSERT(( brdm::test_mutable_iter<rng_t, val_t *>::value ));
393     BOOST_STATIC_ASSERT(( brdm::test_const_iter  <rng_t, val_t const*>::value ));
394 
395     rng_t rng;
396     BOOST_CHECK( brdm::test_init_array(rng, sample) );
397     BOOST_CHECK( brdm::test_random_access(rng) );
398     BOOST_CHECK( brdm::test_emptiness(rng) );
399 }
400 
401 
402 template< class Range >
test_CList(const Range & sample)403 void test_CList(const Range& sample)
404 {
405     typedef typename boost::range_value<Range>::type val_t;
406 
407     typedef ::CList<val_t, const val_t&> rng_t;
408 
409     BOOST_STATIC_ASSERT(( brdm::test_mutable_iter< rng_t, brdm::list_iterator<rng_t,       val_t> >::value ));
410 #if !defined(BOOST_RANGE_MFC_CONST_COL_RETURNS_NON_REF)
411     BOOST_STATIC_ASSERT(( brdm::test_const_iter  < rng_t, brdm::list_iterator<rng_t const, val_t const> >::value ));
412 #else
413     BOOST_STATIC_ASSERT(( brdm::test_const_iter  < rng_t, brdm::list_iterator<rng_t const, val_t const, val_t const> >::value ));
414 #endif
415 
416     rng_t rng;
417     BOOST_CHECK( brdm::test_init_list(rng, sample) );
418     BOOST_CHECK( brdm::test_bidirectional(rng) );
419     BOOST_CHECK( brdm::test_emptiness(rng) );
420 }
421 
422 
423 template< class MapT >
test_CMap(const MapT & sample)424 void test_CMap(const MapT& sample)
425 {
426     typedef typename MapT::key_type k_t;
427     typedef typename MapT::mapped_type m_t;
428 
429     typedef ::CMap<k_t, const k_t&, m_t, const m_t&> rng_t;
430 
431     rng_t rng;
432     boost::function_requires< boost::ForwardRangeConcept<rng_t> >();
433     BOOST_CHECK( brdm::test_init_map(rng, sample) );
434 #if !defined(BOOST_RANGE_MFC_NO_CPAIR)
435     BOOST_CHECK( ::test_mfc_cpair_map(rng, sample) );
436 #endif
437     BOOST_CHECK( brdm::test_emptiness(rng) );
438 }
439 
440 
test_CTypedPtrArray()441 void test_CTypedPtrArray()
442 {
443     typedef ::CTypedPtrArray< ::CPtrArray, int * > rng_t;
444     boost::function_requires< boost::RandomAccessRangeConcept<rng_t> >();
445 
446     rng_t rng;
447     int o1, o2, o3, o4, o5;
448     int *data[] = { &o1, &o2, &o3, &o4, &o5 };
449     BOOST_CHECK( brdm::test_init_array(rng, boost::make_iterator_range(data, data+5)) );
450 
451     BOOST_CHECK( *(boost::begin(rng) + 2) == &o3 );
452     BOOST_CHECK( *(boost::end(rng) - 1) == &o5 );
453 
454     // BOOST_CHECK( brdm::test_random_access(rng) ); this range is not mutable
455     BOOST_CHECK( brdm::test_emptiness(rng) );
456 }
457 
458 
test_CTypedPtrList()459 void test_CTypedPtrList()
460 {
461     typedef ::CTypedPtrList< ::CObList, ::CObList * > rng_t;
462     boost::function_requires< boost::BidirectionalRangeConcept<rng_t> >();
463 
464     rng_t rng;
465 
466     ::CObList o1, o2, o3, o4, o5;
467     ::CObList *data[] = { &o1, &o2, &o3, &o4, &o5 };
468     BOOST_CHECK( brdm::test_init_list(rng, data) );
469 
470     boost::range_iterator<rng_t>::type it = boost::begin(rng);
471     std::advance(it, 1);
472     BOOST_CHECK( *it == &o2 );
473     std::advance(it, 2);
474     BOOST_CHECK( *it == &o4 );
475 
476     // BOOST_CHECK( brdm::test_bidirectional(rng) ); this range is not mutable
477     BOOST_CHECK( brdm::test_emptiness(rng) );
478 }
479 
480 
test_CTypedPtrMap()481 void test_CTypedPtrMap()
482 {
483     typedef ::CTypedPtrMap< ::CMapStringToPtr, ::CString, int *> rng_t;
484     boost::function_requires< boost::ForwardRangeConcept<rng_t> >();
485 
486     rng_t rng;
487     ::CString o0(_T('a')), o1(_T('c')), o2(_T('f')), o3(_T('q')), o4(_T('g'));
488     int d0, d1, d2, d3, d4;
489     std::map< ::CString, int * > data;
490     data[o0] = &d0, data[o1] = &d1, data[o2] = &d2, data[o3] = &d3, data[o4] = &d4;
491 
492     BOOST_CHECK( brdm::test_init_map(rng, data) );
493     BOOST_CHECK( ::test_mfc_map(rng, data) );
494     BOOST_CHECK( brdm::test_emptiness(rng) );
495 }
496 
497 
498 // strings
499 //
500 #if defined(BOOST_RANGE_MFC_HAS_LEGACY_STRING)
501 
502     template< class Range >
test_CString(const Range & sample)503     void test_CString(const Range& sample)
504     {
505         typedef typename boost::range_value<Range>::type val_t;
506 
507         typedef ::CString rng_t; // An old MFC needs the second template argument.
508         BOOST_STATIC_ASSERT(( brdm::test_mutable_iter<rng_t, TCHAR *>::value ));
509         BOOST_STATIC_ASSERT(( brdm::test_const_iter  <rng_t, TCHAR const*>::value ));
510 
511         rng_t rng;
512         BOOST_CHECK( brdm::test_init_string(rng, sample) );
513         BOOST_CHECK( brdm::test_random_access(rng) );
514         BOOST_CHECK( brdm::test_emptiness(rng) );
515     }
516 
517 #endif
518 
519 
520 struct CPerson
521 {
hello_rangeCPerson522     void hello_range() { };
523 };
524 
525 
test_mfc()526 void test_mfc()
527 {
528 #if 0
529     // overview
530     //
531     {
532         CTypedPtrArray<CPtrArray, CList<CString> *> myArray;
533         // ...
534         BOOST_FOREACH (CList<CString> *theList, myArray)
535         {
536             BOOST_FOREACH (CString& str, *theList)
537             {
538                 boost::to_upper(str);
539                 std::sort(boost::begin(str), boost::end(str));
540                 // ...
541             }
542         }
543     }
544 #endif
545 
546     // arrays
547     //
548     {
549         BYTE data[] = { 4,5,1,3,5,12,3,1,3,1,6,1,3,60,1,1,5,1,3,1,10 };
550 
551         ::test_CByteArray(boost::make_iterator_range(data, data+22));
552     }
553 
554     {
555         DWORD data[] = { 4,5,1,3,5,12,3,1,3,1,6,1,3,60,1,1,5,1,3,1,10 };
556 
557         test_CDWordArray(boost::make_iterator_range(data, data+22));
558     }
559 
560     {
561         ::CObArray o1, o2, o3, o4, o5;
562         ::CObject *data[] = { &o1, &o2, &o3, &o4, &o5 };
563 
564         ::test_CObArray(boost::make_iterator_range(data, data+5));
565     }
566 
567     {
568         ::CPtrArray o1, o2, o3, o4, o5;
569         void *data[] = { &o1, &o2, &o3, &o4, &o5 };
570 
571         ::test_CPtrArray(boost::make_iterator_range(data, data+5));
572     }
573 
574     {
575         ::CString data[] = {
576             ::CString(_T('0')), ::CString(_T('1')), ::CString(_T('2')), ::CString(_T('3')),
577             ::CString(_T('4')), ::CString(_T('5')), ::CString(_T('6')), ::CString(_T('7'))
578         };
579 
580         ::test_CStringArray(boost::make_iterator_range(data, data+8));
581     }
582 
583     {
584         ::CUIntArray rng;
585         UINT data[] = { 4,5,1,3,5,12,3,1,3,1,6,1,3,60,1,1,5,1,3,1,10 };
586 
587         ::test_CUIntArray(boost::make_iterator_range(data, data+22));
588     }
589 
590     {
591         ::CWordArray rng;
592         WORD data[] = { 4,5,1,3,5,12,3,1,3,1,6,1,3,60,1,1,5,1,3,1,10 };
593 
594         ::test_CWordArray(boost::make_iterator_range(data, data+22));
595     }
596 
597 
598     // lists
599     //
600     {
601         ::CObList rng;
602         ::CObList o1, o2, o3, o4, o5;
603         ::CObject *data[] = { &o1, &o2, &o3, &o4, &o5 };
604 
605         ::test_CObList(boost::make_iterator_range(data, data+5));
606     }
607 
608     {
609         ::CPtrList rng;
610         ::CPtrList o1, o2, o3, o4, o5;
611         void *data[] = { &o1, &o2, &o3, &o4, &o5 };
612 
613         ::test_CPtrList(boost::make_iterator_range(data, data+5));
614     }
615 
616     {
617         ::CString data[] = {
618             ::CString(_T('0')), ::CString(_T('1')), ::CString(_T('2')), ::CString(_T('3')),
619             ::CString(_T('4')), ::CString(_T('5')), ::CString(_T('6')), ::CString(_T('7'))
620         };
621 
622         ::test_CStringList(boost::make_iterator_range(data, data+8));
623     }
624 
625 
626     // maps
627     //
628     {
629         std::map<void *, WORD> data;
630         int o0, o1, o2, o3, o4;
631         data[&o0] = 15, data[&o1] = 14, data[&o2] = 3, data[&o3] = 6, data[&o4] = 1;
632 
633         ::test_CMapPtrToWord(data);
634     }
635 
636     {
637         std::map<void *, void*> data;
638         int o0, o1, o2, o3, o4;
639         data[&o0] = &o3, data[&o1] = &o2, data[&o2] = &o1, data[&o3] = &o0, data[&o4] = &o4;
640 
641         ::test_CMapPtrToPtr(data);
642     }
643 
644     {
645         std::map< ::CString, CObject * > data;
646         CObArray o0, o1, o2, o3, o4;
647         data[ ::CString('0') ] = &o0, data[ ::CString('1') ] = &o1, data[ ::CString('2') ] = &o2,
648         data[ ::CString('3') ] = &o3, data[ ::CString('4') ] = &o4;
649 
650         ::test_CMapStringToOb(data);
651     }
652 
653     {
654         std::map< ::CString, void * > data;
655         CObArray o0, o1, o2, o3, o4;
656         data[ ::CString('0') ] = &o0, data[ ::CString('1') ] = &o1, data[ ::CString('2') ] = &o2,
657         data[ ::CString('3') ] = &o3, data[ ::CString('4') ] = &o4;
658 
659         ::test_CMapStringToPtr(data);
660     }
661 
662     {
663         std::map< ::CString, ::CString > data;
664         CString o0('a'), o1('b'), o2('c'), o3('d'), o4('e');
665         data[ ::CString('0') ] = o0, data[ ::CString('1') ] = o1, data[ ::CString('2') ] = o2,
666         data[ ::CString('3') ] = o3, data[ ::CString('4') ] = o4;
667 
668         ::test_CMapStringToString(data);
669     }
670 
671     {
672         std::map< WORD, CObject * > data;
673         ::CDWordArray o0, o1, o2, o3, o4;
674         data[21] = &o3, data[52] = &o2, data[12] = &o1, data[76] = &o0, data[54] = &o4;
675 
676         ::test_CMapWordToOb(data);
677     }
678 
679     {
680         std::map< WORD, void * > data;
681         ::CDWordArray o0, o1, o2, o3, o4;
682         data[21] = &o3, data[52] = &o2, data[12] = &o1, data[76] = &o0, data[54] = &o4;
683 
684         ::test_CMapWordToPtr(data);
685     }
686 
687     // templates
688     //
689     {
690         std::string data("0987654321qwertyuiop");
691         ::test_CArray(data);
692         ::test_CList(data);
693     }
694 
695     {
696         std::wstring data(L"asdfghjklzxcvbnm");
697         ::test_CArray(data);
698         ::test_CList(data);
699     }
700 
701     {
702         std::map< int, std::string > data;
703         data[0] = "abcde", data[1] = "ajfie", data[2] = "lij", data[3] = "abc", data[4] = "ioiu";
704 
705         ::test_CMap(data);
706     }
707 
708 
709     // typed
710     //
711     {
712         ::test_CTypedPtrArray();
713         ::test_CTypedPtrList();
714         ::test_CTypedPtrMap();
715     }
716 
717 
718     // strings
719     //
720 #if defined(BOOST_RANGE_MFC_HAS_LEGACY_STRING)
721     {
722         std::string data("123456789 abcdefghijklmn");
723         ::test_CString(data);
724     }
725 #endif
726 
727 
728 } // test_mfc
729 
730 
731 #include <boost/test/unit_test.hpp>
732 using boost::unit_test::test_suite;
733 
734 
735 test_suite *
init_unit_test_suite(int argc,char * argv[])736 init_unit_test_suite(int argc, char* argv[])
737 {
738     test_suite *test = BOOST_TEST_SUITE("MFC Range Test Suite");
739     test->add(BOOST_TEST_CASE(&test_mfc));
740 
741     (void)argc, (void)argv; // unused
742     return test;
743 }
744