@@ -966,4 +966,238 @@ mod tests {
966966 }
967967 }
968968 }
969+
970+ mod export_body_tests {
971+ use super :: super :: OtlpHttpClient ;
972+ use opentelemetry_http:: { Bytes , HttpClient } ;
973+ use std:: collections:: HashMap ;
974+
975+ #[ derive( Debug ) ]
976+ struct MockHttpClient ;
977+
978+ #[ async_trait:: async_trait]
979+ impl HttpClient for MockHttpClient {
980+ async fn send_bytes (
981+ & self ,
982+ _request : http:: Request < Bytes > ,
983+ ) -> Result < http:: Response < Bytes > , opentelemetry_http:: HttpError > {
984+ Ok ( http:: Response :: builder ( )
985+ . status ( 200 )
986+ . body ( Bytes :: new ( ) )
987+ . unwrap ( ) )
988+ }
989+ }
990+
991+ fn create_test_client (
992+ protocol : crate :: Protocol ,
993+ compression : Option < crate :: Compression > ,
994+ ) -> OtlpHttpClient {
995+ OtlpHttpClient :: new (
996+ std:: sync:: Arc :: new ( MockHttpClient ) ,
997+ "http://localhost:4318" . parse ( ) . unwrap ( ) ,
998+ HashMap :: new ( ) ,
999+ protocol,
1000+ std:: time:: Duration :: from_secs ( 10 ) ,
1001+ compression,
1002+ )
1003+ }
1004+
1005+ fn create_test_span_data ( ) -> opentelemetry_sdk:: trace:: SpanData {
1006+ use opentelemetry:: trace:: Status ;
1007+ use opentelemetry:: trace:: {
1008+ SpanContext , SpanId , SpanKind , TraceFlags , TraceId , TraceState ,
1009+ } ;
1010+ use opentelemetry_sdk:: trace:: { SpanData , SpanEvents , SpanLinks } ;
1011+ use std:: borrow:: Cow ;
1012+ use std:: time:: { Duration , SystemTime } ;
1013+
1014+ let span_context = SpanContext :: new (
1015+ TraceId :: from_u128 ( 123 ) ,
1016+ SpanId :: from_u64 ( 456 ) ,
1017+ TraceFlags :: default ( ) ,
1018+ false ,
1019+ TraceState :: default ( ) ,
1020+ ) ;
1021+ SpanData {
1022+ span_context,
1023+ parent_span_id : SpanId :: from_u64 ( 0 ) ,
1024+ span_kind : SpanKind :: Internal ,
1025+ name : Cow :: Borrowed ( "test_span" ) ,
1026+ start_time : SystemTime :: UNIX_EPOCH ,
1027+ end_time : SystemTime :: UNIX_EPOCH + Duration :: from_secs ( 1 ) ,
1028+ attributes : vec ! [ ] ,
1029+ dropped_attributes_count : 0 ,
1030+ events : SpanEvents :: default ( ) ,
1031+ links : SpanLinks :: default ( ) ,
1032+ status : Status :: Unset ,
1033+ instrumentation_scope : opentelemetry:: InstrumentationScope :: default ( ) ,
1034+ }
1035+ }
1036+
1037+ #[ cfg( feature = "trace" ) ]
1038+ #[ test]
1039+ fn test_build_trace_export_body_binary_protocol ( ) {
1040+ let client = create_test_client ( crate :: Protocol :: HttpBinary , None ) ;
1041+ let span_data = create_test_span_data ( ) ;
1042+
1043+ let result = client. build_trace_export_body ( vec ! [ span_data] ) . unwrap ( ) ;
1044+ let ( _body, content_type, content_encoding) = result;
1045+
1046+ assert_eq ! ( content_type, "application/x-protobuf" ) ;
1047+ assert_eq ! ( content_encoding, None ) ;
1048+ }
1049+
1050+ #[ cfg( all( feature = "trace" , feature = "http-json" ) ) ]
1051+ #[ test]
1052+ fn test_build_trace_export_body_json_protocol ( ) {
1053+ let client = create_test_client ( crate :: Protocol :: HttpJson , None ) ;
1054+ let span_data = create_test_span_data ( ) ;
1055+
1056+ let result = client. build_trace_export_body ( vec ! [ span_data] ) . unwrap ( ) ;
1057+ let ( _body, content_type, content_encoding) = result;
1058+
1059+ assert_eq ! ( content_type, "application/json" ) ;
1060+ assert_eq ! ( content_encoding, None ) ;
1061+ }
1062+
1063+ #[ cfg( all( feature = "trace" , feature = "gzip-http" ) ) ]
1064+ #[ test]
1065+ fn test_build_trace_export_body_with_compression ( ) {
1066+ let client =
1067+ create_test_client ( crate :: Protocol :: HttpBinary , Some ( crate :: Compression :: Gzip ) ) ;
1068+ let span_data = create_test_span_data ( ) ;
1069+
1070+ let result = client. build_trace_export_body ( vec ! [ span_data] ) . unwrap ( ) ;
1071+ let ( _body, content_type, content_encoding) = result;
1072+
1073+ assert_eq ! ( content_type, "application/x-protobuf" ) ;
1074+ assert_eq ! ( content_encoding, Some ( "gzip" ) ) ;
1075+ }
1076+
1077+ #[ cfg( feature = "logs" ) ]
1078+ fn create_test_log_batch ( ) -> opentelemetry_sdk:: logs:: LogBatch < ' static > {
1079+ use opentelemetry_sdk:: logs:: LogBatch ;
1080+
1081+ // Use empty batch for simplicity - the method should still handle protocol/compression correctly
1082+ LogBatch :: new ( & [ ] )
1083+ }
1084+
1085+ #[ cfg( feature = "logs" ) ]
1086+ #[ test]
1087+ fn test_build_logs_export_body_binary_protocol ( ) {
1088+ let client = create_test_client ( crate :: Protocol :: HttpBinary , None ) ;
1089+ let batch = create_test_log_batch ( ) ;
1090+
1091+ let result = client. build_logs_export_body ( batch) . unwrap ( ) ;
1092+ let ( _body, content_type, content_encoding) = result;
1093+
1094+ assert_eq ! ( content_type, "application/x-protobuf" ) ;
1095+ assert_eq ! ( content_encoding, None ) ;
1096+ }
1097+
1098+ #[ cfg( all( feature = "logs" , feature = "http-json" ) ) ]
1099+ #[ test]
1100+ fn test_build_logs_export_body_json_protocol ( ) {
1101+ let client = create_test_client ( crate :: Protocol :: HttpJson , None ) ;
1102+ let batch = create_test_log_batch ( ) ;
1103+
1104+ let result = client. build_logs_export_body ( batch) . unwrap ( ) ;
1105+ let ( _body, content_type, content_encoding) = result;
1106+
1107+ assert_eq ! ( content_type, "application/json" ) ;
1108+ assert_eq ! ( content_encoding, None ) ;
1109+ }
1110+
1111+ #[ cfg( all( feature = "logs" , feature = "gzip-http" ) ) ]
1112+ #[ test]
1113+ fn test_build_logs_export_body_with_compression ( ) {
1114+ let client =
1115+ create_test_client ( crate :: Protocol :: HttpBinary , Some ( crate :: Compression :: Gzip ) ) ;
1116+ let batch = create_test_log_batch ( ) ;
1117+
1118+ let result = client. build_logs_export_body ( batch) . unwrap ( ) ;
1119+ let ( _body, content_type, content_encoding) = result;
1120+
1121+ assert_eq ! ( content_type, "application/x-protobuf" ) ;
1122+ assert_eq ! ( content_encoding, Some ( "gzip" ) ) ;
1123+ }
1124+
1125+ #[ cfg( feature = "metrics" ) ]
1126+ #[ test]
1127+ fn test_build_metrics_export_body_binary_protocol ( ) {
1128+ use opentelemetry_sdk:: metrics:: data:: ResourceMetrics ;
1129+
1130+ let client = create_test_client ( crate :: Protocol :: HttpBinary , None ) ;
1131+ let metrics = ResourceMetrics :: default ( ) ;
1132+
1133+ let result = client. build_metrics_export_body ( & metrics) . unwrap ( ) ;
1134+ let ( _body, content_type, content_encoding) = result;
1135+
1136+ assert_eq ! ( content_type, "application/x-protobuf" ) ;
1137+ assert_eq ! ( content_encoding, None ) ;
1138+ }
1139+
1140+ #[ cfg( all( feature = "metrics" , feature = "http-json" ) ) ]
1141+ #[ test]
1142+ fn test_build_metrics_export_body_json_protocol ( ) {
1143+ use opentelemetry_sdk:: metrics:: data:: ResourceMetrics ;
1144+
1145+ let client = create_test_client ( crate :: Protocol :: HttpJson , None ) ;
1146+ let metrics = ResourceMetrics :: default ( ) ;
1147+
1148+ let result = client. build_metrics_export_body ( & metrics) . unwrap ( ) ;
1149+ let ( _body, content_type, content_encoding) = result;
1150+
1151+ assert_eq ! ( content_type, "application/json" ) ;
1152+ assert_eq ! ( content_encoding, None ) ;
1153+ }
1154+
1155+ #[ cfg( all( feature = "metrics" , feature = "gzip-http" ) ) ]
1156+ #[ test]
1157+ fn test_build_metrics_export_body_with_compression ( ) {
1158+ use opentelemetry_sdk:: metrics:: data:: ResourceMetrics ;
1159+
1160+ let client =
1161+ create_test_client ( crate :: Protocol :: HttpBinary , Some ( crate :: Compression :: Gzip ) ) ;
1162+ let metrics = ResourceMetrics :: default ( ) ;
1163+
1164+ let result = client. build_metrics_export_body ( & metrics) . unwrap ( ) ;
1165+ let ( _body, content_type, content_encoding) = result;
1166+
1167+ assert_eq ! ( content_type, "application/x-protobuf" ) ;
1168+ assert_eq ! ( content_encoding, Some ( "gzip" ) ) ;
1169+ }
1170+
1171+ #[ cfg( all( feature = "metrics" , not( feature = "gzip-http" ) ) ) ]
1172+ #[ test]
1173+ fn test_build_metrics_export_body_compression_error_returns_none ( ) {
1174+ use opentelemetry_sdk:: metrics:: data:: ResourceMetrics ;
1175+
1176+ let client =
1177+ create_test_client ( crate :: Protocol :: HttpBinary , Some ( crate :: Compression :: Gzip ) ) ;
1178+ let metrics = ResourceMetrics :: default ( ) ;
1179+
1180+ // Should return None when compression fails (feature not enabled)
1181+ let result = client. build_metrics_export_body ( & metrics) ;
1182+ assert ! ( result. is_none( ) ) ;
1183+ }
1184+
1185+ #[ test]
1186+ fn test_resolve_compression_uses_generic_env_fallback ( ) {
1187+ use super :: super :: HttpExporterBuilder ;
1188+ use crate :: exporter:: tests:: run_env_test;
1189+
1190+ // Test that generic OTEL_EXPORTER_OTLP_COMPRESSION is used when signal-specific env var is not set
1191+ run_env_test (
1192+ vec ! [ ( crate :: OTEL_EXPORTER_OTLP_COMPRESSION , "gzip" ) ] ,
1193+ || {
1194+ let builder = HttpExporterBuilder :: default ( ) ;
1195+ let result = builder
1196+ . resolve_compression ( "NONEXISTENT_SIGNAL_COMPRESSION" )
1197+ . unwrap ( ) ;
1198+ assert_eq ! ( result, Some ( crate :: Compression :: Gzip ) ) ;
1199+ } ,
1200+ ) ;
1201+ }
1202+ }
9691203}
0 commit comments