~ubuntu-branches/ubuntu/karmic/openoffice.org-l10n/karmic

« back to all changes in this revision

Viewing changes to ooo-build/scratch/sc-dptest/source/dpresulttester.cxx

  • Committer: Bazaar Package Importer
  • Author(s): Chris Cheney
  • Date: 2008-01-08 23:17:08 UTC
  • mfrom: (1.1.15 upstream)
  • Revision ID: james.westby@ubuntu.com-20080108231708-7f5yc4h021ikwgyz
Tags: 1:2.3.1-3ubuntu1
* Copy of the openoffice.org source.
  - debian/changelog: Change source name.
  - debian/control.in: Change source name.
  - debian/control: Regenerate control file.

* Resynchronise with Debian (r989). Remaining changes:
  - debian/broffice.org.postrm.in:
    . Change diversions to ubuntu bitmap filenames.
  - debian/broffice.org.preinst.in:
    . Change diversions to ubuntu bitmap filenames.
  - debian/control.2.in:
    . Add file for Ubuntu.
  - debian/control.in:
    . Change maintainer line.
    . Use imagemagick instead of graphicsmagick.
    . Change bzr repo location.
    . Use java-runtime-depends variable for java dependencies.
    . Make openoffice.org-core Depends on openoffice.org-hyphenation.
    . Add package openoffice.org-style-human.
    . Various other minor Ubuntu changes.
  - debian/control.l10n.in:
    . Add file for Ubuntu.
  - debian/control.lang.in:
    . Add L10N_COMMON to Depends.
  - debian/control.mozilla.in:
    . Add Xb-Npp-xxx tags according to "firefox distro add-on suport" spec.
  - debian/control.ubuntu.in:
    . Add file for Ubuntu.
  - debian/deppackage.postinst.in:
    . Add file for Ubuntu.
  - debian/module-po.map:
    . Add file for Ubuntu.
  - debian/ooo-build-ubuntu.diff:
    . Various Ubuntu specific changes to ooo-build.
  - debian/rules:
    . Add USE_LZMA_COMPRESS option.
    . Add USE_COMMON_DOCDIR option.
    . Add support to build on lpia.
    . Add support to build l10n as a separate source.
    . Add java-runtime-depends variable for java dependencies.
    . Add support to chmod +x programs in debian dir.
    . Add support to uuencode binary files in ubuntu dir.
    . Add support to Ubuntu specific bitmaps.
    . Use imagemagick instead of graphicsmagick.
    . Add support for openoffice.org-style-human package.
    . Add support for launchpad translations.
    . Various Ubuntu specific changes.
  - debian/scripts/convert2po:
    . Add file for Ubuntu.
  - debian/scripts/fix_image_rgb:
    . Use imagemagick instead of graphicsmagick.
  - debian/scripts/gsifilter.py:
    . Add file for Ubuntu.
  - debian/scripts/splitgsi:
    . Add file for Ubuntu.
  - debian/template.desktop.in:
    . Add NoDisplay=true.
  - ooo-build/configure.in:
    . Added support for Hardy.
  - ooo-build/distro-configs/UbuntuHardy.conf.in:
    . Added support for Hardy.
  - ooo-build/distro-configs/UbuntuHardy64.conf.in:
    . Added support for Hardy.
  - ooo-build/patches/src680/apply:
    . Added support for Hardy.
  - ooo-build/patches/src680/ubuntu-lpi.diff:
    . Updated patch.
  - ubuntu/*
    . Various Ubuntu specific changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
#include "dpresulttester.hxx"
 
3
 
 
4
#include <com/sun/star/beans/Property.hpp>
 
5
#include <com/sun/star/beans/XPropertySet.hpp>
 
6
#include <com/sun/star/beans/XPropertySetInfo.hpp>
 
7
#include <com/sun/star/container/XEnumeration.hpp>
 
8
#include <com/sun/star/container/XEnumerationAccess.hpp>
 
9
#include <com/sun/star/container/XIndexAccess.hpp>
 
10
#include <com/sun/star/container/XNamed.hpp>
 
11
#include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
 
12
#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
 
13
#include <com/sun/star/sheet/DataPilotFieldReference.hpp>
 
14
#include <com/sun/star/sheet/DataPilotFieldReferenceItemType.hpp>
 
15
#include <com/sun/star/sheet/DataPilotFieldReferenceType.hpp>
 
16
#include <com/sun/star/sheet/DataPilotTableRegion.hpp>
 
17
#include <com/sun/star/sheet/DataPilotTablePositionData.hpp>
 
18
#include <com/sun/star/sheet/DataPilotTablePositionType.hpp>
 
19
#include <com/sun/star/sheet/DataPilotTableResultData.hpp>
 
20
#include <com/sun/star/sheet/DataResultFlags.hpp>
 
21
#include <com/sun/star/sheet/GeneralFunction.hpp>
 
22
#include <com/sun/star/sheet/DataResult.hpp>
 
23
#include <com/sun/star/sheet/XDataPilotDescriptor.hpp>
 
24
#include <com/sun/star/sheet/XDataPilotField.hpp>
 
25
#include <com/sun/star/sheet/XDataPilotFieldGrouping.hpp>
 
26
#include <com/sun/star/sheet/XDataPilotTable2.hpp>
 
27
#include <com/sun/star/sheet/XDataPilotTable.hpp>
 
28
#include <com/sun/star/sheet/XDataPilotTables.hpp>
 
29
#include <com/sun/star/sheet/XDataPilotTablesSupplier.hpp>
 
30
#include <com/sun/star/sheet/XSheetFilterDescriptor.hpp>
 
31
#include <com/sun/star/sheet/XSpreadsheet.hpp>
 
32
#include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
 
33
#include <com/sun/star/sheet/XSpreadsheets.hpp>
 
34
#include <com/sun/star/table/CellAddress.hpp>
 
35
#include <com/sun/star/table/CellRangeAddress.hpp>
 
36
#include <com/sun/star/table/XCell.hpp>
 
37
#include <com/sun/star/table/CellContentType.hpp>
 
38
 
 
39
#include <stdio.h>
 
40
#include <cmath>
 
41
#include <vector>
 
42
#include <boost/shared_ptr.hpp>
 
43
#include <rtl/ustrbuf.hxx>
 
44
 
 
45
using namespace ::com::sun::star;
 
46
using namespace ::com::sun::star::uno;
 
47
using namespace ::com::sun::star::sheet;
 
48
 
 
49
using ::com::sun::star::container::XIndexAccess;
 
50
using ::com::sun::star::beans::Property;
 
51
using ::com::sun::star::beans::XPropertySet;
 
52
using ::com::sun::star::beans::XPropertySetInfo;
 
53
using ::com::sun::star::table::CellAddress;
 
54
using ::com::sun::star::table::CellRangeAddress;
 
55
using ::com::sun::star::table::XCell;
 
56
using ::com::sun::star::table::CellContentType;
 
57
using ::rtl::OUString;
 
58
using ::rtl::OUStringBuffer;
 
59
using ::std::vector;
 
60
using ::boost::shared_ptr;
 
61
 
 
62
namespace dptest {
 
63
 
 
64
ResultTester::DataFieldSetting::DataFieldSetting() : 
 
65
        FieldRef(static_cast<DataPilotFieldReference*>(NULL)) 
 
66
{
 
67
}
 
68
 
 
69
// ============================================================================
 
70
 
 
71
 
 
72
ResultTester::ResultTester(const RuntimeData& data, const Reference<XDataPilotTable2>& xDPTab) :
 
73
    maData(data), mxDPTab(xDPTab), mnFailureCount(0)
 
74
{
 
75
    init();
 
76
}
 
77
 
 
78
ResultTester::ResultTester(const ResultTester& other) :
 
79
    maData(other.maData), mxDPTab(other.mxDPTab), 
 
80
    maDataFieldSettings(other.maDataFieldSettings),
 
81
    mnFailureCount(other.mnFailureCount)
 
82
{
 
83
    init();
 
84
}
 
85
 
 
86
void ResultTester::init()
 
87
{
 
88
    Reference<XDataPilotDescriptor> xDPDesc(mxDPTab, UNO_QUERY_THROW);
 
89
 
 
90
    // Go though each data field
 
91
    Reference<container::XIndexAccess> xDataFields = xDPDesc->getDataFields();
 
92
    sal_Int32 fieldCount = xDataFields->getCount();
 
93
    maDataFieldSettings.reserve(fieldCount);
 
94
    for (sal_Int32 i = 0; i < fieldCount; ++i)
 
95
    {
 
96
        Reference<XDataPilotField> xField(xDataFields->getByIndex(i), UNO_QUERY_THROW);
 
97
        DataFieldSetting setting;
 
98
 
 
99
        // Get the field ID of a given data field.
 
100
        Reference<container::XNamed> xNamed(xField, UNO_QUERY_THROW);
 
101
        OUString name = xNamed->getName();
 
102
        setting.FieldId = maData.CacheTable.getFieldIndex(name);
 
103
 
 
104
        // Get the function used for aggregation.
 
105
        Reference<XPropertySet> xPS(xField, UNO_QUERY_THROW);
 
106
        getPropertyValue(xPS, ascii("Function"), setting.Function);
 
107
 
 
108
        // Get the referenced item information (if any).
 
109
        bool hasReference = false;
 
110
        getPropertyValue(xPS, ascii("HasReference"), hasReference);
 
111
        if (hasReference)
 
112
        {
 
113
            setting.FieldRef.reset(new DataPilotFieldReference);
 
114
            getPropertyValue(xPS, ascii("Reference"), *setting.FieldRef);
 
115
        }
 
116
        maDataFieldSettings.push_back(setting);
 
117
    }
 
118
}
 
119
 
 
120
void ResultTester::operator()(const CellAddress& cell)
 
121
{
 
122
    DataPilotTablePositionData posData = mxDPTab->getPositionData(cell);
 
123
 
 
124
    if (posData.PositionType != DataPilotTablePositionType::RESULT)
 
125
        // This cell doesn't belong to the result area.  Bail out.
 
126
        return;
 
127
 
 
128
    DataPilotTableResultData resData;
 
129
    if (!(posData.PositionData >>= resData))
 
130
        // For whatever reason unpacking of the result data failed.  Bail out.
 
131
        return;
 
132
 
 
133
    vector<DataTable::Filter> filters;
 
134
    sal_Int32 filterSize = resData.FieldFilters.getLength();
 
135
    filters.reserve(filterSize);
 
136
    for (sal_Int32 i = 0; i < filterSize; ++i)
 
137
    {
 
138
        sal_Int32 nFieldId = maData.CacheTable.getFieldIndex(resData.FieldFilters[i].FieldName);
 
139
 
 
140
        if (nFieldId >= 0)
 
141
        {
 
142
            DataTable::Filter filter;
 
143
            filter.FieldIndex = nFieldId;
 
144
            filter.MatchStrId = DataTable::getStringId(resData.FieldFilters[i].MatchValue);
 
145
            filters.push_back(filter);
 
146
        }
 
147
    }
 
148
 
 
149
    // ID only for the data field set, not the actual column ID.
 
150
    sal_Int32 nId = resData.DataFieldIndex; 
 
151
    const DataFieldSetting& setting = maDataFieldSettings.at(nId);
 
152
 
 
153
    if (setting.FieldRef.get())
 
154
    {
 
155
        // referenced item exists.
 
156
        switch (setting.FieldRef->ReferenceType)
 
157
        {
 
158
            case DataPilotFieldReferenceType::ITEM_DIFFERENCE:
 
159
            case DataPilotFieldReferenceType::ITEM_PERCENTAGE:
 
160
            case DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE:
 
161
            case DataPilotFieldReferenceType::RUNNING_TOTAL:
 
162
                verifyRefValue(cell, setting, filters, resData.Result);
 
163
            break;
 
164
 
 
165
            case DataPilotFieldReferenceType::ROW_PERCENTAGE:
 
166
            case DataPilotFieldReferenceType::COLUMN_PERCENTAGE:
 
167
            case DataPilotFieldReferenceType::TOTAL_PERCENTAGE:
 
168
                verifyPercentValue(cell, setting, filters, resData.Result);
 
169
            break;
 
170
            case DataPilotFieldReferenceType::INDEX:
 
171
            break;
 
172
        }
 
173
    }
 
174
    else
 
175
    {
 
176
        // normal display mode with no reference
 
177
 
 
178
        Reference<XCell> xCell = maData.OutputSheetRef->getCellByPosition(cell.Column, cell.Row);
 
179
        if (xCell->getType() != table::CellContentType_VALUE)
 
180
        {
 
181
            fprintf(stdout, "Error: cell not value (%ld, %ld)\n", cell.Row, cell.Column);
 
182
            fail();
 
183
            return;
 
184
        }
 
185
 
 
186
        // This ID is the actual column ID of the data field.
 
187
        const sal_Int32 nFieldId = setting.FieldId;
 
188
        const sheet::GeneralFunction func = setting.Function;
 
189
        double val1 = xCell->getValue();
 
190
        double val2 = maData.CacheTable.aggregateValue(filters, nFieldId, func);
 
191
        if (val1 != val2)
 
192
        {
 
193
            fprintf(stdout, "Error: values differ (%ld, %ld) : real value = %g  check value = %g (%s)\n", 
 
194
                    cell.Row, cell.Column,
 
195
                    val1, val2, getFunctionName(func).c_str());
 
196
            fflush(stdout);
 
197
            fail();
 
198
        }
 
199
    }
 
200
}
 
201
 
 
202
sal_Int16 ResultTester::getFailureCount() const
 
203
{
 
204
    return mnFailureCount;
 
205
}
 
206
 
 
207
void ResultTester::verifyRefValue(const CellAddress& cell, 
 
208
                                  const DataFieldSetting& setting, 
 
209
                                  const vector<DataTable::Filter>& filters,
 
210
                                  const DataResult& result)
 
211
{
 
212
    Reference<XCell> xCell = maData.OutputSheetRef->getCellByPosition(cell.Column, cell.Row);
 
213
    table::CellContentType cellType = xCell->getType();
 
214
    double valCell = xCell->getValue();
 
215
 
 
216
    CellRangeAddress resRange = mxDPTab->getOutputRangeByType(DataPilotTableRegion::RESULT);
 
217
    bool isRowSubtotal = (result.Flags & DataResultFlags::SUBTOTAL) && (resRange.EndColumn == cell.Column);
 
218
    bool isColSubtotal = (result.Flags & DataResultFlags::SUBTOTAL) && (resRange.EndRow == cell.Row);
 
219
 
 
220
    const DataPilotFieldReference& ref = *setting.FieldRef;
 
221
    sal_Int32 refFieldId = maData.CacheTable.getFieldIndex(ref.ReferenceField);
 
222
    DataPilotFieldOrientation refOrient = maData.FieldOrientations.at(refFieldId);
 
223
 
 
224
    if (refOrient == DataPilotFieldOrientation_COLUMN && isRowSubtotal && 
 
225
        cellType == table::CellContentType_EMPTY)
 
226
        // This is expected.
 
227
        return;
 
228
 
 
229
    if (refOrient == DataPilotFieldOrientation_ROW && isColSubtotal && 
 
230
        cellType == table::CellContentType_EMPTY)
 
231
        // This is also expected.
 
232
        return;
 
233
 
 
234
    const sal_Int32 nFieldId = setting.FieldId;
 
235
    const sheet::GeneralFunction func = setting.Function;
 
236
 
 
237
    // Obtain the aggregate value with the original filter set.
 
238
    double valOrig = maData.CacheTable.aggregateValue(filters, nFieldId, func);
 
239
 
 
240
    // Go through the filters and find the field that matches the referenced field, then
 
241
    // replace the match value with the referenced item name.
 
242
    vector<DataTable::Filter> filters2;
 
243
    vector<DataTable::Filter>::const_iterator itr = filters.begin(), itrEnd = filters.end();
 
244
    bool isRefItem = false;
 
245
    for (; itr != itrEnd; ++itr)
 
246
    {
 
247
        if (itr->FieldIndex == refFieldId)
 
248
        {
 
249
            // This is the referenced field.  Replace the match value with
 
250
            // the referenced item name.
 
251
            DataTable::Filter filter(*itr);
 
252
            sal_Int32 newStrId = DataTable::getStringId(ref.ReferenceItemName); 
 
253
            if (filter.MatchStrId == newStrId)
 
254
                isRefItem = true;
 
255
            else
 
256
                filter.MatchStrId = newStrId;
 
257
            filters2.push_back(filter);
 
258
        }
 
259
        else
 
260
            filters2.push_back(*itr);
 
261
    }
 
262
 
 
263
    double valRef = maData.CacheTable.aggregateValue(filters2, nFieldId, func);
 
264
 
 
265
    switch (ref.ReferenceType)
 
266
    {
 
267
        case DataPilotFieldReferenceType::NONE:
 
268
            /* no reference mode. */
 
