github.com/alibaba/ilogtail/pkg@v0.0.0-20250526110833-c53b480d046c/protocol/converter/converter_sls_metric_test.go (about)

     1  // Copyright 2022 iLogtail Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package protocol
    16  
    17  import (
    18  	"strconv"
    19  	"testing"
    20  	"time"
    21  
    22  	"github.com/stretchr/testify/assert"
    23  
    24  	"github.com/alibaba/ilogtail/pkg/protocol"
    25  )
    26  
    27  func Test_newMetricReader(t *testing.T) {
    28  	tests := []struct {
    29  		log        *protocol.Log
    30  		wantReader *metricReader
    31  		wantErr    bool
    32  	}{
    33  		{
    34  			log: &protocol.Log{
    35  				Contents: []*protocol.Log_Content{
    36  					{Key: metricNameKey, Value: "name"},
    37  					{Key: metricLabelsKey, Value: "aaa#$#bbb"},
    38  					{Key: metricValueKey, Value: "1"},
    39  					{Key: metricTimeNanoKey, Value: "12344"},
    40  				},
    41  			},
    42  			wantReader: &metricReader{
    43  				name:      "name",
    44  				labels:    "aaa#$#bbb",
    45  				value:     "1",
    46  				timestamp: "12344",
    47  			},
    48  		},
    49  		{
    50  			log: &protocol.Log{
    51  				Contents: []*protocol.Log_Content{
    52  					{Key: metricNameKey, Value: ""},
    53  					{Key: metricLabelsKey, Value: "aaa#$#bbb"},
    54  					{Key: metricValueKey, Value: "1"},
    55  					{Key: metricTimeNanoKey, Value: "12344"},
    56  				},
    57  			},
    58  			wantErr: true,
    59  		},
    60  		{
    61  			log: &protocol.Log{
    62  				Contents: []*protocol.Log_Content{
    63  					{Key: metricNameKey, Value: "name"},
    64  					{Key: metricLabelsKey, Value: "aaa#$#bbb"},
    65  					{Key: metricValueKey, Value: ""},
    66  					{Key: metricTimeNanoKey, Value: "12344"},
    67  				},
    68  			},
    69  			wantErr: true,
    70  		},
    71  	}
    72  
    73  	for _, test := range tests {
    74  		reader := newMetricReader()
    75  		err := reader.set(test.log)
    76  		if test.wantErr {
    77  			assert.NotNil(t, err)
    78  			continue
    79  		}
    80  		assert.Nil(t, err)
    81  		assert.Equal(t, test.wantReader, reader)
    82  	}
    83  }
    84  
    85  func Test_metricReader_readNames(t *testing.T) {
    86  	tests := []struct {
    87  		reader         *metricReader
    88  		wantMetricName string
    89  		wantFieldName  string
    90  	}{
    91  		{
    92  			reader: &metricReader{
    93  				name: "aa",
    94  			},
    95  			wantMetricName: "aa",
    96  			wantFieldName:  "value",
    97  		},
    98  		{
    99  			reader: &metricReader{
   100  				name: "aa:bb",
   101  			},
   102  			wantMetricName: "aa:bb",
   103  			wantFieldName:  "value",
   104  		},
   105  		{
   106  			reader: &metricReader{
   107  				name:      "aa:bb",
   108  				fieldName: "bb",
   109  			},
   110  			wantMetricName: "aa",
   111  			wantFieldName:  "bb",
   112  		},
   113  		{
   114  			reader: &metricReader{
   115  				name: ":",
   116  			},
   117  			wantMetricName: ":",
   118  			wantFieldName:  "value",
   119  		},
   120  		{
   121  			reader: &metricReader{
   122  				name:      "aa:value",
   123  				fieldName: "value",
   124  			},
   125  			wantMetricName: "aa:value",
   126  			wantFieldName:  "value",
   127  		},
   128  	}
   129  
   130  	for _, test := range tests {
   131  		metricName, fieldName := test.reader.readNames()
   132  		assert.Equal(t, test.wantMetricName, metricName)
   133  		assert.Equal(t, test.wantFieldName, fieldName)
   134  	}
   135  }
   136  
   137  func Test_metricReader_readSortedLabels(t *testing.T) {
   138  	tests := []struct {
   139  		reader     *metricReader
   140  		wantLabels []MetricLabel
   141  		wantErr    bool
   142  	}{
   143  		{
   144  			reader: &metricReader{
   145  				labels: "bb#$#aa|aa#$#bb",
   146  			},
   147  			wantLabels: []MetricLabel{
   148  				{Key: "aa", Value: "bb"},
   149  				{Key: "bb", Value: "aa"},
   150  			},
   151  		},
   152  		{
   153  			reader: &metricReader{
   154  				labels: "bb#$#aa",
   155  			},
   156  			wantLabels: []MetricLabel{
   157  				{Key: "bb", Value: "aa"},
   158  			},
   159  		},
   160  		{
   161  			reader: &metricReader{
   162  				labels: "bb#$#aa|aa#$#",
   163  			},
   164  			wantLabels: []MetricLabel{
   165  				{Key: "aa", Value: ""},
   166  				{Key: "bb", Value: "aa"},
   167  			},
   168  		},
   169  		{
   170  			reader: &metricReader{
   171  				labels: "",
   172  			},
   173  			wantLabels: nil,
   174  		},
   175  		{
   176  			reader: &metricReader{
   177  				labels: "bb#$#aa|aa#$#bb|",
   178  			},
   179  			wantLabels: []MetricLabel{
   180  				{Key: "aa", Value: "bb"},
   181  				{Key: "bb", Value: "aa"},
   182  			},
   183  		},
   184  		{
   185  			reader: &metricReader{
   186  				labels: "bb",
   187  			},
   188  			wantErr: true,
   189  		},
   190  		{
   191  			reader: &metricReader{
   192  				labels: "bb#$#aa|eee",
   193  			},
   194  			wantLabels: []MetricLabel{
   195  				{Key: "bb", Value: "aa|eee"},
   196  			},
   197  		},
   198  		{
   199  			reader: &metricReader{
   200  				labels: "bb#$#aa|eee|aa#$#bb",
   201  			},
   202  			wantLabels: []MetricLabel{
   203  				{Key: "aa", Value: "bb"},
   204  				{Key: "bb", Value: "aa|eee"},
   205  			},
   206  		},
   207  		{
   208  			reader: &metricReader{
   209  				labels: "bb#$#aa||eee||aa#$#bb",
   210  			},
   211  			wantLabels: []MetricLabel{
   212  				{Key: "aa", Value: "bb"},
   213  				{Key: "bb", Value: "aa||eee|"},
   214  			},
   215  		},
   216  		{
   217  			reader: &metricReader{
   218  				labels: "cc||bb#$#aa||eee||aa#$#bb",
   219  			},
   220  			wantLabels: []MetricLabel{
   221  				{Key: "aa", Value: "bb"},
   222  				{Key: "cc||bb", Value: "aa||eee|"},
   223  			},
   224  		},
   225  	}
   226  
   227  	for _, test := range tests {
   228  		labels, err := test.reader.readSortedLabels()
   229  		if test.wantErr {
   230  			assert.NotNilf(t, err, "reader", *test.reader)
   231  			continue
   232  		}
   233  		assert.Nil(t, err)
   234  		assert.Equal(t, test.wantLabels, labels)
   235  	}
   236  }
   237  
   238  func Test_metricReader_countLabels(t *testing.T) {
   239  	tests := []struct {
   240  		reader    *metricReader
   241  		wantCount int
   242  	}{
   243  		{
   244  			reader: &metricReader{
   245  				labels: "aa#$#bb",
   246  			},
   247  			wantCount: 1,
   248  		},
   249  		{
   250  			reader: &metricReader{
   251  				labels: "",
   252  			},
   253  			wantCount: 0,
   254  		},
   255  		{
   256  			reader: &metricReader{
   257  				labels: "aa#$#bb|bb#$#cc",
   258  			},
   259  			wantCount: 2,
   260  		},
   261  	}
   262  
   263  	for _, test := range tests {
   264  		n := test.reader.countLabels()
   265  		assert.Equal(t, test.wantCount, n)
   266  	}
   267  }
   268  
   269  func Test_metricReader_readValue(t *testing.T) {
   270  	tests := []struct {
   271  		reader    *metricReader
   272  		wantValue interface{}
   273  		wantErr   bool
   274  	}{
   275  		{
   276  			reader: &metricReader{
   277  				value:     "1",
   278  				valueType: valueTypeBool,
   279  			},
   280  			wantValue: true,
   281  		},
   282  		{
   283  			reader: &metricReader{
   284  				value:     "1",
   285  				valueType: valueTypeInt,
   286  			},
   287  			wantValue: int64(1),
   288  		},
   289  		{
   290  			reader: &metricReader{
   291  				value:     "1.1",
   292  				valueType: valueTypeFloat,
   293  			},
   294  			wantValue: float64(1.1),
   295  		},
   296  		{
   297  			reader: &metricReader{
   298  				value: "",
   299  			},
   300  			wantErr: true,
   301  		},
   302  		{
   303  			reader: &metricReader{
   304  				value:     "aaa",
   305  				valueType: valueTypeString,
   306  			},
   307  			wantValue: "aaa",
   308  		},
   309  	}
   310  
   311  	for _, test := range tests {
   312  		value, err := test.reader.readValue()
   313  		if test.wantErr {
   314  			assert.NotNil(t, err)
   315  			continue
   316  		}
   317  		assert.Equal(t, test.wantValue, value)
   318  	}
   319  }
   320  
   321  func Test_metricReader_readTimestamp(t *testing.T) {
   322  	tests := []struct {
   323  		reader   *metricReader
   324  		wantTime time.Time
   325  		wantErr  bool
   326  	}{
   327  		{
   328  			reader: &metricReader{
   329  				timestamp: strconv.FormatInt(time.Date(2022, 01, 01, 01, 01, 01, 01, time.UTC).UnixNano(), 10),
   330  			},
   331  			wantTime: time.Date(2022, 01, 01, 01, 01, 01, 01, time.UTC),
   332  		},
   333  		{
   334  			reader: &metricReader{
   335  				timestamp: "",
   336  			},
   337  			wantTime: time.Time{},
   338  		},
   339  		{
   340  			reader: &metricReader{
   341  				timestamp: "abc",
   342  			},
   343  			wantErr: true,
   344  		},
   345  	}
   346  
   347  	for _, test := range tests {
   348  		timestamp, err := test.reader.readTimestamp()
   349  		if test.wantErr {
   350  			assert.NotNil(t, err)
   351  			continue
   352  		}
   353  		assert.Nil(t, err)
   354  		assert.Equal(t, test.wantTime, timestamp)
   355  	}
   356  }
   357  
   358  func Test_metricReader_set(t *testing.T) {
   359  	tests := []struct {
   360  		log        *protocol.Log
   361  		wantErr    bool
   362  		wantReader metricReader
   363  	}{
   364  		{
   365  			log: &protocol.Log{Contents: []*protocol.Log_Content{
   366  				{Key: metricNameKey, Value: "_metric"},
   367  				{Key: metricFieldKey, Value: "value"},
   368  				{Key: metricValueTypeKey, Value: "float"},
   369  				{Key: metricValueKey, Value: "1"},
   370  			}},
   371  			wantErr: false,
   372  			wantReader: metricReader{
   373  				name:      "_metric",
   374  				value:     "1",
   375  				valueType: "float",
   376  				fieldName: "value",
   377  			},
   378  		},
   379  		{
   380  			log: &protocol.Log{Contents: []*protocol.Log_Content{
   381  				{Key: metricNameKey, Value: "_metric"},
   382  				{Key: metricFieldKey, Value: "value"},
   383  				{Key: metricValueTypeKey, Value: "string"},
   384  				{Key: metricValueKey, Value: ""},
   385  			}},
   386  			wantErr: false,
   387  			wantReader: metricReader{
   388  				name:      "_metric",
   389  				value:     "",
   390  				valueType: "string",
   391  				fieldName: "value",
   392  			},
   393  		},
   394  		{
   395  			log: &protocol.Log{Contents: []*protocol.Log_Content{
   396  				{Key: metricNameKey, Value: "_metric"},
   397  				{Key: metricFieldKey, Value: "value"},
   398  				{Key: metricValueTypeKey, Value: "float"},
   399  				{Key: metricValueKey, Value: ""},
   400  			}},
   401  			wantErr: true,
   402  		},
   403  	}
   404  
   405  	for _, test := range tests {
   406  		reader := metricReader{}
   407  		err := reader.set(test.log)
   408  		if test.wantErr {
   409  			assert.NotNil(t, err)
   410  			continue
   411  		}
   412  		assert.Nil(t, err)
   413  		assert.Equal(t, test.wantReader, reader)
   414  	}
   415  }