diff options
author | Kohei Yoshida <kohei.yoshida@gmail.com> | 2012-10-30 12:38:32 -0400 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@gmail.com> | 2012-10-30 14:28:58 -0400 |
commit | 8cd13f7e04e920e3d6e1fddf88f61dac08894e06 (patch) | |
tree | f81a81b8e208d68030a1b89f019b385699106a11 /sc/qa | |
parent | 16e72215c96ee734e2cf6d15a465577d289a1549 (diff) |
New unit test for formula dependency tracking.
Change-Id: I5dad87cd67f8644509087394faa7c4880deb8ee6
Diffstat (limited to 'sc/qa')
-rw-r--r-- | sc/qa/unit/ucalc.cxx | 106 |
1 files changed, 90 insertions, 16 deletions
diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx index a5e3a07c010c..890c6bf3c145 100644 --- a/sc/qa/unit/ucalc.cxx +++ b/sc/qa/unit/ucalc.cxx @@ -118,6 +118,7 @@ public: */ void testSheetsFunc(); void testVolatileFunc(); + void testFormulaDepTracking(); void testFuncParam(); void testNamedRange(); void testCSV(); @@ -235,6 +236,7 @@ public: CPPUNIT_TEST(testCellFunctions); CPPUNIT_TEST(testSheetsFunc); CPPUNIT_TEST(testVolatileFunc); + CPPUNIT_TEST(testFormulaDepTracking); CPPUNIT_TEST(testFuncParam); CPPUNIT_TEST(testNamedRange); CPPUNIT_TEST(testCSV); @@ -332,6 +334,22 @@ ScRange insertRangeData(ScDocument* pDoc, const ScAddress& rPos, const char* aDa return aRange; } +class AutoCalcSwitch +{ + ScDocument* mpDoc; + bool mbOldValue; +public: + AutoCalcSwitch(ScDocument* pDoc, bool bAutoCalc) : mpDoc(pDoc), mbOldValue(pDoc->GetAutoCalc()) + { + mpDoc->SetAutoCalc(bAutoCalc); + } + + ~AutoCalcSwitch() + { + mpDoc->SetAutoCalc(mbOldValue); + } +}; + Test::Test() : m_pDoc(0) { @@ -1060,6 +1078,78 @@ void Test::testVolatileFunc() m_pDoc->DeleteTab(0); } +void Test::testFormulaDepTracking() +{ + CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet", m_pDoc->InsertTab (0, "foo")); + + AutoCalcSwitch aACSwitch(m_pDoc, true); // turn on auto calculation. + + // B2 listens on D2. + m_pDoc->SetString(1, 1, 0, "=D2"); + double val = -999.0; // dummy initial value + m_pDoc->GetValue(1, 1, 0, val); + CPPUNIT_ASSERT_MESSAGE("Referencing an empty cell should yield zero.", val == 0.0); + + // Changing the value of D2 should trigger recalculation of B2. + m_pDoc->SetValue(3, 1, 0, 1.1); + m_pDoc->GetValue(1, 1, 0, val); + CPPUNIT_ASSERT_MESSAGE("Failed to recalculate on value change.", val == 1.1); + + // And again. + m_pDoc->SetValue(3, 1, 0, 2.2); + m_pDoc->GetValue(1, 1, 0, val); + CPPUNIT_ASSERT_MESSAGE("Failed to recalculate on value change.", val == 2.2); + + clearRange(m_pDoc, ScRange(0, 0, 0, 10, 10, 0)); + + // Now, let's test the range dependency tracking. + + // B2 listens on D2:E6. + m_pDoc->SetString(1, 1, 0, "=SUM(D2:E6)"); + m_pDoc->GetValue(1, 1, 0, val); + CPPUNIT_ASSERT_MESSAGE("Summing an empty range should yield zero.", val == 0.0); + + // Set value to E3. This should trigger recalc on B2. + m_pDoc->SetValue(4, 2, 0, 2.4); + m_pDoc->GetValue(1, 1, 0, val); + CPPUNIT_ASSERT_MESSAGE("Failed to recalculate on single value change.", val == 2.4); + + // Set value to D5 to trigger recalc again. Note that this causes an + // addition of 1.2 + 2.4 which is subject to binary floating point + // rounding error. We need to use approxEqual to assess its value. + + m_pDoc->SetValue(3, 4, 0, 1.2); + m_pDoc->GetValue(1, 1, 0, val); + CPPUNIT_ASSERT_MESSAGE("Failed to recalculate on single value change.", rtl::math::approxEqual(val, 3.6)); + + // Change the value of D2 (boundary case). + m_pDoc->SetValue(3, 1, 0, 1.0); + m_pDoc->GetValue(1, 1, 0, val); + CPPUNIT_ASSERT_MESSAGE("Failed to recalculate on single value change.", rtl::math::approxEqual(val, 4.6)); + + // Change the value of E6 (another boundary case). + m_pDoc->SetValue(4, 5, 0, 2.0); + m_pDoc->GetValue(1, 1, 0, val); + CPPUNIT_ASSERT_MESSAGE("Failed to recalculate on single value change.", rtl::math::approxEqual(val, 6.6)); + + // Change the value of D6 (another boundary case). + m_pDoc->SetValue(3, 5, 0, 3.0); + m_pDoc->GetValue(1, 1, 0, val); + CPPUNIT_ASSERT_MESSAGE("Failed to recalculate on single value change.", rtl::math::approxEqual(val, 9.6)); + + // Change the value of E2 (another boundary case). + m_pDoc->SetValue(4, 1, 0, 0.4); + m_pDoc->GetValue(1, 1, 0, val); + CPPUNIT_ASSERT_MESSAGE("Failed to recalculate on single value change.", rtl::math::approxEqual(val, 10.0)); + + // Change the existing non-empty value cell (E2). + m_pDoc->SetValue(4, 1, 0, 2.4); + m_pDoc->GetValue(1, 1, 0, val); + CPPUNIT_ASSERT_MESSAGE("Failed to recalculate on single value change.", rtl::math::approxEqual(val, 12.0)); + + m_pDoc->DeleteTab(0); +} + void Test::testFuncParam() { rtl::OUString aTabName("foo"); @@ -1540,22 +1630,6 @@ ScRange refreshGroups(ScDPCollection* pDPs, ScDPObject* pDPObj) return refresh(pDPObj); } -class AutoCalcSwitch -{ - ScDocument* mpDoc; - bool mbOldValue; -public: - AutoCalcSwitch(ScDocument* pDoc, bool bAutoCalc) : mpDoc(pDoc), mbOldValue(pDoc->GetAutoCalc()) - { - mpDoc->SetAutoCalc(bAutoCalc); - } - - ~AutoCalcSwitch() - { - mpDoc->SetAutoCalc(mbOldValue); - } -}; - } void Test::testPivotTable() |