269
            fprintf(stdout, "Error: reference type is set to NONE\n");
 
270
            fail();
 
271
            return;
 
272
 
 
273
        case DataPilotFieldReferenceType::ITEM_DIFFERENCE:
 
274
        {
 
275
            /* subtract the reference value and display the difference. */
 
276
 
 
277
            if (isRefItem && cellType == table::CellContentType_EMPTY)
 
278
                // the referenced item should be empty.
 
279
                return;
 
280
 
 
281
            if (valCell != valOrig - valRef)
 
282
            {
 
283
                fprintf(stdout, "Error: values differ (%ld, %ld) : real value = %g  check value %g - %g = %g (%s)\n",
 
284
                        cell.Row, cell.Column,
 
285
                        valCell, valOrig, valRef, valOrig - valRef,
 
286
                        getFunctionName(func).c_str());
 
287
                fail();
 
288
            }
 
289
            return;
 
290
        }
 
291
        case DataPilotFieldReferenceType::ITEM_PERCENTAGE:
 
292
        {
 
293
            /* each result is dividied by its reference value. */
 
294
 
 
295
            if (valRef == 0.0)
 
296
            {
 
297
                // This is division by zero.  The cell result should also be an error.
 
298
                if ((result.Flags & DataResultFlags::ERROR))
 
299
                    // This is expected.
 
300
                    fprintf(stdout, "Info: division by zero for referenced item (%s)\n",
 
301
                            getReferenceTypeName(ref.ReferenceType).c_str());
 
302
                else
 
303
                    fail();
 
304
 
 
305
                return;
 
306
            }
 
307
 
 
308
            double res = valOrig/valRef;
 
309
            if (!compare(valCell, res))
 
310
            {
 
311
                fprintf(stdout, "Error: values differ (%ld, %ld) : real value = %.10f  check value %g/%g = %.10f (%s)\n",
 
312
                        cell.Row, cell.Column,
 
313
                        valCell, valOrig, valRef, res,
 
314
                        getFunctionName(func).c_str());
 
315
                fail();
 
316
            }
 
317
            return;
 
318
        }
 
