Repository: prebid/prebid-server
Pull request #3145 (2023-09-25 20:30:16)

fix adapter code-coverage github action
PR updates code-coverage github action script to execute only if,
- all files all not removed
- file belongs to the 'adapters' directory

Testings:
- all files are removed: https://github.com/onkarvhanumante/prebid-server/pull/9
- adapter code is updated: https://github.com/onkarvhanumante/prebid-server/pull/10

PR changes will resolve failing code coverage test from PRs - https://github.com/prebid/prebid-server/pull/3143 https://github.com/prebid/prebid-server/pull/3142 https://github.com/prebid/prebid-server/pull/3134 https://github.com/prebid/prebid-server/pull/3133 https://github.com/prebid/prebid-server/pull/3132 https://github.com/prebid/prebid-server/pull/3131 https://github.com/prebid/prebid-server/pull/3130 https://github.com/prebid/prebid-server/pull/3129


Patch:
diff --git a/.github/workflows/adapter-code-coverage.yml b/.github/workflows/adapter-code-coverage.yml
index 5b5dc933..b4c3f074 100644
--- a/.github/workflows/adapter-code-coverage.yml
+++ b/.github/workflows/adapter-code-coverage.yml
@@ -28,9 +28,9 @@ jobs:
           result-encoding: string
           script: |
             const utils = require('./.github/workflows/helpers/pull-request-utils.js')            
