TEST(ValueTest, SetValue) { Value b; b.set(true); EXPECT_EQ(true, b.getBoolean()); Value i1; i1.set(42); EXPECT_EQ(42, i1.getInteger()); Value i2; i2.set(42L); EXPECT_EQ(42, i2.getInteger()); Value f1; f1.set(0.42F); EXPECT_NEAR(0.42, f1.getFloat(), 0.000001); Value f2; f2.set(0.42); EXPECT_NEAR(0.42, f2.getFloat(), 0.000001); Value s1; s1.set("foobar"); EXPECT_EQ("foobar", s1.getString()); Value s2; s2.set(std::string("foobar")); EXPECT_EQ("foobar", s2.getString()); Value s3; s3.set(QString("foobar")); EXPECT_EQ("foobar", s3.getString()); Value::Array arr; arr.push_back(Value(42)); Value a; a.set(arr); EXPECT_EQ(arr, a.getArray()); Value::Object obj; obj["foobar"] = Value(42); Value o1; o1.set(obj); EXPECT_EQ(obj, o1.getObject()); Value o2; o2.set(o1); EXPECT_EQ(o1, o2); }
TEST(ValueTest, CreateValue) { Value b = true; EXPECT_EQ(true, b.getBoolean()); Value i1 = 42; EXPECT_EQ(42, i1.getInteger()); Value i2 = 42L; EXPECT_EQ(42, i2.getInteger()); Value f1 = 0.42F; EXPECT_NEAR(0.42, f1.getFloat(), 0.000001); Value f2 = 0.42; EXPECT_NEAR(0.42, f2.getFloat(), 0.000001); Value s1 = "foobar"; EXPECT_EQ("foobar", s1.getString()); Value s2 = std::string("foobar"); EXPECT_EQ("foobar", s2.getString()); Value s3 = QString("foobar"); EXPECT_EQ("foobar", s3.getString()); Value::Array arr; arr.push_back(Value(42)); Value a = arr; EXPECT_EQ(arr, a.getArray()); Value::Object obj; obj["foobar"] = Value(42); Value o1 = obj; EXPECT_EQ(obj, o1.getObject()); Value o2 = o1; EXPECT_EQ(o1, o2); }
Value XmlRpcSystemMethods::SystemMulticall( const Request::Parameters& parameters) const { const Value dummyId; Value::Array result; for (auto& call : parameters.at(0).AsArray()) { try { if (call[xml::METHOD_NAME_TAG].AsString() == SYSTEM_MULTICALL) { throw InternalErrorFault("Recursive system.multicall forbidden"); } auto& array = call[xml::PARAMS_TAG].AsArray(); Request::Parameters callParams(array.begin(), array.end()); auto retval = myDispatcher.Invoke( call[xml::METHOD_NAME_TAG].AsString(), callParams, dummyId); retval.ThrowIfFault(); Value::Array a; a.emplace_back(std::move(retval.GetResult())); result.push_back(std::move(a)); } catch (const Fault& ex) { Value::Struct fault; fault[xml::FAULT_CODE_NAME] = ex.GetCode(); fault[xml::FAULT_STRING_NAME] = ex.GetString(); result.push_back(std::move(fault)); } catch (const std::exception& ex) { Value::Struct fault; fault[xml::FAULT_CODE_NAME] = 0; fault[xml::FAULT_STRING_NAME] = ex.what(); result.push_back(std::move(fault)); } catch (...) { Value::Struct fault; fault[xml::FAULT_CODE_NAME] = 0; fault[xml::FAULT_STRING_NAME] = "Unknown error"; result.push_back(std::move(fault)); } } return std::move(result); }
void __makeTasks__prev( string rule, string file, string target, TaskQueue* queue, OS* os, string& input, bool finalRule=false ) { os->pushString(rule.c_str()); os->pushValueById(rules->valueID); if(!os->in()) { cerr << "[IceTea]: " << rule << " does not exist."; return; } os->pushString(rule.c_str()); os->getProperty(); Value::Object myRule(os, os->getAbsoluteOffs(-1)); // Now get the two most important properties Value::Array* accepts = (Value::Array*)myRule["accepts"]; Value::Object* outputs = (Value::Object*)myRule["output"]; // Now create some strings. Value::String* o_myPattern = (Value::String*)(*outputs)["pattern"]; Value::String* o_myExpected = (Value::String*)(*outputs)["expected"]; string myPattern = (*o_myPattern); string myExpected = (*o_myExpected); // Clean up the heap delete outputs; delete o_myPattern; delete o_myExpected; // Replace stuff... string basename = PathToFileName(file.c_str()); string ext = StripFileExtension(basename); ReplaceStringInPlace(myExpected, "%t", target); ReplaceStringInPlace(myExpected, "%b", basename); ReplaceStringInPlace(myExpected, "%e", ext); ReplaceStringInPlace(myExpected, "%f", file); //cout <<rule<< " Working: " << file << " --> " << myExpected << endl; // Does the file we are processing actually HAVE a rule it can be run with, at all? os->pushValueById(rules->valueID); os->getProperty(-1, "keys"); Value::Array rkeys(os); bool hasARule=false; for(int r=0; r<rkeys.length(); r++) { Value::String* ruleName = (Value::String*)rkeys[r]; Value::Object* val = (Value::Object*)(*rules)[(*ruleName)]; Value::Array* rAccepts = (Value::Array*)(*val)["accepts"]; for(int o=0; o<rAccepts->length(); o++) { Value::String* rPat = (Value::String*)(*rAccepts)[o]; if(WildcardMatch(file.c_str(), (*rPat))) { hasARule=true; break; } } delete ruleName; delete val; } if(!hasARule) { cerr << "[IceTea]: It appears, that "<< file << " has no rule it can be ran with!" << " The file will be added verbatim. Be aware of this." << endl; return; } // Does the file we have, already match any pattern in the accept array? bool fits=false; for(int i=0; i<accepts->length(); i++) { Value::String* o_pat = (Value::String*)(*accepts)[i]; string pat = (*o_pat); //cout << "Comparing with: " << pat << endl; if(WildcardMatch(file.c_str(), pat.c_str())) { fits=true; break; } delete o_pat; } if(!fits) { //cout << "Finding new processor rule..." << endl; // Our file is not accepted by the rule. // So let's one that works and process it with that. // Problem is, a rule may have multiple accepts... // so we have to go over all of them and look for a rule. for(int j=0; j<accepts->length(); j++) { Value::String* o_pat = (Value::String*)(*accepts)[j]; string pat = (*o_pat); // Now we search up for the rule that HAS the pattern as its output pattern. // that also is why you only define an output pattern as STRING. os->pushValueById(rules->valueID); os->getProperty(-1, "keys"); // triggers the getKeys method. Value::Array keys(os); for(int e=0; e<keys.length(); e++) { Value::String* key = (Value::String*)keys[e]; Value::Object* val = (Value::Object*)(*rules)[(*key)]; Value::Object* v_output = (Value::Object*)(*val)["output"]; Value::String* v_pat = (Value::String*)(*v_output)["pattern"]; string sv_pat = (*v_pat); if( pat == sv_pat ) { //cout << "Comparing " << pat << " to " << sv_pat << " as " << (*key) << endl; // The current rule accepts input, from the found rule. // But does the found rule actually support our file? string n_rule = (*key); string t_input; __makeTasks(n_rule, file, target, queue, os, t_input); string inputFile = (!t_input.empty() ? t_input : file); // We are going to compare output pattern to accept pattern... // But we also must see if our file actually fits as accepted, for the rule we want the output //cout << "Testing rule: " << n_rule << " with: " << file << endl; cout << n_rule << ": " << file << ", " << inputFile << ", " << myExpected << endl; Value::Array* t_accepts = (Value::Array*)(*val)["accepts"]; bool isAccepted=false; for(int p=0; p<t_accepts->length(); p++) { Value::String* t_pat = (Value::String*)(*t_accepts)[p]; cout << "Trying: " << (*t_pat) << endl; if( WildcardMatch(inputFile.c_str(), (*t_pat)) ) { cout << "hit!" << endl; isAccepted=true; break; } delete t_pat; } delete t_accepts; delete key; delete val; delete v_output; delete v_pat; // Determine the "output" if(!finalRule) input = myExpected; else input = inputFile; // But we have to add this as a rule, since it was called that way. if(isAccepted) { if(!finalRule) { Task* t = new Task; t->ruleName = rule; t->targetName = target; t->input.push_back(inputFile); t->output = myExpected; // Find out what type the rule is. A function, or an array of commands? os->pushValueById(myRule.valueID); os->getProperty(-1, "build"); if(os->getTypeStr() == "array") { t->type=COMMAND; for(int k=0; k<os->getLen(); k++) { os->pushNumber(k); os->getProperty(); t->commands.push_back( os->popString().toChar() ); } } else if(os->getTypeStr() == "function") { t->type=SCRIPT; os->pushValueById(myRule.valueID); Value::Object* theRule = new Value::Object(os); t->onBuild = new Value::Method(os, theRule, "build"); } else { cerr << "[IceTea]: Rule '"<< rule << "' must have it's build property defined as function or array! " << "'" << os->getTypeStr() << "' was given instead." << endl; } t->target = (Value::Object*)(*targets)[target]; queue->add(t); return; // Nothing to return here. But we end the function here. } } } } } } else { cout << rule << " Input: " << file << endl; // file fits with out accepted entries! So we create a task and put it in. Task* t = new Task; t->ruleName = rule; t->targetName = target; t->input.push_back(file); t->output = myExpected; // Find out what type the rule is. A function, or an array of commands? os->pushValueById(myRule.valueID); os->getProperty(-1, "build"); if(os->getTypeStr() == "array") { t->type=COMMAND; for(int k=0; k<os->getLen(); k++) { os->pushNumber(k); os->getProperty(); t->commands.push_back( os->popString().toChar() ); } } else if(os->getTypeStr() == "function") { t->type=SCRIPT; os->pushValueById(myRule.valueID); Value::Object* theRule = new Value::Object(os); t->onBuild = new Value::Method(os, theRule, "build"); } else { cerr << "[IceTea]: Rule '"<< rule << "' must have it's build property defined as function or array! " << "'" << os->getTypeStr() << "' was given instead." << endl; } t->target = (Value::Object*)(*targets)[target]; input = myExpected; queue->add(t); } }
Value XmlRpcSystemMethods::SystemMethodSignature( const std::string& methodName) const { try { auto& method = myDispatcher.GetMethod(methodName); if (!method.IsHidden()) { auto& signatures = method.GetSignatures(); if (signatures.empty()) { return SIGNATURE_UNDEFINED; } Value::Array result; result.reserve(signatures.size()); for (auto& signature : signatures) { Value::Array types; types.reserve(signature.size()); for (auto type : signature) { switch (type) { case Value::Type::ARRAY: types.emplace_back(xml::ARRAY_TAG); break; case Value::Type::BINARY: types.emplace_back(xml::BASE_64_TAG); break; case Value::Type::BOOLEAN: types.emplace_back(xml::BOOLEAN_TAG); break; case Value::Type::DATE_TIME: types.emplace_back(xml::DATE_TIME_TAG); break; case Value::Type::DOUBLE: types.emplace_back(xml::DOUBLE_TAG); break; case Value::Type::INTEGER_32: types.emplace_back(xml::INTEGER_32_TAG); break; case Value::Type::INTEGER_64: types.emplace_back(xml::INTEGER_64_TAG); break; case Value::Type::NIL: // Only useful for return value if (types.empty()) { types.emplace_back(xml::NIL_TAG); } break; case Value::Type::STRING: types.emplace_back(xml::STRING_TAG); break; case Value::Type::STRUCT: types.emplace_back(xml::STRUCT_TAG); break; } } result.emplace_back(std::move(types)); } return std::move(result); } } catch (...) { // Ignore } throw Fault("No method " + methodName); }