319
        case DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE:
 
320
        {
 
321
            /* from each result, its reference value is subtracted, and the
 
322
             * difference is further divided by the reference value. 
 
323
             */
 
324
 
 
325
            if (isRefItem && cellType == table::CellContentType_EMPTY)
 
326
                // the referenced item should be empty.
 
327
                return;
 
328
 
 
329
            double res = (valOrig-valRef)/valRef;
 
330
            if (!compare(valCell, res))
 
331
            {
 
332
                fprintf(stdout, "Error: values differ (%ld, %ld) : real value = %.10f  check value (%g-%g)/%g = %.10f (delta = %.10f) (%s)\n",
 
333
                        cell.Row, cell.Column,
 
334
                        valCell, valOrig, valRef, valRef, res, valCell-res,
 
335
                        getFunctionName(func).c_str());
 
336
                fail();
 
337
            }
 
338
            return;
 
339
        }
 
340
        case DataPilotFieldReferenceType::RUNNING_TOTAL:
 
341
        {
 
342
            /* Each result is added to the sum of the results for preceding
 
343
             * items in the base field, in the base field's sort order, and 
 
344
             * the total sum is shown.
 
345
             */
 
346
 
 
347
            fprintf(stdout, "* TEST CODE NOT IMPLEMENTED (%ld, %ld)\n", cell.Row, cell.Column);
 
348
            fail();
 
349
        }
 
