12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267 |
- /*##############################################################################
- Copyright (C) 2020 HPCC Systems®.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ############################################################################## */
- #ifdef _USE_CPPUNIT
- #include "unittests.hpp"
- #include "espcontext.hpp"
- #include "xpathprocessor.hpp"
- #include "esdl_script.hpp"
- #include "wsexcept.hpp"
- #include <stdio.h>
- #include "dllserver.hpp"
- #include "thorplugin.hpp"
- #include "eclrtl.hpp"
- #include "rtlformat.hpp"
- // =============================================================== URI parser
- static constexpr const char * soapRequest = R"!!(<?xml version="1.0" encoding="UTF-8"?>
- <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
- <soap:Body>
- <extra>
- <EchoPersonInfo>
- <_TransactionId>1736623372_3126765312_1333296170</_TransactionId>
- <Context>
- <Row>
- <Common>
- <TransactionId>1736623372_3126765312_1333296170</TransactionId>
- </Common>
- </Row>
- </Context>
- <EchoPersonInfoRequest>
- <Row>
- <Name>
- <First>Joe</First>
- <Last>Doe</Last>
- </Name>
- <Addresses>
- <Address>
- <type>Home</type>
- <Line1>101 Main street</Line1>
- <Line2>Apt 202</Line2>
- <City>Hometown</City>
- <State>HI</State>
- <Zip>96703</Zip>
- </Address>
- </Addresses>
- </Row>
- </EchoPersonInfoRequest>
- </EchoPersonInfo>
- </extra>
- </soap:Body>
- </soap:Envelope>
- )!!";
- static constexpr const char * esdlScript = R"!!(<es:CustomRequestTransform xmlns:es="urn:hpcc:esdl:script" target="soap:Body/extra/{$query}/{$request}">
- <es:variable name="var1" select="'script'"/>
- <es:variable name="var2" select="$var1"/>
- <es:param name='testcase' select="'unknown'"/>
- <es:param name='FailStrict' select='false()'/>
- <es:param name='FailLevel1A' select='false()'/>
- <es:param name='FailLevel1B' select='false()'/>
- <es:param name='AssertLevel1C' select='false()'/>
- <es:param name='FailLevel2A' select='false()'/>
- <es:param name='FailLevel2B' select='false()'/>
- <es:param name='AssertLevel2C' select='false()'/>
- <es:param name="param1" select="'script'"/>
- <es:param name="param2" select="$param1"/>
- <es:set-value target="TestCase" select="$testcase"/>
- <es:set-value target="Var2" select="$var2"/>
- <es:set-value target="Param2" select="$param2"/>
- <es:choose>
- <es:when test="not(es:validateFeaturesAccess('AllowSomething : Read, AllowAnother : Full'))">
- <es:fail code="401" message="concat('authorization failed for something or other (', $clientversion, ')')"/>
- </es:when>
- <es:when test="not(es:getFeatureSecAccessFlags('AllowSomething')=es:secureAccessFlags('Full'))">
- <es:fail code="401" message="concat('auth flag check failed for something (', $clientversion, ')')"/>
- </es:when>
- <es:when test="$FailStrict">
- <es:if test="$undeclared">
- <es:fail code="1" message="'not strict'"/>
- </es:if>
- </es:when>
- <es:when test="$FailLevel1A">
- <es:fail code="11" message="'FailLevel1A'"/>
- </es:when>
- <es:when test="$FailLevel1B">
- <es:if test="$FailLevel1B">
- <es:fail code="12" message="'FailLevel1B'"/>
- </es:if>
- </es:when>
- <es:when test="$AssertLevel1C">
- <es:assert test="not($AssertLevel1C)" code="13" message="'AssertLevel1C'"/>
- </es:when>
- <es:otherwise>
- <es:set-value target="InnerTestCase" select="$testcase"/>
- <es:choose>
- <es:when test="$FailLevel2A">
- <es:fail code="21" message="'FailLevel2A'"/>
- </es:when>
- <es:when test="$FailLevel2B">
- <es:if test="$FailLevel2B">
- <es:fail code="22" message="'FailLevel2B'"/>
- </es:if>
- </es:when>
- <es:when test="$AssertLevel2C">
- <es:assert test="not($AssertLevel2C)" code="23" message="'AssertLevel2C'"/>
- </es:when>
- <es:otherwise>
- <es:set-value target="test" select="'auth success'"/>
- <es:set-value target="Row/Name/Last" select="'XXX'"/>
- <es:set-value target="Row/Name/Last" select="'POE'"/>
- <es:append-to-value target="Row/AppendTo" select="'This'"/>
- <es:append-to-value target="Row/AppendTo" select="'One'"/>
- <es:append-to-value target="Row/AppendTo" select="'String'"/>
- <es:add-value target="Row/Name/Aliases/Alias" select="'moe'"/>
- <es:add-value target="Row/Name/Aliases/Alias" select="'poe'"/>
- <es:add-value target="Row/Name/Aliases/Alias" select="'roe'"/>
- </es:otherwise>
- </es:choose>
- </es:otherwise>
- </es:choose>
- </es:CustomRequestTransform>
- )!!";
- static constexpr const char * esdlScriptNoPrefix = R"!!(<CustomRequestTransform xmlns="urn:hpcc:esdl:script" target="soap:Body/extra/{$query}/{$request}">
- <variable name="var1" select="'script'"/>
- <variable name="var2" select="$var1"/>
- <param name='testcase' select="'unknown'"/>
- <param name='FailStrict' select='false()'/>
- <param name='FailLevel1A' select='false()'/>
- <param name='FailLevel1B' select='false()'/>
- <param name='AssertLevel1C' select='false()'/>
- <param name='FailLevel2A' select='false()'/>
- <param name='FailLevel2B' select='false()'/>
- <param name='AssertLevel2C' select='false()'/>
- <param name="param1" select="'script'"/>
- <param name="param2" select="$param1"/>
- <set-value target="TestCase" select="$testcase"/>
- <set-value target="Var2" select="$var2"/>
- <set-value target="Param2" select="$param2"/>
- <choose>
- <when test="not(validateFeaturesAccess('AllowSomething : Read, AllowAnother : Full'))">
- <fail code="401" message="concat('authorization failed for something or other (', $clientversion, ')')"/>
- </when>
- <when test="not(getFeatureSecAccessFlags('AllowSomething')=secureAccessFlags('Full'))">
- <fail code="401" message="concat('auth flag check failed for something (', $clientversion, ')')"/>
- </when>
- <when test="$FailStrict">
- <if test="$undeclared">
- <fail code="1" message="'not strict'"/>
- </if>
- </when>
- <when test="$FailLevel1A">
- <fail code="11" message="'FailLevel1A'"/>
- </when>
- <when test="$FailLevel1B">
- <if test="$FailLevel1B">
- <fail code="12" message="'FailLevel1B'"/>
- </if>
- </when>
- <when test="$AssertLevel1C">
- <assert test="not($AssertLevel1C)" code="13" message="'AssertLevel1C'"/>
- </when>
- <otherwise>
- <set-value target="InnerTestCase" select="$testcase"/>
- <choose>
- <when test="$FailLevel2A">
- <fail code="21" message="'FailLevel2A'"/>
- </when>
- <when test="$FailLevel2B">
- <if test="$FailLevel2B">
- <fail code="22" message="'FailLevel2B'"/>
- </if>
- </when>
- <when test="$AssertLevel2C">
- <assert test="not($AssertLevel2C)" code="23" message="'AssertLevel2C'"/>
- </when>
- <otherwise>
- <set-value target="test" select="'auth success'"/>
- <set-value target="Row/Name/Last" select="'XXX'"/>
- <set-value target="Row/Name/Last" select="'POE'"/>
- <append-to-value target="Row/AppendTo" select="'This'"/>
- <append-to-value target="Row/AppendTo" select="'One'"/>
- <append-to-value target="Row/AppendTo" select="'String'"/>
- <add-value target="Row/Name/Aliases/Alias" select="'moe'"/>
- <add-value target="Row/Name/Aliases/Alias" select="'poe'"/>
- <add-value target="Row/Name/Aliases/Alias" select="'roe'"/>
- </otherwise>
- </choose>
- </otherwise>
- </choose>
- </CustomRequestTransform>
- )!!";
- static constexpr const char * esdlScriptSelectPath = R"!!(
- <es:CustomRequestTransform xmlns:es="urn:hpcc:esdl:script" target="soap:Body/extra/{$query}/{$request}">
- <es:param name="selectPath" select="''"/>
- <es:set-value target="_OUTPUT_" select="$selectPath"/>
- </es:CustomRequestTransform>
- )!!";
- static constexpr const char * esdlImplicitNamespaceSelectPath = R"!!(
- <es:CustomRequestTransform xmlns:es="urn:hpcc:esdl:script" target="soap:Body/n:extra/n:{$query}/n:{$request}">
- <es:param name="selectPath" select="''"/>
- <es:set-value target="_OUTPUT_" select="$selectPath"/>
- </es:CustomRequestTransform>
- )!!";
- static constexpr const char* selectPathResult = R"!!(<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
- <soap:Body>
- <extra>
- <EchoPersonInfo>
- <Context>
- <Row>
- <Common>
- <TransactionId>1736623372_3126765312_1333296170</TransactionId>
- </Common>
- </Row>
- </Context>
- <_TransactionId>1736623372_3126765312_1333296170</_TransactionId>
- <EchoPersonInfoRequest>
- <Row>
- <Addresses>
- <Address>
- <type>Home</type>
- <Line2>Apt 202</Line2>
- <Line1>101 Main street</Line1>
- <City>Hometown</City>
- <Zip>96703</Zip>
- <State>HI</State>
- </Address>
- </Addresses>
- <Name>
- <Last>Doe</Last>
- <First>Joe</First>
- </Name>
- </Row>
- <_OUTPUT_>Joe</_OUTPUT_>
- </EchoPersonInfoRequest>
- </EchoPersonInfo>
- </extra>
- </soap:Body>
- </soap:Envelope>)!!";
- bool areEquivalentTestXMLStrings(const char *xml1, const char *xml2)
- {
- if (isEmptyString(xml1) || isEmptyString(xml2))
- return false;
- Owned<IPropertyTree> tree1 = createPTreeFromXMLString(xml1);
- Owned<IPropertyTree> tree2 = createPTreeFromXMLString(xml2);
- return areMatchingPTrees(tree1, tree2);
- }
- static const char *target_config = "<method queryname='EchoPersonInfo'/>";
- class ESDLTests : public CppUnit::TestFixture
- {
- CPPUNIT_TEST_SUITE( ESDLTests );
- CPPUNIT_TEST(testEsdlTransformScript);
- CPPUNIT_TEST(testEsdlTransformScriptNoPrefix);
- CPPUNIT_TEST(testEsdlTransformForEach);
- CPPUNIT_TEST(testEsdlTransformVarScope);
- CPPUNIT_TEST(testEsdlTransformLegacy);
- CPPUNIT_TEST(testEsdlTransformIgnoreScriptErrors);
- CPPUNIT_TEST(testEsdlTransformTargetXpathErrors);
- CPPUNIT_TEST(testEsdlTransformFailStrict);
- CPPUNIT_TEST(testEsdlTransformScriptVarParam);
- CPPUNIT_TEST(testEsdlTransformFailLevel1A);
- CPPUNIT_TEST(testEsdlTransformFailLevel1B);
- CPPUNIT_TEST(testEsdlTransformFailLevel1C);
- CPPUNIT_TEST(testEsdlTransformFailLevel2A);
- CPPUNIT_TEST(testEsdlTransformFailLevel2B);
- CPPUNIT_TEST(testEsdlTransformFailLevel2C);
- CPPUNIT_TEST(testEsdlTransformAnyDescendentPath);
- CPPUNIT_TEST(testEsdlTransformAbsoluteSoapPath);
- CPPUNIT_TEST(testEsdlTransformRelativePath);
- CPPUNIT_TEST(testEsdlTransformSelectPath);
- CPPUNIT_TEST(testEsdlTransformImplicitPrefix);
- CPPUNIT_TEST(testEsdlTransformRequestNamespaces);
- CPPUNIT_TEST(testScriptContext);
- CPPUNIT_TEST(testTargetElement);
- //The following require setup, uncomment for development testing for now:
- //CPPUNIT_TEST(testMysql);
- //CPPUNIT_TEST(testScriptMap); //requires a particular roxie query
- //CPPUNIT_TEST(testHTTPPostXml); //requires a particular roxie query
- CPPUNIT_TEST_SUITE_END();
- public:
- ESDLTests(){}
- inline const char *queryTestName(IPropertyTree *cfg)
- {
- const char *testname = cfg->queryProp("Transform/Param[@name='testcase']/@value");
- if (!testname)
- return "unknown";
- return testname;
- }
- IEsdlScriptContext *createTestScriptContext(IEspContext *ctx, const char *xml, const char *config)
- {
- Owned<IEsdlScriptContext> scriptContext = createEsdlScriptContext(ctx);
- scriptContext->setAttribute(ESDLScriptCtxSection_ESDLInfo, "service", "EsdlExample");
- scriptContext->setAttribute(ESDLScriptCtxSection_ESDLInfo, "method", "EchoPersonInfo");
- scriptContext->setAttribute(ESDLScriptCtxSection_ESDLInfo, "request_type", "EchoPersonInfoRequest");
- scriptContext->setAttribute(ESDLScriptCtxSection_ESDLInfo, "request", "EchoPersonInfoRequest");
- scriptContext->setContent(ESDLScriptCtxSection_BindingConfig, config);
- scriptContext->setContent(ESDLScriptCtxSection_TargetConfig, target_config);
- scriptContext->setContent(ESDLScriptCtxSection_ESDLRequest, xml);
- return scriptContext.getClear();
- }
- void runTransform(IEsdlScriptContext *scriptContext, const char *scriptXml, const char *srcSection, const char *tgtSection, const char *testname, int code)
- {
- Owned<IEsdlCustomTransform> tf = createEsdlCustomTransform(scriptXml, nullptr);
- tf->processTransform(scriptContext, srcSection, tgtSection);
- if (code)
- throw MakeStringException(99, "Test failed(%s): expected an explicit exception %d", testname, code);
- }
- void runTest(const char *testname, const char *scriptXml, const char *xml, const char *config, const char *result, int code)
- {
- try
- {
- //printf("starting %s:\n", testname); //uncomment to help debug
- Owned<IEspContext> ctx = createEspContext(nullptr);
- Owned<IEsdlScriptContext> scriptContext = createTestScriptContext(ctx, xml, config);
- runTransform(scriptContext, scriptXml, ESDLScriptCtxSection_ESDLRequest, ESDLScriptCtxSection_FinalRequest, testname, code);
- StringBuffer output;
- scriptContext->toXML(output.clear(), ESDLScriptCtxSection_FinalRequest);
- if (result && !areEquivalentTestXMLStrings(result, output.str()))
- {
- fputs(output.str(), stdout);
- fflush(stdout);
- fprintf(stdout, "\nTest failed(%s)\n", testname);
- CPPUNIT_ASSERT(false);
- }
- }
- catch (IException *E)
- {
- StringBuffer m;
- if (code!=E->errorCode())
- {
- StringBuffer m;
- fprintf(stdout, "\nTest(%s) Expected %d Exception %d - %s\n", testname, code, E->errorCode(), E->errorMessage(m).str());
- E->Release();
- CPPUNIT_ASSERT(false);
- }
- E->Release();
- }
- }
- void testEsdlTransformSelectPath()
- {
- constexpr const char* config = R"!!(
- <config strictParams='true'>
- <Transform>
- <Param name='testcase' value="select-path"/>
- <Param name='selectPath' select="//First"/>
- </Transform>
- </config>
- )!!";
- runTest("select-path", esdlScriptSelectPath, soapRequest, config, selectPathResult, 0);
- }
- void testEsdlTransformAbsoluteSoapPath()
- {
- constexpr const char* config = R"!!(
- <config strictParams='true'>
- <Transform>
- <Param name='testcase' value="absolute-soap-path"/>
- <Param name='selectPath' select="/esdl_script_context/esdl_request/soap:Envelope/soap:Body/extra/EchoPersonInfo/EchoPersonInfoRequest/Row/Name/First"/>
- </Transform>
- </config>
- )!!";
- runTest("absolute-soap-path", esdlScriptSelectPath, soapRequest, config, selectPathResult, 0);
- }
- void testEsdlTransformRelativePath()
- {
- constexpr const char* config = R"!!(
- <config strictParams='true'>
- <Transform>
- <Param name='testcase' value="relative-path"/>
- <Param name='selectPath' select="soap:Body/extra/EchoPersonInfo/EchoPersonInfoRequest/Row/Name/First"/>
- </Transform>
- </config>
- )!!";
- runTest("relative-path", esdlScriptSelectPath, soapRequest, config, selectPathResult, 0);
- }
- void testEsdlTransformAnyDescendentPath()
- {
- constexpr const char* config = R"!!(
- <config strictParams='true'>
- <Transform>
- <Param name='testcase' value="any-descendent-path"/>
- <Param name='selectPath' select="//First"/>
- </Transform>
- </config>
- )!!";
- runTest("any-descendent-path", esdlScriptSelectPath, soapRequest, config, selectPathResult, 0);
- }
- void testEsdlTransformImplicitPrefix()
- {
- static constexpr const char * soapRequestImplicitPrefix = R"!!(<?xml version="1.0" encoding="UTF-8"?>
- <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://webservices.example.com/WsFooBar">
- <soap:Body>
- <extra>
- <EchoPersonInfo>
- <_TransactionId>1736623372_3126765312_1333296170</_TransactionId>
- <Context>
- <Row>
- <Common>
- <TransactionId>1736623372_3126765312_1333296170</TransactionId>
- </Common>
- </Row>
- </Context>
- <EchoPersonInfoRequest>
- <Row>
- <Name>
- <First>Joe</First>
- <Last>Doe</Last>
- </Name>
- <Addresses>
- <Address>
- <type>Home</type>
- <Line1>101 Main street</Line1>
- <Line2>Apt 202</Line2>
- <City>Hometown</City>
- <State>HI</State>
- <Zip>96703</Zip>
- </Address>
- </Addresses>
- </Row>
- </EchoPersonInfoRequest>
- </EchoPersonInfo>
- </extra>
- </soap:Body>
- </soap:Envelope>
- )!!";
- constexpr const char* implicitPrefixResult = R"!!(<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://webservices.example.com/WsFooBar">
- <soap:Body>
- <extra>
- <EchoPersonInfo>
- <Context>
- <Row>
- <Common>
- <TransactionId>1736623372_3126765312_1333296170</TransactionId>
- </Common>
- </Row>
- </Context>
- <_TransactionId>1736623372_3126765312_1333296170</_TransactionId>
- <EchoPersonInfoRequest>
- <Row>
- <Addresses>
- <Address>
- <type>Home</type>
- <Line2>Apt 202</Line2>
- <Line1>101 Main street</Line1>
- <City>Hometown</City>
- <Zip>96703</Zip>
- <State>HI</State>
- </Address>
- </Addresses>
- <Name>
- <Last>Doe</Last>
- <First>Joe</First>
- </Name>
- </Row>
- <_OUTPUT_>Joe</_OUTPUT_>
- </EchoPersonInfoRequest>
- </EchoPersonInfo>
- </extra>
- </soap:Body>
- </soap:Envelope>)!!";
- constexpr const char* config = R"!!(
- <config strictParams='true'>
- <Transform>
- <Param name='testcase' value="implicit-prefix"/>
- <Param name='selectPath' select="soap:Body/n:extra/n:EchoPersonInfo/n:EchoPersonInfoRequest/n:Row/n:Name/n:First"/>
- </Transform>
- </config>
- )!!";
- constexpr const char* configNoPrefix = R"!!(
- <config strictParams='true'>
- <Transform>
- <Param name='testcase' value="implicit-prefix-not-used"/>
- <Param name='selectPath' select="soap:Body/extra/EchoPersonInfo/EchoPersonInfoRequest/Row/Name/First"/>
- </Transform>
- </config>
- )!!";
- runTest("implicit-prefix", esdlImplicitNamespaceSelectPath, soapRequestImplicitPrefix, config, implicitPrefixResult, 0);
- // The implicit 'n' prefix is required if the content has a namespace defined
- // with no prefix. This test is expected to throw an exception.
- runTest("implicit-prefix-not-used", esdlImplicitNamespaceSelectPath, soapRequestImplicitPrefix, configNoPrefix, implicitPrefixResult, 99);
- }
- void testEsdlTransformRequestNamespaces()
- {
- static constexpr const char * soapRequestNsInvalid = R"!!(<?xml version="1.0" encoding="UTF-8"?>
- <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns="invalid.uri.string">
- <soap:Body>
- <extra>
- <EchoPersonInfo>
- <_TransactionId>1736623372_3126765312_1333296170</_TransactionId>
- <Context>
- <Row>
- <Common>
- <TransactionId>1736623372_3126765312_1333296170</TransactionId>
- </Common>
- </Row>
- </Context>
- <EchoPersonInfoRequest>
- <Row>
- <Name>
- <First>Joe</First>
- <Last>Doe</Last>
- </Name>
- </Row>
- </EchoPersonInfoRequest>
- </EchoPersonInfo>
- </extra>
- </soap:Body>
- </soap:Envelope>
- )!!";
- static constexpr const char * soapRequestNsArbitrary1 = R"!!(<?xml version="1.0" encoding="UTF-8"?>
- <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns="arbitary:urn:text.here?really">
- <soap:Body>
- <extra>
- <EchoPersonInfo>
- <_TransactionId>1736623372_3126765312_1333296170</_TransactionId>
- <Context>
- <Row>
- <Common>
- <TransactionId>1736623372_3126765312_1333296170</TransactionId>
- </Common>
- </Row>
- </Context>
- <EchoPersonInfoRequest>
- <Row>
- <Name>
- <First>Joe</First>
- <Last>Doe</Last>
- </Name>
- </Row>
- </EchoPersonInfoRequest>
- </EchoPersonInfo>
- </extra>
- </soap:Body>
- </soap:Envelope>
- )!!";
- static constexpr const char * soapRequestNsArbitrary2 = R"!!(<?xml version="1.0" encoding="UTF-8"?>
- <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http:hullabaloo//nonsense:foo:bar#fragment">
- <soap:Body>
- <extra>
- <EchoPersonInfo>
- <_TransactionId>1736623372_3126765312_1333296170</_TransactionId>
- <Context>
- <Row>
- <Common>
- <TransactionId>1736623372_3126765312_1333296170</TransactionId>
- </Common>
- </Row>
- </Context>
- <EchoPersonInfoRequest>
- <Row>
- <Name>
- <First>Joe</First>
- <Last>Doe</Last>
- </Name>
- </Row>
- </EchoPersonInfoRequest>
- </EchoPersonInfo>
- </extra>
- </soap:Body>
- </soap:Envelope>
- )!!";
- constexpr const char* namespaceResult = R"!!(<soap:Envelope xmlns="http://webservices.example.com/WsFooBar" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
- <soap:Body>
- <extra>
- <EchoPersonInfo>
- <Context>
- <Row>
- <Common>
- <TransactionId>1736623372_3126765312_1333296170</TransactionId>
- </Common>
- </Row>
- </Context>
- <_TransactionId>1736623372_3126765312_1333296170</_TransactionId>
- <EchoPersonInfoRequest>
- <Row>
- <Name>
- <Last>Doe</Last>
- <First>Joe</First>
- </Name>
- </Row>
- <_OUTPUT_>Joe</_OUTPUT_>
- </EchoPersonInfoRequest>
- </EchoPersonInfo>
- </extra>
- </soap:Body>
- </soap:Envelope>
- )!!";
- constexpr const char* namespaceResultArbitrary1 = R"!!(<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns="arbitary:urn:text.here?really">
- <soap:Body>
- <extra>
- <EchoPersonInfo>
- <Context>
- <Row>
- <Common>
- <TransactionId>1736623372_3126765312_1333296170</TransactionId>
- </Common>
- </Row>
- </Context>
- <_TransactionId>1736623372_3126765312_1333296170</_TransactionId>
- <EchoPersonInfoRequest>
- <Row>
- <Name>
- <Last>Doe</Last>
- <First>Joe</First>
- </Name>
- </Row>
- <_OUTPUT_>Joe</_OUTPUT_>
- </EchoPersonInfoRequest>
- </EchoPersonInfo>
- </extra>
- </soap:Body>
- </soap:Envelope>)!!";
- constexpr const char* namespaceResultArbitrary2 = R"!!(<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http:hullabaloo//nonsense:foo:bar#fragment">
- <soap:Body>
- <extra>
- <EchoPersonInfo>
- <Context>
- <Row>
- <Common>
- <TransactionId>1736623372_3126765312_1333296170</TransactionId>
- </Common>
- </Row>
- </Context>
- <_TransactionId>1736623372_3126765312_1333296170</_TransactionId>
- <EchoPersonInfoRequest>
- <Row>
- <Name>
- <Last>Doe</Last>
- <First>Joe</First>
- </Name>
- </Row>
- <_OUTPUT_>Joe</_OUTPUT_>
- </EchoPersonInfoRequest>
- </EchoPersonInfo>
- </extra>
- </soap:Body>
- </soap:Envelope>)!!";
- constexpr const char* configInvalidURI = R"!!(
- <config strictParams='true'>
- <Transform>
- <Param name='testcase' value="invalid-uri"/>
- <Param name='selectPath' select="soap:Body/n:extra/n:EchoPersonInfo/n:EchoPersonInfoRequest/n:Row/n:Name/n:First"/>
- </Transform>
- </config>
- )!!";
- constexpr const char* configArbitraryURI1 = R"!!(
- <config strictParams='true'>
- <Transform>
- <Param name='testcase' value="arbitrary-uri-1"/>
- <Param name='selectPath' select="soap:Body/n:extra/n:EchoPersonInfo/n:EchoPersonInfoRequest/n:Row/n:Name/n:First"/>
- </Transform>
- </config>
- )!!";
- constexpr const char* configArbitraryURI2 = R"!!(
- <config strictParams='true'>
- <Transform>
- <Param name='testcase' value="arbitrary-uri-2"/>
- <Param name='selectPath' select="soap:Body/n:extra/n:EchoPersonInfo/n:EchoPersonInfoRequest/n:Row/n:Name/n:First"/>
- </Transform>
- </config>
- )!!";
- // An invalid namespace URI that is expected to throw an exception
- runTest("invalid-uri", esdlScriptSelectPath, soapRequestNsInvalid, configInvalidURI, namespaceResult, 5684);
- // Weird but valid URIs for namespaces
- runTest("arbitrary-uri-1", esdlImplicitNamespaceSelectPath, soapRequestNsArbitrary1, configArbitraryURI1, namespaceResultArbitrary1, 0);
- runTest("arbitrary-uri-2", esdlImplicitNamespaceSelectPath, soapRequestNsArbitrary2, configArbitraryURI2, namespaceResultArbitrary2, 0);
- }
- void testEsdlTransformScript()
- {
- constexpr const char *config = R"!!(<config strictParams='true'>
- <Transform>
- <Param name='testcase' value="operations"/>
- </Transform>
- </config>)!!";
- constexpr const char * result = R"!!(<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
- <soap:Body>
- <extra>
- <EchoPersonInfo>
- <Context>
- <Row>
- <Common>
- <TransactionId>1736623372_3126765312_1333296170</TransactionId>
- </Common>
- </Row>
- </Context>
- <_TransactionId>1736623372_3126765312_1333296170</_TransactionId>
- <EchoPersonInfoRequest>
- <InnerTestCase>operations</InnerTestCase>
- <TestCase>operations</TestCase>
- <Var2>script</Var2>
- <Row>
- <Addresses>
- <Address>
- <type>Home</type>
- <Line2>Apt 202</Line2>
- <Line1>101 Main street</Line1>
- <City>Hometown</City>
- <Zip>96703</Zip>
- <State>HI</State>
- </Address>
- </Addresses>
- <Name>
- <Last>POE</Last>
- <Aliases>
- <Alias>moe</Alias>
- <Alias>poe</Alias>
- <Alias>roe</Alias>
- </Aliases>
- <First>Joe</First>
- </Name>
- <AppendTo>ThisOneString</AppendTo>
- </Row>
- <test>auth success</test>
- <Param2>script</Param2>
- </EchoPersonInfoRequest>
- </EchoPersonInfo>
- </extra>
- </soap:Body>
- </soap:Envelope>)!!";
- runTest("operations", esdlScript, soapRequest, config, result, 0);
- }
- void testEsdlTransformScriptNoPrefix()
- {
- constexpr const char *config = R"!!(<config strictParams='true'>
- <Transform>
- <Param name='testcase' value="noprefix"/>
- </Transform>
- </config>)!!";
- constexpr const char * result = R"!!(<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
- <soap:Body>
- <extra>
- <EchoPersonInfo>
- <Context>
- <Row>
- <Common>
- <TransactionId>1736623372_3126765312_1333296170</TransactionId>
- </Common>
- </Row>
- </Context>
- <_TransactionId>1736623372_3126765312_1333296170</_TransactionId>
- <EchoPersonInfoRequest>
- <TestCase>noprefix</TestCase>
- <InnerTestCase>noprefix</InnerTestCase>
- <Var2>script</Var2>
- <Row>
- <Addresses>
- <Address>
- <type>Home</type>
- <Line2>Apt 202</Line2>
- <Line1>101 Main street</Line1>
- <City>Hometown</City>
- <Zip>96703</Zip>
- <State>HI</State>
- </Address>
- </Addresses>
- <Name>
- <Last>POE</Last>
- <Aliases>
- <Alias>moe</Alias>
- <Alias>poe</Alias>
- <Alias>roe</Alias>
- </Aliases>
- <First>Joe</First>
- </Name>
- <AppendTo>ThisOneString</AppendTo>
- </Row>
- <Param2>script</Param2>
- <test>auth success</test>
- </EchoPersonInfoRequest>
- </EchoPersonInfo>
- </extra>
- </soap:Body>
- </soap:Envelope>)!!";
- runTest("noprefix", esdlScriptNoPrefix, soapRequest, config, result, 0);
- }
- void testEsdlTransformFailStrict()
- {
- constexpr const char *config = R"!!(<config strictParams='true'>
- <Transform>
- <Param name='testcase' value="fail strict"/>
- <Param name='FailStrict' select='true()'/>
- <Param name='undeclared' value='inaccessible'/>
- </Transform>
- </config>)!!";
- runTest("fail strict", esdlScript, soapRequest, config, nullptr, 5682);
- constexpr const char *config2 = R"!!(<config strictParams='false'>
- <Transform>
- <Param name='testcase' value="not strict"/>
- <Param name='FailStrict' select='true()'/>
- <Param name='undeclared' select='true()'/>
- </Transform>
- </config>)!!";
- runTest("not strict", esdlScript, soapRequest, config2, nullptr, 1);
- }
- void testEsdlTransformScriptVarParam()
- {
- constexpr const char *config = R"!!(<config strictParams='true'>
- <Transform>
- <Param name='testcase' value="varparam"/>
- <Param name='FailLevel1A' select='false()'/>
- <Param name='FailLevel1B' select='false()'/>
- <Param name='AssertLevel1C' select='false()'/>
- <Param name='FailLevel2A' select='false()'/>
- <Param name='FailLevel2B' select='false()'/>
- <Param name='AssertLevel2C' select='false()'/>
- <Param name='param1' value='provided'/>
- <Param name='param2' select="concat('produced and ', $param1)"/>
- <Param name='var1' value='provided'/>
- <Param name='var2' select="concat('produced and ', $var1)"/>
- </Transform>
- </config>)!!";
- constexpr const char * result = R"!!(<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
- <soap:Body>
- <extra>
- <EchoPersonInfo>
- <Context>
- <Row>
- <Common>
- <TransactionId>1736623372_3126765312_1333296170</TransactionId>
- </Common>
- </Row>
- </Context>
- <_TransactionId>1736623372_3126765312_1333296170</_TransactionId>
- <EchoPersonInfoRequest>
- <InnerTestCase>varparam</InnerTestCase>
- <TestCase>varparam</TestCase>
- <Var2>script</Var2>
- <Row>
- <Addresses>
- <Address>
- <type>Home</type>
- <Line2>Apt 202</Line2>
- <Line1>101 Main street</Line1>
- <City>Hometown</City>
- <Zip>96703</Zip>
- <State>HI</State>
- </Address>
- </Addresses>
- <Name>
- <Last>POE</Last>
- <Aliases>
- <Alias>moe</Alias>
- <Alias>poe</Alias>
- <Alias>roe</Alias>
- </Aliases>
- <First>Joe</First>
- </Name>
- <AppendTo>ThisOneString</AppendTo>
- </Row>
- <test>auth success</test>
- <Param2>produced and provided</Param2>
- </EchoPersonInfoRequest>
- </EchoPersonInfo>
- </extra>
- </soap:Body>
- </soap:Envelope>)!!";
- runTest("fail strict", esdlScript, soapRequest, config, result, 0);
- }
- void testEsdlTransformForEach()
- {
- static constexpr const char * input = R"!!(<?xml version="1.0" encoding="UTF-8"?>
- <root xmlns:xx1="urn:x1" xmlns:xx2="urn:x2">
- <extra>
- <Friends>
- <Name>
- <First>Joe</First>
- <xx1:Alias>Moe</xx1:Alias>
- <xx1:Alias>Poe</xx1:Alias>
- <xx1:Alias>Doe</xx1:Alias>
- </Name>
- <Name>
- <First>Jane</First>
- <xx1:Alias>Jan</xx1:Alias>
- <xx1:Alias>Janie</xx1:Alias>
- <xx1:Alias>Janet</xx1:Alias>
- </Name>
- </Friends>
- <Relatives>
- <Name>
- <First>Jonathon</First>
- <xx1:Alias>John</xx1:Alias>
- <xx1:Alias>Jon</xx1:Alias>
- <xx1:Alias>Johnny</xx1:Alias>
- <xx1:Alias>Johnnie</xx1:Alias>
- </Name>
- <Name>
- <First>Jennifer</First>
- <xx1:Alias>Jen</xx1:Alias>
- <xx1:Alias>Jenny</xx1:Alias>
- <xx1:Alias>Jenna</xx1:Alias>
- </Name>
- </Relatives>
- </extra>
- </root>
- )!!";
- static constexpr const char * forEachScript = R"!!(<es:CustomRequestTransform xmlns:es="urn:hpcc:esdl:script" xmlns:x1="urn:x1" xmlns:x2="urn:x2" target="extra">
- <es:param name="ForBuildListPath"/>
- <es:param name="ForIdPath"/>
- <es:param name="section"/>
- <es:param name="garbage"/>
- <es:for-each select="$ForBuildListPath">
- <es:variable name="q" select="str:decode-uri('%27')"/>
- <es:variable name="path" select="concat($section, '/Name[First=', $q, First, $q, ']/Aliases', $garbage)"/>
- <es:for-each select="x1:Alias">
- <es:choose>
- <es:when test="position()=1">
- <es:append-to-value xpath_target="$path" select="."/>
- </es:when>
- <es:otherwise>
- <es:append-to-value xpath_target="$path" select="','"/>
- <es:append-to-value xpath_target="$path" select="."/>
- </es:otherwise>
- </es:choose>
- </es:for-each>
- </es:for-each>
- <es:for-each select="$ForIdPath">
- <es:add-value target="People/Ids/Id" select="."/>
- </es:for-each>
- </es:CustomRequestTransform>
- )!!";
- constexpr const char * resultFriends = R"!!(<root xmlns:xx1="urn:x1" xmlns:xx2="urn:x2">
- <extra>
- <Relatives>
- <Name>
- <First>Jonathon</First>
- <xx1:Alias>John</xx1:Alias>
- <xx1:Alias>Jon</xx1:Alias>
- <xx1:Alias>Johnny</xx1:Alias>
- <xx1:Alias>Johnnie</xx1:Alias>
- </Name>
- <Name>
- <First>Jennifer</First>
- <xx1:Alias>Jen</xx1:Alias>
- <xx1:Alias>Jenny</xx1:Alias>
- <xx1:Alias>Jenna</xx1:Alias>
- </Name>
- </Relatives>
- <People>
- <Ids>
- <Id>Joe</Id>
- <Id>Jane</Id>
- </Ids>
- </People>
- <Friends>
- <Name>
- <Aliases>Moe,Poe,Doe</Aliases>
- <First>Joe</First>
- <xx1:Alias>Moe</xx1:Alias>
- <xx1:Alias>Poe</xx1:Alias>
- <xx1:Alias>Doe</xx1:Alias>
- </Name>
- <Name>
- <Aliases>Jan,Janie,Janet</Aliases>
- <First>Jane</First>
- <xx1:Alias>Jan</xx1:Alias>
- <xx1:Alias>Janie</xx1:Alias>
- <xx1:Alias>Janet</xx1:Alias>
- </Name>
- </Friends>
- </extra>
- </root>)!!";
- constexpr const char *configFriends = R"!!(<config strictParams="true">
- <Transform>
- <Param name='testcase' value="for each friend"/>
- <Param name='section' select="'Friends'"/>
- <Param name='garbage' select="''"/>
- <Param name='ForBuildListPath' select='/esdl_script_context/esdl_request/root/extra/Friends/Name'/>
- <Param name='ForIdPath' select='extra/Friends/Name/First'/>
- </Transform>
- </config>)!!";
- runTest("for each friend", forEachScript, input, configFriends, resultFriends, 0);
- constexpr const char * resultRelatives = R"!!(<root xmlns:xx1="urn:x1" xmlns:xx2="urn:x2">
- <extra>
- <Relatives>
- <Name>
- <Aliases>John,Jon,Johnny,Johnnie</Aliases>
- <First>Jonathon</First>
- <xx1:Alias>John</xx1:Alias>
- <xx1:Alias>Jon</xx1:Alias>
- <xx1:Alias>Johnny</xx1:Alias>
- <xx1:Alias>Johnnie</xx1:Alias>
- </Name>
- <Name>
- <Aliases>Jen,Jenny,Jenna</Aliases>
- <First>Jennifer</First>
- <xx1:Alias>Jen</xx1:Alias>
- <xx1:Alias>Jenny</xx1:Alias>
- <xx1:Alias>Jenna</xx1:Alias>
- </Name>
- </Relatives>
- <People>
- <Ids>
- <Id>Jonathon</Id>
- <Id>Jennifer</Id>
- </Ids>
- </People>
- <Friends>
- <Name>
- <First>Joe</First>
- <xx1:Alias>Moe</xx1:Alias>
- <xx1:Alias>Poe</xx1:Alias>
- <xx1:Alias>Doe</xx1:Alias>
- </Name>
- <Name>
- <First>Jane</First>
- <xx1:Alias>Jan</xx1:Alias>
- <xx1:Alias>Janie</xx1:Alias>
- <xx1:Alias>Janet</xx1:Alias>
- </Name>
- </Friends>
- </extra>
- </root>)!!";
- constexpr const char *configRelatives = R"!!(<config strictParams="true">
- <Transform>
- <Param name='testcase' value="for each relative"/>
- <Param name='section' select="'Relatives'"/>
- <Param name='garbage' select="''"/>
- <Param name='ForBuildListPath' select='extra/Relatives/Name'/>
- <Param name='ForIdPath' select='/esdl_script_context/esdl_request/root/extra/Relatives/Name/First'/> <!--absolute path may change, highly frowned upon-->
- </Transform>
- </config>)!!";
- runTest("for each relative", forEachScript, input, configRelatives, resultRelatives, 0);
- constexpr const char *configGarbagePathError = R"!!(<config strictParams="true">
- <Transform>
- <Param name='testcase' value="for each garbage path error"/>
- <Param name='section' select="'Friends'"/>
- <Param name='garbage' select="'##'"/>
- <Param name='ForBuildListPath' select='extra/Friends/Name'/>
- <Param name='ForIdPath' select='extra/Friends/Name/First'/>
- </Transform>
- </config>)!!";
- runTest("for each garbage path error", forEachScript, input, configGarbagePathError, nullptr, 5682);
- constexpr const char * resultNada = R"!!(<root xmlns:xx1="urn:x1" xmlns:xx2="urn:x2">
- <extra>
- <Relatives>
- <Name>
- <First>Jonathon</First>
- <xx1:Alias>John</xx1:Alias>
- <xx1:Alias>Jon</xx1:Alias>
- <xx1:Alias>Johnny</xx1:Alias>
- <xx1:Alias>Johnnie</xx1:Alias>
- </Name>
- <Name>
- <First>Jennifer</First>
- <xx1:Alias>Jen</xx1:Alias>
- <xx1:Alias>Jenny</xx1:Alias>
- <xx1:Alias>Jenna</xx1:Alias>
- </Name>
- </Relatives>
- <Friends>
- <Name>
- <First>Joe</First>
- <xx1:Alias>Moe</xx1:Alias>
- <xx1:Alias>Poe</xx1:Alias>
- <xx1:Alias>Doe</xx1:Alias>
- </Name>
- <Name>
- <First>Jane</First>
- <xx1:Alias>Jan</xx1:Alias>
- <xx1:Alias>Janie</xx1:Alias>
- <xx1:Alias>Janet</xx1:Alias>
- </Name>
- </Friends>
- </extra>
- </root>)!!";
- constexpr const char *configNada = R"!!(<config strictParams="true">
- <Transform>
- <Param name='testcase' value="for each nada target"/>
- <Param name='section' select="'Friends'"/>
- <Param name='garbage' select="'/nada'"/>
- <Param name='ForBuildListPath' select='extra/Nada/Name'/>
- <Param name='ForIdPath' select='extra/Friends/Name/First/Nada'/>
- </Transform>
- </config>)!!";
- runTest("for each nada target", forEachScript, input, configNada, resultNada, 0);
- }
- void testEsdlTransformVarScope()
- {
- static constexpr const char * input = R"!!(<?xml version="1.0" encoding="UTF-8"?>
- <root>
- <extra>
- <Friends>
- <Name>
- <First>Joe</First>
- <Alias>Moe</Alias>
- <Alias>Poe</Alias>
- <Alias>Doe</Alias>
- </Name>
- <Name>
- <First>Jane</First>
- <Alias>Jan</Alias>
- <Alias>Janie</Alias>
- <Alias>Janet</Alias>
- </Name>
- </Friends>
- </extra>
- </root>
- )!!";
- static constexpr const char * script = R"!!(<CustomRequestTransform xmlns="urn:hpcc:esdl:script" target="extra">
- <variable name="local" select="'root|'"/>
- <variable name="halfway" select="'root|'"/>
- <variable name="global" select="'root|'"/>
- <append-to-value target="trace-local" select="$local"/>
- <append-to-value target="trace-halfway" select="$halfway"/>
- <append-to-value target="trace-global" select="$global"/>
- <if test="true()">
- <variable name="local" select="'if|'"/>
- <append-to-value target="trace-local" select="$local"/>
- <append-to-value target="trace-halfway" select="$halfway"/>
- <append-to-value target="trace-global" select="$global"/>
- </if>
- <for-each select="extra/Friends/Name">
- <variable name="local" select="'for1|'"/>
- <variable name="q" select="str:decode-uri('%27')"/>
- <variable name="path" select="concat('Friends/Name[First=', $q, First, $q, ']/Aliases')"/>
- <append-to-value target="trace-local" select="$local"/>
- <append-to-value target="trace-halfway" select="$halfway"/>
- <append-to-value target="trace-global" select="$global"/>
- <for-each select="Alias">
- <variable name="halfway" select="'for2|'"/>
- <variable name="local" select="'for2|'"/>
- <append-to-value target="trace-local" select="$local"/>
- <append-to-value target="trace-halfway" select="$halfway"/>
- <append-to-value target="trace-global" select="$global"/>
- <choose>
- <when test="position()=1">
- <variable name="local" select="'when|'"/>
- <append-to-value xpath_target="$path" select="."/>
- <append-to-value target="trace-local" select="$local"/>
- <append-to-value target="trace-halfway" select="$halfway"/>
- <append-to-value target="trace-global" select="$global"/>
- </when>
- <otherwise>
- <variable name="local" select="'otherwise|'"/>
- <append-to-value xpath_target="$path" select="','"/>
- <append-to-value xpath_target="$path" select="."/>
- <append-to-value target="trace-local" select="$local"/>
- <append-to-value target="trace-halfway" select="$halfway"/>
- <append-to-value target="trace-global" select="$global"/>
- </otherwise>
- </choose>
- </for-each>
- </for-each>
- </CustomRequestTransform>
- )!!";
- constexpr const char * result = R"!!(<root>
- <extra>
- <trace-global>root|root|root|root|root|root|root|root|root|root|root|root|root|root|root|root|</trace-global>
- <Friends>
- <Name>
- <Alias>Moe</Alias>
- <Alias>Poe</Alias>
- <Alias>Doe</Alias>
- <Aliases>Moe,Poe,Doe</Aliases>
- <First>Joe</First>
- </Name>
- <Name>
- <Alias>Jan</Alias>
- <Alias>Janie</Alias>
- <Alias>Janet</Alias>
- <Aliases>Jan,Janie,Janet</Aliases>
- <First>Jane</First>
- </Name>
- </Friends>
- <trace-halfway>for2|for2|for2|for2|for2|for2|root|for2|for2|for2|for2|for2|for2|root|root|root|</trace-halfway>
- <trace-local>for2|when|for2|otherwise|for2|otherwise|for1|for2|when|for2|otherwise|for2|otherwise|for1|if|root|</trace-local>
- </extra>
- </root>)!!";
- constexpr const char *config = R"!!(<config strictParams="true">
- <Transform>
- <Param name='testcase' value="variable scope"/>
- </Transform>
- </config>)!!";
- runTest("variable scope", script, input, config, result, 0);
- }
- void testEsdlTransformLegacy()
- {
- static constexpr const char * input = R"!!(<?xml version="1.0" encoding="UTF-8"?>
- <root>
- <Person>
- <Name>
- <First>Joe</First>
- </Name>
- </Person>
- </root>
- )!!";
- static constexpr const char * script = R"!!(<es:CustomRequestTransform xmlns:es="urn:hpcc:esdl:script" target="Person">
- <es:SetValue target="ID" select="Person/Name/First"/>
- <es:AppendValue target="Append" select="Person/Name/First"/>
- <es:AppendValue target="Append" value="'++'"/>
- </es:CustomRequestTransform>
- )!!";
- constexpr const char *config = R"!!(<config><Transform><Param name='testcase' value="legacy"/></Transform></config>)!!";
- constexpr const char * result = R"!!(<root>
- <Person>
- <Append>Joe++</Append>
- <Name>
- <First>Joe</First>
- </Name>
- <ID>Joe</ID>
- </Person>
- </root>)!!";
- runTest("legacy", script, input, config, result, 0);
- }
- void testEsdlTransformIgnoreScriptErrors()
- {
- static constexpr const char * input = R"!!(<?xml version="1.0" encoding="UTF-8"?>
- <root>
- <Person>
- <Name>
- <First>Joe</First>
- </Name>
- </Person>
- </root>
- )!!";
- static constexpr const char * script = R"!!(<es:CustomRequestTransform xmlns:es="urn:hpcc:esdl:script" target="Person">
- <es:SetValue optional='true'/>
- <es:AppendValue select="Person/Name/First" optional='true'/>
- <es:AppendValue target="Append" optional='true'/>
- </es:CustomRequestTransform>
- )!!";
- constexpr const char *config = R"!!(<config><Transform><Param name='testcase' value="ignore script errors"/></Transform></config>)!!";
- constexpr const char * result = R"!!(<root>
- <Person>
- <Name>
- <First>Joe</First>
- </Name>
- </Person>
- </root>)!!";
- runTest("ignore script errors", script, input, config, result, 0);
- }
- void testEsdlTransformTargetXpathErrors()
- {
- static constexpr const char * input = R"!!(<?xml version="1.0" encoding="UTF-8"?>
- <root>
- <Person>
- <Name>
- <First>Joe</First>
- </Name>
- </Person>
- </root>
- )!!";
- static constexpr const char * script = R"!!(<es:CustomRequestTransform xmlns:es="urn:hpcc:esdl:script" target="Person">
- <es:SetValue xpath_target="concat('ID', '##')" select="/root/Person/Name/First"/>
- <es:AppendValue target="Append" select="Person/Name/First"/>
- <es:AppendValue target="Append" value="'++'"/>
- </es:CustomRequestTransform>
- )!!";
- constexpr const char *config = R"!!(<config><Transform><Param name='testcase' value="target xpath errors"/></Transform></config>)!!";
- runTest("target xpath errors", script, input, config, nullptr, 5682); //createPropBranch: cannot create path : ID##
- static constexpr const char * script2 = R"!!(<es:CustomRequestTransform xmlns:es="urn:hpcc:esdl:script" target="Person">
- <es:SetValue target="ID##" select="/root/Person/Name/First"/>
- <es:AppendValue target="Append" select="Person/Name/First"/>
- <es:AppendValue target="Append" value="'++'"/>
- </es:CustomRequestTransform>
- )!!";
- runTest("target xpath errors", script2, input, config, nullptr, 5682); //createPropBranch: cannot create path : ID##
- }
- void testEsdlTransformFailLevel1A()
- {
- constexpr const char *config = R"!!(<config>
- <Transform>
- <Param name='testcase' value="fail Level1A"/>
- <Param name='FailLevel1A' select='true()'/>
- <Param name='FailLevel1B' select='true()'/>
- <Param name='AssertLevel1C' select='true()'/>
- <Param name='FailLevel2A' select='true()'/>
- <Param name='FailLevel2B' select='true()'/>
- <Param name='AssertLevel2C' select='true()'/>
- </Transform>
- </config>)!!";
- runTest("fail Leve1A", esdlScript, soapRequest, config, nullptr, 11);
- }
- void testEsdlTransformFailLevel1B()
- {
- constexpr const char *config = R"!!(<config>
- <Transform>
- <Param name='testcase' value="fail Level1B"/>
- <Param name='FailLevel1A' select='false()'/>
- <Param name='FailLevel1B' select='true()'/>
- <Param name='AssertLevel1C' select='true()'/>
- <Param name='FailLevel2A' select='true()'/>
- <Param name='FailLevel2B' select='true()'/>
- <Param name='AssertLevel2C' select='true()'/>
- </Transform>
- </config>)!!";
- runTest("fail Level1B", esdlScript, soapRequest, config, nullptr, 12);
- }
- void testEsdlTransformFailLevel1C()
- {
- constexpr const char *config = R"!!(<config>
- <Transform>
- <Param name='testcase' value="fail Level1C"/>
- <Param name='FailLevel1A' select='false()'/>
- <Param name='FailLevel1B' select='false()'/>
- <Param name='AssertLevel1C' select='true()'/>
- <Param name='FailLevel2A' select='true()'/>
- <Param name='FailLevel2B' select='true()'/>
- <Param name='AssertLevel2C' select='true()'/>
- </Transform>
- </config>)!!";
- runTest("fail Level1C", esdlScript, soapRequest, config, nullptr, 13);
- }
- void testEsdlTransformFailLevel2A()
- {
- constexpr const char *config = R"!!(<config>
- <Transform>
- <Param name='testcase' value="fail Level2A"/>
- <Param name='FailLevel1A' select='false()'/>
- <Param name='FailLevel1B' select='false()'/>
- <Param name='AssertLevel1C' select='false()'/>
- <Param name='FailLevel2A' select='true()'/>
- <Param name='FailLevel2B' select='true()'/>
- <Param name='AssertLevel2C' select='true()'/>
- </Transform>
- </config>)!!";
- runTest("fail Level2A", esdlScript, soapRequest, config, nullptr, 21);
- }
- void testEsdlTransformFailLevel2B()
- {
- constexpr const char *config = R"!!(<config>
- <Transform>
- <Param name='testcase' value="fail Level2B"/>
- <Param name='FailLevel1A' select='false()'/>
- <Param name='FailLevel1B' select='false()'/>
- <Param name='AssertLevel1C' select='false()'/>
- <Param name='FailLevel2A' select='false()'/>
- <Param name='FailLevel2B' select='true()'/>
- <Param name='AssertLevel2C' select='true()'/>
- </Transform>
- </config>)!!";
- runTest("fail Level2B", esdlScript, soapRequest, config, nullptr, 22);
- }
- void testEsdlTransformFailLevel2C()
- {
- constexpr const char *config = R"!!(<config>
- <Transform>
- <Param name='testcase' value="fail Level2C"/>
- <Param name='FailLevel1A' select='false()'/>
- <Param name='FailLevel1B' select='false()'/>
- <Param name='AssertLevel1C' select='false()'/>
- <Param name='FailLevel2A' select='false()'/>
- <Param name='FailLevel2B' select='false()'/>
- <Param name='AssertLevel2C' select='true()'/>
- </Transform>
- </config>)!!";
- runTest("fail Level2C", esdlScript, soapRequest, config, nullptr, 23);
- }
- void testScriptContext()
- {
- static constexpr const char * input = R"!!(<?xml version="1.0" encoding="UTF-8"?>
- <root>
- <Person>
- <FullName>
- <First>Joe</First>
- <ID>GI101</ID>
- <ID>GI102</ID>
- </FullName>
- </Person>
- </root>
- )!!";
- static constexpr const char * script = R"!!(<es:CustomRequestTransform xmlns:es="urn:hpcc:esdl:script" target="Person">
- <es:param name="testpass"/>
- <es:if test="es:storedValueExists('myvalue')">
- <es:set-value xpath_target="concat('check-value1-pass-', $testpass)" select="concat('already set as of pass-', $testpass)"/>
- <es:set-value target="myvalue" select="es:getStoredStringValue('myvalue')"/>
- <es:remove-node target="Name/ID[1]"/> //removing first one changes the index count so each is 1
- <es:remove-node target="Name/ID[1]"/>
- </es:if>
- <es:if test="es:storedValueExists('myvalue2')">
- <es:set-value xpath_target="concat('check-value2-pass-', $testpass)" select="concat('already set in pass-', $testpass)"/>
- <es:set-value target="myvalue2" select="es:getStoredStringValue('myvalue2')"/>
- </es:if>
- <es:if test="es:logOptionExists('option1')">
- <es:set-value xpath_target="concat('check-logging-option1-pass-', $testpass)" select="concat('already set in pass-', $testpass)"/>
- <es:set-value target="logging-option1" select="es:getLogOption('option1')"/>
- <es:set-value target="logging-option2" select="es:getLogOption('option2')"/>
- <es:set-value target="profile" select="es:getLogProfile()"/>
- </es:if>
- <es:if test="not(es:storedValueExists('myvalue'))">
- <es:set-value xpath_target="concat('check-set-pass-', $testpass)" select="concat('not already set in pass-', $testpass)"/>
- <es:store-value xpath_name="'myvalue2'" select="'another stored value'"/>
- <es:store-value name="myvalue" select="'this is a stored value'"/>
- <es:set-log-option name="option1" select="'this is a logging option value'"/>
- <es:set-log-option xpath_name="'option2'" select="'this is an xpath named logging option value'"/>
- <es:set-log-profile select="'myprofile'"/>
- <es:rename-node target="FullName" new_name="Name"/>
- </es:if>
- </es:CustomRequestTransform>
- )!!";
- constexpr const char *config1 = R"!!(<config>
- <Transform>
- <Param name='testcase' value="script context 1"/>
- <Param name='testpass' value="1"/>
- </Transform>
- </config>)!!";
- constexpr const char *config2 = R"!!(<config>
- <Transform>
- <Param name='testcase' value="script context 2"/>
- <Param name='testpass' value="2"/>
- </Transform>
- </config>)!!";
- try
- {
- Owned<IEspContext> ctx = createEspContext(nullptr);
- Owned<IEsdlScriptContext> scriptContext = createTestScriptContext(ctx, input, config1);
- runTransform(scriptContext, script, ESDLScriptCtxSection_ESDLRequest, "FirstPass", "script context 1", 0);
- scriptContext->setContent(ESDLScriptCtxSection_BindingConfig, config2);
- runTransform(scriptContext, script, "FirstPass", "SecondPass", "script context 2", 0);
- constexpr const char * result = R"!!(<root>
- <Person>
- <Name>
- <First>Joe</First>
- </Name>
- <myvalue>this is a stored value</myvalue>
- <myvalue2>another stored value</myvalue2>
- <logging-option1>this is a logging option value</logging-option1>
- <check-set-pass-1>not already set in pass-1</check-set-pass-1>
- <check-value2-pass-2>already set in pass-2</check-value2-pass-2>
- <logging-option2>this is an xpath named logging option value</logging-option2>
- <profile>myprofile</profile>
- <check-logging-option1-pass-2>already set in pass-2</check-logging-option1-pass-2>
- <check-value1-pass-2>already set as of pass-2</check-value1-pass-2>
- </Person>
- </root>)!!";
- StringBuffer output;
- scriptContext->toXML(output, "SecondPass");
- if (result && !areEquivalentTestXMLStrings(result, output.str()))
- {
- fputs(output.str(), stdout);
- fflush(stdout);
- throw MakeStringException(100, "Test failed(%s)", "script context");
- }
- }
- catch (IException *E)
- {
- StringBuffer m;
- fprintf(stdout, "\nTest(%s) Exception %d - %s\n", "script context", E->errorCode(), E->errorMessage(m).str());
- E->Release();
- CPPUNIT_ASSERT(false);
- }
- }
- void testTargetElement()
- {
- static constexpr const char * input = R"!!(<?xml version="1.0" encoding="UTF-8"?>
- <root>
- <Person>
- <FullName>
- <First>Joe</First>
- <ID>GI101</ID>
- <ID>GI102</ID>
- </FullName>
- <Friends>Jane,John,Jaap,Jessica</Friends>
- </Person>
- </root>
- )!!";
- static constexpr const char * script = R"!!(<es:CustomRequestTransform xmlns:es="urn:hpcc:esdl:script" target="Person">
- <es:variable name='value' select="'abc'"/>
- <es:if-source xpath="NotThere">
- <es:element name="NeverHere">
- <es:copy-of select="."/>
- </es:element>
- </es:if-source>
- <es:if-source xpath="Person">
- <es:set-value target="@found" select="true()"/>
- </es:if-source>
- <es:source xpath="Person">
- <es:ensure-target xpath='How/Did/We/Get'>
- <es:element name='Here'>
- <es:variable name="tkns" select="es:tokenize('aaa,bbb;ccc+yyy', ',;+')"/>
- <es:variable name="friends" select="es:tokenize(Friends, ',')"/>
- <es:set-value target="@whoknows" select="$value"/>
- <es:set-value target="IDontKnow" select="$value"/>
- <es:element name="CopyTokens">
- <es:copy-of select="$tkns"/>
- </es:element>
- <es:element name="CopyFriends">
- <es:copy-of select="$friends"/>
- </es:element>
- <es:element name="CopyFields">
- <es:for-each select="FullName/*">
- <es:element name="CopyField">
- <es:copy-of select="."/>
- </es:element>
- </es:for-each>
- </es:element>
- <es:element name="CopyFullName">
- <es:copy-of select="FullName" new_name='FullerName'/>
- <es:set-value target="FullerName/@valid" select="true()"/>
- </es:element>
- </es:element>
- </es:ensure-target>
- </es:source>
- <es:if-target xpath='PartName'>
- <es:set-value target="NotSet" select="$value"/>
- </es:if-target>
- <es:if-target xpath='FullName'>
- <es:set-value target="IsSet" select="$value"/>
- </es:if-target>
- <es:target xpath='FullName'>
- <es:set-value target="DidntFail" select="$value"/>
- </es:target>
- </es:CustomRequestTransform>
- )!!";
- constexpr const char *config1 = R"!!(<config>
- <Transform>
- <Param name='testcase' value="new features"/>
- </Transform>
- </config>)!!";
- constexpr const char * result = R"!!(<root>
- <Person found="true">
- <FullName>
- <First>Joe</First>
- <ID>GI101</ID>
- <ID>GI102</ID>
- <IsSet>abc</IsSet>
- <DidntFail>abc</DidntFail>
- </FullName>
- <Friends>Jane,John,Jaap,Jessica</Friends>
- <How>
- <Did>
- <We>
- <Get>
- <Here whoknows="abc">
- <IDontKnow>abc</IDontKnow>
- <CopyTokens>
- <token>aaa</token>
- <token>bbb</token>
- <token>ccc</token>
- <token>yyy</token>
- </CopyTokens>
- <CopyFriends>
- <token>Jane</token>
- <token>John</token>
- <token>Jaap</token>
- <token>Jessica</token>
- </CopyFriends>
- <CopyFields>
- <CopyField>
- <First>Joe</First>
- </CopyField>
- <CopyField>
- <ID>GI101</ID>
- </CopyField>
- <CopyField>
- <ID>GI102</ID>
- </CopyField>
- </CopyFields>
- <CopyFullName>
- <FullerName valid="true">
- <First>Joe</First>
- <ID>GI101</ID>
- <ID>GI102</ID>
- </FullerName>
- </CopyFullName>
- </Here>
- </Get>
- </We>
- </Did>
- </How>
- </Person>
- </root>)!!";
- try {
- Owned<IEspContext> ctx = createEspContext(nullptr);
- Owned<IEsdlScriptContext> scriptContext = createTestScriptContext(ctx, input, config1);
- runTransform(scriptContext, script, ESDLScriptCtxSection_ESDLRequest, "FirstPass", "target element 1", 0);
- StringBuffer output;
- scriptContext->toXML(output, "FirstPass");
- if (result && !areEquivalentTestXMLStrings(result, output.str()))
- {
- fputs(output.str(), stdout);
- fflush(stdout);
- throw MakeStringException(100, "Test failed(%s)", "target element");
- }
- }
- catch (IException *E)
- {
- StringBuffer m;
- fprintf(stdout, "\nTest(%s) Exception %d - %s\n", "target element", E->errorCode(), E->errorMessage(m).str());
- E->Release();
- CPPUNIT_ASSERT(false);
- }
- }
- void testHTTPPostXml()
- {
- static constexpr const char * input = R"!!(<?xml version="1.0" encoding="UTF-8"?>
- <root>
- <Person>
- <FullName>
- <First>Joe</First>
- <ID>GI101</ID>
- <ID>GI102</ID>
- </FullName>
- </Person>
- </root>
- )!!";
- static constexpr const char * script = R"!!(<es:CustomRequestTransform xmlns:es="urn:hpcc:esdl:script" target="Person">
- <es:variable name='value' select="'abc'"/>
- <es:http-post-xml url="'http://127.0.0.1:9876'" section="logging" name="roxiestuff">
- <es:content>
- <es:element name="Envelope">
- <es:namespace prefix="soap" uri="http://schemas.xmlsoap.org/soap/envelope/" current="true" />
- <es:element name="Body">
- <es:element name="roxieechopersoninfoRequest">
- <es:namespace uri="urn:hpccsystems:ecl:roxieechopersoninfo" current="true" />
- <es:element name="roxieechopersoninforequest">
- <es:element name="Row">
- <es:element name="Name">
- <es:set-value target="First" value="'aaa'"/>
- <es:set-value target="Last" value="'bbb'"/>
- <es:element name="Aliases">
- <es:set-value target="Alias" value="'ccc'"/>
- <es:set-value target="Alias" value="'ddd'"/>
- <es:add-value target="Alias" value="'eee'"/>
- </es:element>
- </es:element>
- </es:element>
- </es:element>
- </es:element>
- </es:element>
- </es:element>
- </es:content>
- </es:http-post-xml>
- <es:element name="HttpPostStuff">
- <es:copy-of select="$roxiestuff"/>
- </es:element>
- </es:CustomRequestTransform>
- )!!";
- constexpr const char *config1 = R"!!(<config>
- <Transform>
- <Param name='testcase' value="new features"/>
- </Transform>
- </config>)!!";
- constexpr const char * result = R"!!(<root>
- <Person>
- <FullName>
- <First>Joe</First>
- <ID>GI101</ID>
- <ID>GI102</ID>
- </FullName>
- <HttpPostStuff>
- <roxiestuff>
- <request url="http://127.0.0.1:9876">
- <content>
- <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
- <soap:Body>
- <roxieechopersoninfoRequest xmlns="urn:hpccsystems:ecl:roxieechopersoninfo">
- <roxieechopersoninforequest>
- <Row>
- <Name>
- <First>aaa</First>
- <Last>bbb</Last>
- <Aliases>
- <Alias>ccc</Alias>
- <Alias>ddd</Alias>
- </Aliases>
- </Name>
- </Row>
- </roxieechopersoninforequest>
- </roxieechopersoninfoRequest>
- </soap:Body>
- </soap:Envelope>
- </content>
- </request>
- <response status="200 OK" error-code="0" content-type="text/xml">
- <content>
- <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
- <soap:Body>
- <roxieechopersoninfoResponse xmlns="urn:hpccsystems:ecl:roxieechopersoninfo" sequence="0">
- <Results>
- <Result>
- <Dataset xmlns="urn:hpccsystems:ecl:roxieechopersoninfo:result:roxieechopersoninforesponse" name="RoxieEchoPersonInfoResponse">
- <Row>
- <Name>
- <First>aaa</First>
- <Last>bbb</Last>
- <Aliases>
- <Alias>ddd</Alias>
- <Alias>eee</Alias>
- </Aliases>
- </Name>
- <Addresses/>
- </Row>
- </Dataset>
- </Result>
- </Results>
- </roxieechopersoninfoResponse>
- </soap:Body>
- </soap:Envelope>
- </content>
- </response>
- </roxiestuff>
- </HttpPostStuff>
- </Person>
- </root>)!!";
- try {
- Owned<IEspContext> ctx = createEspContext(nullptr);
- Owned<IEsdlScriptContext> scriptContext = createTestScriptContext(ctx, input, config1);
- runTransform(scriptContext, script, ESDLScriptCtxSection_ESDLRequest, "MyResult", "http post xml", 0);
- StringBuffer output;
- scriptContext->toXML(output, "MyResult");
- if (result && !areEquivalentTestXMLStrings(result, output.str()))
- {
- fputs(output.str(), stdout);
- fflush(stdout);
- throw MakeStringException(100, "Test failed(%s)", "http post xml");
- }
- }
- catch (IException *E)
- {
- StringBuffer m;
- fprintf(stdout, "\nTest(%s) Exception %d - %s\n", "http post xml", E->errorCode(), E->errorMessage(m).str());
- E->Release();
- CPPUNIT_ASSERT(false);
- }
- }
- void testMysql()
- {
- constexpr const char *config1 = R"!!(<config>
- <Transform>
- <Param name='testcase' value="new features"/>
- </Transform>
- </config>)!!";
- static constexpr const char * data = R"!!(<?xml version="1.0" encoding="UTF-8"?>
- <root>
- <insert>
- <common_value>178</common_value>
- <common_r8>1.2</common_r8>
- <Row>
- <name>selected1</name>
- <bval>65</bval>
- <boolval>1</boolval>
- <r4>3.4</r4>
- <d>aa55aa55</d>
- <ddd>1234567.89</ddd>
- <u1>Straße1</u1>
- <u2>ᚠᛇᚻ᛫ᛒᛦᚦ᛫ᚠᚱᚩᚠᚢᚱ᛫ᚠᛁᚱᚪ᛫ᚷᛖᚻᚹᛦᛚᚳᚢᛗ</u2>
- <dt>2019-02-01 12:59:59</dt>
- </Row>
- <Row>
- <name>selected2</name>
- <bval>65</bval>
- <boolval>1</boolval>
- <r4>4.5</r4>
- <d>bb66bb66</d>
- <ddd>1234567.89</ddd>
- <u1>Straße3</u1>
- <u2>Straße4</u2>
- <dt>2019-02-01 13:59:59</dt>
- </Row>
- <Row>
- <name>selected3</name>
- <bval>65</bval>
- <boolval>1</boolval>
- <r4>5.6</r4>
- <d>cc77cc77</d>
- <ddd>1234567.89</ddd>
- <u1>Straße5</u1>
- <u2>色は匂へど 散りぬるを</u2>
- <dt>2019-02-01 14:59:59</dt>
- </Row>
- </insert>
- <cities>
- <name>aeiou</name>
- <name>aeou</name>
- <name>aoui</name>
- <name>ei</name>
- <name>aaa</name>
- <name>bbb</name>
- </cities>
- <read>
- <name>selected1</name>
- <name>selected3</name>
- </read>
- </root>
- )!!";
- static constexpr const char * input = R"!!(<?xml version="1.0" encoding="UTF-8"?>
- <root>
- <Person>
- <FullName>
- <First>Joe</First>
- </FullName>
- </Person>
- </root>
- )!!";
- static constexpr const char * script = R"!!(<es:CustomRequestTransform xmlns:es="urn:hpcc:esdl:script" target="Person">
- <es:variable name="secret" select="'mydb'"/>
- <es:variable name="database" select="'classicmodels'"/>
- <es:variable name="section" select="'sql'"/>
- <es:mysql secret="$secret" database="$database" section="$section" name="drop">
- <es:sql>DROP TABLE IF EXISTS tbl1;</es:sql>
- </es:mysql>
- <es:mysql secret="$secret" database="$database" section="$section" name="create">
- <es:sql>CREATE TABLE tbl1 ( name VARCHAR(20), bval BIT(15), value INT, boolval TINYINT, r8 DOUBLE, r4 FLOAT, d BLOB, ddd DECIMAL(10,2), u1 VARCHAR(10), u2 VARCHAR(10), dt DATETIME );</es:sql>
- </es:mysql>
- <es:mysql select="getDataSection('whatever')/this/insert/Row" secret="$secret" database="$database" section="$section" name="insert_each_row" resultset-tag="'inserted'">
- <es:bind name="name" value="name"/>
- <es:bind name="bval" value="bval" type="BIT(15)"/>
- <es:bind name="value" value="../common_value"/>
- <es:bind name="boolval" value="boolval"/>
- <es:bind name="r8" value="../common_r8"/>
- <es:bind name="r4" value="r4"/>
- <es:bind name="d" value="d"/>
- <es:bind name="ddd" value="ddd"/>
- <es:bind name="u1" value="u1"/>
- <es:bind name="u2" value="u2"/>
- <es:bind name="dt" value="dt"/>
- <es:sql>INSERT INTO tbl1 values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);</es:sql>
- </es:mysql>
- <es:mysql secret="$secret" database="$database" section="$section" name="drop">
- <es:sql>DROP TABLE IF EXISTS tblcities;</es:sql>
- </es:mysql>
- <es:mysql secret="$secret" database="$database" section="$section" name="createcites">
- <es:sql>CREATE TABLE tblcities ( city VARCHAR(20) );</es:sql>
- </es:mysql>
- <es:mysql select="getDataSection('whatever')/this/cities/name" secret="$secret" database="$database" section="$section" name="insert_each_row" resultset-tag="'inserted'">
- <es:bind name="city" value="."/>
- <es:sql>INSERT INTO tblcities values (?);</es:sql>
- </es:mysql>
- <es:mysql select="getDataSection('whatever')/this/read/name" secret="$secret" database="$database" section="$section" name="select_each_name" resultset-tag="'selected'">
- <es:bind name="name" value="."/>
- <es:sql>SELECT * FROM tbl1 where name = ?;</es:sql>
- </es:mysql>
- <es:mysql secret="$secret" database="$database" section="$section" name="mysql_session_info" MYSQL_SET_CHARSET_NAME="'latin1'">
- <es:sql>
- SELECT * FROM performance_schema.session_variables
- WHERE VARIABLE_NAME IN (
- 'character_set_client', 'character_set_connection',
- 'character_set_results', 'collation_connection'
- ) ORDER BY VARIABLE_NAME;
- </es:sql>
- </es:mysql>
- <es:mysql secret="$secret" database="$database" section="$section" name="select_all" resultset-tag="'onecall'">
- <es:sql>SELECT * FROM tbl1;</es:sql>
- </es:mysql>
- <es:for-each select="$select_all/onecall/Row">
- <es:element name="r">
- <es:copy-of select="*"/>
- </es:element>
- </es:for-each>
- <es:mysql secret="$secret" database="$database" section="$section" name="mysqlresult">
- <es:sql>SELECT * FROM tblcities;</es:sql>
- </es:mysql>
- <es:variable name="i" select="$mysqlresult/Row/city[contains(.,'i')]" />
- <es:variable name="e" select="$mysqlresult/Row/city[contains(.,'e')]" />
- <es:ensure-target xpath="iii">
- <es:copy-of select="$i" />
- </es:ensure-target>
- <es:ensure-target xpath="eee">
- <es:copy-of select="$e" />
- </es:ensure-target>
- <es:ensure-target xpath="cities">
- <es:for-each select="set:intersection($i, $e)">
- <es:copy-of select="." />
- </es:for-each>
- </es:ensure-target>
- </es:CustomRequestTransform>
- )!!";
- Owned<IEspContext> ctx = createEspContext(nullptr);
- Owned<IEsdlScriptContext> scriptContext = createTestScriptContext(ctx, input, config1);
- scriptContext->appendContent("whatever", "this", data);
- try
- {
- runTransform(scriptContext, script, ESDLScriptCtxSection_ESDLRequest, "MyResult", "http post xml", 0);
- }
- catch (IException *E)
- {
- StringBuffer m;
- fprintf(stdout, "\nTest(%s) Exception %d - %s\n", "mysql", E->errorCode(), E->errorMessage(m).str());
- E->Release();
- }
- StringBuffer output;
- scriptContext->toXML(output);
- fputs(output.str(), stdout);
- fflush(stdout);
- }
- void testScriptMap()
- {
- constexpr const char * serverScripts = R"!!(<Transforms xmlns:es='urn:hpcc:esdl:script'>
- <es:BackendRequest>
- <es:set-value target="Row/Name/First" value="'modified-request-at-service'" />
- </es:BackendRequest>
- <es:BackendRequest>
- <es:set-value target="BRSRV2" value="'s2'" />
- </es:BackendRequest>
- <es:BackendRequest>
- <es:set-value target="BRSRV3" value="'s3'" />
- </es:BackendRequest>
- <es:BackendResponse xmlns:resp="urn:hpccsystems:ecl:roxieechopersoninfo" xmlns:ds1="urn:hpccsystems:ecl:roxieechopersoninfo:result:roxieechopersoninforesponse">
- <es:target xpath="soap:Body">
- <es:target xpath="resp:roxieechopersoninfoResponse">
- <es:target xpath="resp:Results/resp:Result">
- <es:target xpath="ds1:Dataset[@name='RoxieEchoPersonInfoResponse']">
- <es:set-value target="ds1:Row/ds1:Name/ds1:Last" value="'modified-response-at-service'" />
- </es:target>
- </es:target>
- </es:target>
- </es:target>
- </es:BackendResponse>
- <es:BackendResponse>
- <es:set-value target="BRESPSRV2" value="'s22'" />
- </es:BackendResponse>
- <es:BackendResponse>
- <es:set-value target="BRESPSRV3" value="'s33'" />
- </es:BackendResponse>
- <es:PreLogging>
- <es:set-value target="PLSRV1" value="'s111'" />
- </es:PreLogging>
- <es:PreLogging>
- <es:set-value target="PLSRV2" value="'s222'" />
- </es:PreLogging>
- <es:PreLogging>
- <es:set-value target="PLSRV3" value="'s333'" />
- </es:PreLogging>
- </Transforms>)!!";
- constexpr const char * methodScripts = R"!!(<Transforms xmlns:es='urn:hpcc:esdl:script'>
- <es:BackendRequest>
- <es:append-to-value target="Row/Name/First" value="'-and-method'" />
- </es:BackendRequest>
- <es:BackendRequest>
- <es:set-value target="BRMTH2" value="'m2'" />
- </es:BackendRequest>
- <es:BackendRequest>
- <es:set-value target="BRMTH3" value="'m3'" />
- </es:BackendRequest>
- <es:BackendResponse xmlns:resp="urn:hpccsystems:ecl:roxieechopersoninfo" xmlns:ds1="urn:hpccsystems:ecl:roxieechopersoninfo:result:roxieechopersoninforesponse">
- <es:target xpath="soap:Body">
- <es:target xpath="resp:roxieechopersoninfoResponse">
- <es:target xpath="resp:Results/resp:Result">
- <es:target xpath="ds1:Dataset[@name='RoxieEchoPersonInfoResponse']">
- <es:append-to-value target="ds1:Row/ds1:Name/ds1:Last" value="'-and-method'" />
- </es:target>
- </es:target>
- </es:target>
- </es:target>
- </es:BackendResponse>
- <es:BackendResponse xmlns:resp="urn:hpccsystems:ecl:roxieechopersoninfo" xmlns:ds1="urn:hpccsystems:ecl:roxieechopersoninfo:result:roxieechopersoninforesponse">
- <es:http-post-xml url="'http://127.0.0.1:9876'" section="logdata/LogDataset" name="roxie_call_success">
- <es:content>
- <es:element name="Envelope">
- <es:namespace prefix="soap" uri="http://schemas.xmlsoap.org/soap/envelope/" current="true" />
- <es:element name="Body">
- <es:element name="roxieechopersoninfoRequest">
- <es:namespace uri="urn:hpccsystems:ecl:roxieechopersoninfo" current="true" />
- <es:element name="roxieechopersoninforequest">
- <es:element name="Row">
- <es:element name="Name">
- <es:set-value target="First" value="'echoFirst'"/>
- <es:set-value target="Last" value="'echoLast'"/>
- <es:element name="Aliases">
- <es:set-value target="Alias" value="'echoA1'"/>
- <es:add-value target="Alias" value="'echoA2'"/>
- </es:element>
- </es:element>
- </es:element>
- </es:element>
- </es:element>
- </es:element>
- </es:element>
- </es:content>
- </es:http-post-xml>
- <es:target xpath="soap:Body">
- <es:target xpath="resp:roxieechopersoninfoResponse">
- <es:target xpath="resp:Results/resp:Result">
- <es:target xpath="ds1:Dataset[@name='RoxieEchoPersonInfoResponse']">
- <es:source xpath="$roxie_call_success/response/content">
- <es:source xpath="soap:Envelope/soap:Body">
- <es:source xpath="resp:roxieechopersoninfoResponse/resp:Results/resp:Result">
- <es:source xpath="ds1:Dataset/ds1:Row">
- <es:append-to-value target="ds1:Row/ds1:Name/ds1:Last" value="concat('-plus-echoed-alias-', ds1:Name/ds1:Aliases/ds1:Alias[2])" />
- </es:source>
- </es:source>
- </es:source>
- </es:source>
- </es:target>
- </es:target>
- </es:target>
- </es:target>
- </es:BackendResponse>
- <es:BackendResponse>
- <es:set-value target="BRESPMTH3" value="'m33'" />
- </es:BackendResponse>
- <es:PreLogging>
- <es:http-post-xml url="'http://127.0.0.1:9876'" section="logdata/LogDatasets" name="roxie_call_exception">
- <es:content>
- <es:element name="Envelope">
- <es:namespace prefix="soap" uri="http://schemas.xmlsoap.org/soap/envelope/" current="true" />
- <es:element name="Body">
- <es:element name="nonexistent_query">
- <es:namespace uri="urn:hpccsystems:ecl:roxieechopersoninfo" current="true" />
- <es:element name="nonexistent_queryrequest">
- <es:element name="Row">
- <es:element name="Name">
- <es:set-value target="First" value="'aaa'"/>
- <es:set-value target="Last" value="'bbb'"/>
- <es:element name="Aliases">
- <es:set-value target="Alias" value="'ccc'"/>
- <es:set-value target="Alias" value="'ddd'"/>
- </es:element>
- </es:element>
- </es:element>
- </es:element>
- </es:element>
- </es:element>
- </es:element>
- </es:content>
- </es:http-post-xml>
- </es:PreLogging>
- <es:PreLogging>
- <es:set-value target="PLMTH2" value="'m222'" />
- </es:PreLogging>
- <es:PreLogging>
- <es:set-value target="PLMTH3" value="'m333'" />
- </es:PreLogging>
- </Transforms>)!!";
- constexpr const char * input = R"!!(<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
- <soap:Body>
- <roxieechopersoninfoResponse xmlns="urn:hpccsystems:ecl:roxieechopersoninfo" sequence="0">
- <Results>
- <Result>
- <Dataset xmlns="urn:hpccsystems:ecl:roxieechopersoninfo:result:roxieechopersoninforesponse" name="RoxieEchoPersonInfoResponse">
- <Row>
- <Name>
- <First>aaa</First>
- <Last>bbbb</Last>
- <Aliases>
- <Alias>a</Alias>
- <Alias>b</Alias>
- <Alias>c</Alias>
- </Aliases>
- </Name>
- <Addresses>
- <Address>
- <Line1>111</Line1>
- <Line2>222</Line2>
- <City>Boca Raton</City>
- <State>FL</State>
- <Zip>33487</Zip>
- <type>ttt</type>
- </Address>
- </Addresses>
- </Row>
- </Dataset>
- </Result>
- </Results>
- </roxieechopersoninfoResponse>
- </soap:Body>
- </soap:Envelope>)!!";
- constexpr const char *config1 = R"!!(<config>
- <Transform>
- <Param name='testcase' value="transform map"/>
- </Transform>
- </config>)!!";
- constexpr const char * result = R"!!(<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
- <soap:Body>
- <roxieechopersoninfoResponse xmlns="urn:hpccsystems:ecl:roxieechopersoninfo" sequence="0">
- <Results>
- <Result>
- <Dataset xmlns="urn:hpccsystems:ecl:roxieechopersoninfo:result:roxieechopersoninforesponse" name="RoxieEchoPersonInfoResponse">
- <Row>
- <Name>
- <First>aaa</First>
- <Last>modified-response-at-service-and-method-plus-echoed-alias-echoA2</Last>
- <Aliases>
- <Alias>a</Alias>
- <Alias>b</Alias>
- <Alias>c</Alias>
- </Aliases>
- </Name>
- <Addresses>
- <Address>
- <Line1>111</Line1>
- <Line2>222</Line2>
- <City>Boca Raton</City>
- <State>FL</State>
- <Zip>33487</Zip>
- <type>ttt</type>
- </Address>
- </Addresses>
- </Row>
- </Dataset>
- </Result>
- </Results>
- </roxieechopersoninfoResponse>
- </soap:Body>
- <BRESPSRV2>s22</BRESPSRV2>
- <BRESPSRV3>s33</BRESPSRV3>
- <BRESPMTH3>m33</BRESPMTH3>
- </soap:Envelope>)!!";
- Owned<IEspContext> ctx = createEspContext(nullptr);
- Owned<IEsdlScriptContext> scriptContext = createTestScriptContext(ctx, input, config1);
- bool legacy = false;
- Owned<IEsdlTransformMethodMap> map = createEsdlTransformMethodMap();
- map->addMethodTransforms("", serverScripts, legacy);
- map->addMethodTransforms("mymethod", methodScripts, legacy);
- IEsdlTransformSet *serviceSet = map->queryMethodEntryPoint("", "BackendResponse");
- IEsdlTransformSet *methodSet = map->queryMethodEntryPoint("mymethod", "BackendResponse");
- scriptContext->setContent(ESDLScriptCtxSection_InitialResponse, input);
- processServiceAndMethodTransforms(scriptContext, {serviceSet, methodSet}, ESDLScriptCtxSection_InitialResponse, "MyResult");
- StringBuffer output;
- scriptContext->toXML(output, "MyResult");
- if (result && !areEquivalentTestXMLStrings(result, output.str()))
- {
- fputs(output.str(), stdout);
- fflush(stdout);
- throw MakeStringException(100, "Test failed(%s)", "transform map");
- }
- }
- };
- CPPUNIT_TEST_SUITE_REGISTRATION( ESDLTests );
- CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( ESDLTests, "ESDL" );
- #endif // _USE_CPPUNIT
|