Repository: elastic/go-sysinfo
Pull request #158 (2023-03-27 19:08:29)

Make FQDN lookup function more testable
This PR refactors the `shared.FQDN()` function, extracting the lookup algorithm into a helper function, to make the code a bit more testable.  Having done that, the PR also adds a unit test for the helper function.

elasticmachine: 
## :broken_heart: Build Failed


<!-- BUILD BADGES-->
> _the below badges are clickable and redirect to their specific view in the CI or DOCS_
[![Pipeline View](https://img.shields.io/badge/pipeline-pipeline%20-green)](https://beats-ci.elastic.co/blue/organizations/jenkins/Library%2Fgo-sysinfo-mbp%2FPR-158/detail/PR-158/1//pipeline) [![Test View](https://img.shields.io/badge/test-test-green)](https://beats-ci.elastic.co/blue/organizations/jenkins/Library%2Fgo-sysinfo-mbp%2FPR-158/detail/PR-158/1//tests) [![Changes](https://img.shields.io/badge/changes-changes-green)](https://beats-ci.elastic.co/blue/organizations/jenkins/Library%2Fgo-sysinfo-mbp%2FPR-158/detail/PR-158/1//changes) [![Artifacts](https://img.shields.io/badge/artifacts-artifacts-yellow)](https://beats-ci.elastic.co/blue/organizations/jenkins/Library%2Fgo-sysinfo-mbp%2FPR-158/detail/PR-158/1//artifacts) [![preview](https://img.shields.io/badge/docs-preview-yellowgreen)](http://go-sysinfo_158.docs-preview.app.elstc.co/diff)  [![preview](https://img.shields.io/badge/elastic-observability-blue)](https://ci-stats.elastic.co/app/apm/services/beats-ci/transactions/view?rangeFrom=2023-03-27T18:58:44.031Z&rangeTo=2023-03-27T19:18:44.031Z&transactionName=BUILD+Library%2Fgo-sysinfo-mbp%2FPR-%7Bnumber%7D&transactionType=job&latencyAggregationType=avg&traceId=ad0af95c00ae4d8a23ce6e39160ad0dc&transactionId=12c84fd56ba50174)

<!-- BUILD SUMMARY-->
<details><summary>Expand to view the summary</summary>
<p>

#### Build stats




* Start Time: 2023-03-27T19:08:44.031+0000


* Duration: 8 min 53 sec




#### Test stats :test_tube:

| Test         | Results                         |
| ------------ | :-----------------------------: |
| Failed       | 0  |
| Passed       | 24  |
| Skipped      | 0 |
| Total        | 24   |


</p>
</details>

<!-- TEST RESULTS IF ANY-->


<!-- STEPS ERRORS IF ANY -->














### Steps errors [![8](https://img.shields.io/badge/8%20-red)](https://beats-ci.elastic.co/blue/organizations/jenkins/Library%2Fgo-sysinfo-mbp%2FPR-158/detail/PR-158/1//pipeline)
  <details><summary>Expand to view the steps failures</summary>
  <p>


  
  
  
  
##### `go test for 1.18.10 in ubuntu-18 && immutable`
<ul>
<li>Took 0 min 14 sec . View more details <a href="https://beats-ci.elastic.co//blue/rest/organizations/jenkins/pipelines/Library/pipelines/go-sysinfo-mbp/pipelines/PR-158/runs/1/steps/298/log/?start=0">here</a></li>
<li>Description: <code>.ci/scripts/test.sh</code></l1>
</ul>
  
  
  
  
##### `go test for 1.18.10 in windows-2019 && immutable`
<ul>
<li>Took 0 min 23 sec . View more details <a href="https://beats-ci.elastic.co//blue/rest/organizations/jenkins/pipelines/Library/pipelines/go-sysinfo-mbp/pipelines/PR-158/runs/1/steps/496/log/?start=0">here</a></li>
<li>Description: <code>.ci/scripts/test.bat</code></l1>
</ul>
  
  
  
  
##### `go test for 1.18.10 in orka && darwin && x86_64`
<ul>
<li>Took 0 min 17 sec . View more details <a href="https://beats-ci.elastic.co//blue/rest/organizations/jenkins/pipelines/Library/pipelines/go-sysinfo-mbp/pipelines/PR-158/runs/1/steps/249/log/?start=0">here</a></li>
<li>Description: <code>.ci/scripts/test.sh</code></l1>
</ul>
  
  
  
  
##### `go test for 1.19.5 in orka && darwin && arm64`
<ul>
<li>Took 0 min 7 sec . View more details <a href="https://beats-ci.elastic.co//blue/rest/organizations/jenkins/pipelines/Library/pipelines/go-sysinfo-mbp/pipelines/PR-158/runs/1/steps/187/log/?start=0">here</a></li>
<li>Description: <code>.ci/scripts/test.sh</code></l1>
</ul>
  
  
  
  
##### `go test for 1.18.10 in ubuntu-18 && immutable`
<ul>
<li>Took 0 min 8 sec . View more details <a href="https://beats-ci.elastic.co//blue/rest/organizations/jenkins/pipelines/Library/pipelines/go-sysinfo-mbp/pipelines/PR-158/runs/1/steps/330/log/?start=0">here</a></li>
<li>Description: <code>.ci/scripts/test.sh</code></l1>
</ul>
  
  
  
  
##### `go test for 1.18.10 in windows-2019 && immutable`
<ul>
<li>Took 0 min 24 sec . View more details <a href="https://beats-ci.elastic.co//blue/rest/organizations/jenkins/pipelines/Library/pipelines/go-sysinfo-mbp/pipelines/PR-158/runs/1/steps/511/log/?start=0">here</a></li>
<li>Description: <code>.ci/scripts/test.bat</code></l1>
</ul>
  
  
  
  
##### `go test for 1.18.10 in orka && darwin && x86_64`
<ul>
<li>Took 0 min 16 sec . View more details <a href="https://beats-ci.elastic.co//blue/rest/organizations/jenkins/pipelines/Library/pipelines/go-sysinfo-mbp/pipelines/PR-158/runs/1/steps/415/log/?start=0">here</a></li>
<li>Description: <code>.ci/scripts/test.sh</code></l1>
</ul>
  
  
  
  
##### `go test for 1.19.5 in orka && darwin && arm64`
<ul>
<li>Took 0 min 9 sec . View more details <a href="https://beats-ci.elastic.co//blue/rest/organizations/jenkins/pipelines/Library/pipelines/go-sysinfo-mbp/pipelines/PR-158/runs/1/steps/365/log/?start=0">here</a></li>
<li>Description: <code>.ci/scripts/test.sh</code></l1>
</ul>
  
  </p>
  </details>




</p>
</details>

<!--COMMENT_GENERATED_WITH_ID_comment.id-->
ycombinator: The tests added in this PR are failing in CI with a slightly different error (as returned by `shared.fqdn()`) than on my development machine.  So I'm going to relax the error assertions in the test slightly to make the tests less sensitive to the environment they're running in.
ycombinator: /test

Patch:
diff --git a/providers/shared/fqdn.go b/providers/shared/fqdn.go
index 387fda7..2872906 100644
--- a/providers/shared/fqdn.go
+++ b/providers/shared/fqdn.go
@@ -32,6 +32,10 @@ func FQDN() (string, error) {
 		return "", fmt.Errorf("could not get hostname to look for FQDN: %w", err)
 	}
 
+	return fqdn(hostname)
+}
+
+func fqdn(hostname string) (string, error) {
 	var errs error
 	cname, err := net.LookupCNAME(hostname)
 	if err != nil {


Test patch:
diff --git a/providers/shared/fqdn_test.go b/providers/shared/fqdn_test.go
new file mode 100644
index 0000000..23a9450
--- /dev/null
+++ b/providers/shared/fqdn_test.go
@@ -0,0 +1,78 @@
+// Licensed to Elasticsearch B.V. under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Elasticsearch B.V. licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+//go:build linux || darwin
+
+package shared
+
+import (
+	"fmt"
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+func TestFQDN(t *testing.T) {
+	tests := map[string]struct {
+		osHostname       string
+		expectedFQDN     string
+		expectedErrRegex string
+	}{
+		// This test case depends on network, particularly DNS,
+		// being available.  If it starts to fail often enough
+		// due to occasional network/DNS unavailability, we should
+		// probably just delete this test case.
+		"long_real_hostname": {
+			osHostname:       "elastic.co",
+			expectedFQDN:     "elastic.co",
+			expectedErrRegex: "",
+		},
+		"long_nonexistent_hostname": {
+			osHostname:       "foo.bar.elastic.co",
+			expectedFQDN:     "",
+			expectedErrRegex: makeErrorRegex("foo.bar.elastic.co"),
+		},
+		"short_nonexistent_hostname": {
+			osHostname:       "foobarbaz",
+			expectedFQDN:     "",
+			expectedErrRegex: makeErrorRegex("foobarbaz"),
+		},
+	}
+
+	for name, test := range tests {
+		t.Run(name, func(t *testing.T) {
+			actualFQDN, err := fqdn(test.osHostname)
+			require.Equal(t, test.expectedFQDN, actualFQDN)
+
+			if test.expectedErrRegex == "" {
+				require.Nil(t, err)
+			} else {
+				require.Regexp(t, test.expectedErrRegex, err.Error())
+			}
+		})
+	}
+}
+
+func makeErrorRegex(osHostname string) string {
+	return fmt.Sprintf(
+		"could not get FQDN, all methods failed: "+
+			"failed looking up CNAME: lookup %s.*: "+
+			"failed looking up IP: lookup %s.*",
+		osHostname,
+		osHostname,
+	)
+}