File indexing completed on 2024-05-19 16:08:42

0001 /* This file is part of the KDE project
0002    Copyright 2007 Brad Hards <bradh@frogmouth.net>
0003 
0004    This library is free software; you can redistribute it and/or
0005    modify it under the terms of the GNU Library General Public
0006    License as published by the Free Software Foundation; only
0007    version 2 of the License.
0008 
0009    This library is distributed in the hope that it will be useful,
0010    but WITHOUT ANY WARRANTY; without even the implied warranty of
0011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012    Library General Public License for more details.
0013 
0014    You should have received a copy of the GNU Library General Public License
0015    along with this library; see the file COPYING.LIB.  If not, write to
0016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017    Boston, MA 02110-1301, USA.
0018 */
0019 #include "TestLogicFunctions.h"
0020 
0021 #include "TestKspreadCommon.h"
0022 
0023 #include <MockPart.h>
0024 #include <part/Doc.h>
0025 #include <Map.h>
0026 #include <Sheet.h>
0027 
0028 using namespace Calligra::Sheets;
0029 
0030 void TestLogicFunctions::init()
0031 {
0032     m_doc = new Doc(new MockPart);
0033     m_doc->map()->addNewSheet();
0034     m_sheet = m_doc->map()->sheet(0);
0035 }
0036 
0037 void TestLogicFunctions::cleanup()
0038 {
0039     delete m_doc;
0040 }
0041 
0042 void TestLogicFunctions::initTestCase()
0043 {
0044     FunctionModuleRegistry::instance()->loadFunctionModules();
0045 }
0046 
0047 // because we may need to promote expected value from integer to float
0048 #define CHECK_EVAL(x,y) { Value z = (y); QCOMPARE(evaluate(x,z),(z)); }
0049 
0050 Value TestLogicFunctions::evaluate(const QString& formula, Value& ex)
0051 {
0052     Formula f(m_sheet);
0053     QString expr = formula;
0054     if (expr[0] != '=')
0055         expr.prepend('=');
0056     f.setExpression(expr);
0057     Value result = f.eval();
0058 
0059     if (result.isFloat() && ex.isInteger())
0060         ex = Value(ex.asFloat());
0061     if (result.isInteger() && ex.isFloat())
0062         result = Value(result.asFloat());
0063 
0064     return result;
0065 }
0066 
0067 void TestLogicFunctions::testAND()
0068 {
0069     CHECK_EVAL("AND(FALSE();FALSE())", Value(false));
0070     CHECK_EVAL("AND(FALSE();TRUE())", Value(false));
0071     CHECK_EVAL("AND(TRUE();FALSE())", Value(false));
0072     CHECK_EVAL("AND(TRUE();TRUE())", Value(true));
0073     // errors propagate
0074     CHECK_EVAL("AND(TRUE();NA())", Value::errorNA());
0075     CHECK_EVAL("AND(NA();TRUE())", Value::errorNA());
0076     // Nonzero considered TRUE
0077     CHECK_EVAL("AND(1;TRUE())", Value(true));
0078     CHECK_EVAL("AND(2;TRUE())", Value(true));
0079     // zero considered false
0080     CHECK_EVAL("AND(0;TRUE())", Value(false));
0081     // multiple parameters...
0082     CHECK_EVAL("AND(TRUE();TRUE();TRUE())", Value(true));
0083     CHECK_EVAL("AND(TRUE();TRUE();FALSE())", Value(false));
0084     CHECK_EVAL("AND(FALSE();TRUE();TRUE())", Value(false));
0085     CHECK_EVAL("AND(TRUE();FALSE();TRUE())", Value(false));
0086     CHECK_EVAL("AND(TRUE();FALSE();FALSE())", Value(false));
0087     // single parameter
0088     CHECK_EVAL("AND(TRUE())", Value(true));
0089     CHECK_EVAL("AND(FALSE())", Value(false));
0090 
0091     // literal non-convertible text should give an error
0092     //CHECK_EVAL("AND(FALSE();\"a\")", Value::errorVALUE());
0093 }
0094 
0095 void TestLogicFunctions::testFALSE()
0096 {
0097     CHECK_EVAL("FALSE()", Value(false));
0098     // Applications that implement logical values as 0/1 must map FALSE() to 0
0099     CHECK_EVAL("IF(ISNUMBER(FALSE());FALSE()=0;FALSE())", Value(false));
0100     // note that kspread distinguishes between boolean and math
0101     CHECK_EVAL("FALSE()=0", Value(false));
0102     CHECK_EVAL("FALSE()=1", Value(false));
0103     // False converts to 0 in Number context
0104     CHECK_EVAL("2+FALSE()", Value(2));
0105 }
0106 
0107 void TestLogicFunctions::testIF()
0108 {
0109     CHECK_EVAL("IF(FALSE();7;8)", Value(8));
0110     CHECK_EVAL("IF(TRUE();7;8)", Value(7));
0111     CHECK_EVAL("IF(FALSE();7.1;8.2)", Value(8.2));
0112     CHECK_EVAL("IF(TRUE();7.1;8.2)", Value(7.1));
0113     CHECK_EVAL("IF(TRUE();\"HI\";8)", Value("HI"));
0114     CHECK_EVAL("IF(1;7;8)", Value(7));
0115     CHECK_EVAL("IF(5;7;8)", Value(7));
0116     CHECK_EVAL("IF(0;7;8)", Value(8));
0117     // there are a couple of indirect references in the spec test
0118     // vectors here. Sorry
0119     CHECK_EVAL("IF(\"x\";7;8)", Value::errorVALUE());
0120     CHECK_EVAL("IF(\"1\";7;8)", Value::errorVALUE());
0121     CHECK_EVAL("IF(\"\";7;8)", Value::errorVALUE());
0122     CHECK_EVAL("IF(FALSE();7)", Value(false));
0123     CHECK_EVAL("IF(FALSE();7;)", Value(0));
0124     // Assuming A1 is an empty cell, using it in the following
0125     // context should be different from passing no argument at all
0126     CHECK_EVAL("IF(FALSE();7;A1)", Value(Value::Empty));
0127     CHECK_EVAL("IF(TRUE();4;1/0)", Value(4));
0128     CHECK_EVAL("IF(FALSE();1/0;5)", Value(5));
0129     // Empty vs *
0130     CHECK_EVAL("IF(A1==2;2;4)", Value(4));
0131     CHECK_EVAL("IF(A1==2.5;2;4)", Value(4));
0132     CHECK_EVAL("IF(A1==TRUE();2;4)", Value(4));
0133     CHECK_EVAL("IF(A1==\"BAD\";2;4)", Value(4));
0134     // from an excel binary document. seems it produces an parse error
0135     CHECK_EVAL("IF(#-1#0#<>\"\";\"x \"&#-1#0#&#-30#0#;\"\")", Value::errorPARSE());
0136 }
0137 
0138 void TestLogicFunctions::testNOT()
0139 {
0140     CHECK_EVAL("NOT(FALSE())", Value(true));
0141     CHECK_EVAL("NOT(TRUE())", Value(false));
0142     CHECK_EVAL("NOT(1/0)", Value::errorDIV0());
0143     CHECK_EVAL("NOT(\"a\")", Value::errorVALUE());
0144 }
0145 
0146 void TestLogicFunctions::testOR()
0147 {
0148     CHECK_EVAL("OR(FALSE();FALSE())", Value(false));
0149     CHECK_EVAL("OR(FALSE();TRUE())", Value(true));
0150     CHECK_EVAL("OR(TRUE();FALSE())", Value(true));
0151     CHECK_EVAL("OR(TRUE();TRUE())", Value(true));
0152     // errors propagate
0153     CHECK_EVAL("OR(TRUE();NA())", Value::errorNA());
0154     CHECK_EVAL("OR(NA();TRUE())", Value::errorNA());
0155     // Nonzero considered TRUE
0156     CHECK_EVAL("OR(1;TRUE())", Value(true));
0157     CHECK_EVAL("OR(2;TRUE())", Value(true));
0158     // zero considered false
0159     CHECK_EVAL("OR(0;TRUE())", Value(true));
0160     CHECK_EVAL("OR(0;1)", Value(true));
0161     CHECK_EVAL("OR(0;0)", Value(false));
0162     // multiple parameters...
0163     CHECK_EVAL("OR(TRUE();TRUE();TRUE())", Value(true));
0164     CHECK_EVAL("OR(FALSE();FALSE();FALSE())", Value(false));
0165     CHECK_EVAL("OR(TRUE();TRUE();FALSE())", Value(true));
0166     CHECK_EVAL("OR(FALSE();TRUE();TRUE())", Value(true));
0167     CHECK_EVAL("OR(TRUE();FALSE();TRUE())", Value(true));
0168     CHECK_EVAL("OR(TRUE();FALSE();FALSE())", Value(true));
0169     // single parameter
0170     CHECK_EVAL("OR(TRUE())", Value(true));
0171     CHECK_EVAL("OR(FALSE())", Value(false));
0172 
0173     // literal non-convertible text should give an error
0174     //CHECK_EVAL("OR(TRUE();\"a\")", Value::errorVALUE());
0175 }
0176 
0177 void TestLogicFunctions::testTRUE()
0178 {
0179     CHECK_EVAL("TRUE()", Value(true));
0180     // Applications that implement logical values as 0/1 must map TRUE() to 1
0181     CHECK_EVAL("IF(ISNUMBER(TRUE());TRUE()=0;TRUE())", Value(true));
0182     // note that kspread distinguishes between boolean and math
0183     CHECK_EVAL("TRUE()=1", Value(false));
0184     CHECK_EVAL("TRUE()=0", Value(false));
0185     // False converts to 0 in Number context
0186     CHECK_EVAL("2+TRUE()", Value(3));
0187 }
0188 
0189 void TestLogicFunctions::testXOR()
0190 {
0191     CHECK_EVAL("XOR(FALSE();FALSE())", Value(false));
0192     CHECK_EVAL("XOR(FALSE();TRUE())", Value(true));
0193     CHECK_EVAL("XOR(TRUE();FALSE())", Value(true));
0194     CHECK_EVAL("XOR(TRUE();TRUE())", Value(false));
0195     // errors propagate
0196     CHECK_EVAL("XOR(TRUE();NA())", Value::errorNA());
0197     CHECK_EVAL("XOR(NA();TRUE())", Value::errorNA());
0198     CHECK_EVAL("XOR(FALSE();NA())", Value::errorNA());
0199     CHECK_EVAL("XOR(NA();FALSE())", Value::errorNA());
0200     // Nonzero considered TRUE
0201     CHECK_EVAL("XOR(1;TRUE())", Value(false));
0202     CHECK_EVAL("XOR(3;4)", Value(false));
0203     CHECK_EVAL("XOR(2;TRUE())", Value(false));
0204     CHECK_EVAL("XOR(FALSE();1)", Value(true));
0205     CHECK_EVAL("XOR(2;FALSE())", Value(true));
0206     // zero considered false
0207     CHECK_EVAL("XOR(0;TRUE())", Value(true));
0208     CHECK_EVAL("XOR(0;1)", Value(true));
0209     CHECK_EVAL("XOR(0;0)", Value(false));
0210     // multiple parameters...
0211     CHECK_EVAL("XOR(TRUE();TRUE();TRUE())", Value(true));
0212     CHECK_EVAL("XOR(TRUE();FALSE();TRUE();TRUE();TRUE();TRUE())", Value(true));
0213     CHECK_EVAL("XOR(FALSE();FALSE();FALSE())", Value(false));
0214     CHECK_EVAL("XOR(TRUE();TRUE();FALSE())", Value(false));
0215     CHECK_EVAL("XOR(FALSE();TRUE();TRUE())", Value(false));
0216     CHECK_EVAL("XOR(TRUE();FALSE();TRUE())", Value(false));
0217     CHECK_EVAL("XOR(TRUE();FALSE();FALSE())", Value(true));
0218     CHECK_EVAL("XOR(FALSE();FALSE();TRUE())", Value(true));
0219     CHECK_EVAL("XOR(FALSE();FALSE();TRUE();FALSE())", Value(true));
0220     // single parameter
0221     CHECK_EVAL("XOR(TRUE())", Value(true));
0222     CHECK_EVAL("XOR(FALSE())", Value(false));
0223 
0224     // literal non-convertible text should give an error
0225     //CHECK_EVAL("XOR(TRUE();\"a\")", Value::errorVALUE());
0226 }
0227 
0228 QTEST_MAIN(TestLogicFunctions)