-            function directoryExtractor(filepath) {
-              // extract directory name from filepath of the form adapters/<adapter-name>/*.go
-              if (filepath.startsWith("adapters/") && filepath.split("/").length > 2) {
+            function directoryExtractor(filepath, status) {
+              // extract directory name only if file is not removed and file is in adapters directory
+              if (status != "removed" && filepath.startsWith("adapters/") && filepath.split("/").length > 2) {
                 return filepath.split("/")[1]
               }
               return ""
@@ -41,7 +41,7 @@ jobs:
 
       - name: Run coverage tests
         id: run_coverage
-        if: ${{ steps.get_directories.outputs.result }} != ""
+        if: steps.get_directories.outputs.result != ''
         run: |
           directories=$(echo '${{ steps.get_directories.outputs.result }}' | jq -r '.[]')
           go mod download
@@ -74,7 +74,7 @@ jobs:
           repository: prebid/prebid-server
 
       - name: Commit coverage files to coverage-preview branch
-        if: ${{ steps.run_coverage.outputs.coverage_dir }} != ""
+        if: steps.run_coverage.outputs.coverage_dir != ''
         id: commit_coverage
         run: |
           directory=.github/preview/${{ github.run_id }}_$(date +%s)
@@ -88,11 +88,11 @@ jobs:
           echo "remote_coverage_preview_dir=${directory}" >> $GITHUB_OUTPUT
 
       - name: Checkout master branch
-        if: ${{ steps.get_directories.outputs.result }} != ""
+        if: steps.get_directories.outputs.result != ''
         run: git checkout master
 
       - name: Add coverage summary to pull request
-        if: ${{ steps.run_coverage.outputs.coverage_dir }} != "" && ${{ steps.commit_coverage.outputs.remote_coverage_preview_dir }} != ""
+        if: steps.run_coverage.outputs.coverage_dir != '' && steps.commit_coverage.outputs.remote_coverage_preview_dir != ''
         uses: actions/github-script@v6
         with:
           script: |
diff --git a/.github/workflows/helpers/pull-request-utils.js b/.github/workflows/helpers/pull-request-utils.js
index 78ab0bb2..941ae5b6 100644
--- a/.github/workflows/helpers/pull-request-utils.js
+++ b/.github/workflows/helpers/pull-request-utils.js
@@ -213,8 +213,8 @@ class diffHelper {
     })
 
     const directories = []
-    for (const { filename } of data) {
-      const directory = directoryExtractor(filename)
+    for (const { filename, status } of data) {
+      const directory = directoryExtractor(filename, status)
       if (directory != "" && !directories.includes(directory)) {
         directories.push(directory)
       }
diff --git a/adapters/silvermob/silvermob.go b/adapters/silvermob/silvermob.go
index 9130ab4d..d4a1b55b 100644
--- a/adapters/silvermob/silvermob.go
+++ b/adapters/silvermob/silvermob.go
@@ -18,6 +18,10 @@ type SilverMobAdapter struct {
 	endpoint *template.Template
 }
 
+func isValidHost(host string) bool {
+	return host == "eu" || host == "us" || host == "apac"
+}
+
 // Builder builds a new instance of the SilverMob adapter for the given bidder with the given config.
 func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) {
 	template, err := template.New("endpointTemplate").Parse(config.Endpoint)
@@ -121,8 +125,14 @@ func (a *SilverMobAdapter) getImpressionExt(imp *openrtb2.Imp) (*openrtb_ext.Ext
 }
 
 func (a *SilverMobAdapter) buildEndpointURL(params *openrtb_ext.ExtSilverMob) (string, error) {
-	endpointParams := macros.EndpointTemplateParams{ZoneID: params.ZoneID, Host: params.Host}
-	return macros.ResolveMacros(a.endpoint, endpointParams)
+	if isValidHost(params.Host) {
+		endpointParams := macros.EndpointTemplateParams{ZoneID: params.ZoneID, Host: params.Host}
+		return macros.ResolveMacros(a.endpoint, endpointParams)
+	} else {
+		return "", &errortypes.BadInput{
+			Message: fmt.Sprintf("invalid host %s", params.Host),
+		}
+	}
 }
 
 func (a *SilverMobAdapter) MakeBids(
diff --git a/endpoints/info/bidders_detail.go b/endpoints/info/bidders_detail.go
index 9b8d4268..d9dc776f 100644
--- a/endpoints/info/bidders_detail.go
+++ b/endpoints/info/bidders_detail.go
@@ -27,7 +27,11 @@ func NewBiddersDetailEndpoint(bidders config.BidderInfos, aliases map[string]str
 	return func(w http.ResponseWriter, _ *http.Request, ps httprouter.Params) {
 		bidder := ps.ByName("bidderName")
 
-		if response, ok := responses[bidder]; ok {
+		coreBidderName, found := getNormalisedBidderName(bidder, aliases)
+		if !found {
+			w.WriteHeader(http.StatusNotFound)
+		}
+		if response, ok := responses[coreBidderName]; ok {
 			w.Header().Set("Content-Type", "application/json")
 			if _, err := w.Write(response); err != nil {
 				glog.Errorf("error writing response to /info/bidders/%s: %v", bidder, err)
@@ -38,6 +42,20 @@ func NewBiddersDetailEndpoint(bidders config.BidderInfos, aliases map[string]str
 	}
 }
 
+func getNormalisedBidderName(bidderName string, aliases map[string]string) (string, bool) {
+	if strings.ToLower(bidderName) == "all" {
+		return "all", true
+	}
+	coreBidderName, ok := openrtb_ext.NormalizeBidderName(bidderName)
+	if !ok { //check default aliases if not found in coreBidders
+		if _, isDefaultAlias := aliases[bidderName]; isDefaultAlias {
+			return bidderName, true
+		}
+		return "", false
+	}
+	return coreBidderName.String(), true
+}
+
 func prepareBiddersDetailResponse(bidders config.BidderInfos, aliases map[string]string) (map[string][]byte, error) {
 	details, err := mapDetails(bidders, aliases)
 	if err != nil {


Test patch:
diff --git a/adapters/silvermob/silvermobtest/supplemental/invalid-host.json b/adapters/silvermob/silvermobtest/supplemental/invalid-host.json
new file mode 100644
index 00000000..f8b2cd34
--- /dev/null
+++ b/adapters/silvermob/silvermobtest/supplemental/invalid-host.json
@@ -0,0 +1,53 @@
+{
+    "mockBidRequest": {
+      "id": "some-request-id",
+      "device": {
+        "ua": "test-user-agent",
+        "ip": "123.123.123.123",
+        "language": "en",
+        "dnt": 0
+      },
+      "tmax": 1000,
+      "user": {
+        "buyeruid": "awesome-user"
+      },
+      "app": {
+        "publisher": {
+          "id": "123456789"
+        },
+        "cat": [
+          "IAB22-1"
+        ],
+        "bundle": "com.app.awesome",
+        "name": "Awesome App",
+        "domain": "awesomeapp.com",
+        "id": "123456789"
+      },
+      "imp": [
+        {
+          "id": "some-impression-id",
+          "tagid": "ogTAGID",
+          "banner": {
+            "w":320,
+            "h":50
+          },
+          "ext": {
+            "bidder": {
+              "host": "some_host",
+              "zoneid": "0"
+            }
+          }
+        }
+      ]
+    },
+    "httpCalls": [
+    ],
+    "expectedBidResponses": [ 
+    ],
+    "expectedMakeRequestsErrors": [
+      {
+        "value": "invalid host some_host",
+        "comparison": "literal"
+      }
+    ]
+  }
\ No newline at end of file
diff --git a/endpoints/info/bidders_detail_test.go b/endpoints/info/bidders_detail_test.go
index 3be24acf..435d0cec 100644
--- a/endpoints/info/bidders_detail_test.go
+++ b/endpoints/info/bidders_detail_test.go
@@ -2,6 +2,7 @@ package info
 
 import (
 	"bytes"
+	"fmt"
 	"io"
 	"net/http"
 	"net/http/httptest"
@@ -365,22 +366,22 @@ func TestMapMediaTypes(t *testing.T) {
 func TestBiddersDetailHandler(t *testing.T) {
 	bidderAInfo := config.BidderInfo{Endpoint: "https://secureEndpoint.com", Disabled: false, Maintainer: &config.MaintainerInfo{Email: "bidderA"}}
 	bidderAResponse := []byte(`{"status":"ACTIVE","usesHttps":true,"maintainer":{"email":"bidderA"}}`)
-	aliasAResponse := []byte(`{"status":"ACTIVE","usesHttps":true,"maintainer":{"email":"bidderA"},"aliasOf":"a"}`)
+	aliasAResponse := []byte(`{"status":"ACTIVE","usesHttps":true,"maintainer":{"email":"bidderA"},"aliasOf":"appnexus"}`)
 
 	bidderBInfo := config.BidderInfo{Endpoint: "http://unsecureEndpoint.com", Disabled: false, Maintainer: &config.MaintainerInfo{Email: "bidderB"}}
 	bidderBResponse := []byte(`{"status":"ACTIVE","usesHttps":false,"maintainer":{"email":"bidderB"}}`)
 
 	allResponse := bytes.Buffer{}
-	allResponse.WriteString(`{"a":`)
-	allResponse.Write(bidderAResponse)
-	allResponse.WriteString(`,"aAlias":`)
+	allResponse.WriteString(`{"aAlias":`)
 	allResponse.Write(aliasAResponse)
-	allResponse.WriteString(`,"b":`)
+	allResponse.WriteString(`,"appnexus":`)
+	allResponse.Write(bidderAResponse)
+	allResponse.WriteString(`,"rubicon":`)
 	allResponse.Write(bidderBResponse)
 	allResponse.WriteString(`}`)
 
-	bidders := config.BidderInfos{"a": bidderAInfo, "b": bidderBInfo}
-	aliases := map[string]string{"aAlias": "a"}
+	bidders := config.BidderInfos{"appnexus": bidderAInfo, "rubicon": bidderBInfo}
+	aliases := map[string]string{"aAlias": "appnexus"}
 
 	handler := NewBiddersDetailEndpoint(bidders, aliases)
 
@@ -393,14 +394,21 @@ func TestBiddersDetailHandler(t *testing.T) {
 	}{
 		{
 			description:      "Bidder A",
-			givenBidder:      "a",
+			givenBidder:      "appnexus",
 			expectedStatus:   http.StatusOK,
 			expectedHeaders:  http.Header{"Content-Type": []string{"application/json"}},
 			expectedResponse: bidderAResponse,
 		},
 		{
 			description:      "Bidder B",
-			givenBidder:      "b",
+			givenBidder:      "rubicon",
+			expectedStatus:   http.StatusOK,
+			expectedHeaders:  http.Header{"Content-Type": []string{"application/json"}},
+			expectedResponse: bidderBResponse,
+		},
+		{
+			description:      "Bidder B - case insensitive",
+			givenBidder:      "RUBICON",
 			expectedStatus:   http.StatusOK,
 			expectedHeaders:  http.Header{"Content-Type": []string{"application/json"}},
 			expectedResponse: bidderBResponse,
@@ -412,6 +420,13 @@ func TestBiddersDetailHandler(t *testing.T) {
 			expectedHeaders:  http.Header{"Content-Type": []string{"application/json"}},
 			expectedResponse: aliasAResponse,
 		},
+		{
+			description:      "Bidder A Alias - case insensitive",
+			givenBidder:      "aAlias",
+			expectedStatus:   http.StatusOK,
+			expectedHeaders:  http.Header{"Content-Type": []string{"application/json"}},
+			expectedResponse: aliasAResponse,
+		},
 		{
 			description:      "All Bidders",
 			givenBidder:      "all",
@@ -420,11 +435,11 @@ func TestBiddersDetailHandler(t *testing.T) {
 			expectedResponse: allResponse.Bytes(),
 		},
 		{
-			description:      "All Bidders - Wrong Case",
-			givenBidder:      "ALL",
-			expectedStatus:   http.StatusNotFound,
-			expectedHeaders:  http.Header{},
-			expectedResponse: []byte{},
+			description:      "All Bidders - Case insensitive",
+			givenBidder:      "All",
+			expectedStatus:   http.StatusOK,
+			expectedHeaders:  http.Header{"Content-Type": []string{"application/json"}},
+			expectedResponse: allResponse.Bytes(),
 		},
 		{
 			description:      "Invalid Bidder",
@@ -436,16 +451,19 @@ func TestBiddersDetailHandler(t *testing.T) {
 	}
 
 	for _, test := range testCases {
-		responseRecorder := httptest.NewRecorder()
-		handler(responseRecorder, nil, httprouter.Params{{"bidderName", test.givenBidder}})
+		t.Run(test.description, func(t *testing.T) {
+			responseRecorder := httptest.NewRecorder()
+			handler(responseRecorder, nil, httprouter.Params{{"bidderName", test.givenBidder}})
 
-		result := responseRecorder.Result()
-		assert.Equal(t, result.StatusCode, test.expectedStatus, test.description+":statuscode")
+			result := responseRecorder.Result()
+			assert.Equal(t, result.StatusCode, test.expectedStatus, test.description+":statuscode")
 
-		resultBody, _ := io.ReadAll(result.Body)
-		assert.Equal(t, test.expectedResponse, resultBody, test.description+":body")
+			resultBody, _ := io.ReadAll(result.Body)
+			fmt.Println(string(test.expectedResponse))
+			assert.Equal(t, test.expectedResponse, resultBody, test.description+":body")
 
-		resultHeaders := result.Header
-		assert.Equal(t, test.expectedHeaders, resultHeaders, test.description+":headers")
+			resultHeaders := result.Header
+			assert.Equal(t, test.expectedHeaders, resultHeaders, test.description+":headers")
+		})
 	}
 }