1#!/bin/sh
2#
3# aegis - project change supervisor.
4# Copyright (C) 2008, 2011, 2012 Peter Miller
5#
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 3 of the License, or (at
9# your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14# General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License along
17# with this program. If not, see <http://www.gnu.org/licenses/>.
18#
19
20TEST_SUBJECT="fmtgen strings"
21
22# load up standard prelude and test functions
23. test_funcs
24
25#
26# test the functionality
27#
28activity="fmtgen, strings, incl"
29cat > test.def << 'fubar'
30/*
31 * This is a string.
32 */
33fred = string;
34fubar
35test $? -eq 0 || no_result
36
37cat > test.fmtgen.h.ok << 'fubar'
38//
39// This file is generated by fmtgen.
40//
41
42#ifndef TEST_FMTGEN_H
43#define TEST_FMTGEN_H
44#include <libaegis/introspector.h>
45#include <libaegis/output.h>
46
47#ifndef test_DEF
48#define test_DEF
49
50/**
51* The test class is used to represent ''test'' formatted Aegis meta-data.
52* See aetest(5) for more information.
53*/
54class test
55{
56public:
57    /**
58    * The pointer typedef is used to have a pointer type which may be used
59    * by clients of this API, allowing the pointer implementation to be
60    * changed without extensive code changes throughout the rest of the
61    * code base.
62    */
63    typedef aegis_shared_ptr<test> pointer;
64
65    /**
66    * The destructor.
67    */
68    virtual ~test();
69
70private:
71    /**
72    * The default constructor. It is private on purpose, use the #create
73    * class method instead.
74    */
75    test();
76
77public:
78    /**
79    * The create class method is used to create new dynamically allocated
80    * instances of this class.
81    */
82    static pointer create();
83
84private:
85    /**
86    * The copy constructor. It is private on purpose, use the #create class
87    * method instead.
88    *
89    * @param rhs
90    *     The right hand side of the initialization.
91    */
92    test(const test &rhs);
93
94public:
95    /**
96    * The create class method is used to create new dynamically allocated
97    * instances of this class.
98    *
99    * @param rhs
100    *     The right hand side of the initialization.
101    */
102    static pointer create(const test &rhs);
103
104    /**
105    * The assignment operator.
106    *
107    * @param rhs
108    *     The right hand side of the assignment.
109    */
110    test &operator=(const test &rhs);
111
112private:
113    /**
114    * This is a string.
115    */
116    nstring fred;
117
118public:
119    /**
120    * The fred_get method is used to obtain the value of the fred instance
121    * variable, or the default if it has not been set.
122    */
123    nstring fred_get() const;
124
125    /**
126    * The fred_is_set method is used to determine whether or not the fred
127    * instance variable has been set.
128    */
129    bool fred_is_set() const;
130
131    /**
132    * The fred_set method is used to set the value of the #fred instance
133    * variable, and record that it has been set.
134    */
135    void fred_set(const nstring &value);
136
137    /**
138    * The fred_clear method is used to reset the the #fred instance
139    * variable to its default value, and record that it is no longer set.
140    */
141    void fred_clear();
142
143    /**
144    * The fred_introspector_factory method is used to obtain an
145    * introspector for the #fred instance variable.
146    */
147    introspector::pointer fred_introspector_factory();
148
149public:
150    /**
151    * The introspector_factory method is used to create an introspector for
152    * this class and instance, usually used with the meta-data parser when
153    * reading the contents of a meta-data file.
154    */
155    introspector::pointer introspector_factory();
156
157    /**
158    * The write method is used to write this structure's contents to the
159    * given output.
160    *
161    * @param fp
162    *     Where to write the output.
163    */
164    void write(const output::pointer &fp) const;
165
166    /**
167    * The write_xml method is used to write this structure's contents to
168    * the given output as XML.
169    *
170    * @param fp
171    *     Where to write the output.
172    */
173    void write_xml(const output::pointer &fp) const;
174
175    /**
176    * The trace_print method is used by the trace_test macro to print an
177    * object of this type.
178    *
179    * @param name
180    *     The name of the variable being printed.
181    */
182    void trace_print(const char *name) const;
183
184    /**
185    * The create_from_file class method is used to read the given file to
186    * create a new dynamically allocated instance of this class.
187    *
188    * @param filename
189    *     The name of the file to be read.
190    * @note
191    *     If any errors are encountered, this method will not return. All
192    *     errors will print a fatal error message, and exit with an exit
193    *     status of 1.
194    */
195    static pointer create_from_file(const nstring &filename);
196
197    /**
198    * The write_file method is used to write the data to the named file,
199    * via the #write method.
200    *
201    * @param filename
202    *     The name of the file to be written.
203    * @param compress
204    *     true if data should be compressed, false if not.
205    * @note
206    *     If any errors are encountered, this method will not return. All
207    *     errors will print a fatal error message, and exit with an exit
208    *     status of 1.
209    */
210    void write_file(const nstring &filename, bool compress) const;
211
212    /**
213    * The report_init class method is used to initialize the report
214    * generator with the names and values of enumerations used by this
215    * meta-data.
216    */
217    static void report_init();
218};
219
220/**
221* The test_trace macro is used to conditionally print a trace of a test
222* value, if the DEBUG macro is defined.
223*/
224#include <common/debug.h>
225#ifndef test_trace
226#ifdef DEBUG
227#define test_trace(x) ((void)(trace_pretest_ && (trace_where_, (x).trace_print(trace_stringize(x)), 0)))
228#else
229#define test_trace(x)
230#endif
231#endif
232
233#endif // test_DEF
234
235#endif // TEST_FMTGEN_H
236fubar
237test $? -eq 0 || no_result
238
239fmtgen -ii test.fmtgen.h test.def
240if test $? -ne 0 ; then fail; fi
241
242diff test.fmtgen.h.ok test.fmtgen.h
243if test $? -ne 0 ; then fail; fi
244
245activity="fmtgen, strings, code"
246cat > test.fmtgen.cc.ok << 'fubar'
247//
248// This file is generated by fmtgen.
249//
250#include <test.fmtgen.h>
251#include <libaegis/introspector/nstring.h>
252#include <common/ac/assert.h>
253#include <common/trace.h>
254
255test::~test()
256{
257    trace(("%s\n", __PRETTY_FUNCTION__));
258}
259
260test::test() :
261    fred()
262{
263    trace(("%s\n", __PRETTY_FUNCTION__));
264}
265
266test::pointer
267test::create()
268{
269    trace(("%s\n", __PRETTY_FUNCTION__));
270    return pointer(new test());
271}
272
273test::test(const test &rhs) :
274    fred(rhs.fred)
275{
276    trace(("%s\n", __PRETTY_FUNCTION__));
277}
278
279test::pointer
280test::create(const test &rhs)
281{
282    trace(("%s\n", __PRETTY_FUNCTION__));
283    return pointer(new test(rhs));
284}
285
286test &
287test::operator=(const test &rhs)
288{
289    trace(("%s\n", __PRETTY_FUNCTION__));
290    if (this != &rhs)
291    {
292        fred = rhs.fred;
293    }
294    return *this;
295}
296
297nstring
298test::fred_get()
299    const
300{
301    return fred;
302}
303
304bool
305test::fred_is_set()
306    const
307{
308    return !fred.empty();
309}
310
311void
312test::fred_set(const nstring &value_)
313{
314    fred = value_;
315}
316
317void
318test::fred_clear()
319{
320    fred.clear();
321}
322
323introspector::pointer
324test::fred_introspector_factory()
325{
326    return introspector_nstring::create(fred);
327}
328#include <libaegis/introspector/structure.h>
329
330introspector::pointer
331test::introspector_factory()
332{
333    trace(("%s\n", __PRETTY_FUNCTION__));
334    introspector_structure::pointer ip =
335        introspector_structure::create("test");
336    ip->register_member ( "fred", introspector_structure::adapter_by_method
337        < test > ::create ( this, &test::fred_introspector_factory,
338            &test::fred_is_set));
339    return ip;
340};
341
342void
343test::write(const output::pointer &fp)
344    const
345{
346    trace(("%s\n{\n", __PRETTY_FUNCTION__));
347    introspector_nstring::write(fp, "fred", fred, false);
348    trace(("}\n"));
349}
350
351void
352test::write_xml(const output::pointer &fp)
353    const
354{
355    trace(("%s\n{\n", __PRETTY_FUNCTION__));
356    fp->fputs("<test>\n");
357    introspector_nstring::write_xml(fp, "fred", fred);
358    fp->fputs("</test>\n");
359    trace(("}\n"));
360}
361
362void
363test::trace_print(const char *name_)
364    const
365{
366    if (name_ && *name_)
367    {
368        trace_printf("%s = ", name_);
369    }
370    trace_printf("{\n");
371    trace_string_real("fred", fred);
372    trace_printf("}");
373    trace_printf((name_ && *name_) ? ";\n" : ",\n");
374}
375#include <libaegis/meta_context/introspector.h>
376#include <libaegis/os.h>
377
378test::pointer
379test::create_from_file(const nstring &filename)
380{
381    trace(("%s\n{\n", __PRETTY_FUNCTION__));
382    pointer p = create();
383    introspector::pointer ip = p->introspector_factory();
384    meta_context_introspector meta;
385    os_become_must_be_active();
386    meta.parse_file(filename, ip);
387    trace(("}\n"));
388    return p;
389}
390#include <libaegis/io.h>
391#include <libaegis/output/file.h>
392#include <libaegis/output/filter/gzip.h>
393#include <libaegis/output/filter/indent.h>
394
395void
396test::write_file(const nstring &filename, bool needs_compression)
397    const
398{
399    trace(("%s\n{\n", __PRETTY_FUNCTION__));
400    if (filename)
401        os_become_must_be_active();
402    output::pointer fp = (needs_compression ?
403        output_filter_gzip::create(output_file::binary_open(filename)) :
404        output_file::text_open(filename));
405    fp = output_filter_indent::create(fp);
406    io_comment_emit(fp);
407    write(fp);
408    type_enum_option_clear();
409    trace(("}\n"));
410}
411
412void
413test::report_init(void)
414{
415    trace(("%s\n{\n", __PRETTY_FUNCTION__));
416    trace(("}\n"));
417}
418fubar
419test $? -eq 0 || no_result
420
421fmtgen -ic test.fmtgen.cc test.def
422if test $? -ne 0 ; then fail; fi
423
424diff test.fmtgen.cc.ok test.fmtgen.cc
425if test $? -ne 0 ; then fail; fi
426
427#
428# Only definite negatives are possible.
429# The functionality exercised by this test appears to work,
430# no other guarantees are made.
431#
432pass
433
434
435// vim: set ts=8 sw=4 et :
436