diff options
-rw-r--r-- | sc/qa/unit/helper/qahelper.cxx | 12 | ||||
-rw-r--r-- | sc/qa/unit/helper/qahelper.hxx | 4 | ||||
-rw-r--r-- | sc/qa/unit/ucalc.hxx | 2 | ||||
-rw-r--r-- | sc/qa/unit/ucalc_formula.cxx | 82 |
4 files changed, 97 insertions, 3 deletions
diff --git a/sc/qa/unit/helper/qahelper.cxx b/sc/qa/unit/helper/qahelper.cxx index 951cd613b64a..91b4a12d1724 100644 --- a/sc/qa/unit/helper/qahelper.cxx +++ b/sc/qa/unit/helper/qahelper.cxx @@ -473,6 +473,18 @@ bool checkFormulaPositions( return true; } +ScTokenArray* compileFormula( + ScDocument* pDoc, const OUString& rFormula, const ScAddress* pPos, + formula::FormulaGrammar::Grammar eGram ) +{ + ScAddress aPos(0,0,0); + if (pPos) + aPos = *pPos; + ScCompiler aComp(pDoc, aPos); + aComp.SetGrammar(eGram); + return aComp.CompileString(rFormula); +} + void clearFormulaCellChangedFlag( ScDocument& rDoc, const ScRange& rRange ) { const ScAddress& s = rRange.aStart; diff --git a/sc/qa/unit/helper/qahelper.hxx b/sc/qa/unit/helper/qahelper.hxx index 915d167b10fb..805c6d2a596a 100644 --- a/sc/qa/unit/helper/qahelper.hxx +++ b/sc/qa/unit/helper/qahelper.hxx @@ -125,6 +125,10 @@ SCQAHELPER_DLLPUBLIC bool checkFormulaPosition(ScDocument& rDoc, const ScAddress SCQAHELPER_DLLPUBLIC bool checkFormulaPositions( ScDocument& rDoc, SCTAB nTab, SCCOL nCol, const SCROW* pRows, size_t nRowCount); +SCQAHELPER_DLLPUBLIC ScTokenArray* compileFormula( + ScDocument* pDoc, const OUString& rFormula, const ScAddress* pPos = NULL, + formula::FormulaGrammar::Grammar eGram = formula::FormulaGrammar::GRAM_NATIVE ); + template<size_t _Size> bool checkOutput(ScDocument* pDoc, const ScRange& aOutRange, const char* aOutputCheck[][_Size], const char* pCaption) { diff --git a/sc/qa/unit/ucalc.hxx b/sc/qa/unit/ucalc.hxx index ec32e235194a..6291fd94e485 100644 --- a/sc/qa/unit/ucalc.hxx +++ b/sc/qa/unit/ucalc.hxx @@ -123,6 +123,7 @@ public: void testFormulaTokenEquality(); void testFormulaRefData(); void testFormulaCompiler(); + void testFormulaCompilerJumpReordering(); void testFormulaRefUpdate(); void testFormulaRefUpdateRange(); void testFormulaRefUpdateSheets(); @@ -383,6 +384,7 @@ public: CPPUNIT_TEST(testFormulaTokenEquality); CPPUNIT_TEST(testFormulaRefData); CPPUNIT_TEST(testFormulaCompiler); + CPPUNIT_TEST(testFormulaCompilerJumpReordering); CPPUNIT_TEST(testFormulaRefUpdate); CPPUNIT_TEST(testFormulaRefUpdateRange); CPPUNIT_TEST(testFormulaRefUpdateSheets); diff --git a/sc/qa/unit/ucalc_formula.cxx b/sc/qa/unit/ucalc_formula.cxx index 4d4d0c26647d..3b374d754827 100644 --- a/sc/qa/unit/ucalc_formula.cxx +++ b/sc/qa/unit/ucalc_formula.cxx @@ -781,9 +781,7 @@ void Test::testFormulaCompiler() { boost::scoped_ptr<ScTokenArray> pArray; { - ScCompiler aComp(m_pDoc, ScAddress()); - aComp.SetGrammar(aTests[i].eInputGram); - pArray.reset(aComp.CompileString(OUString::createFromAscii(aTests[i].pInput))); + pArray.reset(compileFormula(m_pDoc, OUString::createFromAscii(aTests[i].pInput), NULL, aTests[i].eInputGram)); CPPUNIT_ASSERT_MESSAGE("Token array shouldn't be NULL!", pArray.get()); } @@ -792,6 +790,84 @@ void Test::testFormulaCompiler() } } +void Test::testFormulaCompilerJumpReordering() +{ + struct TokenCheck + { + OpCode meOp; + StackVar meType; + }; + + // Set separators first. + ScFormulaOptions aOptions; + aOptions.SetFormulaSepArg(";"); + aOptions.SetFormulaSepArrayCol(";"); + aOptions.SetFormulaSepArrayRow("|"); + getDocShell().SetFormulaOptions(aOptions); + + { + OUString aInput("=IF(B1;12;\"text\")"); + + // Compile formula string first. + boost::scoped_ptr<ScTokenArray> pCode(compileFormula(m_pDoc, aInput)); + CPPUNIT_ASSERT(pCode.get()); + + // Then generate RPN tokens. + ScCompiler aCompRPN(m_pDoc, ScAddress(), *pCode); + aCompRPN.SetGrammar(FormulaGrammar::GRAM_NATIVE); + aCompRPN.CompileTokenArray(); + + // RPN tokens should be ordered: B1, ocIf, C1, ocSep, D1, ocClose. + TokenCheck aCheckRPN[] = + { + { ocPush, svSingleRef }, + { ocIf, 0 }, + { ocPush, svDouble }, + { ocSep, 0 }, + { ocPush, svString }, + { ocClose, 0 }, + }; + + sal_uInt16 nLen = pCode->GetCodeLen(); + CPPUNIT_ASSERT_MESSAGE("Wrong RPN token count.", nLen == SAL_N_ELEMENTS(aCheckRPN)); + + FormulaToken** ppTokens = pCode->GetCode(); + for (sal_uInt16 i = 0; i < nLen; ++i) + { + const FormulaToken* p = ppTokens[i]; + CPPUNIT_ASSERT_EQUAL(aCheckRPN[i].meOp, p->GetOpCode()); + if (aCheckRPN[i].meOp == ocPush) + CPPUNIT_ASSERT_EQUAL(static_cast<int>(aCheckRPN[i].meType), static_cast<int>(p->GetType())); + } + + // Generate RPN tokens again, but this time no jump command reordering. + pCode->DelRPN(); + ScCompiler aCompRPN2(m_pDoc, ScAddress(), *pCode); + aCompRPN2.SetGrammar(FormulaGrammar::GRAM_NATIVE); + aCompRPN2.EnableJumpCommandReorder(false); + aCompRPN2.CompileTokenArray(); + + TokenCheck aCheckRPN2[] = + { + { ocPush, svSingleRef }, + { ocPush, svDouble }, + { ocPush, svString }, + { ocIf, 0 }, + }; + + nLen = pCode->GetCodeLen(); + CPPUNIT_ASSERT_MESSAGE("Wrong RPN token count.", nLen == SAL_N_ELEMENTS(aCheckRPN2)); + ppTokens = pCode->GetCode(); + for (sal_uInt16 i = 0; i < nLen; ++i) + { + const FormulaToken* p = ppTokens[i]; + CPPUNIT_ASSERT_EQUAL(aCheckRPN2[i].meOp, p->GetOpCode()); + if (aCheckRPN[i].meOp == ocPush) + CPPUNIT_ASSERT_EQUAL(static_cast<int>(aCheckRPN2[i].meType), static_cast<int>(p->GetType())); + } + } +} + void Test::testFormulaRefUpdate() { m_pDoc->InsertTab(0, "Formula"); |