1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153 |
- #include <yql/essentials/minikql/mkql_program_builder.h>
- #include <yql/essentials/minikql/mkql_node_printer.h>
- #include "mkql_computation_list_adapter.h"
- #include "mkql_computation_node_impl.h"
- #include "mkql_computation_node.h"
- #include "mkql_value_builder.h"
- #include <yql/essentials/minikql/mkql_function_registry.h>
- #include <yql/essentials/minikql/mkql_string_util.h>
- #include <yql/essentials/minikql/invoke_builtins/mkql_builtins.h>
- #include "mkql_validate.h"
- #include <yql/essentials/minikql/mkql_type_builder.h>
- #include <yql/essentials/minikql/mkql_utils.h>
- #include <yql/essentials/minikql/comp_nodes/mkql_factories.h>
- #include <library/cpp/testing/unittest/registar.h>
- #include <util/generic/algorithm.h>
- #include <yql/essentials/public/udf/udf_helpers.h>
- namespace NYql {
- namespace {
- using namespace NKikimr::NMiniKQL;
- static const ui32 RAW_INDEX_NO_HOLE = -1;
- static const ui32 RAW_BROKEN_INDEX_LIST_TO_DICT = 1;
- template<class T>
- NUdf::TUnboxedValue ToUnboxedValue(const T& val) {
- return NUdf::TUnboxedValuePod(val);
- }
- NUdf::TUnboxedValue ToUnboxedValue(const TString& val) {
- return MakeString(val);
- }
- NUdf::TUnboxedValue ToUnboxedValue(const NUdf::IBoxedValuePtr& val) {
- return NUdf::TUnboxedValuePod(NUdf::IBoxedValuePtr(val));
- }
- } // namespace NMiniKQL
- /// support for build Struct type @{
- namespace NUdf {
- template<class TContainer>
- struct TListRefIterator: public TBoxedValue {
- TListRefIterator(const TContainer& listRef, ui32 holePos)
- : ListRef(listRef)
- , Index(-1)
- , HolePos(holePos)
- {}
- private:
- const TContainer& ListRef;
- ui32 Index;
- ui32 HolePos;
- bool Next(NUdf::TUnboxedValue& value) final {
- if (++Index >= ListRef.size())
- return false;
- value = Index == HolePos ? NUdf::TUnboxedValue(NUdf::TUnboxedValuePod(42)) : ToUnboxedValue(ListRef[Index]);
- return true;
- }
- };
- template<class TContainer, ui32 TIndexDictBrokenHole = RAW_INDEX_NO_HOLE, bool TNoDictIndex = false>
- struct TListRef: public NUdf::TBoxedValue {
- TListRef(const TContainer& listRef, ui32 holePos = RAW_INDEX_NO_HOLE)
- : ListRef(listRef)
- , HolePos(holePos)
- {}
- private:
- const TContainer& ListRef;
- const NUdf::IValueBuilder* ValueBuilder;
- ui32 HolePos;
- bool HasFastListLength() const override {
- return true;
- }
- ui64 GetListLength() const override {
- return ListRef.size();
- }
- ui64 GetEstimatedListLength() const override {
- return ListRef.size();
- }
- NUdf::TUnboxedValue GetListIterator() const override {
- return NUdf::TUnboxedValuePod(new TListRefIterator<TContainer>(ListRef, HolePos));
- }
- NUdf::IBoxedValuePtr ToIndexDictImpl(const IValueBuilder& builder) const override {
- return TNoDictIndex ? nullptr : builder.ToIndexDict(NUdf::TUnboxedValuePod(
- new TListRef<TContainer, TIndexDictBrokenHole, true>(ListRef, TIndexDictBrokenHole))).AsBoxed();
- }
- };
- struct PersonStruct {
- static const size_t MEMBERS_COUNT = 3;
- static ui32 MetaIndexes[MEMBERS_COUNT];
- static ui32 MetaBackIndexes[MEMBERS_COUNT];
- TString FirstName;
- TString LastName;
- ui32 Age;
- NUdf::TUnboxedValue GetByIndex(ui32 index) const {
- switch (index) {
- case 0: return ToUnboxedValue(FirstName);
- case 1: return ToUnboxedValue(LastName);
- case 2: return NUdf::TUnboxedValuePod(Age);
- default: Y_ABORT("Unexpected");
- }
- }
- };
- ui32 PersonStruct::MetaIndexes[MEMBERS_COUNT];
- ui32 PersonStruct::MetaBackIndexes[MEMBERS_COUNT];
- struct PersonStructWithOptList {
- static const size_t MEMBERS_COUNT = 4;
- static ui32 MetaIndexes[MEMBERS_COUNT];
- static ui32 MetaBackIndexes[MEMBERS_COUNT];
- TString FirstName;
- TString LastName;
- ui32 Age;
- typedef std::vector<ui32> TTagList;
- TTagList Tags;
- NUdf::TUnboxedValue GetByIndex(ui32 index) const {
- switch (index) {
- case 0: return ToUnboxedValue(FirstName);
- case 1: return ToUnboxedValue(LastName);
- case 2: return NUdf::TUnboxedValuePod(Age);
- case 3: return Tags.empty() ?
- NUdf::TUnboxedValuePod() :
- NUdf::TUnboxedValuePod(new TListRef<TTagList>(Tags));
- default: Y_ABORT("Unexpected");
- }
- }
- };
- ui32 PersonStructWithOptList::MetaIndexes[MEMBERS_COUNT];
- ui32 PersonStructWithOptList::MetaBackIndexes[MEMBERS_COUNT];
- struct TCallableOneUi32Arg {
- };
- namespace NImpl {
- template<>
- struct TTypeBuilderHelper<NUdf::PersonStruct> {
- static TType* Build(const IFunctionTypeInfoBuilder& builder) {
- auto structBuilder = builder.Struct(3);
- structBuilder->AddField<char*>("FirstName", &PersonStruct::MetaIndexes[0])
- .AddField<char*>("LastName", &PersonStruct::MetaIndexes[1])
- .AddField<ui32>("Age", &PersonStruct::MetaIndexes[2]);
- auto structType = structBuilder->Build();
- for (const auto& index: PersonStruct::MetaIndexes) {
- Y_ABORT_UNLESS(index < NUdf::PersonStruct::MEMBERS_COUNT);
- NUdf::PersonStruct::MetaBackIndexes[index] = &index - PersonStruct::MetaIndexes;
- Y_ABORT_UNLESS(NUdf::PersonStruct::MetaBackIndexes[index] < NUdf::PersonStruct::MEMBERS_COUNT);
- }
- return structType;
- }
- };
- template<>
- struct TTypeBuilderHelper<NUdf::PersonStructWithOptList> {
- static TType* Build(const IFunctionTypeInfoBuilder& builder) {
- auto listTags = builder.List()->Item<ui32>().Build();
- auto optionalListTags = builder.Optional()->Item(listTags).Build();
- auto structBuilder = builder.Struct(3);
- structBuilder->AddField<char*>("FirstName", &PersonStructWithOptList::MetaIndexes[0])
- .AddField<char*>("LastName", &PersonStructWithOptList::MetaIndexes[1])
- .AddField<ui32>("Age", &PersonStructWithOptList::MetaIndexes[2])
- .AddField("Tags", optionalListTags, &PersonStructWithOptList::MetaIndexes[3]);
- auto structType = structBuilder->Build();
- for (const auto& index: PersonStructWithOptList::MetaIndexes) {
- Y_ABORT_UNLESS(index < NUdf::PersonStructWithOptList::MEMBERS_COUNT);
- NUdf::PersonStructWithOptList::MetaBackIndexes[index] = &index - PersonStructWithOptList::MetaIndexes;
- Y_ABORT_UNLESS(NUdf::PersonStructWithOptList::MetaBackIndexes[index] < NUdf::PersonStructWithOptList::MEMBERS_COUNT);
- }
- return structType;
- }
- };
- template<>
- struct TTypeBuilderHelper<NUdf::TCallableOneUi32Arg> {
- static TType* Build(const IFunctionTypeInfoBuilder& builder) {
- auto callableBuilder = builder.Callable(1);
- callableBuilder->Returns<ui32>();
- callableBuilder->Arg<ui32>();
- return callableBuilder->Build();
- }
- };
- } // namespace NImpl
- } // namespace NUdf
- /// @}
- struct TBrokenSeqListIterator: public NUdf::TBoxedValue {
- TBrokenSeqListIterator(ui32 size, ui32 holePos)
- : Size(size)
- , HolePos(holePos)
- , Index(-1)
- {}
- private:
- ui32 Size;
- ui32 HolePos;
- ui32 Index;
- bool Skip() final {
- return ++Index < Size;
- }
- bool Next(NUdf::TUnboxedValue& value) final {
- if (!Skip())
- return false;
- value = Index == HolePos ? NUdf::TUnboxedValuePod() : NUdf::TUnboxedValuePod(Index);
- return true;
- }
- };
- struct TBrokenSeqListBoxedValue: public NUdf::TBoxedValue {
- TBrokenSeqListBoxedValue(ui32 size, ui32 holePos)
- : ListSize(size)
- , HolePos(holePos)
- {}
- private:
- ui32 ListSize;
- ui32 HolePos;
- bool HasFastListLength() const override {
- return true;
- }
- ui64 GetListLength() const override {
- return ListSize;
- }
- ui64 GetEstimatedListLength() const override {
- return ListSize;
- }
- NUdf::TUnboxedValue GetListIterator() const override {
- return NUdf::TUnboxedValuePod(new TBrokenSeqListIterator(ListSize, HolePos));
- }
- };
- template<class TStructType>
- struct TBrokenStructBoxedValue: public NUdf::TBoxedValue {
- TBrokenStructBoxedValue(const TStructType& data, ui32 holePos = RAW_INDEX_NO_HOLE)
- : Struct(data)
- , HolePos(holePos)
- {}
- private:
- const TStructType& Struct;
- ui32 HolePos;
- NUdf::TUnboxedValue GetElement(ui32 index) const override {
- if (index == HolePos) {
- return NUdf::TUnboxedValuePod();
- }
- return Struct.GetByIndex(TStructType::MetaBackIndexes[index]);
- }
- };
- namespace {
- template<>
- NUdf::TUnboxedValue ToUnboxedValue<NUdf::PersonStruct>(const NUdf::PersonStruct& val) {
- return NUdf::TUnboxedValuePod(new TBrokenStructBoxedValue<NUdf::PersonStruct>(val));
- }
- template<>
- NUdf::TUnboxedValue ToUnboxedValue<NUdf::PersonStructWithOptList>(const NUdf::PersonStructWithOptList& val) {
- return NUdf::TUnboxedValuePod(new TBrokenStructBoxedValue<NUdf::PersonStructWithOptList>(val));
- }
- template<class TTupleType>
- struct TBrokenTupleBoxedValue: public NUdf::TBoxedValue {
- TBrokenTupleBoxedValue(const TTupleType& tuple, ui32 holePos)
- : Tuple(tuple)
- , HolePos(holePos)
- {}
- private:
- const TTupleType& Tuple;
- ui32 HolePos;
- NUdf::TUnboxedValue GetElement(ui32 index) const override {
- if (index == HolePos) {
- return NUdf::TUnboxedValuePod();
- }
- switch (index) {
- case 0: return ToUnboxedValue(std::get<0>(Tuple));
- case 1: return ToUnboxedValue(std::get<1>(Tuple));
- case 2: return ToUnboxedValue(std::get<2>(Tuple));
- case 3: return ToUnboxedValue(std::get<3>(Tuple));
- default: Y_ABORT("Unexpected");
- }
- }
- };
- typedef std::pair<ui32, ui32> PosPair;
- template<class TKey, class TValue>
- struct TBrokenDictIterator: public NUdf::TBoxedValue {
- TBrokenDictIterator(const std::vector<std::pair<TKey, TValue>>& dictData, PosPair holePos)
- : DictData(dictData)
- , HolePos(holePos)
- , Index(-1)
- {}
- private:
- const std::vector<std::pair<TKey, TValue>>& DictData;
- PosPair HolePos;
- ui32 Index;
- bool Skip() final {
- return ++Index < DictData.size();
- }
- bool Next(NUdf::TUnboxedValue& key) final {
- if (!Skip())
- return false;
- key = Index == HolePos.first ? NUdf::TUnboxedValuePod() : NUdf::TUnboxedValuePod(DictData[Index].first);
- return true;
- }
- bool NextPair(NUdf::TUnboxedValue& key, NUdf::TUnboxedValue& payload) final {
- if (!Next(key))
- return false;
- payload = Index == HolePos.second ? NUdf::TUnboxedValue() : ToUnboxedValue(DictData[Index].second);
- return true;
- }
- };
- template<class TKey, class TValue>
- struct TBrokenDictBoxedValue: public NUdf::TBoxedValue {
- TBrokenDictBoxedValue(const std::vector<std::pair<TKey, TValue>>& dictData,
- PosPair holePos, NUdf::TUnboxedValue&& hole = NUdf::TUnboxedValuePod())
- : DictData(dictData)
- , HolePos(holePos)
- , Hole(std::move(hole))
- {}
- private:
- const std::vector<std::pair<TKey, TValue>> DictData;
- PosPair HolePos;
- NUdf::TUnboxedValue Hole;
- NUdf::TUnboxedValue GetKeysIterator() const override {
- return NUdf::TUnboxedValuePod(new TBrokenDictIterator<TKey, TValue>(DictData, HolePos));
- }
- NUdf::TUnboxedValue GetDictIterator() const override {
- return NUdf::TUnboxedValuePod(new TBrokenDictIterator<TKey, TValue>(DictData, HolePos));
- }
- };
- struct TThrowerValue: public NUdf::TBoxedValue {
- static long Count;
- TThrowerValue(NUdf::IBoxedValuePtr&& owner = NUdf::IBoxedValuePtr())
- : Owner(std::move(owner))
- { ++Count; }
- ~TThrowerValue() { --Count; }
- private:
- const NUdf::IBoxedValuePtr Owner;
- bool Skip() override {
- ythrow yexception() << "Throw";
- }
- NUdf::TUnboxedValue GetListIterator() const override {
- return NUdf::TUnboxedValuePod(new TThrowerValue(const_cast<TThrowerValue*>(this)));
- }
- };
- SIMPLE_UDF(TException, NUdf::TListType<ui32>()) {
- Y_UNUSED(valueBuilder);
- Y_UNUSED(args);
- return NUdf::TUnboxedValuePod(new TThrowerValue);
- }
- long TThrowerValue::Count = 0L;
- SIMPLE_UDF(TVoid, void()) {
- Y_UNUSED(valueBuilder);
- Y_UNUSED(args);
- return NUdf::TUnboxedValuePod::Void();
- }
- SIMPLE_UDF_RUN(TNonEmpty, ui32(), NUdf::TOptional<void>) {
- Y_UNUSED(valueBuilder);
- Y_UNUSED(args);
- return NUdf::TUnboxedValuePod(42);
- }
- SIMPLE_UDF(TOptionalNonEmpty, NUdf::TOptional<ui32>()) {
- Y_UNUSED(valueBuilder);
- Y_UNUSED(args);
- return NUdf::TUnboxedValuePod(42);
- }
- SIMPLE_UDF_RUN(TOptionalEmpty, NUdf::TOptional<ui32>(), NUdf::TOptional<void>) {
- Y_UNUSED(valueBuilder);
- Y_UNUSED(args);
- return NUdf::TUnboxedValuePod();
- }
- SIMPLE_UDF(TSub2Mul2BrokenOnLess2, ui32(ui32)) {
- Y_UNUSED(valueBuilder);
- const ui32 arg = args[0].Get<ui32>();
- if (arg >= 2) {
- return NUdf::TUnboxedValuePod((arg - 2) * 2);
- }
- return NUdf::TUnboxedValuePod();
- }
- SIMPLE_UDF_RUN(TBackSub2Mul2, ui32(NUdf::TCallableOneUi32Arg, ui32), NUdf::TOptional<void>) {
- const auto func = args[0];
- const auto& arg = args[1];
- auto usedArg = NUdf::TUnboxedValuePod();
- if (arg.Get<ui32>() < 100) {
- usedArg = arg;
- }
- auto funcResult = func.Run(valueBuilder, &usedArg);
- const auto& backResult = funcResult.Get<ui32>() / 2 + 2;
- return NUdf::TUnboxedValuePod(backResult);
- }
- SIMPLE_UDF(TSeqList, NUdf::TListType<ui32>(ui32)) {
- const ui32 size = args[0].Get<ui32>();
- std::vector<NUdf::TUnboxedValue> res;
- res.resize(size);
- for (ui32 i = 0; i < size; ++i) {
- res[i] = NUdf::TUnboxedValuePod(i);
- }
- return valueBuilder->NewList(res.data(), res.size());
- }
- SIMPLE_UDF_RUN(TSeqListWithHole, NUdf::TListType<ui32>(ui32, ui32), NUdf::TOptional<void>) {
- Y_UNUSED(valueBuilder);
- const ui32 size = args[0].Get<ui32>();
- const ui32 hole = args[1].Get<ui32>();
- NUdf::IBoxedValuePtr boxed(new TBrokenSeqListBoxedValue(size, hole));
- return NUdf::TUnboxedValuePod(std::move(boxed));
- }
- static const auto TUPLE = std::make_tuple(ui8(33), TString("world"), ui64(0xFEEDB00B2A115E), TString("funny bunny"));
- typedef NUdf::TTuple<ui8, char*, ui64, char*> NUdfTuple;
- SIMPLE_UDF(TTuple, NUdfTuple(ui32)) {
- Y_UNUSED(valueBuilder);
- const ui32 holePos = args[0].Get<ui32>();
- NUdf::IBoxedValuePtr boxed(new TBrokenTupleBoxedValue<decltype(TUPLE)>(TUPLE, holePos));
- return NUdf::TUnboxedValuePod(std::move(boxed));
- }
- static const std::vector<std::pair<ui32, ui64>> DICT_DIGIT2DIGIT = {
- {1, 100500},
- {42, 0xDEADBEAF},
- {911, 1234567890},
- {777, 777777777777},
- };
- typedef NUdf::TDict<ui32, ui64> NUdfDictDigDig;
- SIMPLE_UDF_RUN(TDictDigDig, NUdfDictDigDig(ui32, ui32), NUdf::TOptional<void>) {
- Y_UNUSED(valueBuilder);
- const ui32 holeKey = args[0].Get<ui32>();
- const ui32 holeValue = args[1].Get<ui32>();
- NUdf::IBoxedValuePtr boxed(new TBrokenDictBoxedValue<ui32, ui64>(
- DICT_DIGIT2DIGIT, std::make_pair(holeKey, holeValue)));
- return NUdf::TUnboxedValuePod(std::move(boxed));
- }
- SIMPLE_UDF(TDictDigDigHoleAsOpt, NUdfDictDigDig(ui32, ui32)) {
- Y_UNUSED(valueBuilder);
- const ui32 holeKey = args[0].Get<ui32>();
- const ui32 holeValue = args[1].Get<ui32>();
- NUdf::IBoxedValuePtr boxed(new TBrokenDictBoxedValue<ui32, ui64>(DICT_DIGIT2DIGIT,
- std::make_pair(holeKey, holeValue),
- NUdf::TUnboxedValuePod()));
- return NUdf::TUnboxedValuePod(std::move(boxed));
- }
- static const NUdf::PersonStruct STRUCT_PERSON_JONNIE = {"Johnnie Walker", "Blue Label", 25};
- static const NUdf::PersonStruct STRUCT_PERSON_HITHCOCK = {"Alfred", "Hithcock", 81};
- static const NUdf::PersonStruct STRUCT_PERSON_LOVECRAFT = {"Howard", "Lovecraft", 25};
- static const NUdf::PersonStruct STRUCT_PERSON_KING = {"Stephen", "King", 25};
- static const NUdf::PersonStructWithOptList STRUCT_PERSON_HITHCOCK_LIST = {"Alfred", "Hithcock", 81, {}};
- static const NUdf::PersonStructWithOptList STRUCT_PERSON_LOVECRAFT_LIST = {"Howard", "Lovecraft", 25, {3, 2, 99}};
- static const NUdf::PersonStructWithOptList STRUCT_PERSON_KING_LIST = {"Stephen", "King", 25, {}};
- SIMPLE_UDF_RUN(TPersonStruct, NUdf::PersonStruct(ui32), NUdf::TOptional<void>) {
- Y_UNUSED(valueBuilder);
- const ui32 holePos = args[0].Get<ui32>();
- NUdf::IBoxedValuePtr boxed(new TBrokenStructBoxedValue<NUdf::PersonStruct>(STRUCT_PERSON_JONNIE, holePos));
- return NUdf::TUnboxedValuePod(std::move(boxed));
- }
- typedef NUdf::TTuple<NUdf::PersonStructWithOptList,NUdf::PersonStruct,NUdf::PersonStructWithOptList,NUdf::PersonStruct> NUdfPersonTuple;
- static const auto TUPLE_OF_PERSON = std::make_tuple(
- STRUCT_PERSON_HITHCOCK_LIST,
- STRUCT_PERSON_JONNIE,
- STRUCT_PERSON_LOVECRAFT_LIST,
- STRUCT_PERSON_KING);
- static const auto TUPLE_OF_PERSON_NO_LIST = std::make_tuple(STRUCT_PERSON_HITHCOCK_LIST,
- STRUCT_PERSON_JONNIE,
- STRUCT_PERSON_KING_LIST,
- STRUCT_PERSON_KING);
- SIMPLE_UDF(TTupleOfPersonStruct, NUdfPersonTuple(ui32)) {
- Y_UNUSED(valueBuilder);
- const ui32 holePos = args[0].Get<ui32>();
- NUdf::IBoxedValuePtr boxed(new TBrokenTupleBoxedValue<decltype(TUPLE_OF_PERSON)>(TUPLE_OF_PERSON, holePos));
- return NUdf::TUnboxedValuePod(std::move(boxed));
- }
- SIMPLE_UDF(TTupleOfPersonStructNoList, NUdfPersonTuple(ui32)) {
- Y_UNUSED(valueBuilder);
- const ui32 holePos = args[0].Get<ui32>();
- NUdf::IBoxedValuePtr boxed(new TBrokenTupleBoxedValue<decltype(TUPLE_OF_PERSON_NO_LIST)>(TUPLE_OF_PERSON_NO_LIST, holePos));
- return NUdf::TUnboxedValuePod(std::move(boxed));
- }
- static const std::vector<NUdf::PersonStructWithOptList> LIST_OF_STRUCT_PERSON = {
- STRUCT_PERSON_HITHCOCK_LIST,
- STRUCT_PERSON_LOVECRAFT_LIST,
- STRUCT_PERSON_KING_LIST
- };
- typedef NUdf::TDict<ui64,NUdf::PersonStructWithOptList> TIndexDictFromPersonList;
- SIMPLE_UDF(TListOfPersonStructToIndexDict, TIndexDictFromPersonList(ui32)) {
- Y_UNUSED(valueBuilder);
- Y_UNUSED(args);
- NUdf::IBoxedValuePtr boxed(new NUdf::TListRef<decltype(LIST_OF_STRUCT_PERSON)>(LIST_OF_STRUCT_PERSON));
- return valueBuilder->ToIndexDict(NUdf::TUnboxedValuePod(std::move(boxed)));
- }
- SIMPLE_UDF(TListOfPersonStruct, NUdf::TListType<NUdf::PersonStructWithOptList>(ui32)) {
- Y_UNUSED(valueBuilder);
- Y_UNUSED(args);
- NUdf::IBoxedValuePtr boxed(new NUdf::TListRef<decltype(LIST_OF_STRUCT_PERSON)>(LIST_OF_STRUCT_PERSON));
- return NUdf::TUnboxedValuePod(std::move(boxed));
- }
- SIMPLE_UDF(TListOfPersonStructWithBrokenIndexToDict, NUdf::TListType<NUdf::PersonStructWithOptList>()) {
- Y_UNUSED(valueBuilder);
- Y_UNUSED(args);
- NUdf::IBoxedValuePtr boxed(new NUdf::TListRef<decltype(LIST_OF_STRUCT_PERSON), RAW_BROKEN_INDEX_LIST_TO_DICT>(
- LIST_OF_STRUCT_PERSON));
- return NUdf::TUnboxedValuePod(std::move(boxed));
- }
- static const NUdf::PersonStruct* DICT_DIGIT2PERSON_BROKEN_CONTENT_BY_INDEX[] = {
- &STRUCT_PERSON_HITHCOCK, &STRUCT_PERSON_JONNIE, &STRUCT_PERSON_LOVECRAFT
- };
- const ui32 DICT_DIGIT2PERSON_BROKEN_PERSON_INDEX = 1;
- const ui32 DICT_DIGIT2PERSON_BROKEN_STRUCT_INDEX = 2;
- const std::vector<std::pair<ui32, NUdf::IBoxedValuePtr>> MAKE_DICT_DIGIT2PERSON_BROKEN() {
- std::vector<std::pair<ui32, NUdf::IBoxedValuePtr>> DICT_DIGIT2PERSON_BROKEN = {
- { 333, new TBrokenStructBoxedValue<NUdf::PersonStruct>(STRUCT_PERSON_HITHCOCK, RAW_INDEX_NO_HOLE) },
- { 5, new TBrokenStructBoxedValue<NUdf::PersonStruct>(STRUCT_PERSON_JONNIE, DICT_DIGIT2PERSON_BROKEN_STRUCT_INDEX) },
- { 77, new TBrokenStructBoxedValue<NUdf::PersonStruct>(STRUCT_PERSON_LOVECRAFT, RAW_INDEX_NO_HOLE) },
- };
- return DICT_DIGIT2PERSON_BROKEN;
- }
- typedef NUdf::TDict<ui32,NUdf::PersonStruct> NUdfDictDigPerson;
- std::vector<std::pair<ui32, NUdf::IBoxedValuePtr>> MAKE_DICT_DIGIT2PERSON() {
- const std::vector<std::pair<ui32, NUdf::IBoxedValuePtr>> DICT_DIGIT2PERSON = {
- { 333, new TBrokenStructBoxedValue<NUdf::PersonStruct>(STRUCT_PERSON_HITHCOCK, RAW_INDEX_NO_HOLE) },
- { 5, new TBrokenStructBoxedValue<NUdf::PersonStruct>(STRUCT_PERSON_JONNIE, RAW_INDEX_NO_HOLE) },
- { 77, new TBrokenStructBoxedValue<NUdf::PersonStruct>(STRUCT_PERSON_LOVECRAFT, RAW_INDEX_NO_HOLE) },
- };
- return DICT_DIGIT2PERSON;
- }
- SIMPLE_UDF(TDictOfPerson, NUdfDictDigPerson()) {
- Y_UNUSED(args);
- Y_UNUSED(valueBuilder);
- NUdf::IBoxedValuePtr boxed(new TBrokenDictBoxedValue<ui32, NUdf::IBoxedValuePtr>(
- MAKE_DICT_DIGIT2PERSON(), std::make_pair(RAW_INDEX_NO_HOLE, RAW_INDEX_NO_HOLE)));
- return NUdf::TUnboxedValuePod(std::move(boxed));
- }
- SIMPLE_UDF_RUN(TDictOfPersonBroken, NUdfDictDigPerson(), NUdf::TOptional<void>) {
- Y_UNUSED(args);
- Y_UNUSED(valueBuilder);
- NUdf::IBoxedValuePtr boxed(new TBrokenDictBoxedValue<ui32, NUdf::IBoxedValuePtr>(
- MAKE_DICT_DIGIT2PERSON_BROKEN(), std::make_pair(RAW_INDEX_NO_HOLE, RAW_INDEX_NO_HOLE)));
- return NUdf::TUnboxedValuePod(std::move(boxed));
- }
- SIMPLE_MODULE(TUtUDF,
- TException,
- TVoid,
- TNonEmpty,
- TOptionalNonEmpty,
- TOptionalEmpty,
- TSub2Mul2BrokenOnLess2,
- TBackSub2Mul2,
- TSeqList,
- TSeqListWithHole,
- TTuple,
- TDictDigDig,
- TDictDigDigHoleAsOpt,
- TPersonStruct,
- TTupleOfPersonStruct,
- TTupleOfPersonStructNoList,
- TListOfPersonStructToIndexDict,
- TListOfPersonStruct,
- TListOfPersonStructWithBrokenIndexToDict,
- TDictOfPerson,
- TDictOfPersonBroken
- )
- } // unnamed namespace
- TIntrusivePtr<IFunctionRegistry> CreateFunctionRegistryWithUDFs() {
- auto freg = CreateFunctionRegistry(CreateBuiltinRegistry())->Clone();
- freg->AddModule("", "UtUDF", new TUtUDF());
- return freg;
- }
- Y_UNIT_TEST_SUITE(TMiniKQLValidateTest) {
- typedef std::function<std::vector<TRuntimeNode>(TProgramBuilder&)> BuildArgsFunc;
- typedef std::function<void(const NUdf::TUnboxedValuePod&, const NUdf::IValueBuilder*)> ValidateValueFunc;
- typedef std::function<void(const NUdf::TUnboxedValuePod&, const NUdf::IValueBuilder*, const TType* type)> FullValidateValueFunc;
- void ProcessSimpleUdfFunc(const char* udfFuncName, BuildArgsFunc argsFunc = BuildArgsFunc(), ValidateValueFunc validateFunc = ValidateValueFunc(),
- FullValidateValueFunc fullValidateFunc = FullValidateValueFunc(),
- NUdf::EValidateMode validateMode = NUdf::EValidateMode::Lazy) {
- TScopedAlloc alloc(__LOCATION__);
- TTypeEnvironment env(alloc);
- NUdf::ITypeInfoHelper::TPtr typeInfoHelper(new TTypeInfoHelper);
- auto functionRegistry = CreateFunctionRegistryWithUDFs();
- auto randomProvider = CreateDeterministicRandomProvider(1);
- auto timeProvider = CreateDeterministicTimeProvider(10000000);
- TProgramBuilder pgmBuilder(env, *functionRegistry);
- auto funcName = pgmBuilder.Udf(udfFuncName);
- std::vector<TRuntimeNode> execArgs;
- if (argsFunc) {
- execArgs = argsFunc(pgmBuilder);
- }
- auto pgmReturn = pgmBuilder.Apply(funcName, execArgs);
- TExploringNodeVisitor explorer;
- explorer.Walk(pgmReturn.GetNode(), env);
- TComputationPatternOpts opts(alloc.Ref(), env, GetBuiltinFactory(),
- functionRegistry.Get(), validateMode,
- NUdf::EValidatePolicy::Exception, "OFF", EGraphPerProcess::Multi);
- auto pattern = MakeComputationPattern(explorer, pgmReturn, {}, opts);
- auto graph = pattern->Clone(opts.ToComputationOptions(*randomProvider, *timeProvider));
- const auto builder = static_cast<TDefaultValueBuilder*>(graph->GetTerminator());
- builder->RethrowAtTerminate();
- const TBindTerminator bind(graph->GetTerminator());
- auto value = graph->GetValue();
- if (validateFunc) {
- validateFunc(value, builder);
- }
- if (fullValidateFunc) {
- ui32 flags = 0;
- TFunctionTypeInfo funcInfo;
- TType* userType = nullptr;
- TStringBuf typeConfig;
- TStatus status = functionRegistry->FindFunctionTypeInfo(env, typeInfoHelper, nullptr, udfFuncName, userType, typeConfig, flags, {}, nullptr, &funcInfo);
- MKQL_ENSURE(status.IsOk(), status.GetError());
- auto type = funcInfo.FunctionType->GetReturnType();
- fullValidateFunc(value, builder, type);
- }
- }
- Y_UNIT_TEST(TestUdfException) {
- ValidateValueFunc validateFunc = [](const NUdf::TUnboxedValuePod& value, const NUdf::IValueBuilder* valueBuilder) {
- valueBuilder->NewStringNotFilled(0xBAD).AsStringValue().Ref(); // Leak string.
- NUdf::TBoxedValueAccessor::Skip(*value.GetListIterator().AsBoxed().Release()); // Leak value and throw exception.
- };
- UNIT_ASSERT_EXCEPTION(ProcessSimpleUdfFunc("UtUDF.Exception", {}, validateFunc), yexception);
- UNIT_ASSERT_VALUES_EQUAL(TThrowerValue::Count, 0L);
- }
- Y_UNIT_TEST(TestUdfResultCheckVoid) {
- ProcessSimpleUdfFunc("UtUDF.Void");
- }
- Y_UNIT_TEST(TestUdfResultCheckExceptionOnEmpty) {
- TScopedAlloc alloc(__LOCATION__);
- TTypeEnvironment env(alloc);
- bool wrapped = false;
- UNIT_ASSERT_EXCEPTION(TValidate<TValidateErrorPolicyThrow>::Value(nullptr, env.GetTypeOfTypeLazy(),
- NUdf::TUnboxedValuePod(), "ut for verify empty value exception", &wrapped), TUdfValidateException);
- UNIT_ASSERT(!wrapped);
- }
- Y_UNIT_TEST(TestUdfResultCheckNonEmpty) {
- ProcessSimpleUdfFunc("UtUDF.NonEmpty");
- }
- Y_UNIT_TEST(TestUdfResultCheckOptionalNonEmpty) {
- ProcessSimpleUdfFunc("UtUDF.OptionalNonEmpty");
- }
- Y_UNIT_TEST(TestUdfResultCheckOptionalEmpty) {
- ProcessSimpleUdfFunc("UtUDF.OptionalEmpty");
- }
- std::vector<TRuntimeNode> MakeCallableInArgs(ui32 testVal, TProgramBuilder& pgmBuilder) {
- const auto& functionRegistry = pgmBuilder.GetFunctionRegistry();
- const auto udfFuncName = "UtUDF.Sub2Mul2BrokenOnLess2";
- ui32 flags = 0;
- TFunctionTypeInfo funcInfo;
- TType* userType = nullptr;
- TStringBuf typeConfig;
- NUdf::ITypeInfoHelper::TPtr typeInfoHelper(new TTypeInfoHelper);
- TStatus status = functionRegistry.FindFunctionTypeInfo(pgmBuilder.GetTypeEnvironment(), typeInfoHelper, nullptr,
- udfFuncName, userType, typeConfig, flags, {}, nullptr, &funcInfo);
- MKQL_ENSURE(status.IsOk(), status.GetError());
- auto callable = pgmBuilder.Udf(udfFuncName);
- return std::vector<TRuntimeNode>{callable, pgmBuilder.NewDataLiteral(testVal)};
- };
- Y_UNIT_TEST(TestVerifyArgsCallableCorrect) {
- ui32 testVal = 44;
- BuildArgsFunc argsFunc = [testVal](TProgramBuilder& pgmBuilder) {
- return MakeCallableInArgs(testVal, pgmBuilder);
- };
- ValidateValueFunc validateFunc = [testVal](const NUdf::TUnboxedValuePod& value, const NUdf::IValueBuilder* valueBuilder) {
- Y_UNUSED(valueBuilder);
- UNIT_ASSERT_VALUES_EQUAL(testVal, value.Get<ui32>());
- };
- ProcessSimpleUdfFunc("UtUDF.BackSub2Mul2", argsFunc, validateFunc);
- }
- Y_UNIT_TEST(TestVerifyArgsCallableBrokenOnArgument) {
- ui32 testVal = 101;
- BuildArgsFunc argsFunc = [testVal](TProgramBuilder& pgmBuilder) {
- return MakeCallableInArgs(testVal, pgmBuilder);
- };
- UNIT_ASSERT_EXCEPTION(ProcessSimpleUdfFunc("UtUDF.BackSub2Mul2", argsFunc), TUdfValidateException);
- }
- Y_UNIT_TEST(TestVerifyArgsCallableBrokenOnReturn) {
- ui32 testVal = 1;
- BuildArgsFunc argsFunc = [testVal](TProgramBuilder& pgmBuilder) {
- return MakeCallableInArgs(testVal, pgmBuilder);
- };
- UNIT_ASSERT_EXCEPTION(ProcessSimpleUdfFunc("UtUDF.BackSub2Mul2", argsFunc), TUdfValidateException);
- }
- Y_UNIT_TEST(TestUdfResultCheckEmptySeqList) {
- BuildArgsFunc argsFunc = [](TProgramBuilder& pgmBuilder) {
- return std::vector<TRuntimeNode>{pgmBuilder.NewDataLiteral<ui32>(0)};
- };
- ValidateValueFunc validateFunc = [](const NUdf::TUnboxedValuePod& value, const NUdf::IValueBuilder* valueBuilder) {
- Y_UNUSED(valueBuilder);
- auto listIter = value.GetListIterator();
- UNIT_ASSERT(!listIter.Skip());
- };
- ProcessSimpleUdfFunc("UtUDF.SeqList", argsFunc, validateFunc);
- }
- Y_UNIT_TEST(TestUdfResultCheckSeqList) {
- static constexpr ui32 listSize = 31;
- BuildArgsFunc argsFunc = [](TProgramBuilder& pgmBuilder) {
- return std::vector<TRuntimeNode>{pgmBuilder.NewDataLiteral(listSize)};
- };
- ValidateValueFunc validateFunc = [](const NUdf::TUnboxedValuePod& value, const NUdf::IValueBuilder* valueBuilder) {
- Y_UNUSED(valueBuilder);
- ui32 index = 0;
- auto listIter = value.GetListIterator();
- for (NUdf::TUnboxedValue item; listIter.Next(item); ++index) {
- UNIT_ASSERT_VALUES_EQUAL(item.Get<ui32>(), index);
- }
- UNIT_ASSERT_VALUES_EQUAL(index, listSize);
- };
- ProcessSimpleUdfFunc("UtUDF.SeqList", argsFunc, validateFunc);
- }
- Y_UNIT_TEST(TestUdfResultCheckSeqListWithHoleFirst) {
- BuildArgsFunc argsFunc = [](TProgramBuilder& pgmBuilder) {
- const ui32 listSize = 31;
- return std::vector<TRuntimeNode>{pgmBuilder.NewDataLiteral(listSize),
- pgmBuilder.NewDataLiteral<ui32>(0)};
- };
- ValidateValueFunc validateFunc = [](const NUdf::TUnboxedValuePod& value, const NUdf::IValueBuilder* valueBuilder) {
- Y_UNUSED(valueBuilder);
- auto listIter = value.GetListIterator();
- NUdf::TUnboxedValue item;
- UNIT_ASSERT_EXCEPTION(listIter.Next(item), TUdfValidateException);
- for (ui32 index = 1; listIter.Next(item); ++index) {
- UNIT_ASSERT_VALUES_EQUAL(item.Get<ui32>(), index);
- }
- };
- ProcessSimpleUdfFunc("UtUDF.SeqListWithHole", argsFunc, validateFunc);
- UNIT_ASSERT_EXCEPTION(ProcessSimpleUdfFunc("UtUDF.SeqListWithHole", argsFunc, validateFunc, {}, NUdf::EValidateMode::Greedy), TUdfValidateException);
- }
- Y_UNIT_TEST(TestUdfResultCheckSeqListWithHoleMiddle) {
- static constexpr ui32 listSize = 31;
- BuildArgsFunc argsFunc = [](TProgramBuilder& pgmBuilder) {
- return std::vector<TRuntimeNode>{pgmBuilder.NewDataLiteral(listSize),
- pgmBuilder.NewDataLiteral(listSize / 2)};
- };
- ValidateValueFunc validateFunc = [](const NUdf::TUnboxedValuePod& value, const NUdf::IValueBuilder* valueBuilder) {
- Y_UNUSED(valueBuilder);
- UNIT_ASSERT_VALUES_EQUAL(value.GetListLength(), listSize);
- ui32 index = 0;
- const auto listIter = value.GetListIterator();
- for (NUdf::TUnboxedValue item; index < listSize / 2 && listIter.Next(item); ++index) {
- UNIT_ASSERT_VALUES_EQUAL(item.Get<ui32>(), index);
- }
- NUdf::TUnboxedValue bad;
- UNIT_ASSERT_EXCEPTION(listIter.Next(bad), TUdfValidateException);
- ++index;
- for (NUdf::TUnboxedValue item; listIter.Next(item); ++index) {
- UNIT_ASSERT_VALUES_EQUAL(item.Get<ui32>(), index);
- }
- };
- ProcessSimpleUdfFunc("UtUDF.SeqListWithHole", argsFunc, validateFunc);
- UNIT_ASSERT_EXCEPTION(ProcessSimpleUdfFunc("UtUDF.SeqListWithHole", argsFunc, validateFunc, {}, NUdf::EValidateMode::Greedy), TUdfValidateException);
- }
- Y_UNIT_TEST(TestUdfResultCheckSeqListWithHoleLast) {
- static constexpr ui32 listSize = 31;
- BuildArgsFunc argsFunc = [](TProgramBuilder& pgmBuilder) {
- return std::vector<TRuntimeNode>{pgmBuilder.NewDataLiteral(listSize),
- pgmBuilder.NewDataLiteral(listSize - 1)};
- };
- ValidateValueFunc validateFunc = [](const NUdf::TUnboxedValuePod& value, const NUdf::IValueBuilder* valueBuilder) {
- Y_UNUSED(valueBuilder);
- UNIT_ASSERT_VALUES_EQUAL(value.GetListLength(), listSize);
- ui32 index = 0;
- auto listIter = value.GetListIterator();
- for (NUdf::TUnboxedValue item; index < listSize - 1 && listIter.Next(item); ++index) {
- UNIT_ASSERT_VALUES_EQUAL(item.Get<ui32>(), index);
- }
- UNIT_ASSERT_VALUES_EQUAL(index, listSize - 1);
- NUdf::TUnboxedValue bad;
- UNIT_ASSERT_EXCEPTION(listIter.Next(bad), TUdfValidateException);
- };
- ProcessSimpleUdfFunc("UtUDF.SeqListWithHole", argsFunc, validateFunc);
- UNIT_ASSERT_EXCEPTION(ProcessSimpleUdfFunc("UtUDF.SeqListWithHole", argsFunc, validateFunc, {}, NUdf::EValidateMode::Greedy), TUdfValidateException);
- }
- Y_UNIT_TEST(TestUdfResultCheckTuple) {
- BuildArgsFunc argsFunc = [](TProgramBuilder& pgmBuilder) {
- return std::vector<TRuntimeNode>{pgmBuilder.NewDataLiteral(RAW_INDEX_NO_HOLE)};
- };
- ProcessSimpleUdfFunc("UtUDF.Tuple", argsFunc);
- }
- Y_UNIT_TEST(TestUdfResultCheckTupleWithHoleFirst) {
- BuildArgsFunc argsFunc = [](TProgramBuilder& pgmBuilder) {
- return std::vector<TRuntimeNode>{pgmBuilder.NewDataLiteral<ui32>(0)};
- };
- UNIT_ASSERT_EXCEPTION(ProcessSimpleUdfFunc("UtUDF.Tuple", argsFunc), TUdfValidateException);
- }
- Y_UNIT_TEST(TestUdfResultCheckTupleWithHoleMiddle) {
- BuildArgsFunc argsFunc = [](TProgramBuilder& pgmBuilder) {
- return std::vector<TRuntimeNode>{pgmBuilder.NewDataLiteral<ui32>(std::tuple_size<decltype(TUPLE)>::value / 2)};
- };
- UNIT_ASSERT_EXCEPTION(ProcessSimpleUdfFunc("UtUDF.Tuple", argsFunc), TUdfValidateException);
- }
- Y_UNIT_TEST(TestUdfResultCheckTupleWithHoleLast) {
- BuildArgsFunc argsFunc = [](TProgramBuilder& pgmBuilder) {
- return std::vector<TRuntimeNode>{pgmBuilder.NewDataLiteral<ui32>(std::tuple_size<decltype(TUPLE)>::value - 1)};
- };
- UNIT_ASSERT_EXCEPTION(ProcessSimpleUdfFunc("UtUDF.Tuple", argsFunc), TUdfValidateException);
- }
- Y_UNIT_TEST(TestUdfResultCheckDictDigitDigitFull) {
- BuildArgsFunc argsFunc = [](TProgramBuilder& pgmBuilder) {
- return std::vector<TRuntimeNode>{pgmBuilder.NewDataLiteral(RAW_INDEX_NO_HOLE),
- pgmBuilder.NewDataLiteral(RAW_INDEX_NO_HOLE)};
- };
- ValidateValueFunc validateFunc = [](const NUdf::TUnboxedValuePod& value, const NUdf::IValueBuilder* valueBuilder) {
- Y_UNUSED(valueBuilder);
- auto dictIter = value.GetDictIterator();
- ui32 index = 0;
- for (NUdf::TUnboxedValue key, payload; dictIter.NextPair(key, payload); ++index) {
- UNIT_ASSERT_VALUES_EQUAL(key.Get<ui32>(), DICT_DIGIT2DIGIT[index].first);
- UNIT_ASSERT_VALUES_EQUAL(payload.Get<ui64>(), DICT_DIGIT2DIGIT[index].second);
- }
- UNIT_ASSERT_VALUES_EQUAL(index, DICT_DIGIT2DIGIT.size());
- };
- ProcessSimpleUdfFunc("UtUDF.DictDigDig", argsFunc, validateFunc);
- }
- Y_UNIT_TEST(TestUdfResultCheckDictDigitDigitKeyHole) {
- BuildArgsFunc argsFunc = [](TProgramBuilder& pgmBuilder) {
- return std::vector<TRuntimeNode>{pgmBuilder.NewDataLiteral<ui32>(0),
- pgmBuilder.NewDataLiteral(RAW_INDEX_NO_HOLE)};
- };
- ValidateValueFunc validateFunc = [](const NUdf::TUnboxedValuePod& value, const NUdf::IValueBuilder* valueBuilder) {
- Y_UNUSED(valueBuilder);
- auto dictIter = value.GetDictIterator();
- NUdf::TUnboxedValue key, payload;
- UNIT_ASSERT_EXCEPTION(dictIter.NextPair(key, payload), TUdfValidateException);
- for (ui32 index = 1; dictIter.NextPair(key, payload); ++index) {
- UNIT_ASSERT_VALUES_EQUAL(key.Get<ui32>(), DICT_DIGIT2DIGIT[index].first);
- UNIT_ASSERT_VALUES_EQUAL(payload.Get<ui64>(), DICT_DIGIT2DIGIT[index].second);
- }
- };
- ProcessSimpleUdfFunc("UtUDF.DictDigDig", argsFunc, validateFunc);
- }
- Y_UNIT_TEST(TestUdfResultCheckDictDigitDigitValueHole) {
- BuildArgsFunc argsFunc = [](TProgramBuilder& pgmBuilder) {
- return std::vector<TRuntimeNode>{pgmBuilder.NewDataLiteral(RAW_INDEX_NO_HOLE),
- pgmBuilder.NewDataLiteral<ui32>(DICT_DIGIT2DIGIT.size() - 1)};
- };
- ValidateValueFunc validateFunc = [](const NUdf::TUnboxedValuePod& value, const NUdf::IValueBuilder* valueBuilder) {
- Y_UNUSED(valueBuilder);
- auto dictIter = value.GetDictIterator();
- NUdf::TUnboxedValue key, payload;
- for (ui32 index = 0; index < DICT_DIGIT2DIGIT.size() - 1 && dictIter.NextPair(key, payload); ++index) {
- UNIT_ASSERT_VALUES_EQUAL(key.Get<ui32>(), DICT_DIGIT2DIGIT[index].first);
- UNIT_ASSERT_VALUES_EQUAL(payload.Get<ui64>(), DICT_DIGIT2DIGIT[index].second);
- }
- UNIT_ASSERT_EXCEPTION(dictIter.NextPair(key, payload), TUdfValidateException);
- };
- ProcessSimpleUdfFunc("UtUDF.DictDigDig", argsFunc, validateFunc);
- }
- Y_UNIT_TEST(TestUdfResultCheckDictDigitDigitHoleAsOptKeyHole) {
- BuildArgsFunc argsFunc = [](TProgramBuilder& pgmBuilder) {
- return std::vector<TRuntimeNode>{pgmBuilder.NewDataLiteral(RAW_INDEX_NO_HOLE),
- pgmBuilder.NewDataLiteral<ui32>(0)};
- };
- ValidateValueFunc validateFunc = [](const NUdf::TUnboxedValuePod& value, const NUdf::IValueBuilder* valueBuilder) {
- Y_UNUSED(valueBuilder);
- auto dictIter = value.GetDictIterator();
- NUdf::TUnboxedValue key, payload;
- UNIT_ASSERT_EXCEPTION(dictIter.NextPair(key, payload), TUdfValidateException);
- for (ui32 index = 1; dictIter.NextPair(key, payload); ++index) {
- UNIT_ASSERT_VALUES_EQUAL(key.Get<ui32>(), DICT_DIGIT2DIGIT[index].first);
- UNIT_ASSERT_VALUES_EQUAL(payload.Get<ui64>(), DICT_DIGIT2DIGIT[index].second);
- }
- };
- ProcessSimpleUdfFunc("UtUDF.DictDigDig", argsFunc, validateFunc);
- }
- Y_UNIT_TEST(TestUdfResultCheckDictDigitDigitHoleAsOptValueHole) {
- BuildArgsFunc argsFunc = [](TProgramBuilder& pgmBuilder) {
- return std::vector<TRuntimeNode>{pgmBuilder.NewDataLiteral<ui32>(DICT_DIGIT2DIGIT.size() - 1),
- pgmBuilder.NewDataLiteral(RAW_INDEX_NO_HOLE)};
- };
- ValidateValueFunc validateFunc = [](const NUdf::TUnboxedValuePod& value, const NUdf::IValueBuilder* valueBuilder) {
- Y_UNUSED(valueBuilder);
- auto dictIter = value.GetDictIterator();
- NUdf::TUnboxedValue key, payload;
- for (ui32 index = 0; index < DICT_DIGIT2DIGIT.size() - 1 && dictIter.NextPair(key, payload); ++index) {
- UNIT_ASSERT_VALUES_EQUAL(key.Get<ui32>(), DICT_DIGIT2DIGIT[index].first);
- UNIT_ASSERT_VALUES_EQUAL(payload.Get<ui64>(), DICT_DIGIT2DIGIT[index].second);
- }
- UNIT_ASSERT_EXCEPTION(dictIter.NextPair(key, payload), TUdfValidateException);
- };
- ProcessSimpleUdfFunc("UtUDF.DictDigDig", argsFunc, validateFunc);
- }
- Y_UNIT_TEST(TestUdfResultCheckPersonStruct) {
- BuildArgsFunc argsFunc = [](TProgramBuilder& pgmBuilder) {
- return std::vector<TRuntimeNode>{pgmBuilder.NewDataLiteral(RAW_INDEX_NO_HOLE)};
- };
- ProcessSimpleUdfFunc("UtUDF.PersonStruct", argsFunc);
- }
- Y_UNIT_TEST(TestUdfResultCheckPersonStructWithHoleFirst) {
- BuildArgsFunc argsFunc = [](TProgramBuilder& pgmBuilder) {
- return std::vector<TRuntimeNode>{pgmBuilder.NewDataLiteral<ui32>(0)};
- };
- UNIT_ASSERT_EXCEPTION(ProcessSimpleUdfFunc("UtUDF.PersonStruct", argsFunc), TUdfValidateException);
- }
- Y_UNIT_TEST(TestUdfResultCheckPersonStructWithHoleMiddle) {
- BuildArgsFunc argsFunc = [](TProgramBuilder& pgmBuilder) {
- return std::vector<TRuntimeNode>{pgmBuilder.NewDataLiteral<ui32>(1)};
- };
- UNIT_ASSERT_EXCEPTION(ProcessSimpleUdfFunc("UtUDF.PersonStruct", argsFunc), TUdfValidateException);
- }
- Y_UNIT_TEST(TestUdfResultCheckPersonStructWithHoleLast) {
- BuildArgsFunc argsFunc = [](TProgramBuilder& pgmBuilder) {
- return std::vector<TRuntimeNode>{pgmBuilder.NewDataLiteral<ui32>(2)};
- };
- UNIT_ASSERT_EXCEPTION(ProcessSimpleUdfFunc("UtUDF.PersonStruct", argsFunc), TUdfValidateException);
- }
- Y_UNIT_TEST(TestUdfResultCheckTupleOfPersonStruct) {
- BuildArgsFunc argsFunc = [](TProgramBuilder& pgmBuilder) {
- return std::vector<TRuntimeNode>{pgmBuilder.NewDataLiteral(RAW_INDEX_NO_HOLE)};
- };
- FullValidateValueFunc fullValidateFunc = [](const NUdf::TUnboxedValuePod& value, const NUdf::IValueBuilder* valueBuilder,
- const TType* type) {
- bool wrapped = false;
- TValidate<TValidateErrorPolicyThrow, TValidateModeGreedy<TValidateErrorPolicyThrow>>::Value(valueBuilder, type, NUdf::TUnboxedValuePod(value), "full verify func", &wrapped);
- UNIT_ASSERT(!wrapped);
- TValidate<TValidateErrorPolicyThrow, TValidateModeLazy<TValidateErrorPolicyThrow>>::Value(valueBuilder, type, NUdf::TUnboxedValuePod(value), "full verify func", &wrapped);
- UNIT_ASSERT(wrapped);
- };
- ProcessSimpleUdfFunc("UtUDF.TupleOfPersonStruct", argsFunc, {}, fullValidateFunc);
- ProcessSimpleUdfFunc("UtUDF.TupleOfPersonStruct", argsFunc, {}, fullValidateFunc, NUdf::EValidateMode::Greedy);
- }
- Y_UNIT_TEST(TestUdfResultCheckTupleOfPersonStructNoList) {
- BuildArgsFunc argsFunc = [](TProgramBuilder& pgmBuilder) {
- return std::vector<TRuntimeNode>{pgmBuilder.NewDataLiteral(RAW_INDEX_NO_HOLE)};
- };
- FullValidateValueFunc fullValidateFunc = [](const NUdf::TUnboxedValuePod& value,
- const NUdf::IValueBuilder* valueBuilder, const TType* type) {
- bool wrapped = false;
- TValidate<TValidateErrorPolicyThrow>::Value(valueBuilder, type, NUdf::TUnboxedValuePod(value), "full verify func", &wrapped);
- UNIT_ASSERT(!wrapped);
- };
- ProcessSimpleUdfFunc("UtUDF.TupleOfPersonStructNoList", argsFunc, {}, fullValidateFunc);
- ProcessSimpleUdfFunc("UtUDF.TupleOfPersonStructNoList", argsFunc, {}, fullValidateFunc, NUdf::EValidateMode::Greedy);
- }
- void ValidateDictOfPersonStructFunc(const NUdf::TUnboxedValuePod& value, ui32 lookupIndex = 2, ui32 broken_index = RAW_INDEX_NO_HOLE) {
- const auto person = value.Lookup(NUdf::TUnboxedValuePod(ui64(lookupIndex)));
- UNIT_ASSERT(person);
- auto firstName = person.GetElement(NUdf::PersonStructWithOptList::MetaIndexes[0]);
- UNIT_ASSERT_VALUES_EQUAL(TString(firstName.AsStringRef()), LIST_OF_STRUCT_PERSON[lookupIndex].FirstName);
- auto lastName = person.GetElement(NUdf::PersonStructWithOptList::MetaIndexes[1]);
- UNIT_ASSERT_VALUES_EQUAL(TString(lastName.AsStringRef()), LIST_OF_STRUCT_PERSON[lookupIndex].LastName);
- UNIT_ASSERT_VALUES_EQUAL(person.GetElement(NUdf::PersonStructWithOptList::MetaIndexes[2]).Get<ui32>(), LIST_OF_STRUCT_PERSON[lookupIndex].Age);
- UNIT_ASSERT(!person.GetElement(NUdf::PersonStructWithOptList::MetaIndexes[3]));
- auto dictIter = value.GetDictIterator();
- NUdf::TUnboxedValue key, payload;
- for (ui32 index = 0; index < broken_index && dictIter.NextPair(key, payload); ++index) {
- UNIT_ASSERT_VALUES_EQUAL(key.Get<ui64>(), index);
- auto person = payload;
- auto firstName = person.GetElement(NUdf::PersonStructWithOptList::MetaIndexes[0]);
- UNIT_ASSERT_VALUES_EQUAL(TString(firstName.AsStringRef()), LIST_OF_STRUCT_PERSON[index].FirstName);
- auto lastName = person.GetElement(NUdf::PersonStructWithOptList::MetaIndexes[1]);
- UNIT_ASSERT_VALUES_EQUAL(TString(lastName.AsStringRef()), LIST_OF_STRUCT_PERSON[index].LastName);
- UNIT_ASSERT_VALUES_EQUAL(person.GetElement(NUdf::PersonStructWithOptList::MetaIndexes[2]).Get<ui32>(), LIST_OF_STRUCT_PERSON[index].Age);
- const auto origListPtr = LIST_OF_STRUCT_PERSON[index].Tags;
- if (origListPtr.empty()) {
- UNIT_ASSERT(!person.GetElement(NUdf::PersonStructWithOptList::MetaIndexes[3]));
- } else {
- auto memberTags = person.GetElement(NUdf::PersonStructWithOptList::MetaIndexes[3]);
- UNIT_ASSERT(memberTags);
- UNIT_ASSERT_VALUES_EQUAL(memberTags.GetListLength(), origListPtr.size());
- auto origIter = origListPtr.begin();
- auto iter = memberTags.GetListIterator();
- for (NUdf::TUnboxedValue item; iter.Next(item); ++origIter) {
- UNIT_ASSERT_VALUES_EQUAL(item.Get<ui32>(), *origIter);
- }
- }
- }
- if (broken_index < RAW_INDEX_NO_HOLE)
- UNIT_ASSERT_EXCEPTION(dictIter.NextPair(key, payload), TUdfValidateException);
- }
- Y_UNIT_TEST(TestUdfResultCheckListOfPersonStructToIndexDict) {
- BuildArgsFunc argsFunc = [](TProgramBuilder& pgmBuilder) {
- return std::vector<TRuntimeNode>{pgmBuilder.NewDataLiteral(RAW_INDEX_NO_HOLE)};
- };
- ValidateValueFunc validateFunc = [](const NUdf::TUnboxedValuePod& value, const NUdf::IValueBuilder* valueBuilder) {
- Y_UNUSED(valueBuilder);
- ValidateDictOfPersonStructFunc(value);
- };
- ProcessSimpleUdfFunc("UtUDF.ListOfPersonStructToIndexDict", argsFunc, validateFunc);
- }
- Y_UNIT_TEST(TestUdfResultCheckListOfPersonStruct) {
- BuildArgsFunc argsFunc = [](TProgramBuilder& pgmBuilder) {
- return std::vector<TRuntimeNode>{pgmBuilder.NewDataLiteral(RAW_INDEX_NO_HOLE)};
- };
- FullValidateValueFunc fullValidateFunc = [](const NUdf::TUnboxedValuePod& value,
- const NUdf::IValueBuilder* valueBuilder, const TType* type) {
- Y_UNUSED(type);
- auto indexDict = valueBuilder->ToIndexDict(value);
- ValidateDictOfPersonStructFunc(indexDict);
- };
- ProcessSimpleUdfFunc("UtUDF.ListOfPersonStruct", argsFunc, {}, fullValidateFunc);
- }
- Y_UNIT_TEST(TestUdfResultCheckListOfPersonStructWithBrokenIndexToDict) {
- FullValidateValueFunc fullValidateFunc = [](const NUdf::TUnboxedValuePod& value, const NUdf::IValueBuilder* valueBuilder,
- const TType* type) {
- Y_UNUSED(type);
- auto indexDict = valueBuilder->ToIndexDict(value);
- static_assert(RAW_BROKEN_INDEX_LIST_TO_DICT == 1, "a list is too small");
- ValidateDictOfPersonStructFunc(indexDict, RAW_BROKEN_INDEX_LIST_TO_DICT - 1, RAW_BROKEN_INDEX_LIST_TO_DICT);
- /// verify lookup fail on broken index
- UNIT_ASSERT_EXCEPTION(ValidateDictOfPersonStructFunc(indexDict, RAW_BROKEN_INDEX_LIST_TO_DICT, RAW_BROKEN_INDEX_LIST_TO_DICT), TUdfValidateException);
- ValidateDictOfPersonStructFunc(indexDict, RAW_BROKEN_INDEX_LIST_TO_DICT + 1, RAW_BROKEN_INDEX_LIST_TO_DICT);
- };
- ProcessSimpleUdfFunc("UtUDF.ListOfPersonStructWithBrokenIndexToDict", {}, {}, fullValidateFunc);
- }
- Y_UNIT_TEST(TestUdfResultCheckDictOfPerson) {
- ValidateValueFunc validateFunc = [](const NUdf::TUnboxedValuePod& value, const NUdf::IValueBuilder*) {
- auto dictIter = value.GetDictIterator();
- NUdf::TUnboxedValue key, payload;
- for (ui32 index = 0; dictIter.NextPair(key, payload); ++index) {
- UNIT_ASSERT_VALUES_EQUAL(key.Get<ui32>(), MAKE_DICT_DIGIT2PERSON()[index].first);
- auto person = payload;
- auto firstName = person.GetElement(NUdf::PersonStruct::MetaIndexes[0]);
- UNIT_ASSERT_VALUES_EQUAL(TString(firstName.AsStringRef()), DICT_DIGIT2PERSON_BROKEN_CONTENT_BY_INDEX[index]->FirstName);
- auto lastName = person.GetElement(NUdf::PersonStruct::MetaIndexes[1]);
- UNIT_ASSERT_VALUES_EQUAL(TString(lastName.AsStringRef()), DICT_DIGIT2PERSON_BROKEN_CONTENT_BY_INDEX[index]->LastName);
- UNIT_ASSERT_VALUES_EQUAL(person.GetElement(NUdf::PersonStruct::MetaIndexes[2]).Get<ui32>(), DICT_DIGIT2PERSON_BROKEN_CONTENT_BY_INDEX[index]->Age);
- }
- };
- ProcessSimpleUdfFunc("UtUDF.DictOfPerson", {}, validateFunc);
- }
- Y_UNIT_TEST(TestUdfResultCheckDictOfPersonBroken) {
- ValidateValueFunc validateFunc = [](const NUdf::TUnboxedValuePod& value, const NUdf::IValueBuilder*) {
- auto dictIter = value.GetDictIterator();
- NUdf::TUnboxedValue key, payload;
- for (ui32 index = 0; index < DICT_DIGIT2PERSON_BROKEN_PERSON_INDEX && dictIter.NextPair(key, payload); ++index) {
- UNIT_ASSERT_VALUES_EQUAL(key.Get<ui32>(), MAKE_DICT_DIGIT2PERSON_BROKEN()[index].first);
- auto person = payload;
- auto firstName = person.GetElement(NUdf::PersonStruct::MetaIndexes[0]);
- UNIT_ASSERT_VALUES_EQUAL(TString(firstName.AsStringRef()), DICT_DIGIT2PERSON_BROKEN_CONTENT_BY_INDEX[index]->FirstName);
- auto lastName = person.GetElement(NUdf::PersonStruct::MetaIndexes[1]);
- UNIT_ASSERT_VALUES_EQUAL(TString(lastName.AsStringRef()), DICT_DIGIT2PERSON_BROKEN_CONTENT_BY_INDEX[index]->LastName);
- UNIT_ASSERT_VALUES_EQUAL(person.GetElement(NUdf::PersonStruct::MetaIndexes[2]).Get<ui32>(), DICT_DIGIT2PERSON_BROKEN_CONTENT_BY_INDEX[index]->Age);
- }
- UNIT_ASSERT_EXCEPTION(dictIter.NextPair(key, payload), TUdfValidateException);
- };
- ProcessSimpleUdfFunc("UtUDF.DictOfPersonBroken", {}, validateFunc);
- }
- }
- }
|