#include "all.h" #include #include #include enum ESimpleEnum { ValueA, ValueB, }; enum class EEnumClass { ValueC, ValueD, }; #define LWTRACE_UT_PROVIDER(PROBE, EVENT, GROUPS, TYPES, NAMES) \ PROBE(NoParam, GROUPS("Group"), TYPES(), NAMES()) \ PROBE(IntParam, GROUPS("Group"), TYPES(ui32), NAMES("value")) \ PROBE(StringParam, GROUPS("Group"), TYPES(TString), NAMES("value")) \ PROBE(SymbolParam, GROUPS("Group"), TYPES(NLWTrace::TSymbol), NAMES("symbol")) \ PROBE(CheckParam, GROUPS("Group"), TYPES(NLWTrace::TCheck), NAMES("value")) \ PROBE(EnumParams, GROUPS("Group"), TYPES(ESimpleEnum, EEnumClass), NAMES("simpleEnum", "enumClass")) \ PROBE(InstantParam, GROUPS("Group"), TYPES(TInstant), NAMES("value")) \ PROBE(DurationParam, GROUPS("Group"), TYPES(TDuration), NAMES("value")) \ PROBE(ProtoEnum, GROUPS("Group"), TYPES(NLWTrace::EOperatorType), NAMES("value")) \ PROBE(IntIntParams, GROUPS("Group"), TYPES(ui32, ui64), NAMES("value1", "value2")) \ /**/ LWTRACE_DECLARE_PROVIDER(LWTRACE_UT_PROVIDER) LWTRACE_DEFINE_PROVIDER(LWTRACE_UT_PROVIDER) LWTRACE_USING(LWTRACE_UT_PROVIDER) using namespace NLWTrace; Y_UNIT_TEST_SUITE(LWTraceTrace) { #ifndef LWTRACE_DISABLE Y_UNIT_TEST(Smoke) { TManager mngr(*Singleton(), true); TQuery q; bool parsed = NProtoBuf::TextFormat::ParseFromString(R"END( Blocks { ProbeDesc { Name: "NoParam" Provider: "LWTRACE_UT_PROVIDER" } Action { LogAction { } } } )END", &q); UNIT_ASSERT(parsed); mngr.New("Query1", q); LWPROBE(NoParam); struct { void Push(TThread::TId, const TLogItem& item) { UNIT_ASSERT(TString(item.Probe->Event.Name) == "NoParam"); } } reader; mngr.ReadLog("Query1", reader); LWPROBE(EnumParams, ValueA, EEnumClass::ValueC); LWPROBE(InstantParam, TInstant::Seconds(42)); LWPROBE(DurationParam, TDuration::MilliSeconds(146)); LWPROBE(ProtoEnum, OT_EQ); } Y_UNIT_TEST(Predicate) { TManager mngr(*Singleton(), true); TQuery q; bool parsed = NProtoBuf::TextFormat::ParseFromString(R"END( Blocks { ProbeDesc { Name: "IntParam" Provider: "LWTRACE_UT_PROVIDER" } Predicate { Operators { Type: OT_NE Argument { Param: "value" } Argument { Value: "1" } } } Action { LogAction { } } } )END", &q); UNIT_ASSERT(parsed); mngr.New("QueryName", q); LWPROBE(IntParam, 3); LWPROBE(IntParam, 1); LWPROBE(IntParam, 4); LWPROBE(IntParam, 1); LWPROBE(IntParam, 1); LWPROBE(IntParam, 5); struct { ui32 expected = 3; ui32 logsCount = 0; void Push(TThread::TId, const TLogItem& item) { UNIT_ASSERT(TString(item.Probe->Event.Name) == "IntParam"); ui32 value = item.GetParam("value").GetParam().Get(); UNIT_ASSERT(value == expected); expected++; logsCount++; } } reader; mngr.ReadLog("QueryName", reader); UNIT_ASSERT(reader.logsCount == 3); } Y_UNIT_TEST(StatementAction) { TManager mngr(*Singleton(), true); TQuery q; bool parsed = NProtoBuf::TextFormat::ParseFromString(R"END( Blocks { ProbeDesc { Name: "IntParam" Provider: "LWTRACE_UT_PROVIDER" } Action { StatementAction { Type: ST_INC Argument { Variable: "varInc" } } } Action { StatementAction { Type: ST_DEC Argument { Variable: "varDec" } } } Action { StatementAction { Type: ST_MOV Argument { Variable: "varMov" } Argument { Value: "3" } } } Action { StatementAction { Type: ST_ADD_EQ Argument { Variable: "varAddEq" } Argument { Value: "2" } } } Action { StatementAction { Type: ST_ADD_EQ Argument { Variable: "varAddEq" } Argument { Value: "3" } } } Action { StatementAction { Type: ST_SUB_EQ Argument { Variable: "varSubEq" } Argument { Value: "5" } } } Action { StatementAction { Type: ST_ADD Argument { Variable: "varAdd" } Argument { Value: "3" } Argument { Value: "2" } } } Action { StatementAction { Type: ST_SUB Argument { Variable: "varSub" } Argument { Value: "3" } Argument { Value: "2" } } } Action { StatementAction { Type: ST_MUL Argument { Variable: "varMul" } Argument { Value: "6" } Argument { Value: "2" } } } Action { StatementAction { Type: ST_DIV Argument { Variable: "varDiv" } Argument { Value: "6" } Argument { Value: "2" } } } Action { StatementAction { Type: ST_MOD Argument { Variable: "varMod" } Argument { Value: "17" } Argument { Value: "5" } } } } Blocks { ProbeDesc { Name: "IntParam" Provider: "LWTRACE_UT_PROVIDER" } Predicate { Operators { Type: OT_EQ Argument { Variable: "varInc" } Argument { Value: "1" } } Operators { Type: OT_EQ Argument { Variable: "varDec" } Argument { Value: "-1" } } Operators { Type: OT_EQ Argument { Variable: "varMov" } Argument { Value: "3" } } Operators { Type: OT_EQ Argument { Variable: "varAddEq" } Argument { Value: "5" } } Operators { Type: OT_EQ Argument { Variable: "varSubEq" } Argument { Value: "-5" } } Operators { Type: OT_EQ Argument { Variable: "varAdd" } Argument { Value: "5" } } Operators { Type: OT_EQ Argument { Variable: "varSub" } Argument { Value: "1" } } Operators { Type: OT_EQ Argument { Variable: "varMul" } Argument { Value: "12" } } Operators { Type: OT_EQ Argument { Variable: "varDiv" } Argument { Value: "3" } } Operators { Type: OT_EQ Argument { Variable: "varMod" } Argument { Value: "2" } } } Action { LogAction { } } } )END", &q); UNIT_ASSERT(parsed); mngr.New("QueryName", q); LWPROBE(IntParam, 1); LWPROBE(IntParam, 2); struct { int logsCount = 0; void Push(TThread::TId, const TLogItem& item) { UNIT_ASSERT(TString(item.Probe->Event.Name) == "IntParam"); ui32 value = item.GetParam("value").GetParam().Get(); UNIT_ASSERT(value == 1); logsCount++; } } reader; mngr.ReadLog("QueryName", reader); UNIT_ASSERT(reader.logsCount == 1); } Y_UNIT_TEST(StatementActionWithParams) { TManager mngr(*Singleton(), true); TQuery q; bool parsed = NProtoBuf::TextFormat::ParseFromString(R"END( Blocks { ProbeDesc { Name: "IntIntParams" Provider: "LWTRACE_UT_PROVIDER" } Action { StatementAction { Type: ST_MOV Argument { Variable: "varMov" } Argument { Param: "value1" } } } Action { StatementAction { Type: ST_ADD_EQ Argument { Variable: "varAddEq" } Argument { Param: "value1" } } } Action { StatementAction { Type: ST_SUB_EQ Argument { Variable: "varSubEq" } Argument { Param: "value1" } } } Action { StatementAction { Type: ST_ADD Argument { Variable: "varAdd" } Argument { Param: "value1" } Argument { Param: "value2" } } } Action { StatementAction { Type: ST_SUB Argument { Variable: "varSub" } Argument { Param: "value1" } Argument { Param: "value2" } } } Action { StatementAction { Type: ST_MUL Argument { Variable: "varMul" } Argument { Param: "value1" } Argument { Param: "value2" } } } Action { StatementAction { Type: ST_DIV Argument { Variable: "varDiv" } Argument { Param: "value1" } Argument { Param: "value2" } } } Action { StatementAction { Type: ST_MOD Argument { Variable: "varMod" } Argument { Param: "value1" } Argument { Param: "value2" } } } } Blocks { ProbeDesc { Name: "IntIntParams" Provider: "LWTRACE_UT_PROVIDER" } Predicate { Operators { Type: OT_EQ Argument { Variable: "varMov" } Argument { Param: "value1" } } Operators { Type: OT_EQ Argument { Variable: "varAddEq" } Argument { Param: "value1" } } Operators { Type: OT_EQ Argument { Variable: "varSubEq" } Argument { Value: "-22" } } Operators { Type: OT_EQ Argument { Variable: "varAdd" } Argument { Value: "25" } } Operators { Type: OT_EQ Argument { Variable: "varSub" } Argument { Value: "19" } } Operators { Type: OT_EQ Argument { Variable: "varMul" } Argument { Value: "66" } } Operators { Type: OT_EQ Argument { Variable: "varDiv" } Argument { Value: "7" } } Operators { Type: OT_EQ Argument { Variable: "varMod" } Argument { Value: "1" } } } Action { LogAction { } } } )END", &q); UNIT_ASSERT(parsed); mngr.New("QueryName", q); LWPROBE(IntIntParams, 22, 3); struct { int logsCount = 0; void Push(TThread::TId, const TLogItem& item) { UNIT_ASSERT(TString(item.Probe->Event.Name) == "IntIntParams"); logsCount++; } } reader; mngr.ReadLog("QueryName", reader); UNIT_ASSERT(reader.logsCount == 1); } Y_UNIT_TEST(PerThreadLogSize) { TManager mngr(*Singleton(), true); TQuery q; bool parsed = NProtoBuf::TextFormat::ParseFromString(R"END( PerThreadLogSize: 3 Blocks { ProbeDesc { Name: "IntParam" Provider: "LWTRACE_UT_PROVIDER" } Action { LogAction { } } } )END", &q); UNIT_ASSERT(parsed); mngr.New("QueryRandom", q); LWPROBE(IntParam, 1); LWPROBE(IntParam, 2); LWPROBE(IntParam, 3); LWPROBE(IntParam, 4); struct { ui32 logsCount = 0; ui32 expected = 2; void Push(TThread::TId, const TLogItem& item) { UNIT_ASSERT(TString(item.Probe->Event.Name) == "IntParam"); ui32 value = item.GetParam("value").GetParam().Get(); UNIT_ASSERT(value == expected); logsCount++; expected++; } } reader; mngr.ReadLog("QueryRandom", reader); UNIT_ASSERT(reader.logsCount == 3); } Y_UNIT_TEST(CustomAction) { static ui32 nCustomActionsCalls = 0; class TMyActionExecutor: public TCustomActionExecutor { public: TMyActionExecutor(TProbe* probe, const TCustomAction&, TSession*) : TCustomActionExecutor(probe, false /* not destructive */) {} private: bool DoExecute(TOrbit&, const TParams& params) override { (void)params; nCustomActionsCalls++; return true; } }; TManager mngr(*Singleton(), true); mngr.RegisterCustomAction("MyCustomAction", [](TProbe* probe, const TCustomAction& action, TSession* session) { return new TMyActionExecutor(probe, action, session); } ); TQuery q; bool parsed = NProtoBuf::TextFormat::ParseFromString(R"END( Blocks { ProbeDesc { Name: "NoParam" Provider: "LWTRACE_UT_PROVIDER" } Action { CustomAction { Name: "MyCustomAction" } } } )END", &q); UNIT_ASSERT(parsed); mngr.New("Query1", q); LWPROBE(NoParam); UNIT_ASSERT(nCustomActionsCalls == 1); } Y_UNIT_TEST(SafeModeSleepException) { TManager mngr(*Singleton(), false); TQuery q; bool parsed = NProtoBuf::TextFormat::ParseFromString(R"END( Blocks { ProbeDesc { Name: "NoParam" Provider: "LWTRACE_UT_PROVIDER" } Action { SleepAction { NanoSeconds: 1000000000 } } } )END", &q); UNIT_ASSERT(parsed); UNIT_ASSERT_EXCEPTION(mngr.New("QueryName", q), yexception); } Y_UNIT_TEST(Sleep) { TManager mngr(*Singleton(), true); TQuery q; bool parsed = NProtoBuf::TextFormat::ParseFromString(R"END( Blocks { ProbeDesc { Name: "NoParam" Provider: "LWTRACE_UT_PROVIDER" } Action { SleepAction { NanoSeconds: 1000 } } } )END", &q); UNIT_ASSERT(parsed); mngr.New("QueryName", q); const ui64 sleepTimeNs = 1000; // 1 us TInstant t0 = Now(); LWPROBE(NoParam); TInstant t1 = Now(); UNIT_ASSERT(t1.NanoSeconds() - t0.NanoSeconds() >= sleepTimeNs); } Y_UNIT_TEST(ProtoEnumTraits) { using TPbEnumTraits = TParamTraits; TString str; TPbEnumTraits::ToString(TPbEnumTraits::ToStoreType(OT_EQ), &str); UNIT_ASSERT_STRINGS_EQUAL(str, "OT_EQ (0)"); } Y_UNIT_TEST(Track) { TManager mngr(*Singleton(), true); TQuery q; bool parsed = NProtoBuf::TextFormat::ParseFromString(R"END( Blocks { ProbeDesc { Name: "IntParam" Provider: "LWTRACE_UT_PROVIDER" } Action { RunLogShuttleAction { } } } )END", &q); UNIT_ASSERT(parsed); mngr.New("Query1", q); { TOrbit orbit; LWTRACK(IntParam, orbit, 1); LWTRACK(StringParam, orbit, "str"); } struct { void Push(TThread::TId, const TTrackLog& tl) { UNIT_ASSERT(tl.Items.size() == 2); UNIT_ASSERT(TString(tl.Items[0].Probe->Event.Name) == "IntParam"); UNIT_ASSERT(TString(tl.Items[1].Probe->Event.Name) == "StringParam"); } } reader; mngr.ReadDepot("Query1", reader); } Y_UNIT_TEST(ShouldSerializeTracks) { TManager manager(*Singleton(), false); TOrbit orbit; TTraceRequest req; req.SetIsTraced(true); manager.HandleTraceRequest(req, orbit); LWTRACK(NoParam, orbit); LWTRACK(IntParam, orbit, 1); LWTRACK(StringParam, orbit, "str"); LWTRACK(EnumParams, orbit, ValueA, EEnumClass::ValueC); LWTRACK(InstantParam, orbit, TInstant::Seconds(42)); LWTRACK(DurationParam, orbit, TDuration::MilliSeconds(146)); LWTRACK(ProtoEnum, orbit, OT_EQ); LWTRACK(IntIntParams, orbit, 1, 2); TTraceResponse resp; orbit.Serialize(0, *resp.MutableTrace()); auto& r = resp.GetTrace(); UNIT_ASSERT_VALUES_EQUAL(8, r.EventsSize()); const auto& p0 = r.GetEvents(0); UNIT_ASSERT_VALUES_EQUAL("NoParam", p0.GetName()); UNIT_ASSERT_VALUES_EQUAL("LWTRACE_UT_PROVIDER", p0.GetProvider()); UNIT_ASSERT_VALUES_EQUAL(0 , p0.ParamsSize()); const auto& p1 = r.GetEvents(1); UNIT_ASSERT_VALUES_EQUAL("IntParam", p1.GetName()); UNIT_ASSERT_VALUES_EQUAL("LWTRACE_UT_PROVIDER", p1.GetProvider()); UNIT_ASSERT_VALUES_EQUAL(1, p1.GetParams(0).GetUintValue()); const auto& p2 = r.GetEvents(2); UNIT_ASSERT_VALUES_EQUAL("StringParam", p2.GetName()); UNIT_ASSERT_VALUES_EQUAL("LWTRACE_UT_PROVIDER", p2.GetProvider()); UNIT_ASSERT_VALUES_EQUAL("str", p2.GetParams(0).GetStrValue()); const auto& p3 = r.GetEvents(3); UNIT_ASSERT_VALUES_EQUAL("EnumParams", p3.GetName()); UNIT_ASSERT_VALUES_EQUAL("LWTRACE_UT_PROVIDER", p3.GetProvider()); UNIT_ASSERT_VALUES_EQUAL((ui32)ValueA, p3.GetParams(0).GetIntValue()); UNIT_ASSERT_VALUES_EQUAL((ui32)EEnumClass::ValueC, p3.GetParams(1).GetIntValue()); const auto& p4 = r.GetEvents(4); UNIT_ASSERT_VALUES_EQUAL("InstantParam", p4.GetName()); UNIT_ASSERT_VALUES_EQUAL("LWTRACE_UT_PROVIDER", p4.GetProvider()); UNIT_ASSERT_VALUES_EQUAL(42, p4.GetParams(0).GetDoubleValue()); const auto& p5 = r.GetEvents(5); UNIT_ASSERT_VALUES_EQUAL("DurationParam", p5.GetName()); UNIT_ASSERT_VALUES_EQUAL("LWTRACE_UT_PROVIDER", p5.GetProvider()); UNIT_ASSERT_VALUES_EQUAL(146, p5.GetParams(0).GetDoubleValue()); const auto& p6 = r.GetEvents(6); UNIT_ASSERT_VALUES_EQUAL("ProtoEnum", p6.GetName()); UNIT_ASSERT_VALUES_EQUAL("LWTRACE_UT_PROVIDER", p6.GetProvider()); UNIT_ASSERT_VALUES_EQUAL((int)OT_EQ, p6.GetParams(0).GetIntValue()); const auto& p7 = r.GetEvents(7); UNIT_ASSERT_VALUES_EQUAL("IntIntParams", p7.GetName()); UNIT_ASSERT_VALUES_EQUAL("LWTRACE_UT_PROVIDER", p7.GetProvider()); UNIT_ASSERT_VALUES_EQUAL(1, p7.GetParams(0).GetUintValue()); UNIT_ASSERT_VALUES_EQUAL(2, p7.GetParams(1).GetUintValue()); } Y_UNIT_TEST(ShouldDeserializeTracks) { TManager manager(*Singleton(), false); TTraceResponse resp; auto& r = *resp.MutableTrace()->MutableEvents(); auto& p0 = *r.Add(); p0.SetName("NoParam"); p0.SetProvider("LWTRACE_UT_PROVIDER"); auto& p1 = *r.Add(); p1.SetName("IntParam"); p1.SetProvider("LWTRACE_UT_PROVIDER"); auto& p1param = *p1.MutableParams()->Add(); p1param.SetUintValue(1); auto& p2 = *r.Add(); p2.SetName("StringParam"); p2.SetProvider("LWTRACE_UT_PROVIDER"); auto& p2param = *p2.MutableParams()->Add(); p2param.SetStrValue("str"); auto& p3 = *r.Add(); p3.SetName("EnumParams"); p3.SetProvider("LWTRACE_UT_PROVIDER"); auto& p3param1 = *p3.MutableParams()->Add(); p3param1.SetUintValue((ui64)EEnumClass::ValueC); auto& p3param2 = *p3.MutableParams()->Add(); p3param2.SetIntValue((ui64)EEnumClass::ValueC); auto& p4 = *r.Add(); p4.SetName("InstantParam"); p4.SetProvider("LWTRACE_UT_PROVIDER"); auto& p4param = *p4.MutableParams()->Add(); p4param.SetDoubleValue(42); auto& p5 = *r.Add(); p5.SetName("DurationParam"); p5.SetProvider("LWTRACE_UT_PROVIDER"); auto& p5param = *p5.MutableParams()->Add(); p5param.SetDoubleValue(146); auto& p6 = *r.Add(); p6.SetName("ProtoEnum"); p6.SetProvider("LWTRACE_UT_PROVIDER"); auto& p6param = *p6.MutableParams()->Add(); p6param.SetIntValue((i64)OT_EQ); auto& p7 = *r.Add(); p7.SetName("IntIntParams"); p7.SetProvider("LWTRACE_UT_PROVIDER"); auto& p7param1 = *p7.MutableParams()->Add(); p7param1.SetIntValue(1); auto& p7param2 = *p7.MutableParams()->Add(); p7param2.SetIntValue(2); TOrbit orbit; UNIT_ASSERT_VALUES_EQUAL( manager.HandleTraceResponse(resp, manager.GetProbesMap(), orbit).IsSuccess, true); } Y_UNIT_TEST(ShouldDeserializeWhatSerialized) { TManager manager(*Singleton(), false); TOrbit orbit; TOrbit child; TTraceRequest req; req.SetIsTraced(true); bool traced = manager.HandleTraceRequest(req, orbit); UNIT_ASSERT(traced); LWTRACK(NoParam, orbit); orbit.Fork(child); LWTRACK(IntParam, orbit, 1); LWTRACK(IntParam, child, 2); LWTRACK(StringParam, orbit, "str1"); LWTRACK(StringParam, child, "str2"); LWTRACK(EnumParams, orbit, ValueA, EEnumClass::ValueC); LWTRACK(InstantParam, orbit, TInstant::Seconds(42)); LWTRACK(DurationParam, orbit, TDuration::MilliSeconds(146)); LWTRACK(ProtoEnum, orbit, OT_EQ); LWTRACK(IntIntParams, orbit, 1, 2); orbit.Join(child); TTraceResponse resp1; auto& r1 = *resp1.MutableTrace(); orbit.Serialize(0, r1); UNIT_ASSERT_VALUES_EQUAL(r1.EventsSize(), 12); TOrbit other; traced = manager.HandleTraceRequest(req, other); UNIT_ASSERT(traced); UNIT_ASSERT_VALUES_EQUAL( manager.HandleTraceResponse(resp1, manager.GetProbesMap(), other).IsSuccess, true); TTraceResponse resp2; auto& r2 = *resp2.MutableTrace(); other.Serialize(0, r2); UNIT_ASSERT_VALUES_EQUAL(r2.EventsSize(), 12); TString proto1; bool parsed = NProtoBuf::TextFormat::PrintToString(resp1, &proto1); UNIT_ASSERT(parsed); TString proto2; parsed = NProtoBuf::TextFormat::PrintToString(resp2, &proto2); UNIT_ASSERT(parsed); UNIT_ASSERT_VALUES_EQUAL(proto1, proto2); } Y_UNIT_TEST(TrackForkJoin) { TManager mngr(*Singleton(), true); TQuery q; bool parsed = NProtoBuf::TextFormat::ParseFromString(R"END( Blocks { ProbeDesc { Name: "NoParam" Provider: "LWTRACE_UT_PROVIDER" } Action { RunLogShuttleAction { } } } )END", &q); UNIT_ASSERT(parsed); mngr.New("Query1", q); { TOrbit a, b, c, d; // Graph: // c // / \ // b-f-b-j-b // / \ // a-f-a-f-a-j-a-j-a // \ / // d // // Merged track: // a-f(b)-a-f(d)-a-j(d,1)-d-a-j(b,6)-b-f(c)-b-j(c,1)-c-b-a LWTRACK(NoParam, a); a.Fork(b); LWTRACK(IntParam, a, 1); a.Fork(d); LWTRACK(IntParam, a, 2); LWTRACK(IntParam, b, 3); b.Fork(c); LWTRACK(IntParam, b, 4); LWTRACK(IntParam, c, 5); b.Join(c); LWTRACK(IntParam, b, 6); LWTRACK(IntParam, d, 7); a.Join(d); LWTRACK(IntParam, a, 8); a.Join(b); LWTRACK(IntParam, a, 9); } struct { void Push(TThread::TId, const TTrackLog& tl) { UNIT_ASSERT(tl.Items.size() == 16); UNIT_ASSERT(TString(tl.Items[0].Probe->Event.Name) == "NoParam"); UNIT_ASSERT(TString(tl.Items[1].Probe->Event.Name) == "Fork"); UNIT_ASSERT(tl.Items[2].Params.Param[0].Get() == 1); UNIT_ASSERT(TString(tl.Items[3].Probe->Event.Name) == "Fork"); UNIT_ASSERT(tl.Items[4].Params.Param[0].Get() == 2); UNIT_ASSERT(TString(tl.Items[5].Probe->Event.Name) == "Join"); UNIT_ASSERT(tl.Items[6].Params.Param[0].Get() == 7); UNIT_ASSERT(tl.Items[7].Params.Param[0].Get() == 8); UNIT_ASSERT(TString(tl.Items[8].Probe->Event.Name) == "Join"); UNIT_ASSERT(tl.Items[9].Params.Param[0].Get() == 3); UNIT_ASSERT(TString(tl.Items[10].Probe->Event.Name) == "Fork"); UNIT_ASSERT(tl.Items[11].Params.Param[0].Get() == 4); UNIT_ASSERT(TString(tl.Items[12].Probe->Event.Name) == "Join"); UNIT_ASSERT(tl.Items[13].Params.Param[0].Get() == 5); UNIT_ASSERT(tl.Items[14].Params.Param[0].Get() == 6); UNIT_ASSERT(tl.Items[15].Params.Param[0].Get() == 9); } } reader; mngr.ReadDepot("Query1", reader); } Y_UNIT_TEST(TrackForkError) { TManager mngr(*Singleton(), true); TQuery q; bool parsed = NProtoBuf::TextFormat::ParseFromString(R"END( Blocks { ProbeDesc { Name: "NoParam" Provider: "LWTRACE_UT_PROVIDER" } Action { RunLogShuttleAction { MaxTrackLength: 100 } } } )END", &q); UNIT_ASSERT(parsed); mngr.New("Query1", q); constexpr size_t n = (100 + 2) / 3 + 1; { TVector> span; while (1) { TVector orbit(n); LWTRACK(NoParam, orbit[0]); if (!orbit[0].HasShuttles()) { break; } for (size_t i = 1; i < n; i++) { if (!orbit[i - 1].Fork(orbit[i])) { break; } LWTRACK(IntParam, orbit[i], i); } span.emplace_back(std::move(orbit)); } for (auto& orbit: span) { for (auto it = orbit.rbegin(); it + 1 != orbit.rend(); it++) { (it + 1)->Join(*it); } } } struct { void Push(TThread::TId, const TTrackLog& tl) { UNIT_ASSERT(tl.Items.size() == 100); UNIT_ASSERT(tl.Truncated); } } reader; mngr.ReadDepot("Query1", reader); } Y_UNIT_TEST(ShouldResetFailedForksCounterUponShuttleParking) { TManager mngr(*Singleton(), true); TQuery q; bool parsed = NProtoBuf::TextFormat::ParseFromString(R"END( Blocks { ProbeDesc { Name: "NoParam" Provider: "LWTRACE_UT_PROVIDER" } Action { RunLogShuttleAction { MaxTrackLength: 100 ShuttlesCount: 2 } } } )END", &q); UNIT_ASSERT(parsed); mngr.New("Query1", q); struct { ui32 cnt = 0; void Push(TThread::TId, const TTrackLog&) { ++cnt; } } reader; { // Run shuttle ans fail fork TOrbit initial; TOrbit fork1; TOrbit fork2; LWTRACK(NoParam, initial); UNIT_ASSERT_VALUES_EQUAL(initial.HasShuttles(), true); UNIT_ASSERT_VALUES_EQUAL(initial.Fork(fork1), true); LWTRACK(IntParam, fork1, 1); UNIT_ASSERT_VALUES_EQUAL(fork1.Fork(fork2), false); initial.Join(fork1); } mngr.ReadDepot("Query1", reader); UNIT_ASSERT_VALUES_EQUAL(reader.cnt, 0); reader.cnt = 0; { TOrbit initial; LWTRACK(NoParam, initial); UNIT_ASSERT_VALUES_EQUAL(initial.HasShuttles(), true); } mngr.ReadDepot("Query1", reader); UNIT_ASSERT_VALUES_EQUAL(reader.cnt, 1); } #endif // LWTRACE_DISABLE }