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)