func lookup_field(msg *message.Message, fn string, fi int, ai int) (int, unsafe.Pointer, int) { var field *message.Field if fi != 0 { fields := msg.FindAllFields(fn) if fi >= len(fields) { return 0, unsafe.Pointer(nil), 0 } field = fields[fi] } else { if field = msg.FindFirstField(fn); field == nil { return 0, unsafe.Pointer(nil), 0 } } fieldType := int(field.GetValueType()) switch field.GetValueType() { case message.Field_STRING: if ai >= len(field.ValueString) { return fieldType, unsafe.Pointer(nil), 0 } value := field.ValueString[ai] cs := C.CString(value) // freed by the caller return fieldType, unsafe.Pointer(cs), len(value) case message.Field_BYTES: if ai >= len(field.ValueBytes) { return fieldType, unsafe.Pointer(nil), 0 } value := field.ValueBytes[ai] return fieldType, unsafe.Pointer(&field.ValueBytes[ai][0]), len(value) case message.Field_INTEGER: if ai >= len(field.ValueInteger) { return fieldType, unsafe.Pointer(nil), 0 } return fieldType, unsafe.Pointer(&field.ValueInteger[ai]), 0 case message.Field_DOUBLE: if ai >= len(field.ValueDouble) { return fieldType, unsafe.Pointer(nil), 0 } return fieldType, unsafe.Pointer(&field.ValueDouble[ai]), 0 case message.Field_BOOL: if ai >= len(field.ValueBool) { return fieldType, unsafe.Pointer(nil), 0 } return fieldType, unsafe.Pointer(&field.ValueBool[ai]), 0 } return 0, unsafe.Pointer(nil), 0 }
func getFieldAsString(msg *message.Message, mvar *messageVariable) string { var field *message.Field if mvar.fi != 0 { fields := msg.FindAllFields(mvar.name) if mvar.fi >= len(fields) { return "" } field = fields[mvar.fi] } else { if field = msg.FindFirstField(mvar.name); field == nil { return "" } } switch field.GetValueType() { case message.Field_STRING: if mvar.ai >= len(field.ValueString) { return "" } return field.ValueString[mvar.ai] case message.Field_BYTES: if mvar.ai >= len(field.ValueBytes) { return "" } return string(field.ValueBytes[mvar.ai]) case message.Field_INTEGER: if mvar.ai >= len(field.ValueInteger) { return "" } return fmt.Sprintf("%d", field.ValueInteger[mvar.ai]) case message.Field_DOUBLE: if mvar.ai >= len(field.ValueDouble) { return "" } return fmt.Sprintf("%g", field.ValueDouble[mvar.ai]) case message.Field_BOOL: if mvar.ai >= len(field.ValueBool) { return "" } return fmt.Sprintf("%t", field.ValueBool[mvar.ai]) } return "" }
func TestInjectMessage(t *testing.T) { var sbc SandboxConfig tests := []string{ "lua types", "cloudwatch metric", "external reference", "array only", "private keys", "special characters", "message field all types", "internal reference", } outputs := []string{ `{"value":1}1.2 string nil true false`, `{"StatisticValues":[{"Minimum":0,"SampleCount":0,"Sum":0,"Maximum":0},{"Minimum":0,"SampleCount":0,"Sum":0,"Maximum":0}],"Dimensions":[{"Name":"d1","Value":"v1"},{"Name":"d2","Value":"v2"}],"MetricName":"example","Timestamp":0,"Value":0,"Unit":"s"}`, `{"a":{"y":2,"x":1}}`, `[1,2,3]`, `{"x":1,"_m":1,"_private":[1,2]}`, `{"special\tcharacters":"\"\t\r\n\b\f\\\/"}`, "\x10\x80\x94\xeb\xdc\x03\x52\x13\x0a\x06\x6e\x75\x6d\x62\x65\x72\x10\x03\x39\x00\x00\x00\x00\x00\x00\xf0\x3f\x52\x2c\x0a\x07\x6e\x75\x6d\x62\x65\x72\x73\x10\x03\x1a\x05\x63\x6f\x75\x6e\x74\x3a\x18\x00\x00\x00\x00\x00\x00\xf0\x3f\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x08\x40\x52\x0e\x0a\x05\x62\x6f\x6f\x6c\x73\x10\x04\x42\x03\x01\x00\x00\x52\x0a\x0a\x04\x62\x6f\x6f\x6c\x10\x04\x40\x01\x52\x10\x0a\x06\x73\x74\x72\x69\x6e\x67\x22\x06\x73\x74\x72\x69\x6e\x67\x52\x15\x0a\x07\x73\x74\x72\x69\x6e\x67\x73\x22\x02\x73\x31\x22\x02\x73\x32\x22\x02\x73\x33", `{"y":[2],"x":[1,2,3],"ir":[1,2,3]}`, } if false { // lua jit values outputs[1] = `{"Timestamp":0,"Value":0,"StatisticValues":[{"SampleCount":0,"Sum":0,"Maximum":0,"Minimum":0},{"SampleCount":0,"Sum":0,"Maximum":0,"Minimum":0}],"Unit":"s","MetricName":"example","Dimensions":[{"Name":"d1","Value":"v1"},{"Name":"d2","Value":"v2"}]}` } sbc.ScriptFilename = "./testsupport/inject_message.lua" sbc.MemoryLimit = 100000 sbc.InstructionLimit = 1000 sbc.OutputLimit = 8000 pack := getTestPack() sb, err := lua.CreateLuaSandbox(&sbc) if err != nil { t.Errorf("%s", err) } err = sb.Init("", "") if err != nil { t.Errorf("%s", err) } cnt := 0 sb.InjectMessage(func(p, pt, pn string) int { if len(pt) == 0 { // no type is a Heka protobuf message if p[18:] != outputs[cnt] { // ignore the UUID t.Errorf("Output is incorrect, expected: \"%x\" received: \"%x\"", outputs[cnt], p[18:]) } } else { if p != outputs[cnt] { t.Errorf("Output is incorrect, expected: \"%s\" received: \"%s\"", outputs[cnt], p) } } if cnt == 6 { msg := new(message.Message) err := proto.Unmarshal([]byte(p), msg) if err != nil { t.Errorf("%s", err) } if msg.GetTimestamp() != 1e9 { t.Errorf("Timestamp expected %d received %d", int(1e9), pack.Message.GetTimestamp()) } if field := msg.FindFirstField("numbers"); field != nil { if field.GetRepresentation() != "count" { t.Errorf("'numbers' representation expected count received %s", 1e9, field.GetRepresentation()) } } else { t.Errorf("'numbers' field not found") } tests := []string{ "Timestamp == 1000000000", "Fields[number] == 1", "Fields[numbers][0][0] == 1 && Fields[numbers][0][1] == 2 && Fields[numbers][0][2] == 3", "Fields[string] == 'string'", "Fields[strings][0][0] == 's1' && Fields[strings][0][1] == 's2' && Fields[strings][0][2] == 's3'", "Fields[bool] == TRUE", "Fields[bools][0][0] == TRUE && Fields[bools][0][1] == FALSE && Fields[bools][0][2] == FALSE", } for _, v := range tests { ms, _ := message.CreateMatcherSpecification(v) match := ms.Match(msg) if !match { t.Errorf("Test failed %s", v) } } } cnt++ return 0 }) for _, v := range tests { pack.Message.SetPayload(v) r := sb.ProcessMessage(pack) if r != 0 { t.Errorf("ProcessMessage should return 0, received %d %s", r, sb.LastError()) } } sb.Destroy("") if cnt != len(tests) { t.Errorf("InjectMessage was called %d times, expected %d", cnt, len(tests)) } }