@@ -648,6 +648,228 @@ TEST_F(ProbeCompilerTest, parse_bpftrace) {
648648 testing::proto::EqualsProto (absl::Substitute (kBPFTraceProgramPb , literal_bpf_trace)));
649649}
650650
651+ constexpr char kBPFTraceProgramMaxKernel [] = R"bpftrace(
652+ kprobe:tcp_drop
653+ {
654+ ...
655+ }
656+ )bpftrace" ;
657+
658+ constexpr char kBPFTraceProgramMinKernel [] = R"bpftrace(
659+ tracepoint:skb:kfree_skb
660+ {
661+ ...
662+ }
663+ )bpftrace" ;
664+
665+ // Test that we can compile/parse a single TraceProgram object with a valid selector
666+ constexpr char kBPFSingleTraceProgramObjectPxl [] = R"pxl(
667+ import pxtrace
668+ import px
669+
670+ after_519_trace_program = pxtrace.TraceProgram(
671+ program="""$0""",
672+ min_kernel='5.19',
673+ )
674+
675+ table_name = 'tcp_drop_table'
676+ pxtrace.UpsertTracepoint('tcp_drop_tracer',
677+ table_name,
678+ after_519_trace_program,
679+ pxtrace.kprobe(),
680+ '10m')
681+ )pxl" ;
682+
683+ constexpr char kBPFSingleTraceProgramObjectPb [] = R"proto(
684+ name: "tcp_drop_tracer"
685+ ttl {
686+ seconds: 600
687+ }
688+ programs {
689+ table_name: "tcp_drop_table"
690+ bpftrace {
691+ program: "$0"
692+ }
693+ selectors {
694+ selector_type: MIN_KERNEL
695+ value: "5.19"
696+ }
697+ }
698+ )proto" ;
699+
700+ TEST_F (ProbeCompilerTest, parse_single_bpftrace_program_object) {
701+ ASSERT_OK_AND_ASSIGN (auto probe_ir,
702+ CompileProbeScript (absl::Substitute (kBPFSingleTraceProgramObjectPxl ,
703+ kBPFTraceProgramMinKernel )));
704+ plannerpb::CompileMutationsResponse pb;
705+ EXPECT_OK (probe_ir->ToProto (&pb));
706+ ASSERT_EQ (pb.mutations_size (), 1 );
707+
708+ std::string literal_bpf_trace_min = kBPFTraceProgramMinKernel ;
709+ literal_bpf_trace_min =
710+ std::regex_replace (literal_bpf_trace_min, std::regex (R"( \\\n)" ), R"( \\\\n)" );
711+ literal_bpf_trace_min = std::regex_replace (literal_bpf_trace_min, std::regex (" \n " ), " \\ n" );
712+ literal_bpf_trace_min = std::regex_replace (literal_bpf_trace_min, std::regex (" \" " ), " \\\" " );
713+
714+ EXPECT_THAT (pb.mutations ()[0 ].trace (),
715+ testing::proto::EqualsProto (
716+ absl::Substitute (kBPFSingleTraceProgramObjectPb , literal_bpf_trace_min)));
717+ }
718+
719+ // Test that we can compile a list of TraceProgram objects with valid selectors
720+ constexpr char kBPFTraceProgramObjectsPxl [] = R"pxl(
721+ import pxtrace
722+ import px
723+
724+ before_518_trace_program = pxtrace.TraceProgram(
725+ program="""$0""",
726+ max_kernel='5.18',
727+ )
728+
729+ after_519_trace_program = pxtrace.TraceProgram(
730+ program="""$1""",
731+ min_kernel='5.19',
732+ )
733+
734+ table_name = 'tcp_drop_table'
735+ pxtrace.UpsertTracepoint('tcp_drop_tracer',
736+ table_name,
737+ [before_518_trace_program, after_519_trace_program],
738+ pxtrace.kprobe(),
739+ '10m')
740+ )pxl" ;
741+
742+ constexpr char kBPFTraceProgramObjectsPb [] = R"proto(
743+ name: "tcp_drop_tracer"
744+ ttl {
745+ seconds: 600
746+ }
747+ programs {
748+ table_name: "tcp_drop_table"
749+ bpftrace {
750+ program: "$0"
751+ }
752+ selectors {
753+ selector_type: MAX_KERNEL
754+ value: "5.18"
755+ }
756+ }
757+ programs {
758+ table_name: "tcp_drop_table"
759+ bpftrace {
760+ program: "$1"
761+ }
762+ selectors {
763+ selector_type: MIN_KERNEL
764+ value: "5.19"
765+ }
766+ }
767+ )proto" ;
768+
769+ TEST_F (ProbeCompilerTest, parse_multiple_bpftrace_program_objects) {
770+ ASSERT_OK_AND_ASSIGN (auto probe_ir, CompileProbeScript (absl::Substitute (
771+ kBPFTraceProgramObjectsPxl , kBPFTraceProgramMinKernel ,
772+ kBPFTraceProgramMaxKernel )));
773+ plannerpb::CompileMutationsResponse pb;
774+ EXPECT_OK (probe_ir->ToProto (&pb));
775+ ASSERT_EQ (pb.mutations_size (), 1 );
776+
777+ std::string literal_bpf_trace_min = kBPFTraceProgramMinKernel ;
778+ literal_bpf_trace_min =
779+ std::regex_replace (literal_bpf_trace_min, std::regex (R"( \\\n)" ), R"( \\\\n)" );
780+ literal_bpf_trace_min = std::regex_replace (literal_bpf_trace_min, std::regex (" \n " ), " \\ n" );
781+ literal_bpf_trace_min = std::regex_replace (literal_bpf_trace_min, std::regex (" \" " ), " \\\" " );
782+
783+ std::string literal_bpf_trace_max = kBPFTraceProgramMaxKernel ;
784+ literal_bpf_trace_max =
785+ std::regex_replace (literal_bpf_trace_max, std::regex (R"( \\\n)" ), R"( \\\\n)" );
786+ literal_bpf_trace_max = std::regex_replace (literal_bpf_trace_max, std::regex (" \n " ), " \\ n" );
787+ literal_bpf_trace_max = std::regex_replace (literal_bpf_trace_max, std::regex (" \" " ), " \\\" " );
788+
789+ EXPECT_THAT (pb.mutations ()[0 ].trace (),
790+ testing::proto::EqualsProto (absl::Substitute (
791+ kBPFTraceProgramObjectsPb , literal_bpf_trace_min, literal_bpf_trace_max)));
792+ }
793+
794+ // Test that passing an unsupported selector type to TraceProgram throws a compiler error
795+ constexpr char kBPFUnsupportedTraceProgramObjectSelectorPxl [] = R"pxl(
796+ import pxtrace
797+ import px
798+
799+ after_519_trace_program = pxtrace.TraceProgram(
800+ program="""$0""",
801+ min_kernel='5.19',
802+ my_unsupported_selector='12345',
803+ )
804+
805+ table_name = 'tcp_drop_table'
806+ pxtrace.UpsertTracepoint('tcp_drop_tracer',
807+ table_name,
808+ after_519_trace_program,
809+ pxtrace.kprobe(),
810+ '10m')
811+ )pxl" ;
812+
813+ TEST_F (ProbeCompilerTest, parse_unsupported_selector_in_trace_program_object) {
814+ auto probe_ir_or_s = CompileProbeScript (kBPFUnsupportedTraceProgramObjectSelectorPxl );
815+ ASSERT_NOT_OK (probe_ir_or_s);
816+ EXPECT_THAT (
817+ probe_ir_or_s.status (),
818+ HasCompilerError (" Unsupported selector argument provided \' my_unsupported_selector\' " ));
819+ }
820+
821+ // Test that an invalid selector value throws a compiler error (currently needs to be a string)
822+ constexpr char kBPFInvalidTraceProgramObjectSelectorPxl [] = R"pxl(
823+ import pxtrace
824+ import px
825+
826+ after_519_trace_program = pxtrace.TraceProgram(
827+ program="""$0""",
828+ min_kernel='5.19',
829+ max_kernel=None,
830+ )
831+
832+ table_name = 'tcp_drop_table'
833+ pxtrace.UpsertTracepoint('tcp_drop_tracer',
834+ table_name,
835+ after_519_trace_program,
836+ pxtrace.kprobe(),
837+ '10m')
838+ )pxl" ;
839+
840+ TEST_F (ProbeCompilerTest, parse_invalid_trace_program_object) {
841+ auto probe_ir_or_s = CompileProbeScript (kBPFInvalidTraceProgramObjectSelectorPxl );
842+ ASSERT_NOT_OK (probe_ir_or_s);
843+ EXPECT_THAT (probe_ir_or_s.status (),
844+ HasCompilerError (" Expected \' String\' in arg \' max_kernel\' , got \' none\' " ));
845+ }
846+
847+ // Test that an empty selector value throws a compiler error
848+ constexpr char kBPFEmptyTraceProgramObjectSelectorPxl [] = R"pxl(
849+ import pxtrace
850+ import px
851+
852+ after_519_trace_program = pxtrace.TraceProgram(
853+ program="""$0""",
854+ min_kernel='5.19',
855+ max_kernel='',
856+ )
857+
858+ table_name = 'tcp_drop_table'
859+ pxtrace.UpsertTracepoint('tcp_drop_tracer',
860+ table_name,
861+ after_519_trace_program,
862+ pxtrace.kprobe(),
863+ '10m')
864+ )pxl" ;
865+
866+ TEST_F (ProbeCompilerTest, parse_empty_trace_program_object) {
867+ auto probe_ir_or_s = CompileProbeScript (kBPFEmptyTraceProgramObjectSelectorPxl );
868+ ASSERT_NOT_OK (probe_ir_or_s);
869+ EXPECT_THAT (probe_ir_or_s.status (),
870+ HasCompilerError (" Empty selector value provided for \' max_kernel\' " ));
871+ }
872+
651873constexpr char kConfigChangePxl [] = R"pxl(
652874import pxconfig
653875import px
0 commit comments