github.com/prebid/prebid-server/v2@v2.18.0/stored_requests/backends/file_fetcher/fetcher_test.go (about)

     1  package file_fetcher
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"fmt"
     7  	"testing"
     8  
     9  	"github.com/prebid/prebid-server/v2/stored_requests"
    10  	"github.com/prebid/prebid-server/v2/util/jsonutil"
    11  	"github.com/stretchr/testify/assert"
    12  )
    13  
    14  func TestFileFetcher(t *testing.T) {
    15  	// Load the test input files for testing
    16  	fetcher, err := NewFileFetcher("./test")
    17  	if err != nil {
    18  		t.Errorf("Failed to create a Fetcher: %v", err)
    19  	}
    20  
    21  	// Test stored request and stored imps
    22  	storedReqs, storedImps, errs := fetcher.FetchRequests(context.Background(), []string{"1", "2"}, []string{"some-imp"})
    23  	assertErrorCount(t, 0, errs)
    24  
    25  	validateStoredReqOne(t, storedReqs)
    26  	validateStoredReqTwo(t, storedReqs)
    27  	validateImp(t, storedImps)
    28  }
    29  
    30  func TestStoredResponseFileFetcher(t *testing.T) {
    31  	// grab the fetcher that do not have /test/stored_responses/stored_responses FS directory
    32  	directoryNotExistfetcher, err := NewFileFetcher("./test/stored_responses")
    33  	if err != nil {
    34  		t.Errorf("Failed to create a Fetcher: %v", err)
    35  	}
    36  
    37  	// we should receive 1 error since we do not have "stored_responses" directory in ./test/stored_responses
    38  	_, errs := directoryNotExistfetcher.FetchResponses(context.Background(), []string{})
    39  	assertErrorCount(t, 1, errs)
    40  
    41  	// grab the fetcher that has /test/stored_responses FS directory
    42  	fetcher, err := NewFileFetcher("./test")
    43  	if err != nil {
    44  		t.Errorf("Failed to create a Fetcher: %v", err)
    45  	}
    46  
    47  	// Test stored responses, we have 3 stored responses in ./test/stored_responses
    48  	storedResps, errs := fetcher.FetchResponses(context.Background(), []string{"bar", "escaped", "does_not_exist"})
    49  	// expect 1 error since we do not have "does_not_exist" stored response file from ./test
    50  	assertErrorCount(t, 1, errs)
    51  
    52  	validateStoredResponse[map[string]string](t, storedResps, "bar", func(val map[string]string) error {
    53  		if len(val) != 1 {
    54  			return fmt.Errorf("Unexpected value length. Expected %d, Got %d", 1, len(val))
    55  		}
    56  
    57  		data, hadKey := val["test"]
    58  		if !hadKey {
    59  			return fmt.Errorf(`missing key "test" in the value`)
    60  		}
    61  
    62  		expectedVal := "bar"
    63  		if data != expectedVal {
    64  			return fmt.Errorf(`Bad value for key "test". Expected "%s", Got "%s"`, expectedVal, data)
    65  		}
    66  		return nil
    67  	})
    68  
    69  	validateStoredResponse[string](t, storedResps, "escaped", func(val string) error {
    70  		expectedVal := `esca"ped`
    71  		if val != expectedVal {
    72  			return fmt.Errorf(`Bad data. Expected "%v", Got "%s"`, expectedVal, val)
    73  		}
    74  		return nil
    75  	})
    76  }
    77  
    78  func TestAccountFetcher(t *testing.T) {
    79  	fetcher, err := NewFileFetcher("./test")
    80  	assert.NoError(t, err, "Failed to create test fetcher")
    81  
    82  	account, errs := fetcher.FetchAccount(context.Background(), json.RawMessage(`{"events_enabled":true}`), "valid")
    83  	assertErrorCount(t, 0, errs)
    84  	assert.JSONEq(t, `{"disabled":false, "events_enabled":true, "id":"valid" }`, string(account))
    85  
    86  	_, errs = fetcher.FetchAccount(context.Background(), json.RawMessage(`{"events_enabled":true}`), "nonexistent")
    87  	assertErrorCount(t, 1, errs)
    88  	assert.Error(t, errs[0])
    89  	assert.Equal(t, stored_requests.NotFoundError{ID: "nonexistent", DataType: "Account"}, errs[0])
    90  
    91  	_, errs = fetcher.FetchAccount(context.Background(), json.RawMessage(`{"events_enabled"}`), "valid")
    92  	assertErrorCount(t, 1, errs)
    93  	assert.Error(t, errs[0])
    94  	assert.Equal(t, fmt.Errorf("Invalid JSON Document"), errs[0])
    95  
    96  }
    97  
    98  func TestInvalidDirectory(t *testing.T) {
    99  	_, err := NewFileFetcher("./nonexistant-directory")
   100  	if err == nil {
   101  		t.Errorf("There should be an error if we use a directory which doesn't exist.")
   102  	}
   103  }
   104  
   105  func validateStoredReqOne(t *testing.T, storedRequests map[string]json.RawMessage) {
   106  	value, hasID := storedRequests["1"]
   107  	if !hasID {
   108  		t.Fatalf("Expected stored request data to have id: %d", 1)
   109  	}
   110  
   111  	var req1Val map[string]string
   112  	if err := jsonutil.UnmarshalValid(value, &req1Val); err != nil {
   113  		t.Errorf("Failed to unmarshal 1: %v", err)
   114  	}
   115  	if len(req1Val) != 1 {
   116  		t.Errorf("Unexpected req1Val length. Expected %d, Got %d", 1, len(req1Val))
   117  	}
   118  	data, hadKey := req1Val["test"]
   119  	if !hadKey {
   120  		t.Errorf("req1Val should have had a \"test\" key, but it didn't.")
   121  	}
   122  	if data != "foo" {
   123  		t.Errorf(`Bad data in "test" of stored request "1". Expected %s, Got %s`, "foo", data)
   124  	}
   125  }
   126  
   127  func validateStoredReqTwo(t *testing.T, storedRequests map[string]json.RawMessage) {
   128  	value, hasId := storedRequests["2"]
   129  	if !hasId {
   130  		t.Fatalf("Expected stored request map to have id: %d", 2)
   131  	}
   132  
   133  	var req2Val string
   134  	if err := jsonutil.UnmarshalValid(value, &req2Val); err != nil {
   135  		t.Errorf("Failed to unmarshal %d: %v", 2, err)
   136  	}
   137  	if req2Val != `esca"ped` {
   138  		t.Errorf(`Bad data in stored request "2". Expected %v, Got %s`, `esca"ped`, req2Val)
   139  	}
   140  }
   141  
   142  func validateImp(t *testing.T, storedImps map[string]json.RawMessage) {
   143  	value, hasId := storedImps["some-imp"]
   144  	if !hasId {
   145  		t.Fatal("Expected Stored Imp map to have id: some-imp")
   146  	}
   147  
   148  	var impVal map[string]bool
   149  	if err := jsonutil.UnmarshalValid(value, &impVal); err != nil {
   150  		t.Errorf("Failed to unmarshal some-imp: %v", err)
   151  	}
   152  	if len(impVal) != 1 {
   153  		t.Errorf("Unexpected impVal length. Expected %d, Got %d", 1, len(impVal))
   154  	}
   155  	data, hadKey := impVal["imp"]
   156  	if !hadKey {
   157  		t.Errorf("some-imp should have had a \"imp\" key, but it didn't.")
   158  	}
   159  	if !data {
   160  		t.Errorf(`Bad data in "imp" of stored request "some-imp". Expected true, Got %t`, data)
   161  	}
   162  }
   163  
   164  func assertErrorCount(t *testing.T, num int, errs []error) {
   165  	t.Helper()
   166  	if len(errs) != num {
   167  		t.Errorf("Wrong number of errors. Expected %d. Got %d. Errors are %v", num, len(errs), errs)
   168  	}
   169  }
   170  
   171  func newCategoryFetcher(directory string) (stored_requests.CategoryFetcher, error) {
   172  	fetcher, err := NewFileFetcher(directory)
   173  	if err != nil {
   174  		return nil, err
   175  	}
   176  	catfetcher, ok := fetcher.(stored_requests.CategoryFetcher)
   177  	if !ok {
   178  		return nil, fmt.Errorf("Failed to type cast fetcher to CategoryFetcher")
   179  	}
   180  	return catfetcher, nil
   181  }
   182  
   183  func TestCategoriesFetcherWithPublisher(t *testing.T) {
   184  	fetcher, err := newCategoryFetcher("./test/category-mapping")
   185  	if err != nil {
   186  		t.Errorf("Failed to create a category Fetcher: %v", err)
   187  	}
   188  	category, err := fetcher.FetchCategories(nil, "test", "categories", "IAB1-1")
   189  	assert.Equal(t, nil, err, "Categories were loaded incorrectly")
   190  	assert.Equal(t, "Beverages", category, "Categories were loaded incorrectly")
   191  }
   192  
   193  func TestCategoriesFetcherWithoutPublisher(t *testing.T) {
   194  	fetcher, err := newCategoryFetcher("./test/category-mapping")
   195  	if err != nil {
   196  		t.Errorf("Failed to create a category Fetcher: %v", err)
   197  	}
   198  	category, err := fetcher.FetchCategories(nil, "test", "", "IAB1-1")
   199  	assert.Equal(t, nil, err, "Categories were loaded incorrectly")
   200  	assert.Equal(t, "VideoGames", category, "Categories were loaded incorrectly")
   201  }
   202  
   203  func TestCategoriesFetcherNoCategory(t *testing.T) {
   204  	fetcher, err := newCategoryFetcher("./test/category-mapping")
   205  	if err != nil {
   206  		t.Errorf("Failed to create a category Fetcher: %v", err)
   207  	}
   208  	_, fetchingErr := fetcher.FetchCategories(nil, "test", "", "IAB1-100")
   209  	assert.Equal(t, fmt.Errorf("Unable to find category for adserver 'test', publisherId: '', iab category: 'IAB1-100'"),
   210  		fetchingErr, "Categories were loaded incorrectly")
   211  }
   212  
   213  func TestCategoriesFetcherBrokenJson(t *testing.T) {
   214  	fetcher, err := newCategoryFetcher("./test/category-mapping")
   215  	if err != nil {
   216  		t.Errorf("Failed to create a category Fetcher: %v", err)
   217  	}
   218  	_, fetchingErr := fetcher.FetchCategories(nil, "test", "broken", "IAB1-100")
   219  	assert.Equal(t, fmt.Errorf("Unable to unmarshal categories for adserver: 'test', publisherId: 'broken'"),
   220  		fetchingErr, "Categories were loaded incorrectly")
   221  }
   222  
   223  func TestCategoriesFetcherNoCategoriesFile(t *testing.T) {
   224  	fetcher, err := newCategoryFetcher("./test/category-mapping")
   225  	if err != nil {
   226  		t.Errorf("Failed to create a category Fetcher: %v", err)
   227  	}
   228  	_, fetchingErr := fetcher.FetchCategories(nil, "test", "not_exists", "IAB1-100")
   229  	assert.Equal(t, fmt.Errorf("Unable to find mapping file for adserver: 'test', publisherId: 'not_exists'"),
   230  		fetchingErr, "Categories were loaded incorrectly")
   231  }
   232  
   233  // validateStoredResponse - reusable function in the stored response test to verify the actual data read from the fetcher
   234  func validateStoredResponse[T any](t *testing.T, storedInfo map[string]json.RawMessage, id string, verifyFunc func(outputVal T) error) {
   235  	storedValue, hasID := storedInfo[id]
   236  	if !hasID {
   237  		t.Fatalf(`Expected stored response data to have id: "%s"`, id)
   238  	}
   239  
   240  	var unmarshalledValue T
   241  	if err := jsonutil.UnmarshalValid(storedValue, &unmarshalledValue); err != nil {
   242  		t.Errorf(`Failed to unmarshal stored response data of id "%s": %v`, id, err)
   243  	}
   244  
   245  	if err := verifyFunc(unmarshalledValue); err != nil {
   246  		t.Errorf(`Bad data in stored response of id: "%s": %v`, id, err)
   247  	}
   248  }