...

Source file src/go.opentelemetry.io/otel/sdk/resource/os_release_unix_test.go

Documentation: go.opentelemetry.io/otel/sdk/resource

     1  // Copyright The OpenTelemetry 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  //go:build aix || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
    16  // +build aix dragonfly freebsd linux netbsd openbsd solaris zos
    17  
    18  package resource_test
    19  
    20  import (
    21  	"bytes"
    22  	"io"
    23  	"testing"
    24  
    25  	"github.com/stretchr/testify/require"
    26  
    27  	"go.opentelemetry.io/otel/sdk/resource"
    28  )
    29  
    30  func TestParseOSReleaseFile(t *testing.T) {
    31  	osReleaseUbuntu := bytes.NewBufferString(`NAME="Ubuntu"
    32  VERSION="20.04.2 LTS (Focal Fossa)"
    33  ID=ubuntu
    34  ID_LIKE=debian
    35  PRETTY_NAME="Ubuntu 20.04.2 LTS"
    36  VERSION_ID="20.04"
    37  HOME_URL="https://www.ubuntu.com/"
    38  SUPPORT_URL="https://help.ubuntu.com/"
    39  BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
    40  PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
    41  VERSION_CODENAME=focal
    42  UBUNTU_CODENAME=focal`)
    43  
    44  	parsedUbuntu := map[string]string{
    45  		"NAME":               "Ubuntu",
    46  		"VERSION":            "20.04.2 LTS (Focal Fossa)",
    47  		"ID":                 "ubuntu",
    48  		"ID_LIKE":            "debian",
    49  		"PRETTY_NAME":        "Ubuntu 20.04.2 LTS",
    50  		"VERSION_ID":         "20.04",
    51  		"HOME_URL":           "https://www.ubuntu.com/",
    52  		"SUPPORT_URL":        "https://help.ubuntu.com/",
    53  		"BUG_REPORT_URL":     "https://bugs.launchpad.net/ubuntu/",
    54  		"PRIVACY_POLICY_URL": "https://www.ubuntu.com/legal/terms-and-policies/privacy-policy",
    55  		"VERSION_CODENAME":   "focal",
    56  		"UBUNTU_CODENAME":    "focal",
    57  	}
    58  
    59  	osReleaseDebian := bytes.NewBufferString(`PRETTY_NAME="Debian GNU/Linux 10 (buster)"
    60  NAME="Debian GNU/Linux"
    61  VERSION_ID="10"
    62  VERSION="10 (buster)"
    63  VERSION_CODENAME=buster
    64  ID=debian
    65  HOME_URL="https://www.debian.org/"
    66  SUPPORT_URL="https://www.debian.org/support"
    67  BUG_REPORT_URL="https://bugs.debian.org/"`)
    68  
    69  	parsedDebian := map[string]string{
    70  		"PRETTY_NAME":      "Debian GNU/Linux 10 (buster)",
    71  		"NAME":             "Debian GNU/Linux",
    72  		"VERSION_ID":       "10",
    73  		"VERSION":          "10 (buster)",
    74  		"VERSION_CODENAME": "buster",
    75  		"ID":               "debian",
    76  		"HOME_URL":         "https://www.debian.org/",
    77  		"SUPPORT_URL":      "https://www.debian.org/support",
    78  		"BUG_REPORT_URL":   "https://bugs.debian.org/",
    79  	}
    80  
    81  	osReleaseAlpine := bytes.NewBufferString(`NAME="Alpine Linux"
    82  ID=alpine
    83  VERSION_ID=3.13.4
    84  PRETTY_NAME="Alpine Linux v3.13"
    85  HOME_URL="https://alpinelinux.org/"
    86  BUG_REPORT_URL="https://bugs.alpinelinux.org/"`)
    87  
    88  	parsedAlpine := map[string]string{
    89  		"NAME":           "Alpine Linux",
    90  		"ID":             "alpine",
    91  		"VERSION_ID":     "3.13.4",
    92  		"PRETTY_NAME":    "Alpine Linux v3.13",
    93  		"HOME_URL":       "https://alpinelinux.org/",
    94  		"BUG_REPORT_URL": "https://bugs.alpinelinux.org/",
    95  	}
    96  
    97  	osReleaseMock := bytes.NewBufferString(`
    98  # This line should be skipped
    99  
   100  QUOTED1="Quoted value 1"
   101  QUOTED2='Quoted value 2'
   102  ESCAPED1="\$HOME"
   103  ESCAPED2="\"release\""
   104  ESCAPED3="rock\'n\'roll"
   105  ESCAPED4="\\var"
   106  
   107  =line with missing key should be skipped
   108  
   109  PROP1=name=john
   110  	PROP2  =  Value  
   111  PROP3='This value will be overwritten by the next one'
   112  PROP3='Final value'`)
   113  
   114  	parsedMock := map[string]string{
   115  		"QUOTED1":  "Quoted value 1",
   116  		"QUOTED2":  "Quoted value 2",
   117  		"ESCAPED1": "$HOME",
   118  		"ESCAPED2": `"release"`,
   119  		"ESCAPED3": "rock'n'roll",
   120  		"ESCAPED4": `\var`,
   121  		"PROP1":    "name=john",
   122  		"PROP2":    "Value",
   123  		"PROP3":    "Final value",
   124  	}
   125  
   126  	tt := []struct {
   127  		Name      string
   128  		OSRelease io.Reader
   129  		Parsed    map[string]string
   130  	}{
   131  		{"Ubuntu", osReleaseUbuntu, parsedUbuntu},
   132  		{"Debian", osReleaseDebian, parsedDebian},
   133  		{"Alpine", osReleaseAlpine, parsedAlpine},
   134  		{"Mock", osReleaseMock, parsedMock},
   135  	}
   136  
   137  	for _, tc := range tt {
   138  		tc := tc
   139  
   140  		t.Run(tc.Name, func(t *testing.T) {
   141  			result := resource.ParseOSReleaseFile(tc.OSRelease)
   142  			require.EqualValues(t, tc.Parsed, result)
   143  		})
   144  	}
   145  }
   146  
   147  func TestSkip(t *testing.T) {
   148  	tt := []struct {
   149  		Name     string
   150  		Line     string
   151  		Expected bool
   152  	}{
   153  		{"Empty string", "", true},
   154  		{"Only whitespace", "   ", true},
   155  		{"Hashtag prefix 1", "# Sample text", true},
   156  		{"Hashtag prefix 2", "  # Sample text", true},
   157  		{"Hashtag and whitespace 1", "#  ", true},
   158  		{"Hashtag and whitespace 2", "  #", true},
   159  		{"Hashtag and whitespace 3", "  #  ", true},
   160  		{"Nonempty string", "Sample text", false},
   161  		{"Nonempty string with whitespace around", " Sample text ", false},
   162  		{"Nonempty string with middle hashtag", "Sample #text", false},
   163  		{"Nonempty string with ending hashtag", "Sample text #", false},
   164  	}
   165  
   166  	for _, tc := range tt {
   167  		tc := tc
   168  
   169  		t.Run(tc.Name, func(t *testing.T) {
   170  			result := resource.Skip(tc.Line)
   171  			require.EqualValues(t, tc.Expected, result)
   172  		})
   173  	}
   174  }
   175  
   176  func TestParse(t *testing.T) {
   177  	tt := []struct {
   178  		Name          string
   179  		Line          string
   180  		ExpectedKey   string
   181  		ExpectedValue string
   182  		OK            bool
   183  	}{
   184  		{"Empty string", "", "", "", false},
   185  		{"No separator", "wrong", "", "", false},
   186  		{"Empty key", "=john", "", "", false},
   187  		{"Empty key value", "=", "", "", false},
   188  		{"Empty value", "name=", "name", "", true},
   189  		{"Key value 1", "name=john", "name", "john", true},
   190  		{"Key value 2", "name=john=dev", "name", "john=dev", true},
   191  	}
   192  
   193  	for _, tc := range tt {
   194  		tc := tc
   195  
   196  		t.Run(tc.Name, func(t *testing.T) {
   197  			key, value, ok := resource.Parse(tc.Line)
   198  			require.EqualValues(t, tc.ExpectedKey, key)
   199  			require.EqualValues(t, tc.ExpectedValue, value)
   200  			require.EqualValues(t, tc.OK, ok)
   201  		})
   202  	}
   203  }
   204  
   205  func TestUnquote(t *testing.T) {
   206  	tt := []struct {
   207  		Name     string
   208  		Text     string
   209  		Expected string
   210  	}{
   211  		{"Empty string", ``, ``},
   212  		{"Single double quote", `"`, `"`},
   213  		{"Single single quote", `'`, `'`},
   214  		{"Empty double quotes", `""`, ``},
   215  		{"Empty single quotes", `''`, ``},
   216  		{"Empty mixed quotes 1", `"'`, `"'`},
   217  		{"Empty mixed quotes 2", `'"`, `'"`},
   218  		{"Double quotes", `"Sample text"`, `Sample text`},
   219  		{"Single quotes", `'Sample text'`, `Sample text`},
   220  		{"Half-open starting double quote", `"Sample text`, `"Sample text`},
   221  		{"Half-open ending double quote", `Sample text"`, `Sample text"`},
   222  		{"Half-open starting single quote", `'Sample text`, `'Sample text`},
   223  		{"Half-open ending single quote", `Sample text'`, `Sample text'`},
   224  		{"Double double quotes", `""Sample text""`, `"Sample text"`},
   225  		{"Double single quotes", `''Sample text''`, `'Sample text'`},
   226  		{"Mismatch quotes 1", `"Sample text'`, `"Sample text'`},
   227  		{"Mismatch quotes 2", `'Sample text"`, `'Sample text"`},
   228  		{"No quotes", `Sample text`, `Sample text`},
   229  		{"Internal double quote", `Sample "text"`, `Sample "text"`},
   230  		{"Internal single quote", `Sample 'text'`, `Sample 'text'`},
   231  	}
   232  
   233  	for _, tc := range tt {
   234  		tc := tc
   235  
   236  		t.Run(tc.Name, func(t *testing.T) {
   237  			result := resource.Unquote(tc.Text)
   238  			require.EqualValues(t, tc.Expected, result)
   239  		})
   240  	}
   241  }
   242  
   243  func TestUnescape(t *testing.T) {
   244  	tt := []struct {
   245  		Name     string
   246  		Text     string
   247  		Expected string
   248  	}{
   249  		{"Empty string", ``, ``},
   250  		{"Escaped dollar sign", `\$var`, `$var`},
   251  		{"Escaped double quote", `\"var`, `"var`},
   252  		{"Escaped single quote", `\'var`, `'var`},
   253  		{"Escaped backslash", `\\var`, `\var`},
   254  		{"Escaped backtick", "\\`var", "`var"},
   255  	}
   256  
   257  	for _, tc := range tt {
   258  		tc := tc
   259  
   260  		t.Run(tc.Name, func(t *testing.T) {
   261  			result := resource.Unescape(tc.Text)
   262  			require.EqualValues(t, tc.Expected, result)
   263  		})
   264  	}
   265  }
   266  
   267  func TestBuildOSRelease(t *testing.T) {
   268  	tt := []struct {
   269  		Name     string
   270  		Values   map[string]string
   271  		Expected string
   272  	}{
   273  		{"Nil values", nil, ""},
   274  		{"Empty values", map[string]string{}, ""},
   275  		{"Name and version only", map[string]string{
   276  			"NAME":    "Ubuntu",
   277  			"VERSION": "20.04.2 LTS (Focal Fossa)",
   278  		}, "Ubuntu 20.04.2 LTS (Focal Fossa)"},
   279  		{"Name and version preferred", map[string]string{
   280  			"NAME":        "Ubuntu",
   281  			"VERSION":     "20.04.2 LTS (Focal Fossa)",
   282  			"VERSION_ID":  "20.04",
   283  			"PRETTY_NAME": "Ubuntu 20.04.2 LTS",
   284  		}, "Ubuntu 20.04.2 LTS (Focal Fossa)"},
   285  		{"Version ID fallback", map[string]string{
   286  			"NAME":       "Ubuntu",
   287  			"VERSION_ID": "20.04",
   288  		}, "Ubuntu 20.04"},
   289  		{"Pretty name fallback due to missing name", map[string]string{
   290  			"VERSION":     "20.04.2 LTS (Focal Fossa)",
   291  			"PRETTY_NAME": "Ubuntu 20.04.2 LTS",
   292  		}, "Ubuntu 20.04.2 LTS"},
   293  		{"Pretty name fallback due to missing version", map[string]string{
   294  			"NAME":        "Ubuntu",
   295  			"PRETTY_NAME": "Ubuntu 20.04.2 LTS",
   296  		}, "Ubuntu 20.04.2 LTS"},
   297  	}
   298  
   299  	for _, tc := range tt {
   300  		tc := tc
   301  
   302  		t.Run(tc.Name, func(t *testing.T) {
   303  			result := resource.BuildOSRelease(tc.Values)
   304  			require.EqualValues(t, tc.Expected, result)
   305  		})
   306  	}
   307  }
   308  

View as plain text