You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							161 lines
						
					
					
						
							5.5 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							161 lines
						
					
					
						
							5.5 KiB
						
					
					
				
								package engine
							 | 
						|
								
							 | 
						|
								import (
							 | 
						|
									"context"
							 | 
						|
									"testing"
							 | 
						|
								
							 | 
						|
									"github.com/seaweedfs/seaweedfs/weed/pb/schema_pb"
							 | 
						|
								)
							 | 
						|
								
							 | 
						|
								// TestSchemaAwareParsing tests the schema-aware message parsing functionality
							 | 
						|
								func TestSchemaAwareParsing(t *testing.T) {
							 | 
						|
									// Create a mock HybridMessageScanner with schema
							 | 
						|
									recordSchema := &schema_pb.RecordType{
							 | 
						|
										Fields: []*schema_pb.Field{
							 | 
						|
											{
							 | 
						|
												Name: "user_id",
							 | 
						|
												Type: &schema_pb.Type{Kind: &schema_pb.Type_ScalarType{ScalarType: schema_pb.ScalarType_INT32}},
							 | 
						|
											},
							 | 
						|
											{
							 | 
						|
												Name: "event_type",
							 | 
						|
												Type: &schema_pb.Type{Kind: &schema_pb.Type_ScalarType{ScalarType: schema_pb.ScalarType_STRING}},
							 | 
						|
											},
							 | 
						|
											{
							 | 
						|
												Name: "cpu_usage",
							 | 
						|
												Type: &schema_pb.Type{Kind: &schema_pb.Type_ScalarType{ScalarType: schema_pb.ScalarType_DOUBLE}},
							 | 
						|
											},
							 | 
						|
											{
							 | 
						|
												Name: "is_active",
							 | 
						|
												Type: &schema_pb.Type{Kind: &schema_pb.Type_ScalarType{ScalarType: schema_pb.ScalarType_BOOL}},
							 | 
						|
											},
							 | 
						|
										},
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									scanner := &HybridMessageScanner{
							 | 
						|
										recordSchema: recordSchema,
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									t.Run("JSON Message Parsing", func(t *testing.T) {
							 | 
						|
										jsonData := []byte(`{"user_id": 1234, "event_type": "login", "cpu_usage": 75.5, "is_active": true}`)
							 | 
						|
								
							 | 
						|
										result, err := scanner.parseJSONMessage(jsonData)
							 | 
						|
										if err != nil {
							 | 
						|
											t.Fatalf("Failed to parse JSON message: %v", err)
							 | 
						|
										}
							 | 
						|
								
							 | 
						|
										// Verify user_id as int32
							 | 
						|
										if userIdVal := result.Fields["user_id"]; userIdVal == nil {
							 | 
						|
											t.Error("user_id field missing")
							 | 
						|
										} else if userIdVal.GetInt32Value() != 1234 {
							 | 
						|
											t.Errorf("Expected user_id=1234, got %v", userIdVal.GetInt32Value())
							 | 
						|
										}
							 | 
						|
								
							 | 
						|
										// Verify event_type as string
							 | 
						|
										if eventTypeVal := result.Fields["event_type"]; eventTypeVal == nil {
							 | 
						|
											t.Error("event_type field missing")
							 | 
						|
										} else if eventTypeVal.GetStringValue() != "login" {
							 | 
						|
											t.Errorf("Expected event_type='login', got %v", eventTypeVal.GetStringValue())
							 | 
						|
										}
							 | 
						|
								
							 | 
						|
										// Verify cpu_usage as double
							 | 
						|
										if cpuVal := result.Fields["cpu_usage"]; cpuVal == nil {
							 | 
						|
											t.Error("cpu_usage field missing")
							 | 
						|
										} else if cpuVal.GetDoubleValue() != 75.5 {
							 | 
						|
											t.Errorf("Expected cpu_usage=75.5, got %v", cpuVal.GetDoubleValue())
							 | 
						|
										}
							 | 
						|
								
							 | 
						|
										// Verify is_active as bool
							 | 
						|
										if isActiveVal := result.Fields["is_active"]; isActiveVal == nil {
							 | 
						|
											t.Error("is_active field missing")
							 | 
						|
										} else if !isActiveVal.GetBoolValue() {
							 | 
						|
											t.Errorf("Expected is_active=true, got %v", isActiveVal.GetBoolValue())
							 | 
						|
										}
							 | 
						|
								
							 | 
						|
										t.Logf("JSON parsing correctly converted types: int32=%d, string='%s', double=%.1f, bool=%v",
							 | 
						|
											result.Fields["user_id"].GetInt32Value(),
							 | 
						|
											result.Fields["event_type"].GetStringValue(),
							 | 
						|
											result.Fields["cpu_usage"].GetDoubleValue(),
							 | 
						|
											result.Fields["is_active"].GetBoolValue())
							 | 
						|
									})
							 | 
						|
								
							 | 
						|
									t.Run("Raw Data Type Conversion", func(t *testing.T) {
							 | 
						|
										// Test string conversion
							 | 
						|
										stringType := &schema_pb.Type{Kind: &schema_pb.Type_ScalarType{ScalarType: schema_pb.ScalarType_STRING}}
							 | 
						|
										stringVal, err := scanner.convertRawDataToSchemaValue([]byte("hello world"), stringType)
							 | 
						|
										if err != nil {
							 | 
						|
											t.Errorf("Failed to convert string: %v", err)
							 | 
						|
										} else if stringVal.GetStringValue() != "hello world" {
							 | 
						|
											t.Errorf("String conversion failed: got %v", stringVal.GetStringValue())
							 | 
						|
										}
							 | 
						|
								
							 | 
						|
										// Test int32 conversion
							 | 
						|
										int32Type := &schema_pb.Type{Kind: &schema_pb.Type_ScalarType{ScalarType: schema_pb.ScalarType_INT32}}
							 | 
						|
										int32Val, err := scanner.convertRawDataToSchemaValue([]byte("42"), int32Type)
							 | 
						|
										if err != nil {
							 | 
						|
											t.Errorf("Failed to convert int32: %v", err)
							 | 
						|
										} else if int32Val.GetInt32Value() != 42 {
							 | 
						|
											t.Errorf("Int32 conversion failed: got %v", int32Val.GetInt32Value())
							 | 
						|
										}
							 | 
						|
								
							 | 
						|
										// Test double conversion
							 | 
						|
										doubleType := &schema_pb.Type{Kind: &schema_pb.Type_ScalarType{ScalarType: schema_pb.ScalarType_DOUBLE}}
							 | 
						|
										doubleVal, err := scanner.convertRawDataToSchemaValue([]byte("3.14159"), doubleType)
							 | 
						|
										if err != nil {
							 | 
						|
											t.Errorf("Failed to convert double: %v", err)
							 | 
						|
										} else if doubleVal.GetDoubleValue() != 3.14159 {
							 | 
						|
											t.Errorf("Double conversion failed: got %v", doubleVal.GetDoubleValue())
							 | 
						|
										}
							 | 
						|
								
							 | 
						|
										// Test bool conversion
							 | 
						|
										boolType := &schema_pb.Type{Kind: &schema_pb.Type_ScalarType{ScalarType: schema_pb.ScalarType_BOOL}}
							 | 
						|
										boolVal, err := scanner.convertRawDataToSchemaValue([]byte("true"), boolType)
							 | 
						|
										if err != nil {
							 | 
						|
											t.Errorf("Failed to convert bool: %v", err)
							 | 
						|
										} else if !boolVal.GetBoolValue() {
							 | 
						|
											t.Errorf("Bool conversion failed: got %v", boolVal.GetBoolValue())
							 | 
						|
										}
							 | 
						|
								
							 | 
						|
										t.Log("Raw data type conversions working correctly")
							 | 
						|
									})
							 | 
						|
								
							 | 
						|
									t.Run("Invalid JSON Graceful Handling", func(t *testing.T) {
							 | 
						|
										invalidJSON := []byte(`{"user_id": 1234, "malformed": }`)
							 | 
						|
								
							 | 
						|
										_, err := scanner.parseJSONMessage(invalidJSON)
							 | 
						|
										if err == nil {
							 | 
						|
											t.Error("Expected error for invalid JSON, but got none")
							 | 
						|
										}
							 | 
						|
								
							 | 
						|
										t.Log("Invalid JSON handled gracefully with error")
							 | 
						|
									})
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// TestSchemaAwareParsingIntegration tests the full integration with SQL engine
							 | 
						|
								func TestSchemaAwareParsingIntegration(t *testing.T) {
							 | 
						|
									engine := NewTestSQLEngine()
							 | 
						|
								
							 | 
						|
									// Test that the enhanced schema-aware parsing doesn't break existing functionality
							 | 
						|
									result, err := engine.ExecuteSQL(context.Background(), "SELECT *, _source FROM user_events LIMIT 2")
							 | 
						|
									if err != nil {
							 | 
						|
										t.Fatalf("Schema-aware parsing broke basic SELECT: %v", err)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									if len(result.Rows) == 0 {
							 | 
						|
										t.Error("No rows returned - schema parsing may have issues")
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Check that _source column is still present (hybrid functionality)
							 | 
						|
									foundSourceColumn := false
							 | 
						|
									for _, col := range result.Columns {
							 | 
						|
										if col == "_source" {
							 | 
						|
											foundSourceColumn = true
							 | 
						|
											break
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									if !foundSourceColumn {
							 | 
						|
										t.Log("_source column missing - running in fallback mode without real cluster")
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									t.Log("Schema-aware parsing integrates correctly with SQL engine")
							 | 
						|
								}
							 |