github.com/prebid/prebid-server@v0.275.0/privacy/scrubber_test.go (about)

     1  package privacy
     2  
     3  import (
     4  	"encoding/json"
     5  	"github.com/prebid/prebid-server/config"
     6  	"testing"
     7  
     8  	"github.com/prebid/openrtb/v19/openrtb2"
     9  	"github.com/stretchr/testify/assert"
    10  )
    11  
    12  func TestScrubDevice(t *testing.T) {
    13  	device := getTestDevice()
    14  
    15  	testCases := []struct {
    16  		description string
    17  		expected    *openrtb2.Device
    18  		id          ScrubStrategyDeviceID
    19  		ipv4        ScrubStrategyIPV4
    20  		ipv6        ScrubStrategyIPV6
    21  		geo         ScrubStrategyGeo
    22  	}{
    23  		{
    24  			description: "All Strategies - None",
    25  			expected:    device,
    26  			id:          ScrubStrategyDeviceIDNone,
    27  			ipv4:        ScrubStrategyIPV4None,
    28  			ipv6:        ScrubStrategyIPV6None,
    29  			geo:         ScrubStrategyGeoNone,
    30  		},
    31  		{
    32  			description: "All Strategies - Strictest",
    33  			expected: &openrtb2.Device{
    34  				DIDMD5:   "",
    35  				DIDSHA1:  "",
    36  				DPIDMD5:  "",
    37  				DPIDSHA1: "",
    38  				MACSHA1:  "",
    39  				MACMD5:   "",
    40  				IFA:      "",
    41  				IP:       "1.2.3.0",
    42  				IPv6:     "2001:1db8:2233:4400::",
    43  				Geo:      &openrtb2.Geo{},
    44  			},
    45  			id:   ScrubStrategyDeviceIDAll,
    46  			ipv4: ScrubStrategyIPV4Subnet,
    47  			ipv6: ScrubStrategyIPV6Subnet,
    48  			geo:  ScrubStrategyGeoFull,
    49  		},
    50  		{
    51  			description: "Isolated - ID - All",
    52  			expected: &openrtb2.Device{
    53  				DIDMD5:   "",
    54  				DIDSHA1:  "",
    55  				DPIDMD5:  "",
    56  				DPIDSHA1: "",
    57  				MACSHA1:  "",
    58  				MACMD5:   "",
    59  				IFA:      "",
    60  				IP:       "1.2.3.4",
    61  				IPv6:     "2001:1db8:2233:4455:6677:ff00:0042:8329",
    62  				Geo:      device.Geo,
    63  			},
    64  			id:   ScrubStrategyDeviceIDAll,
    65  			ipv4: ScrubStrategyIPV4None,
    66  			ipv6: ScrubStrategyIPV6None,
    67  			geo:  ScrubStrategyGeoNone,
    68  		},
    69  		{
    70  			description: "Isolated - IPv4 - Lowest 8",
    71  			expected: &openrtb2.Device{
    72  				DIDMD5:   "anyDIDMD5",
    73  				DIDSHA1:  "anyDIDSHA1",
    74  				DPIDMD5:  "anyDPIDMD5",
    75  				DPIDSHA1: "anyDPIDSHA1",
    76  				MACSHA1:  "anyMACSHA1",
    77  				MACMD5:   "anyMACMD5",
    78  				IFA:      "anyIFA",
    79  				IP:       "1.2.3.0",
    80  				IPv6:     "2001:1db8:2233:4455:6677:ff00:0042:8329",
    81  				Geo:      device.Geo,
    82  			},
    83  			id:   ScrubStrategyDeviceIDNone,
    84  			ipv4: ScrubStrategyIPV4Subnet,
    85  			ipv6: ScrubStrategyIPV6None,
    86  			geo:  ScrubStrategyGeoNone,
    87  		},
    88  		{
    89  			description: "Isolated - IPv6",
    90  			expected: &openrtb2.Device{
    91  				DIDMD5:   "anyDIDMD5",
    92  				DIDSHA1:  "anyDIDSHA1",
    93  				DPIDMD5:  "anyDPIDMD5",
    94  				DPIDSHA1: "anyDPIDSHA1",
    95  				MACSHA1:  "anyMACSHA1",
    96  				MACMD5:   "anyMACMD5",
    97  				IFA:      "anyIFA",
    98  				IP:       "1.2.3.4",
    99  				IPv6:     "2001:1db8:2233:4400::",
   100  				Geo:      device.Geo,
   101  			},
   102  			id:   ScrubStrategyDeviceIDNone,
   103  			ipv4: ScrubStrategyIPV4None,
   104  			ipv6: ScrubStrategyIPV6Subnet,
   105  			geo:  ScrubStrategyGeoNone,
   106  		},
   107  		{
   108  			description: "Isolated - Geo - Reduced Precision",
   109  			expected: &openrtb2.Device{
   110  				DIDMD5:   "anyDIDMD5",
   111  				DIDSHA1:  "anyDIDSHA1",
   112  				DPIDMD5:  "anyDPIDMD5",
   113  				DPIDSHA1: "anyDPIDSHA1",
   114  				MACSHA1:  "anyMACSHA1",
   115  				MACMD5:   "anyMACMD5",
   116  				IFA:      "anyIFA",
   117  				IP:       "1.2.3.4",
   118  				IPv6:     "2001:1db8:2233:4455:6677:ff00:0042:8329",
   119  				Geo: &openrtb2.Geo{
   120  					Lat:   123.46,
   121  					Lon:   678.89,
   122  					Metro: "some metro",
   123  					City:  "some city",
   124  					ZIP:   "some zip",
   125  				},
   126  			},
   127  			id:   ScrubStrategyDeviceIDNone,
   128  			ipv4: ScrubStrategyIPV4None,
   129  			ipv6: ScrubStrategyIPV6None,
   130  			geo:  ScrubStrategyGeoReducedPrecision,
   131  		},
   132  		{
   133  			description: "Isolated - Geo - Full",
   134  			expected: &openrtb2.Device{
   135  				DIDMD5:   "anyDIDMD5",
   136  				DIDSHA1:  "anyDIDSHA1",
   137  				DPIDMD5:  "anyDPIDMD5",
   138  				DPIDSHA1: "anyDPIDSHA1",
   139  				MACSHA1:  "anyMACSHA1",
   140  				MACMD5:   "anyMACMD5",
   141  				IFA:      "anyIFA",
   142  				IP:       "1.2.3.4",
   143  				IPv6:     "2001:1db8:2233:4455:6677:ff00:0042:8329",
   144  				Geo:      &openrtb2.Geo{},
   145  			},
   146  			id:   ScrubStrategyDeviceIDNone,
   147  			ipv4: ScrubStrategyIPV4None,
   148  			ipv6: ScrubStrategyIPV6None,
   149  			geo:  ScrubStrategyGeoFull,
   150  		},
   151  	}
   152  	testIPMasking := getTestIPMasking()
   153  	for _, test := range testCases {
   154  		result := NewScrubber(testIPMasking.IPv6Config, testIPMasking.IPv4Config).ScrubDevice(device, test.id, test.ipv4, test.ipv6, test.geo)
   155  		assert.Equal(t, test.expected, result, test.description)
   156  	}
   157  }
   158  
   159  func TestScrubDeviceNil(t *testing.T) {
   160  	testIPMasking := getTestIPMasking()
   161  	result := NewScrubber(testIPMasking.IPv6Config, testIPMasking.IPv4Config).ScrubDevice(nil, ScrubStrategyDeviceIDNone, ScrubStrategyIPV4None, ScrubStrategyIPV6None, ScrubStrategyGeoNone)
   162  	assert.Nil(t, result)
   163  }
   164  
   165  func TestScrubUser(t *testing.T) {
   166  	user := getTestUser()
   167  
   168  	testCases := []struct {
   169  		description string
   170  		expected    *openrtb2.User
   171  		scrubUser   ScrubStrategyUser
   172  		scrubGeo    ScrubStrategyGeo
   173  	}{
   174  		{
   175  			description: "User ID And Demographic & Geo Full",
   176  			expected: &openrtb2.User{
   177  				ID:       "",
   178  				BuyerUID: "",
   179  				Yob:      0,
   180  				Gender:   "",
   181  				Ext:      json.RawMessage(`{}`),
   182  				Geo:      &openrtb2.Geo{},
   183  			},
   184  			scrubUser: ScrubStrategyUserIDAndDemographic,
   185  			scrubGeo:  ScrubStrategyGeoFull,
   186  		},
   187  		{
   188  			description: "User ID And Demographic & Geo Reduced",
   189  			expected: &openrtb2.User{
   190  				ID:       "",
   191  				BuyerUID: "",
   192  				Yob:      0,
   193  				Gender:   "",
   194  				Ext:      json.RawMessage(`{}`),
   195  				Geo: &openrtb2.Geo{
   196  					Lat:   123.46,
   197  					Lon:   678.89,
   198  					Metro: "some metro",
   199  					City:  "some city",
   200  					ZIP:   "some zip",
   201  				},
   202  			},
   203  			scrubUser: ScrubStrategyUserIDAndDemographic,
   204  			scrubGeo:  ScrubStrategyGeoReducedPrecision,
   205  		},
   206  		{
   207  			description: "User ID And Demographic & Geo None",
   208  			expected: &openrtb2.User{
   209  				ID:       "",
   210  				BuyerUID: "",
   211  				Yob:      0,
   212  				Gender:   "",
   213  				Ext:      json.RawMessage(`{}`),
   214  				Geo: &openrtb2.Geo{
   215  					Lat:   123.456,
   216  					Lon:   678.89,
   217  					Metro: "some metro",
   218  					City:  "some city",
   219  					ZIP:   "some zip",
   220  				},
   221  			},
   222  			scrubUser: ScrubStrategyUserIDAndDemographic,
   223  			scrubGeo:  ScrubStrategyGeoNone,
   224  		},
   225  		{
   226  			description: "User None & Geo Full",
   227  			expected: &openrtb2.User{
   228  				ID:       "anyID",
   229  				BuyerUID: "anyBuyerUID",
   230  				Yob:      42,
   231  				Gender:   "anyGender",
   232  				Ext:      json.RawMessage(`{}`),
   233  				Geo:      &openrtb2.Geo{},
   234  			},
   235  			scrubUser: ScrubStrategyUserNone,
   236  			scrubGeo:  ScrubStrategyGeoFull,
   237  		},
   238  		{
   239  			description: "User None & Geo Reduced",
   240  			expected: &openrtb2.User{
   241  				ID:       "anyID",
   242  				BuyerUID: "anyBuyerUID",
   243  				Yob:      42,
   244  				Gender:   "anyGender",
   245  				Ext:      json.RawMessage(`{}`),
   246  				Geo: &openrtb2.Geo{
   247  					Lat:   123.46,
   248  					Lon:   678.89,
   249  					Metro: "some metro",
   250  					City:  "some city",
   251  					ZIP:   "some zip",
   252  				},
   253  			},
   254  			scrubUser: ScrubStrategyUserNone,
   255  			scrubGeo:  ScrubStrategyGeoReducedPrecision,
   256  		},
   257  		{
   258  			description: "User None & Geo None",
   259  			expected: &openrtb2.User{
   260  				ID:       "anyID",
   261  				BuyerUID: "anyBuyerUID",
   262  				Yob:      42,
   263  				Gender:   "anyGender",
   264  				Ext:      json.RawMessage(`{}`),
   265  				Geo: &openrtb2.Geo{
   266  					Lat:   123.456,
   267  					Lon:   678.89,
   268  					Metro: "some metro",
   269  					City:  "some city",
   270  					ZIP:   "some zip",
   271  				},
   272  			},
   273  			scrubUser: ScrubStrategyUserNone,
   274  			scrubGeo:  ScrubStrategyGeoNone,
   275  		},
   276  	}
   277  
   278  	testIPMasking := getTestIPMasking()
   279  	for _, test := range testCases {
   280  		result := NewScrubber(testIPMasking.IPv6Config, testIPMasking.IPv4Config).ScrubUser(user, test.scrubUser, test.scrubGeo)
   281  		assert.Equal(t, test.expected, result, test.description)
   282  	}
   283  }
   284  
   285  func TestScrubUserNil(t *testing.T) {
   286  	testIPMasking := getTestIPMasking()
   287  	result := NewScrubber(testIPMasking.IPv6Config, testIPMasking.IPv4Config).ScrubUser(nil, ScrubStrategyUserNone, ScrubStrategyGeoNone)
   288  	assert.Nil(t, result)
   289  }
   290  
   291  func TestScrubRequest(t *testing.T) {
   292  
   293  	imps := []openrtb2.Imp{
   294  		{ID: "testId", Ext: json.RawMessage(`{"test": 1, "tid": 2}`)},
   295  	}
   296  	source := &openrtb2.Source{
   297  		TID: "testTid",
   298  	}
   299  	device := getTestDevice()
   300  	user := getTestUser()
   301  	user.Ext = json.RawMessage(`{"data": 1, "eids": 2}`)
   302  	user.EIDs = []openrtb2.EID{{Source: "test"}}
   303  
   304  	testCases := []struct {
   305  		description    string
   306  		enforcement    Enforcement
   307  		userExtPresent bool
   308  		expected       *openrtb2.BidRequest
   309  	}{
   310  		{
   311  			description:    "enforce transmitUFPD with user.ext",
   312  			enforcement:    Enforcement{UFPD: true},
   313  			userExtPresent: true,
   314  			expected: &openrtb2.BidRequest{
   315  				Imp:    imps,
   316  				Source: source,
   317  				User: &openrtb2.User{
   318  					EIDs: []openrtb2.EID{{Source: "test"}},
   319  					Geo:  user.Geo,
   320  					Ext:  json.RawMessage(`{"eids":2}`),
   321  				},
   322  				Device: &openrtb2.Device{
   323  					IP:   "1.2.3.4",
   324  					IPv6: "2001:1db8:2233:4455:6677:ff00:0042:8329",
   325  					Geo:  device.Geo,
   326  				},
   327  			},
   328  		},
   329  		{
   330  			description:    "enforce transmitUFPD without user.ext",
   331  			enforcement:    Enforcement{UFPD: true},
   332  			userExtPresent: false,
   333  			expected: &openrtb2.BidRequest{
   334  				Imp:    imps,
   335  				Source: source,
   336  				User: &openrtb2.User{
   337  					EIDs: []openrtb2.EID{{Source: "test"}},
   338  					Geo:  user.Geo,
   339  				},
   340  				Device: &openrtb2.Device{
   341  					IP:   "1.2.3.4",
   342  					IPv6: "2001:1db8:2233:4455:6677:ff00:0042:8329",
   343  					Geo:  device.Geo,
   344  				},
   345  			},
   346  		},
   347  		{
   348  			description:    "enforce transmitEids",
   349  			enforcement:    Enforcement{Eids: true},
   350  			userExtPresent: true,
   351  			expected: &openrtb2.BidRequest{
   352  				Imp:    imps,
   353  				Source: source,
   354  				Device: device,
   355  				User: &openrtb2.User{
   356  					ID:       "anyID",
   357  					BuyerUID: "anyBuyerUID",
   358  					Yob:      42,
   359  					Gender:   "anyGender",
   360  					Geo:      user.Geo,
   361  					EIDs:     nil,
   362  					Ext:      json.RawMessage(`{"data":1}`),
   363  				},
   364  			},
   365  		},
   366  		{
   367  			description:    "enforce transmitTid",
   368  			enforcement:    Enforcement{TID: true},
   369  			userExtPresent: true,
   370  			expected: &openrtb2.BidRequest{
   371  				Imp: []openrtb2.Imp{
   372  					{ID: "testId", Ext: json.RawMessage(`{"test":1}`)},
   373  				},
   374  				Source: &openrtb2.Source{
   375  					TID: "",
   376  				},
   377  				Device: device,
   378  				User: &openrtb2.User{
   379  					ID:       "anyID",
   380  					BuyerUID: "anyBuyerUID",
   381  					Yob:      42,
   382  					Gender:   "anyGender",
   383  					Geo:      user.Geo,
   384  					EIDs:     []openrtb2.EID{{Source: "test"}},
   385  					Ext:      json.RawMessage(`{"data": 1, "eids": 2}`),
   386  				},
   387  			},
   388  		},
   389  		{
   390  			description:    "enforce precise Geo",
   391  			enforcement:    Enforcement{PreciseGeo: true},
   392  			userExtPresent: true,
   393  			expected: &openrtb2.BidRequest{
   394  				Imp:    imps,
   395  				Source: source,
   396  				User: &openrtb2.User{
   397  					ID:       "anyID",
   398  					BuyerUID: "anyBuyerUID",
   399  					Yob:      42,
   400  					Gender:   "anyGender",
   401  					Geo: &openrtb2.Geo{
   402  						Lat: 123.46, Lon: 678.89,
   403  						Metro: "some metro",
   404  						City:  "some city",
   405  						ZIP:   "some zip",
   406  					},
   407  					EIDs: []openrtb2.EID{{Source: "test"}},
   408  					Ext:  json.RawMessage(`{"data": 1, "eids": 2}`),
   409  				},
   410  				Device: &openrtb2.Device{
   411  					IFA:      "anyIFA",
   412  					DIDSHA1:  "anyDIDSHA1",
   413  					DIDMD5:   "anyDIDMD5",
   414  					DPIDSHA1: "anyDPIDSHA1",
   415  					DPIDMD5:  "anyDPIDMD5",
   416  					MACSHA1:  "anyMACSHA1",
   417  					MACMD5:   "anyMACMD5",
   418  					IP:       "1.2.3.0",
   419  					IPv6:     "2001:1db8:2233:4400::",
   420  					Geo: &openrtb2.Geo{
   421  						Lat: 123.46, Lon: 678.89,
   422  						Metro: "some metro",
   423  						City:  "some city",
   424  						ZIP:   "some zip",
   425  					},
   426  				},
   427  			},
   428  		},
   429  	}
   430  
   431  	testIPMasking := getTestIPMasking()
   432  	for _, test := range testCases {
   433  		t.Run(test.description, func(t *testing.T) {
   434  			bidRequest := &openrtb2.BidRequest{
   435  				Imp: []openrtb2.Imp{
   436  					{ID: "testId", Ext: json.RawMessage(`{"test": 1, "tid": 2}`)},
   437  				},
   438  				Source: &openrtb2.Source{
   439  					TID: "testTid",
   440  				},
   441  				User:   getTestUser(),
   442  				Device: getTestDevice(),
   443  			}
   444  			if test.userExtPresent {
   445  				bidRequest.User.Ext = json.RawMessage(`{"data": 1, "eids": 2}`)
   446  			} else {
   447  				bidRequest.User.Ext = nil
   448  			}
   449  			bidRequest.User.EIDs = []openrtb2.EID{{Source: "test"}}
   450  
   451  			result := NewScrubber(testIPMasking.IPv6Config, testIPMasking.IPv4Config).ScrubRequest(bidRequest, test.enforcement)
   452  			assert.Equal(t, test.expected, result, test.description)
   453  		})
   454  	}
   455  }
   456  
   457  func TestScrubIP(t *testing.T) {
   458  	testCases := []struct {
   459  		IP        string
   460  		cleanedIP string
   461  		bits      int
   462  		maskBits  int
   463  	}{
   464  		{
   465  			IP:        "0:0:0:0:0:0:0:0",
   466  			cleanedIP: "::",
   467  			bits:      128,
   468  			maskBits:  56,
   469  		},
   470  		{
   471  			IP:        "",
   472  			cleanedIP: "",
   473  			bits:      128,
   474  			maskBits:  56,
   475  		},
   476  		{
   477  			IP:        "1111:2222:3333:4444:5555:6666:7777:8888",
   478  			cleanedIP: "1111:2222:3333:4400::",
   479  			bits:      128,
   480  			maskBits:  56,
   481  		},
   482  		{
   483  			IP:        "1111:2222:3333:4444:5555:6666:7777:8888",
   484  			cleanedIP: "1111:2222::",
   485  			bits:      128,
   486  			maskBits:  34,
   487  		},
   488  		{
   489  			IP:        "1111:0:3333:4444:5555:6666:7777:8888",
   490  			cleanedIP: "1111:0:3333:4400::",
   491  			bits:      128,
   492  			maskBits:  56,
   493  		},
   494  		{
   495  			IP:        "1111::6666:7777:8888",
   496  			cleanedIP: "1111::",
   497  			bits:      128,
   498  			maskBits:  56,
   499  		},
   500  		{
   501  			IP:        "2001:1db8:0000:0000:0000:ff00:0042:8329",
   502  			cleanedIP: "2001:1db8::ff00:0:0",
   503  			bits:      128,
   504  			maskBits:  96,
   505  		},
   506  		{
   507  			IP:        "2001:1db8:0000:0000:0000:ff00:0:0",
   508  			cleanedIP: "2001:1db8::ff00:0:0",
   509  			bits:      128,
   510  			maskBits:  96,
   511  		},
   512  		{
   513  			IP:        "2001:1db8:0000:0000:0000:ff00:0042:8329",
   514  			cleanedIP: "2001:1db8::ff00:42:0",
   515  			bits:      128,
   516  			maskBits:  112,
   517  		},
   518  		{
   519  			IP:        "2001:1db8:0000:0000:0000:ff00:0042:0",
   520  			cleanedIP: "2001:1db8::ff00:42:0",
   521  			bits:      128,
   522  			maskBits:  112,
   523  		},
   524  		{
   525  			IP:        "127.0.0.1",
   526  			cleanedIP: "127.0.0.0",
   527  			bits:      32,
   528  			maskBits:  24,
   529  		},
   530  		{
   531  			IP:        "0.0.0.0",
   532  			cleanedIP: "0.0.0.0",
   533  			bits:      32,
   534  			maskBits:  24,
   535  		},
   536  		{
   537  			IP:        "192.127.111.134",
   538  			cleanedIP: "192.127.111.0",
   539  			bits:      32,
   540  			maskBits:  24,
   541  		},
   542  		{
   543  			IP:        "192.127.111.0",
   544  			cleanedIP: "192.127.111.0",
   545  			bits:      32,
   546  			maskBits:  24,
   547  		},
   548  	}
   549  	for _, test := range testCases {
   550  		t.Run(test.IP, func(t *testing.T) {
   551  			// bits: ipv6 - 128, ipv4 - 32
   552  			result := scrubIP(test.IP, test.maskBits, test.bits)
   553  			assert.Equal(t, test.cleanedIP, result)
   554  		})
   555  	}
   556  }
   557  
   558  func TestScrubGeoFull(t *testing.T) {
   559  	geo := &openrtb2.Geo{
   560  		Lat:   123.456,
   561  		Lon:   678.89,
   562  		Metro: "some metro",
   563  		City:  "some city",
   564  		ZIP:   "some zip",
   565  	}
   566  	geoExpected := &openrtb2.Geo{
   567  		Lat:   0,
   568  		Lon:   0,
   569  		Metro: "",
   570  		City:  "",
   571  		ZIP:   "",
   572  	}
   573  
   574  	result := scrubGeoFull(geo)
   575  
   576  	assert.Equal(t, geoExpected, result)
   577  }
   578  
   579  func TestScrubGeoFullWhenNil(t *testing.T) {
   580  	result := scrubGeoFull(nil)
   581  	assert.Nil(t, result)
   582  }
   583  
   584  func TestScrubGeoPrecision(t *testing.T) {
   585  	geo := &openrtb2.Geo{
   586  		Lat:   123.456,
   587  		Lon:   678.89,
   588  		Metro: "some metro",
   589  		City:  "some city",
   590  		ZIP:   "some zip",
   591  	}
   592  	geoExpected := &openrtb2.Geo{
   593  		Lat:   123.46,
   594  		Lon:   678.89,
   595  		Metro: "some metro",
   596  		City:  "some city",
   597  		ZIP:   "some zip",
   598  	}
   599  
   600  	result := scrubGeoPrecision(geo)
   601  
   602  	assert.Equal(t, geoExpected, result)
   603  }
   604  
   605  func TestScrubGeoPrecisionWhenNil(t *testing.T) {
   606  	result := scrubGeoPrecision(nil)
   607  	assert.Nil(t, result)
   608  }
   609  
   610  func TestScrubUserExtIDs(t *testing.T) {
   611  	testCases := []struct {
   612  		description string
   613  		userExt     json.RawMessage
   614  		expected    json.RawMessage
   615  	}{
   616  		{
   617  			description: "Nil",
   618  			userExt:     nil,
   619  			expected:    nil,
   620  		},
   621  		{
   622  			description: "Empty String",
   623  			userExt:     json.RawMessage(``),
   624  			expected:    json.RawMessage(``),
   625  		},
   626  		{
   627  			description: "Empty Object",
   628  			userExt:     json.RawMessage(`{}`),
   629  			expected:    json.RawMessage(`{}`),
   630  		},
   631  		{
   632  			description: "Do Nothing When Malformed",
   633  			userExt:     json.RawMessage(`malformed`),
   634  			expected:    json.RawMessage(`malformed`),
   635  		},
   636  		{
   637  			description: "Do Nothing When No IDs Present",
   638  			userExt:     json.RawMessage(`{"anyExisting":42}}`),
   639  			expected:    json.RawMessage(`{"anyExisting":42}}`),
   640  		},
   641  		{
   642  			description: "Remove eids",
   643  			userExt:     json.RawMessage(`{"eids":[{"source":"anySource","id":"anyId","uids":[{"id":"anyId","ext":{"id":42}}],"ext":{"id":42}}]}`),
   644  			expected:    json.RawMessage(`{}`),
   645  		},
   646  		{
   647  			description: "Remove eids - With Other Data",
   648  			userExt:     json.RawMessage(`{"anyExisting":42,"eids":[{"source":"anySource","id":"anyId","uids":[{"id":"anyId","ext":{"id":42}}],"ext":{"id":42}}]}`),
   649  			expected:    json.RawMessage(`{"anyExisting":42}`),
   650  		},
   651  		{
   652  			description: "Remove eids - With Other Nested Data",
   653  			userExt:     json.RawMessage(`{"anyExisting":{"existing":42},"eids":[{"source":"anySource","id":"anyId","uids":[{"id":"anyId","ext":{"id":42}}],"ext":{"id":42}}]}`),
   654  			expected:    json.RawMessage(`{"anyExisting":{"existing":42}}`),
   655  		},
   656  		{
   657  			description: "Remove eids Only",
   658  			userExt:     json.RawMessage(`{"eids":[{"source":"anySource","id":"anyId","uids":[{"id":"anyId","ext":{"id":42}}],"ext":{"id":42}}]}`),
   659  			expected:    json.RawMessage(`{}`),
   660  		},
   661  		{
   662  			description: "Remove eids Only - Empty Array",
   663  			userExt:     json.RawMessage(`{"eids":[]}`),
   664  			expected:    json.RawMessage(`{}`),
   665  		},
   666  		{
   667  			description: "Remove eids Only - With Other Data",
   668  			userExt:     json.RawMessage(`{"anyExisting":42,"eids":[{"source":"anySource","id":"anyId","uids":[{"id":"anyId","ext":{"id":42}}],"ext":{"id":42}}]}`),
   669  			expected:    json.RawMessage(`{"anyExisting":42}`),
   670  		},
   671  		{
   672  			description: "Remove eids Only - With Other Nested Data",
   673  			userExt:     json.RawMessage(`{"anyExisting":{"existing":42},"eids":[{"source":"anySource","id":"anyId","uids":[{"id":"anyId","ext":{"id":42}}],"ext":{"id":42}}]}`),
   674  			expected:    json.RawMessage(`{"anyExisting":{"existing":42}}`),
   675  		},
   676  	}
   677  
   678  	for _, test := range testCases {
   679  		result := scrubExtIDs(test.userExt, "eids")
   680  		assert.Equal(t, test.expected, result, test.description)
   681  	}
   682  }
   683  
   684  func getTestUser() *openrtb2.User {
   685  	return &openrtb2.User{
   686  		ID:       "anyID",
   687  		BuyerUID: "anyBuyerUID",
   688  		Yob:      42,
   689  		Gender:   "anyGender",
   690  		Ext:      json.RawMessage(`{}`),
   691  		Geo: &openrtb2.Geo{
   692  			Lat:   123.456,
   693  			Lon:   678.89,
   694  			Metro: "some metro",
   695  			City:  "some city",
   696  			ZIP:   "some zip",
   697  		},
   698  	}
   699  }
   700  
   701  func getTestDevice() *openrtb2.Device {
   702  	return &openrtb2.Device{
   703  		DIDMD5:   "anyDIDMD5",
   704  		DIDSHA1:  "anyDIDSHA1",
   705  		DPIDMD5:  "anyDPIDMD5",
   706  		DPIDSHA1: "anyDPIDSHA1",
   707  		MACSHA1:  "anyMACSHA1",
   708  		MACMD5:   "anyMACMD5",
   709  		IFA:      "anyIFA",
   710  		IP:       "1.2.3.4",
   711  		IPv6:     "2001:1db8:2233:4455:6677:ff00:0042:8329",
   712  		Geo: &openrtb2.Geo{
   713  			Lat:   123.456,
   714  			Lon:   678.89,
   715  			Metro: "some metro",
   716  			City:  "some city",
   717  			ZIP:   "some zip",
   718  		},
   719  	}
   720  }
   721  
   722  func getTestIPMasking() config.AccountPrivacy {
   723  	return config.AccountPrivacy{
   724  		IPv6Config: config.IPv6{
   725  			54,
   726  		},
   727  		IPv4Config: config.IPv4{
   728  			24,
   729  		},
   730  	}
   731  }