From 1ec697bdb97a34c378b85188009d3f2181774526 Mon Sep 17 00:00:00 2001 From: saurabh-narkhede Date: Wed, 8 Jan 2025 00:59:57 +0530 Subject: [PATCH] add test cases --- .../openwrap/cache/gocache/compliance_test.go | 95 +++++ .../openwrap/database/mysql/compliance.go | 1 + .../database/mysql/compliance_test.go | 156 ++++++++ modules/pubmatic/openwrap/geo.go | 22 +- modules/pubmatic/openwrap/geo_test.go | 345 ++++++++++++++++++ .../publisherfeature/compliance_test.go | 181 +++++++++ 6 files changed, 785 insertions(+), 15 deletions(-) create mode 100644 modules/pubmatic/openwrap/cache/gocache/compliance_test.go create mode 100644 modules/pubmatic/openwrap/database/mysql/compliance_test.go create mode 100644 modules/pubmatic/openwrap/geo_test.go create mode 100644 modules/pubmatic/openwrap/publisherfeature/compliance_test.go diff --git a/modules/pubmatic/openwrap/cache/gocache/compliance_test.go b/modules/pubmatic/openwrap/cache/gocache/compliance_test.go new file mode 100644 index 0000000000..63ed3214c8 --- /dev/null +++ b/modules/pubmatic/openwrap/cache/gocache/compliance_test.go @@ -0,0 +1,95 @@ +package gocache + +import ( + "errors" + "testing" + + "github.com/golang/mock/gomock" + gocache "github.com/patrickmn/go-cache" + + "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/config" + "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/database" + mock_database "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/database/mock" + "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/metrics" + mock_metrics "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/metrics/mock" + "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models" + "github.com/stretchr/testify/assert" +) + +func TestCache_GetGDPRCountryCodes(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + mockDatabase := mock_database.NewMockDatabase(ctrl) + mockEngine := mock_metrics.NewMockMetricsEngine(ctrl) + type fields struct { + cache *gocache.Cache + cfg config.Cache + db database.Database + metricEngine metrics.MetricsEngine + } + tests := []struct { + name string + fields fields + want map[string]struct{} + setup func() + wantErr bool + }{ + { + name: "Valid Data present in DB, return same", + want: map[string]struct{}{ + "US": {}, + "LV": {}, + "DE": {}, + }, + setup: func() { + mockDatabase.EXPECT().GetGDPRCountryCodes().Return(map[string]struct{}{ + "US": {}, + "LV": {}, + "DE": {}, + }, nil) + }, + fields: fields{ + cache: gocache.New(100, 100), + db: mockDatabase, + cfg: config.Cache{ + CacheDefaultExpiry: 1000, + }, + }, + wantErr: false, + }, + { + name: "Error In DB, Set Empty", + want: nil, + setup: func() { + mockDatabase.EXPECT().GetGDPRCountryCodes().Return(nil, errors.New("QUERY FAILD")) + mockEngine.EXPECT().RecordDBQueryFailure(models.GDPRCountryCodesQuery, "", "").Return() + }, + fields: fields{ + cache: gocache.New(100, 100), + db: mockDatabase, + cfg: config.Cache{ + CacheDefaultExpiry: 1000, + }, + metricEngine: mockEngine, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.setup() + c := &cache{ + cache: tt.fields.cache, + cfg: tt.fields.cfg, + db: tt.fields.db, + metricEngine: tt.fields.metricEngine, + } + got, err := c.GetGDPRCountryCodes() + if (err != nil) != tt.wantErr { + t.Errorf("cache.GetGDPRCountryCodes() error = %v, wantErr %v", err, tt.wantErr) + return + } + assert.Equal(t, tt.want, got, tt.name) + }) + } +} diff --git a/modules/pubmatic/openwrap/database/mysql/compliance.go b/modules/pubmatic/openwrap/database/mysql/compliance.go index 775f66e9d3..ed2ef72e36 100644 --- a/modules/pubmatic/openwrap/database/mysql/compliance.go +++ b/modules/pubmatic/openwrap/database/mysql/compliance.go @@ -25,6 +25,7 @@ func (db *mySqlDB) GetGDPRCountryCodes() (map[string]struct{}, error) { glog.Error("ErrRowScanFailed GetGDPRCountryCodes Err: ", err.Error()) continue } + //TO-DO keeping case-sensitive? countryCodes[countryCode] = struct{}{} } diff --git a/modules/pubmatic/openwrap/database/mysql/compliance_test.go b/modules/pubmatic/openwrap/database/mysql/compliance_test.go new file mode 100644 index 0000000000..df411ed3bf --- /dev/null +++ b/modules/pubmatic/openwrap/database/mysql/compliance_test.go @@ -0,0 +1,156 @@ +package mysql + +import ( + "database/sql" + "errors" + "regexp" + "testing" + + "github.com/DATA-DOG/go-sqlmock" + "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/config" + "github.com/stretchr/testify/assert" +) + +func Test_mySqlDB_GetGDPRCountryCodes(t *testing.T) { + type fields struct { + cfg config.Database + } + tests := []struct { + name string + fields fields + want map[string]struct{} + wantErr error + setup func() *sql.DB + }{ + { + name: "empty query in config file", + fields: fields{ + cfg: config.Database{ + MaxDbContextTimeout: 100, + }, + }, + want: nil, + wantErr: errors.New("all expectations were already fulfilled, call to Query '' with args [] was not expected"), + setup: func() *sql.DB { + db, _, err := sqlmock.New() + if err != nil { + t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) + } + return db + }, + }, + { + name: "valid rows returned from DB", + fields: fields{ + cfg: config.Database{ + MaxDbContextTimeout: 100, + Queries: config.Queries{ + GetGDPRCountryCodes: "^SELECT (.+) FROM KomliAdServer.geo (.+)", + }, + }, + }, + want: map[string]struct{}{ + "DE": {}, + "LV": {}, + }, + wantErr: nil, + setup: func() *sql.DB { + db, mock, err := sqlmock.New() + if err != nil { + t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) + } + rows := sqlmock.NewRows([]string{"countrycode"}). + AddRow(`DE`). + AddRow(`LV`) + mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM KomliAdServer.geo (.+)")).WillReturnRows(rows) + return db + }, + }, + { + name: "no rows returned from DB", + fields: fields{ + cfg: config.Database{ + MaxDbContextTimeout: 100, + Queries: config.Queries{ + GetGDPRCountryCodes: "^SELECT (.+) FROM KomliAdServer.geo (.+)", + }, + }, + }, + want: map[string]struct{}{}, + wantErr: nil, + setup: func() *sql.DB { + db, mock, err := sqlmock.New() + if err != nil { + t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) + } + rows := sqlmock.NewRows([]string{"countrycode"}) + mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM KomliAdServer.geo (.+)")).WillReturnRows(rows) + return db + }, + }, + { + name: "partial row scan error", + fields: fields{ + cfg: config.Database{ + MaxDbContextTimeout: 1000000, + Queries: config.Queries{ + GetGDPRCountryCodes: "^SELECT (.+) FROM KomliAdServer.geo (.+)", + }, + }, + }, + want: map[string]struct{}{}, + wantErr: nil, + setup: func() *sql.DB { + db, mock, err := sqlmock.New() + if err != nil { + t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) + } + rows := sqlmock.NewRows([]string{"countrycode", "extra_column"}). + AddRow(`DE`, `12`) + rows = rows.RowError(1, errors.New("error in row scan")) + mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM KomliAdServer.geo (.+)")).WillReturnRows(rows) + return db + }, + }, + { + name: "error in row scan", + fields: fields{ + cfg: config.Database{ + MaxDbContextTimeout: 100, + Queries: config.Queries{ + GetGDPRCountryCodes: "^SELECT (.+) FROM KomliAdServer.geo (.+)", + }, + }, + }, + want: nil, + wantErr: errors.New("error in row scan"), + setup: func() *sql.DB { + db, mock, err := sqlmock.New() + if err != nil { + t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) + } + rows := sqlmock.NewRows([]string{"countrycode"}). + AddRow(`DE`). + AddRow(`LV`) + rows = rows.RowError(1, errors.New("error in row scan")) + mock.ExpectQuery(regexp.QuoteMeta("^SELECT (.+) FROM KomliAdServer.geo (.+)")).WillReturnRows(rows) + return db + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + db := &mySqlDB{ + conn: tt.setup(), + cfg: tt.fields.cfg, + } + got, err := db.GetGDPRCountryCodes() + if tt.wantErr == nil { + assert.NoError(t, err, tt.name) + } else { + assert.EqualError(t, err, tt.wantErr.Error(), tt.name) + } + assert.Equal(t, tt.want, got) + }) + } +} diff --git a/modules/pubmatic/openwrap/geo.go b/modules/pubmatic/openwrap/geo.go index 13f97f1c33..b84063ec18 100644 --- a/modules/pubmatic/openwrap/geo.go +++ b/modules/pubmatic/openwrap/geo.go @@ -10,7 +10,6 @@ import ( "git.pubmatic.com/PubMatic/go-common/util" "github.com/golang/glog" - "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/geodb/netacuity" "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/metrics" "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/metrics/prometheus" "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models" @@ -33,18 +32,6 @@ const ( headerAccessControlAllowOriginValue = "*" ) -// geoHandler provides a handler for geo lookups. -type geoHandler struct { - geoService netacuity.NetAcuity -} - -// NewGeo initializes and returns a new GeoHandler. -func NewGeo() *geoHandler { - return &geoHandler{ - geoService: netacuity.NetAcuity{}, - } -} - var gppSectionIDs = map[string]int{ "ca": 8, "va": 9, @@ -64,7 +51,7 @@ const ( ) // Handler for /geo endpoint -func (handler *geoHandler) Handler(w http.ResponseWriter, r *http.Request) { +func Handler(w http.ResponseWriter, r *http.Request) { var pubIdStr string metricEngine := ow.GetMetricEngine() metricLabels := metrics.Labels{RType: models.EndpointGeo, RequestStatus: prometheus.RequestStatusOK} @@ -77,6 +64,11 @@ func (handler *geoHandler) Handler(w http.ResponseWriter, r *http.Request) { } }() + if r.Method != http.MethodGet { + w.WriteHeader(http.StatusMethodNotAllowed) + metricLabels.RequestStatus = prometheus.RequestStatusBadInput + return + } pubIdStr = r.URL.Query().Get(models.PublisherID) _, err := strconv.Atoi(pubIdStr) if err != nil { @@ -91,7 +83,7 @@ func (handler *geoHandler) Handler(w http.ResponseWriter, r *http.Request) { w.Header().Set(headerContentType, headerContentTypeValue) w.Header().Set(headerAccessControlAllowOrigin, "*") success := false - geoInfo, _ := handler.geoService.LookUp(ip) + geoInfo, _ := ow.geoInfoFetcher.LookUp(ip) if geoInfo != nil { if geoInfo.ISOCountryCode != "" { success = true diff --git a/modules/pubmatic/openwrap/geo_test.go b/modules/pubmatic/openwrap/geo_test.go new file mode 100644 index 0000000000..208cf3ede1 --- /dev/null +++ b/modules/pubmatic/openwrap/geo_test.go @@ -0,0 +1,345 @@ +package openwrap + +import ( + "errors" + "net/http" + "net/http/httptest" + "testing" + + "github.com/golang/mock/gomock" + "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/geodb" + mock_geodb "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/geodb/mock" + metrics "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/metrics" + mock_metrics "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/metrics/mock" + "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/metrics/prometheus" + "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models" + mock_feature "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/publisherfeature/mock" + "github.com/stretchr/testify/assert" +) + +const ( + geoWithPubid = `http://localhost:8001/geo?pubid=23105` + geoWithoutPubid = `http://localhost:8001/geo` + geoWithWrongPubid = `http://localhost:8001/geo?pubid=bad` +) + +type headerType int + +const ( + NoHeaders headerType = iota + NonEURequest + EURequest + USPRequest + GPPCountryRequest + InvalidIP + InvalidUID + NilGeo + GeoLookupFail + EmptyGeo +) + +func getTestHTTPRequest(url string, headers http.Header) *http.Request { + r, err := http.NewRequest("GET", url, nil) + if err != nil { + panic("error: creating an http request") + } + + for k, v := range headers { + r.Header.Add(k, v[0]) + } + + if err := r.ParseForm(); err != nil { + panic("error: parsing http request") + } + return r +} + +func getHeaders(headerType headerType) http.Header { + switch headerType { + case NoHeaders: + return nil + case NonEURequest: + return http.Header{ + "User-Agent": []string{"golang sample request"}, + "Cookie": []string{"KADUSERCOOKIE=pmuserid"}, + "SOURCE_IP": []string{"115.114.134.174"}, + } + case EURequest: + return http.Header{ + "User-Agent": []string{"golang sample request"}, + "Cookie": []string{"KADUSERCOOKIE=pmuserid"}, + "SOURCE_IP": []string{"2.16.1.255"}, + } + case USPRequest: + return http.Header{ + "User-Agent": []string{"golang sample request"}, + "Cookie": []string{"KADUSERCOOKIE=pmuserid"}, + "SOURCE_IP": []string{"43.135.143.132"}, + } + case GPPCountryRequest: + return http.Header{ + "User-Agent": []string{"golang sample request"}, + "Cookie": []string{"KADUSERCOOKIE=pmuserid"}, + "SOURCE_IP": []string{"208.253.114.165"}, + } + case InvalidIP: + return http.Header{ + "User-Agent": []string{"golang sample request"}, + "Cookie": []string{"KADUSERCOOKIE=pmuserid"}, + "SOURCE_IP": []string{"115.114.134"}, + } + case InvalidUID: + return http.Header{ + "User-Agent": []string{"golang sample request"}, + "Cookie": []string{"KADUSERCOOKIE=pmuserid}"}, + } + case EmptyGeo: + return http.Header{ + "SOURCE_IP": []string{"30.30.30.30"}, + } + case GeoLookupFail: + return http.Header{ + "SOURCE_IP": []string{"20.20.20.20"}, + } + case NilGeo: + return http.Header{ + "SOURCE_IP": []string{"10.10.10.10"}, + } + } + return nil +} + +func TestHandler(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockMetrics := mock_metrics.NewMockMetricsEngine(ctrl) + mockgeodb := mock_geodb.NewMockGeography(ctrl) + mockFeature := mock_feature.NewMockFeature(ctrl) + + originalOw := ow + defer func() { ow = originalOw }() + ow = &OpenWrap{ + metricEngine: mockMetrics, + geoInfoFetcher: mockgeodb, + pubFeatures: mockFeature, + } + + type args struct { + r *http.Request + setup func() + } + type want struct { + geo string + statuCode int + header []string + } + tests := []struct { + name string + args args + setup geodb.Geography + want want + }{ + { + name: "POST request", + args: args{ + r: func() *http.Request { + r, err := http.NewRequest("POST", geoWithoutPubid, nil) + if err != nil { + panic("error: creating an http request") + } + return r + }(), + setup: func() { + labels := metrics.Labels{RType: models.EndpointGeo, RequestStatus: prometheus.RequestStatusBadInput} + mockMetrics.EXPECT().RecordRequest(labels) + }, + }, + want: want{ + geo: "", + statuCode: http.StatusMethodNotAllowed, + header: nil, + }, + }, + { + name: "invalid pubid", + args: args{ + r: getTestHTTPRequest(geoWithWrongPubid, getHeaders(NoHeaders)), + setup: func() { + labels := metrics.Labels{RType: models.EndpointGeo, RequestStatus: prometheus.RequestStatusBadInput} + mockMetrics.EXPECT().RecordRequest(labels) + }, + }, + want: want{ + geo: "", + statuCode: http.StatusBadRequest, + header: nil, + }, + }, + { + name: "pubid not present", + args: args{ + r: getTestHTTPRequest(geoWithoutPubid, getHeaders(NoHeaders)), + setup: func() { + labels := metrics.Labels{RType: models.EndpointGeo, RequestStatus: prometheus.RequestStatusBadInput} + mockMetrics.EXPECT().RecordRequest(labels) + }, + }, + want: want{ + geo: "", + statuCode: http.StatusBadRequest, + header: nil, + }, + }, + { + name: "valid pubid with no ip in headers", + args: args{ + r: getTestHTTPRequest(geoWithPubid, getHeaders(NoHeaders)), + setup: func() { + labels := metrics.Labels{RType: models.EndpointGeo, RequestStatus: prometheus.RequestStatusOK} + mockMetrics.EXPECT().RecordRequest(labels) + mockMetrics.EXPECT().RecordGeoLookupFailure(models.EndpointGeo) + mockgeodb.EXPECT().LookUp(gomock.Any()).Return(&geodb.GeoInfo{}, nil) + }, + }, + want: want{ + geo: "", + statuCode: http.StatusOK, + header: nil, + }, + }, + { + name: "ip Lookup fail", + args: args{ + r: getTestHTTPRequest(geoWithPubid, getHeaders(GeoLookupFail)), + setup: func() { + labels := metrics.Labels{RType: models.EndpointGeo, RequestStatus: prometheus.RequestStatusOK} + mockMetrics.EXPECT().RecordRequest(labels) + mockMetrics.EXPECT().RecordGeoLookupFailure(models.EndpointGeo) + mockgeodb.EXPECT().LookUp(gomock.Any()).Return(nil, errors.New("ErrDummy")) + }, + }, + want: want{ + geo: "", + statuCode: http.StatusOK, + header: nil, + }, + }, + { + name: "ip lookup returns nil", + args: args{ + r: getTestHTTPRequest(geoWithPubid, getHeaders(NilGeo)), + setup: func() { + labels := metrics.Labels{RType: models.EndpointGeo, RequestStatus: prometheus.RequestStatusOK} + mockMetrics.EXPECT().RecordRequest(labels) + mockMetrics.EXPECT().RecordGeoLookupFailure(models.EndpointGeo) + mockgeodb.EXPECT().LookUp(gomock.Any()).Return(nil, nil) + }, + }, + want: want{ + geo: "", + statuCode: http.StatusOK, + header: nil, + }, + }, + { + name: "empty countrycode", + args: args{ + r: getTestHTTPRequest(geoWithPubid, getHeaders(NonEURequest)), + setup: func() { + labels := metrics.Labels{RType: models.EndpointGeo, RequestStatus: prometheus.RequestStatusOK} + mockMetrics.EXPECT().RecordRequest(labels) + mockMetrics.EXPECT().RecordGeoLookupFailure(models.EndpointGeo) + mockgeodb.EXPECT().LookUp(gomock.Any()).Return(&geodb.GeoInfo{ISOCountryCode: ""}, nil) + }, + }, + want: want{ + geo: "", + statuCode: http.StatusOK, + header: nil, + }, + }, + { + name: "EU region request", + args: args{ + r: getTestHTTPRequest(geoWithPubid, getHeaders(EURequest)), + setup: func() { + labels := metrics.Labels{RType: models.EndpointGeo, RequestStatus: prometheus.RequestStatusOK} + mockMetrics.EXPECT().RecordRequest(labels) + mockFeature.EXPECT().IsCountryGDPREnabled(gomock.Any()).Return(true) + mockgeodb.EXPECT().LookUp(gomock.Any()). + Return(&geodb.GeoInfo{ISOCountryCode: "UK", CountryCode: "uk", RegionCode: "lnd"}, nil) + }, + }, + want: want{ + geo: "{\"cc\":\"UK\",\"sc\":\"lnd\",\"compliance\":\"GDPR\"}\n", + statuCode: http.StatusOK, + header: []string{"max-age=172800"}, + }, + }, + { + name: "non-EU region request", + args: args{ + r: getTestHTTPRequest(geoWithPubid, getHeaders(NonEURequest)), + setup: func() { + labels := metrics.Labels{RType: models.EndpointGeo, RequestStatus: prometheus.RequestStatusOK} + mockMetrics.EXPECT().RecordRequest(labels) + mockFeature.EXPECT().IsCountryGDPREnabled(gomock.Any()).Return(false) + mockgeodb.EXPECT().LookUp(gomock.Any()). + Return(&geodb.GeoInfo{ISOCountryCode: "IN", CountryCode: "in", RegionCode: "mh"}, nil) + }, + }, + want: want{ + geo: "{\"cc\":\"IN\",\"sc\":\"mh\"}\n", + statuCode: http.StatusOK, + header: []string{"max-age=172800"}, + }, + }, + { + name: "statecode is california(USP compliance)", + args: args{ + r: getTestHTTPRequest(geoWithPubid, getHeaders(EURequest)), + setup: func() { + labels := metrics.Labels{RType: models.EndpointGeo, RequestStatus: prometheus.RequestStatusOK} + mockMetrics.EXPECT().RecordRequest(labels) + mockFeature.EXPECT().IsCountryGDPREnabled(gomock.Any()).Return(false) + mockgeodb.EXPECT().LookUp(gomock.Any()). + Return(&geodb.GeoInfo{ISOCountryCode: "US", CountryCode: "us", RegionCode: "ca"}, nil) + }, + }, + want: want{ + geo: "{\"cc\":\"US\",\"sc\":\"ca\",\"compliance\":\"USP\"}\n", + statuCode: http.StatusOK, + header: []string{"max-age=172800"}, + }, + }, + { + name: "gpp country request", + args: args{ + r: getTestHTTPRequest(geoWithPubid, getHeaders(EURequest)), + setup: func() { + labels := metrics.Labels{RType: models.EndpointGeo, RequestStatus: prometheus.RequestStatusOK} + mockMetrics.EXPECT().RecordRequest(labels) + mockFeature.EXPECT().IsCountryGDPREnabled(gomock.Any()).Return(false) + mockgeodb.EXPECT().LookUp(gomock.Any()). + Return(&geodb.GeoInfo{ISOCountryCode: "US", CountryCode: "us", RegionCode: "va"}, nil) + }, + }, + want: want{ + geo: "{\"cc\":\"US\",\"sc\":\"va\",\"compliance\":\"GPP\",\"sectionId\":9}\n", + statuCode: http.StatusOK, + header: []string{"max-age=172800"}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.args.setup() + w := httptest.NewRecorder() + Handler(w, tt.args.r) + assert.Equal(t, tt.want.statuCode, w.Result().StatusCode) + assert.Equal(t, tt.want.geo, w.Body.String()) + assert.Equal(t, tt.want.header, w.Header().Values("Cache-Control")) + }) + } +} diff --git a/modules/pubmatic/openwrap/publisherfeature/compliance_test.go b/modules/pubmatic/openwrap/publisherfeature/compliance_test.go new file mode 100644 index 0000000000..7910407f36 --- /dev/null +++ b/modules/pubmatic/openwrap/publisherfeature/compliance_test.go @@ -0,0 +1,181 @@ +package publisherfeature + +import ( + "errors" + "testing" + + "github.com/golang/mock/gomock" + "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/cache" + mock_cache "github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/cache/mock" + "github.com/stretchr/testify/assert" +) + +func TestFeatureUpdateGDPRCountryCodes(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + mockCache := mock_cache.NewMockCache(ctrl) + + type fields struct { + cache cache.Cache + gdprCountryCodes gdprCountryCodes + } + tests := []struct { + name string + fields fields + setup func() + expectedGDPRCountryCodes gdprCountryCodes + }{ + { + name: "query failed", + fields: fields{ + cache: mockCache, + gdprCountryCodes: newGDPRCountryCodes(), + }, + setup: func() { + mockCache.EXPECT().GetGDPRCountryCodes().Return(nil, errors.New("QUERY FAILED")) + }, + expectedGDPRCountryCodes: gdprCountryCodes{ + codes: [2]map[string]struct{}{ + make(map[string]struct{}), + make(map[string]struct{}), + }, + index: 1, + }, + }, + { + name: "query success", + fields: fields{ + cache: mockCache, + gdprCountryCodes: newGDPRCountryCodes(), + }, + setup: func() { + mockCache.EXPECT().GetGDPRCountryCodes().Return(map[string]struct{}{ + "US": {}, + "DE": {}, + }, nil) + }, + expectedGDPRCountryCodes: gdprCountryCodes{ + codes: [2]map[string]struct{}{ + {}, + { + "US": {}, + "DE": {}, + }, + }, + index: 1, + }, + }, + { + name: "query success toggled", + fields: fields{ + cache: mockCache, + gdprCountryCodes: gdprCountryCodes{ + codes: [2]map[string]struct{}{ + {}, + { + "US": {}, + "DE": {}, + }, + }, + index: 1, + }, + }, + setup: func() { + mockCache.EXPECT().GetGDPRCountryCodes().Return(map[string]struct{}{ + "US": {}, + "DE": {}, + }, nil) + }, + expectedGDPRCountryCodes: gdprCountryCodes{ + codes: [2]map[string]struct{}{ + { + "US": {}, + "DE": {}, + }, + { + "US": {}, + "DE": {}, + }, + }, + index: 0, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.setup() + fe := &feature{ + cache: tt.fields.cache, + gdprCountryCodes: tt.fields.gdprCountryCodes, + } + defer func() { + fe = nil + }() + fe.updateGDPRCountryCodes() + assert.Equal(t, tt.expectedGDPRCountryCodes, fe.gdprCountryCodes, tt.name) + }) + } +} + +func TestFeature_IsCountryGDPREnabled(t *testing.T) { + type fields struct { + gdprCountryCodes gdprCountryCodes + } + type args struct { + countryCode string + } + tests := []struct { + name string + fields fields + args args + want bool + }{ + { + name: "gdpr enabled for countrycode", + args: args{ + countryCode: "LV", + }, + fields: fields{ + gdprCountryCodes: gdprCountryCodes{ + codes: [2]map[string]struct{}{ + {}, + { + "LV": {}, + "DE": {}, + }, + }, + index: 1, + }, + }, + want: true, + }, + { + name: "gdpr disabled for countrycode", + args: args{ + countryCode: "IN", + }, + fields: fields{ + gdprCountryCodes: gdprCountryCodes{ + codes: [2]map[string]struct{}{ + {}, + { + "LV": {}, + "DE": {}, + }, + }, + index: 1, + }, + }, + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + fe := &feature{ + gdprCountryCodes: tt.fields.gdprCountryCodes, + } + got := fe.IsCountryGDPREnabled(tt.args.countryCode) + assert.Equal(t, tt.want, got, tt.name) + }) + } +}