350
        break;
 
351
        default:
 
352
            fprintf(stdout, "* UNKNOWN REFERENCE TYPE (%ld, %ld)\n",
 
353
                    cell.Row, cell.Column);
 
354
            fail();
 
355
    }
 
356
}
 
357
 
 
358
void ResultTester::verifyPercentValue(const ::com::sun::star::table::CellAddress& cell, 
 
359
                                      const DataFieldSetting& setting,
 
360
                                      const vector<DataTable::Filter>& filters,
 
361
                                      const DataResult& result)
 
362
{
 
363
    const sal_Int32 nFieldId = setting.FieldId;
 
364
    const sheet::GeneralFunction func = setting.Function;
 
365
    const DataPilotFieldReference& ref = *setting.FieldRef;
 
366
    sal_Int32 refFieldId = maData.CacheTable.getFieldIndex(ref.ReferenceField);
 
367
    DataPilotFieldOrientation refOrient = maData.FieldOrientations.at(refFieldId);
 
368
 
 
369
    // Obtain the aggregate value with the original filter set.
 
370
    double valOrig = maData.CacheTable.aggregateValue(filters, nFieldId, func);
 
371
 
 
372
    // Go through the filters and find the field that matches the referenced field, then
 
373
    // replace the match value with the referenced item name.
 
374
    vector<DataTable::Filter> filters2;
 
375
    vector<DataTable::Filter>::const_iterator itr = filters.begin(), itrEnd = filters.end();
 
376
    bool isRefItem = false;
 
377
    for (; itr != itrEnd; ++itr)
 
378
    {
 
379
        if (itr->FieldIndex == refFieldId)
 
380
        {
 
381
            // This is the referenced field.  Replace the match value with
 
382
            // the referenced item name.
 
383
            DataTable::Filter filter(*itr);
 
384
            sal_Int32 newStrId = DataTable::getStringId(ref.ReferenceItemName); 
 
385
            if (filter.MatchStrId == newStrId)
 
386
                isRefItem = true;
 
387
            else
 
388
                filter.MatchStrId = newStrId;
 
389
            filters2.push_back(filter);
 
390
        }
 
391
        else
 
392
            filters2.push_back(*itr);
 
393
    }
 
394
 
 
395
    Reference<XCell> xCell = maData.OutputSheetRef->getCellByPosition(cell.Column, cell.Row);
 
396
    table::CellContentType cellType = xCell->getType();
 
397
    double valCell = xCell->getValue();
 
398
 
 
399
    CellRangeAddress resRange = mxDPTab->getOutputRangeByType(DataPilotTableRegion::RESULT);
 
400
    bool isRowSubtotal = (result.Flags & DataResultFlags::SUBTOTAL) && (resRange.EndColumn == cell.Column);
 
401
    bool isColSubtotal = (result.Flags & DataResultFlags::SUBTOTAL) && (resRange.EndRow == cell.Row);
 
402
    double valRef = maData.CacheTable.aggregateValue(filters2, nFieldId, func);
 
403
 
 
404
    switch (ref.ReferenceType)
 
405
    {
 
406
        case DataPilotFieldReferenceType::ROW_PERCENTAGE:
 
407
        {
 
408
            // Each result is divided by the total result for its row in 
 
409
            // the DataPilot table. 
 
410
            fprintf(stdout, "* TEST CODE NOT IMPLEMENTED (%ld, %ld)\n", cell.Row, cell.Column);
 
411
            fail();
 
412
        }
 
413
        break;
 
414
        case DataPilotFieldReferenceType::COLUMN_PERCENTAGE:
 
415
        {
 
416
            // Same as DataPilotFieldReferenceType::ROW_PERCENTAGE , but the total 
 
417
            // for the result's column is used. 
 
418
            fprintf(stdout, "* TEST CODE NOT IMPLEMENTED (%ld, %ld)\n", cell.Row, cell.Column);
 
419
            fail();
 
420
        }
 
421
        break;
 
422
        case DataPilotFieldReferenceType::TOTAL_PERCENTAGE:
 
423
        {
 
424
            // Same as DataPilotFieldReferenceType::ROW_PERCENTAGE , but the grand 
 
425
            // total for the result's data field is used. 
 
426
            fprintf(stdout, "* TEST CODE NOT IMPLEMENTED (%ld, %ld)\n", cell.Row, cell.Column);
 
427
            fail();
 
428
        }
 
429
        break;
 
430
        case DataPilotFieldReferenceType::INDEX:
 
431
        {
 
432
            // The row and column totals and the grand total, following the same 
 
433
            // rules as above, are used to calculate the following expression.
 
434
            fprintf(stdout, "* TEST CODE NOT IMPLEMENTED (%ld, %ld)\n", cell.Row, cell.Column);
 
435
            fail();
 
436
        }
 
437
        break;
 
438
        default:
 
439
            fprintf(stdout, "* UNKNOWN REFERENCE TYPE (%ld, %ld)\n",
 
440
                    cell.Row, cell.Column);
 
441
            fail();
 
442
    }
 
443
}
 
444
 
 
445
void ResultTester::fail()
 
446
{
 
447
    throw RuntimeException();
 
448
    ++mnFailureCount;
 
449
}
 
450
 
 
451
}