storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/pkg/event/config_test.go (about)

     1  /*
     2   * MinIO Cloud Storage, (C) 2018 MinIO, Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package event
    18  
    19  import (
    20  	"encoding/xml"
    21  	"reflect"
    22  	"strings"
    23  	"testing"
    24  )
    25  
    26  func TestValidateFilterRuleValue(t *testing.T) {
    27  	testCases := []struct {
    28  		value     string
    29  		expectErr bool
    30  	}{
    31  		{"foo/.", true},
    32  		{"../foo", true},
    33  		{`foo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/bazfoo/bar/baz`, true},
    34  		{string([]byte{0xff, 0xfe, 0xfd}), true},
    35  		{`foo\bar`, true},
    36  		{"Hello/世界", false},
    37  	}
    38  
    39  	for i, testCase := range testCases {
    40  		err := ValidateFilterRuleValue(testCase.value)
    41  		expectErr := (err != nil)
    42  
    43  		if expectErr != testCase.expectErr {
    44  			t.Fatalf("test %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
    45  		}
    46  	}
    47  }
    48  
    49  func TestFilterRuleUnmarshalXML(t *testing.T) {
    50  	testCases := []struct {
    51  		data           []byte
    52  		expectedResult *FilterRule
    53  		expectErr      bool
    54  	}{
    55  		{[]byte(`<FilterRule></FilterRule>`), nil, true},
    56  		{[]byte(`<FilterRule><Name></Name></FilterRule>`), nil, true},
    57  		{[]byte(`<FilterRule><Value></Value></FilterRule>`), nil, true},
    58  		{[]byte(`<FilterRule><Name></Name><Value></Value></FilterRule>`), nil, true},
    59  		{[]byte(`<FilterRule><Name>Prefix</Name><Value>Hello/世界</Value></FilterRule>`), nil, true},
    60  		{[]byte(`<FilterRule><Name>ends</Name><Value>foo/bar</Value></FilterRule>`), nil, true},
    61  		{[]byte(`<FilterRule><Name>prefix</Name><Value>Hello/世界</Value></FilterRule>`), &FilterRule{"prefix", "Hello/世界"}, false},
    62  		{[]byte(`<FilterRule><Name>suffix</Name><Value>foo/bar</Value></FilterRule>`), &FilterRule{"suffix", "foo/bar"}, false},
    63  	}
    64  
    65  	for i, testCase := range testCases {
    66  		result := &FilterRule{}
    67  		err := xml.Unmarshal(testCase.data, result)
    68  		expectErr := (err != nil)
    69  
    70  		if expectErr != testCase.expectErr {
    71  			t.Fatalf("test %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
    72  		}
    73  
    74  		if !testCase.expectErr {
    75  			if !reflect.DeepEqual(result, testCase.expectedResult) {
    76  				t.Fatalf("test %v: data: expected: %v, got: %v", i+1, testCase.expectedResult, result)
    77  			}
    78  		}
    79  	}
    80  }
    81  
    82  func TestFilterRuleListUnmarshalXML(t *testing.T) {
    83  	testCases := []struct {
    84  		data           []byte
    85  		expectedResult *FilterRuleList
    86  		expectErr      bool
    87  	}{
    88  		{[]byte(`<S3Key><FilterRule><Name>suffix</Name><Value>Hello/世界</Value></FilterRule><FilterRule><Name>suffix</Name><Value>foo/bar</Value></FilterRule></S3Key>`), nil, true},
    89  		{[]byte(`<S3Key><FilterRule><Name>prefix</Name><Value>Hello/世界</Value></FilterRule><FilterRule><Name>prefix</Name><Value>foo/bar</Value></FilterRule></S3Key>`), nil, true},
    90  		{[]byte(`<S3Key><FilterRule><Name>prefix</Name><Value>Hello/世界</Value></FilterRule></S3Key>`), &FilterRuleList{[]FilterRule{{"prefix", "Hello/世界"}}}, false},
    91  		{[]byte(`<S3Key><FilterRule><Name>suffix</Name><Value>foo/bar</Value></FilterRule></S3Key>`), &FilterRuleList{[]FilterRule{{"suffix", "foo/bar"}}}, false},
    92  		{[]byte(`<S3Key><FilterRule><Name>prefix</Name><Value>Hello/世界</Value></FilterRule><FilterRule><Name>suffix</Name><Value>foo/bar</Value></FilterRule></S3Key>`), &FilterRuleList{[]FilterRule{{"prefix", "Hello/世界"}, {"suffix", "foo/bar"}}}, false},
    93  	}
    94  
    95  	for i, testCase := range testCases {
    96  		result := &FilterRuleList{}
    97  		err := xml.Unmarshal(testCase.data, result)
    98  		expectErr := (err != nil)
    99  
   100  		if expectErr != testCase.expectErr {
   101  			t.Fatalf("test %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
   102  		}
   103  
   104  		if !testCase.expectErr {
   105  			if !reflect.DeepEqual(result, testCase.expectedResult) {
   106  				t.Fatalf("test %v: data: expected: %v, got: %v", i+1, testCase.expectedResult, result)
   107  			}
   108  		}
   109  	}
   110  }
   111  
   112  func TestFilterRuleListPattern(t *testing.T) {
   113  	testCases := []struct {
   114  		filterRuleList FilterRuleList
   115  		expectedResult string
   116  	}{
   117  		{FilterRuleList{}, ""},
   118  		{FilterRuleList{[]FilterRule{{"prefix", "Hello/世界"}}}, "Hello/世界*"},
   119  		{FilterRuleList{[]FilterRule{{"suffix", "foo/bar"}}}, "*foo/bar"},
   120  		{FilterRuleList{[]FilterRule{{"prefix", "Hello/世界"}, {"suffix", "foo/bar"}}}, "Hello/世界*foo/bar"},
   121  	}
   122  
   123  	for i, testCase := range testCases {
   124  		result := testCase.filterRuleList.Pattern()
   125  
   126  		if result != testCase.expectedResult {
   127  			t.Fatalf("test %v: data: expected: %v, got: %v", i+1, testCase.expectedResult, result)
   128  		}
   129  	}
   130  }
   131  
   132  func TestQueueUnmarshalXML(t *testing.T) {
   133  	dataCase1 := []byte(`
   134  <QueueConfiguration>
   135     <Id>1</Id>
   136     <Filter></Filter>
   137     <Queue>arn:minio:sqs:us-east-1:1:webhook</Queue>
   138     <Event>s3:ObjectAccessed:*</Event>
   139     <Event>s3:ObjectCreated:*</Event>
   140     <Event>s3:ObjectRemoved:*</Event>
   141  </QueueConfiguration>`)
   142  
   143  	dataCase2 := []byte(`
   144  <QueueConfiguration>
   145     <Id>1</Id>
   146      <Filter>
   147          <S3Key>
   148              <FilterRule>
   149                  <Name>prefix</Name>
   150                  <Value>images/</Value>
   151              </FilterRule>
   152              <FilterRule>
   153                  <Name>suffix</Name>
   154                  <Value>jpg</Value>
   155              </FilterRule>
   156          </S3Key>
   157     </Filter>
   158     <Queue>arn:minio:sqs:us-east-1:1:webhook</Queue>
   159     <Event>s3:ObjectCreated:Put</Event>
   160  </QueueConfiguration>`)
   161  
   162  	dataCase3 := []byte(`
   163  <QueueConfiguration>
   164     <Id>1</Id>
   165      <Filter>
   166          <S3Key>
   167              <FilterRule>
   168                  <Name>prefix</Name>
   169                  <Value>images/</Value>
   170              </FilterRule>
   171              <FilterRule>
   172                  <Name>suffix</Name>
   173                  <Value>jpg</Value>
   174              </FilterRule>
   175          </S3Key>
   176     </Filter>
   177     <Queue>arn:minio:sqs:us-east-1:1:webhook</Queue>
   178     <Event>s3:ObjectCreated:Put</Event>
   179     <Event>s3:ObjectCreated:Put</Event>
   180  </QueueConfiguration>`)
   181  
   182  	testCases := []struct {
   183  		data      []byte
   184  		expectErr bool
   185  	}{
   186  		{dataCase1, false},
   187  		{dataCase2, false},
   188  		{dataCase3, true},
   189  	}
   190  
   191  	for i, testCase := range testCases {
   192  		err := xml.Unmarshal(testCase.data, &Queue{})
   193  		expectErr := (err != nil)
   194  
   195  		if expectErr != testCase.expectErr {
   196  			t.Fatalf("test %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
   197  		}
   198  	}
   199  }
   200  
   201  func TestQueueValidate(t *testing.T) {
   202  	data := []byte(`
   203  <QueueConfiguration>
   204     <Id>1</Id>
   205     <Filter></Filter>
   206     <Queue>arn:minio:sqs:us-east-1:1:webhook</Queue>
   207     <Event>s3:ObjectAccessed:*</Event>
   208     <Event>s3:ObjectCreated:*</Event>
   209     <Event>s3:ObjectRemoved:*</Event>
   210  </QueueConfiguration>`)
   211  	queue1 := &Queue{}
   212  	if err := xml.Unmarshal(data, queue1); err != nil {
   213  		panic(err)
   214  	}
   215  
   216  	data = []byte(`
   217  <QueueConfiguration>
   218     <Id>1</Id>
   219      <Filter>
   220          <S3Key>
   221              <FilterRule>
   222                  <Name>prefix</Name>
   223                  <Value>images/</Value>
   224              </FilterRule>
   225              <FilterRule>
   226                  <Name>suffix</Name>
   227                  <Value>jpg</Value>
   228              </FilterRule>
   229          </S3Key>
   230     </Filter>
   231     <Queue>arn:minio:sqs:us-east-1:1:webhook</Queue>
   232     <Event>s3:ObjectCreated:Put</Event>
   233  </QueueConfiguration>`)
   234  	queue2 := &Queue{}
   235  	if err := xml.Unmarshal(data, queue2); err != nil {
   236  		panic(err)
   237  	}
   238  
   239  	data = []byte(`
   240  <QueueConfiguration>
   241     <Id>1</Id>
   242     <Filter></Filter>
   243     <Queue>arn:minio:sqs:eu-west-2:1:webhook</Queue>
   244     <Event>s3:ObjectAccessed:*</Event>
   245     <Event>s3:ObjectCreated:*</Event>
   246     <Event>s3:ObjectRemoved:*</Event>
   247  </QueueConfiguration>`)
   248  	queue3 := &Queue{}
   249  	if err := xml.Unmarshal(data, queue3); err != nil {
   250  		panic(err)
   251  	}
   252  
   253  	targetList1 := NewTargetList()
   254  
   255  	targetList2 := NewTargetList()
   256  	if err := targetList2.Add(&ExampleTarget{TargetID{"1", "webhook"}, false, false}); err != nil {
   257  		panic(err)
   258  	}
   259  
   260  	testCases := []struct {
   261  		queue      *Queue
   262  		region     string
   263  		targetList *TargetList
   264  		expectErr  bool
   265  	}{
   266  		{queue1, "eu-west-1", nil, true},
   267  		{queue2, "us-east-1", targetList1, true},
   268  		{queue3, "", targetList2, false},
   269  		{queue2, "us-east-1", targetList2, false},
   270  	}
   271  
   272  	for i, testCase := range testCases {
   273  		err := testCase.queue.Validate(testCase.region, testCase.targetList)
   274  		expectErr := (err != nil)
   275  
   276  		if expectErr != testCase.expectErr {
   277  			t.Fatalf("test %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
   278  		}
   279  	}
   280  }
   281  
   282  func TestQueueSetRegion(t *testing.T) {
   283  	data := []byte(`
   284  <QueueConfiguration>
   285     <Id>1</Id>
   286     <Filter></Filter>
   287     <Queue>arn:minio:sqs:us-east-1:1:webhook</Queue>
   288     <Event>s3:ObjectAccessed:*</Event>
   289     <Event>s3:ObjectCreated:*</Event>
   290     <Event>s3:ObjectRemoved:*</Event>
   291  </QueueConfiguration>`)
   292  	queue1 := &Queue{}
   293  	if err := xml.Unmarshal(data, queue1); err != nil {
   294  		panic(err)
   295  	}
   296  
   297  	data = []byte(`
   298  <QueueConfiguration>
   299     <Id>1</Id>
   300      <Filter>
   301          <S3Key>
   302              <FilterRule>
   303                  <Name>prefix</Name>
   304                  <Value>images/</Value>
   305              </FilterRule>
   306              <FilterRule>
   307                  <Name>suffix</Name>
   308                  <Value>jpg</Value>
   309              </FilterRule>
   310          </S3Key>
   311     </Filter>
   312     <Queue>arn:minio:sqs::1:webhook</Queue>
   313     <Event>s3:ObjectCreated:Put</Event>
   314  </QueueConfiguration>`)
   315  	queue2 := &Queue{}
   316  	if err := xml.Unmarshal(data, queue2); err != nil {
   317  		panic(err)
   318  	}
   319  
   320  	testCases := []struct {
   321  		queue          *Queue
   322  		region         string
   323  		expectedResult ARN
   324  	}{
   325  		{queue1, "eu-west-1", ARN{TargetID{"1", "webhook"}, "eu-west-1"}},
   326  		{queue1, "", ARN{TargetID{"1", "webhook"}, ""}},
   327  		{queue2, "us-east-1", ARN{TargetID{"1", "webhook"}, "us-east-1"}},
   328  		{queue2, "", ARN{TargetID{"1", "webhook"}, ""}},
   329  	}
   330  
   331  	for i, testCase := range testCases {
   332  		testCase.queue.SetRegion(testCase.region)
   333  		result := testCase.queue.ARN
   334  
   335  		if !reflect.DeepEqual(result, testCase.expectedResult) {
   336  			t.Fatalf("test %v: data: expected: %v, got: %v", i+1, testCase.expectedResult, result)
   337  		}
   338  	}
   339  }
   340  
   341  func TestQueueToRulesMap(t *testing.T) {
   342  	data := []byte(`
   343  <QueueConfiguration>
   344     <Id>1</Id>
   345     <Filter></Filter>
   346     <Queue>arn:minio:sqs:us-east-1:1:webhook</Queue>
   347     <Event>s3:ObjectAccessed:*</Event>
   348     <Event>s3:ObjectCreated:*</Event>
   349     <Event>s3:ObjectRemoved:*</Event>
   350  </QueueConfiguration>`)
   351  	queueCase1 := &Queue{}
   352  	if err := xml.Unmarshal(data, queueCase1); err != nil {
   353  		panic(err)
   354  	}
   355  
   356  	data = []byte(`
   357  <QueueConfiguration>
   358     <Id>1</Id>
   359      <Filter>
   360          <S3Key>
   361              <FilterRule>
   362                  <Name>prefix</Name>
   363                  <Value>images/</Value>
   364              </FilterRule>
   365              <FilterRule>
   366                  <Name>suffix</Name>
   367                  <Value>jpg</Value>
   368              </FilterRule>
   369          </S3Key>
   370     </Filter>
   371     <Queue>arn:minio:sqs:us-east-1:1:webhook</Queue>
   372     <Event>s3:ObjectCreated:Put</Event>
   373  </QueueConfiguration>`)
   374  	queueCase2 := &Queue{}
   375  	if err := xml.Unmarshal(data, queueCase2); err != nil {
   376  		panic(err)
   377  	}
   378  
   379  	rulesMapCase1 := NewRulesMap([]Name{ObjectAccessedAll, ObjectCreatedAll, ObjectRemovedAll}, "*", TargetID{"1", "webhook"})
   380  	rulesMapCase2 := NewRulesMap([]Name{ObjectCreatedPut}, "images/*jpg", TargetID{"1", "webhook"})
   381  
   382  	testCases := []struct {
   383  		queue          *Queue
   384  		expectedResult RulesMap
   385  	}{
   386  		{queueCase1, rulesMapCase1},
   387  		{queueCase2, rulesMapCase2},
   388  	}
   389  
   390  	for i, testCase := range testCases {
   391  		result := testCase.queue.ToRulesMap()
   392  
   393  		if !reflect.DeepEqual(result, testCase.expectedResult) {
   394  			t.Fatalf("test %v: data: expected: %v, got: %v", i+1, testCase.expectedResult, result)
   395  		}
   396  	}
   397  }
   398  
   399  func TestConfigUnmarshalXML(t *testing.T) {
   400  	dataCase1 := []byte(`
   401  <NotificationConfiguration   xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
   402     <QueueConfiguration>
   403        <Id>1</Id>
   404        <Filter></Filter>
   405        <Queue>arn:minio:sqs:us-east-1:1:webhook</Queue>
   406        <Event>s3:ObjectAccessed:*</Event>
   407        <Event>s3:ObjectCreated:*</Event>
   408        <Event>s3:ObjectRemoved:*</Event>
   409     </QueueConfiguration>
   410  </NotificationConfiguration>
   411  `)
   412  
   413  	dataCase2 := []byte(`
   414  	<NotificationConfiguration  xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
   415  	   <QueueConfiguration>
   416  	      <Id>1</Id>
   417  	       <Filter>
   418  	           <S3Key>
   419  	               <FilterRule>
   420  	                   <Name>prefix</Name>
   421  	                   <Value>images/</Value>
   422  	               </FilterRule>
   423  	               <FilterRule>
   424  	                   <Name>suffix</Name>
   425  	                   <Value>jpg</Value>
   426  	               </FilterRule>
   427  	           </S3Key>
   428  	      </Filter>
   429  	      <Queue>arn:minio:sqs:us-east-1:1:webhook</Queue>
   430  	      <Event>s3:ObjectCreated:Put</Event>
   431  	   </QueueConfiguration>
   432  	</NotificationConfiguration>
   433  	`)
   434  
   435  	dataCase3 := []byte(`
   436  	<NotificationConfiguration>
   437  	   <QueueConfiguration>
   438  	      <Id>1</Id>
   439  	      <Filter></Filter>
   440  	      <Queue>arn:minio:sqs:us-east-1:1:webhook</Queue>
   441  	      <Event>s3:ObjectAccessed:*</Event>
   442  	      <Event>s3:ObjectCreated:*</Event>
   443  	      <Event>s3:ObjectRemoved:*</Event>
   444  	   </QueueConfiguration>
   445  	   <QueueConfiguration>
   446  	      <Id>2</Id>
   447  	       <Filter>
   448  	           <S3Key>
   449  	               <FilterRule>
   450  	                   <Name>prefix</Name>
   451  	                   <Value>images/</Value>
   452  	               </FilterRule>
   453  	               <FilterRule>
   454  	                   <Name>suffix</Name>
   455  	                   <Value>jpg</Value>
   456  	               </FilterRule>
   457  	           </S3Key>
   458  	      </Filter>
   459  	      <Queue>arn:minio:sqs:us-east-1:1:webhook</Queue>
   460  	      <Event>s3:ObjectCreated:Put</Event>
   461  	   </QueueConfiguration>
   462  	</NotificationConfiguration>
   463  	`)
   464  
   465  	dataCase4 := []byte(`
   466  	<NotificationConfiguration  xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
   467  	   <QueueConfiguration>
   468  	      <Id>1</Id>
   469  	      <Filter></Filter>
   470  	      <Queue>arn:minio:sqs:us-east-1:1:webhook</Queue>
   471  	      <Event>s3:ObjectAccessed:*</Event>
   472  	      <Event>s3:ObjectCreated:*</Event>
   473  	      <Event>s3:ObjectRemoved:*</Event>
   474  	   </QueueConfiguration>
   475  	   <CloudFunctionConfiguration>
   476  	      <Id>1</Id>
   477  	      <Filter>
   478  	             <S3Key>
   479  	                 <FilterRule>
   480  	                     <Name>suffix</Name>
   481  	                     <Value>.jpg</Value>
   482  	                 </FilterRule>
   483  	             </S3Key>
   484  	      </Filter>
   485  	      <Cloudcode>arn:aws:lambda:us-west-2:444455556666:cloud-function-A</Cloudcode>
   486  	      <Event>s3:ObjectCreated:Put</Event>
   487  	   </CloudFunctionConfiguration>
   488  	   <TopicConfiguration>
   489  	      <Topic>arn:aws:sns:us-west-2:444455556666:sns-notification-one</Topic>
   490  	      <Event>s3:ObjectCreated:*</Event>
   491  	  </TopicConfiguration>
   492  	</NotificationConfiguration>
   493  	`)
   494  
   495  	dataCase5 := []byte(`<NotificationConfiguration  xmlns="http://s3.amazonaws.com/doc/2006-03-01/" ></NotificationConfiguration>`)
   496  
   497  	testCases := []struct {
   498  		data      []byte
   499  		expectErr bool
   500  	}{
   501  		{dataCase1, false},
   502  		{dataCase2, false},
   503  		{dataCase3, false},
   504  		{dataCase4, true},
   505  		// make sure we don't fail when queue is empty.
   506  		{dataCase5, false},
   507  	}
   508  
   509  	for i, testCase := range testCases {
   510  		err := xml.Unmarshal(testCase.data, &Config{})
   511  		expectErr := (err != nil)
   512  
   513  		if expectErr != testCase.expectErr {
   514  			t.Fatalf("test %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
   515  		}
   516  	}
   517  }
   518  
   519  func TestConfigValidate(t *testing.T) {
   520  	data := []byte(`
   521  <NotificationConfiguration  xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
   522     <QueueConfiguration>
   523        <Id>1</Id>
   524        <Filter></Filter>
   525        <Queue>arn:minio:sqs:us-east-1:1:webhook</Queue>
   526        <Event>s3:ObjectAccessed:*</Event>
   527        <Event>s3:ObjectCreated:*</Event>
   528        <Event>s3:ObjectRemoved:*</Event>
   529     </QueueConfiguration>
   530  </NotificationConfiguration>
   531  `)
   532  	config1 := &Config{}
   533  	if err := xml.Unmarshal(data, config1); err != nil {
   534  		panic(err)
   535  	}
   536  
   537  	data = []byte(`
   538  <NotificationConfiguration  xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
   539     <QueueConfiguration>
   540        <Id>1</Id>
   541         <Filter>
   542             <S3Key>
   543                 <FilterRule>
   544                     <Name>prefix</Name>
   545                     <Value>images/</Value>
   546                 </FilterRule>
   547                 <FilterRule>
   548                     <Name>suffix</Name>
   549                     <Value>jpg</Value>
   550                 </FilterRule>
   551             </S3Key>
   552        </Filter>
   553        <Queue>arn:minio:sqs:us-east-1:1:webhook</Queue>
   554        <Event>s3:ObjectCreated:Put</Event>
   555     </QueueConfiguration>
   556  </NotificationConfiguration>
   557  `)
   558  	config2 := &Config{}
   559  	if err := xml.Unmarshal(data, config2); err != nil {
   560  		panic(err)
   561  	}
   562  
   563  	data = []byte(`
   564  <NotificationConfiguration  xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
   565     <QueueConfiguration>
   566        <Id>1</Id>
   567        <Filter></Filter>
   568        <Queue>arn:minio:sqs:us-east-1:1:webhook</Queue>
   569        <Event>s3:ObjectAccessed:*</Event>
   570        <Event>s3:ObjectCreated:*</Event>
   571        <Event>s3:ObjectRemoved:*</Event>
   572     </QueueConfiguration>
   573     <QueueConfiguration>
   574        <Id>2</Id>
   575         <Filter>
   576             <S3Key>
   577                 <FilterRule>
   578                     <Name>prefix</Name>
   579                     <Value>images/</Value>
   580                 </FilterRule>
   581                 <FilterRule>
   582                     <Name>suffix</Name>
   583                     <Value>jpg</Value>
   584                 </FilterRule>
   585             </S3Key>
   586        </Filter>
   587        <Queue>arn:minio:sqs:us-east-1:1:webhook</Queue>
   588        <Event>s3:ObjectCreated:Put</Event>
   589     </QueueConfiguration>
   590  </NotificationConfiguration>
   591  `)
   592  	config3 := &Config{}
   593  	if err := xml.Unmarshal(data, config3); err != nil {
   594  		panic(err)
   595  	}
   596  
   597  	targetList1 := NewTargetList()
   598  
   599  	targetList2 := NewTargetList()
   600  	if err := targetList2.Add(&ExampleTarget{TargetID{"1", "webhook"}, false, false}); err != nil {
   601  		panic(err)
   602  	}
   603  
   604  	testCases := []struct {
   605  		config     *Config
   606  		region     string
   607  		targetList *TargetList
   608  		expectErr  bool
   609  	}{
   610  		{config1, "eu-west-1", nil, true},
   611  		{config2, "us-east-1", targetList1, true},
   612  		{config3, "", targetList2, false},
   613  		{config2, "us-east-1", targetList2, false},
   614  	}
   615  
   616  	for i, testCase := range testCases {
   617  		err := testCase.config.Validate(testCase.region, testCase.targetList)
   618  		expectErr := (err != nil)
   619  
   620  		if expectErr != testCase.expectErr {
   621  			t.Fatalf("test %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
   622  		}
   623  	}
   624  }
   625  
   626  func TestConfigSetRegion(t *testing.T) {
   627  	data := []byte(`
   628  <NotificationConfiguration  xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
   629     <QueueConfiguration>
   630        <Id>1</Id>
   631        <Filter></Filter>
   632        <Queue>arn:minio:sqs:us-east-1:1:webhook</Queue>
   633        <Event>s3:ObjectAccessed:*</Event>
   634        <Event>s3:ObjectCreated:*</Event>
   635        <Event>s3:ObjectRemoved:*</Event>
   636     </QueueConfiguration>
   637  </NotificationConfiguration>
   638  `)
   639  	config1 := &Config{}
   640  	if err := xml.Unmarshal(data, config1); err != nil {
   641  		panic(err)
   642  	}
   643  
   644  	data = []byte(`
   645  <NotificationConfiguration  xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
   646     <QueueConfiguration>
   647        <Id>1</Id>
   648         <Filter>
   649             <S3Key>
   650                 <FilterRule>
   651                     <Name>prefix</Name>
   652                     <Value>images/</Value>
   653                 </FilterRule>
   654                 <FilterRule>
   655                     <Name>suffix</Name>
   656                     <Value>jpg</Value>
   657                 </FilterRule>
   658             </S3Key>
   659        </Filter>
   660        <Queue>arn:minio:sqs::1:webhook</Queue>
   661        <Event>s3:ObjectCreated:Put</Event>
   662     </QueueConfiguration>
   663  </NotificationConfiguration>
   664  `)
   665  	config2 := &Config{}
   666  	if err := xml.Unmarshal(data, config2); err != nil {
   667  		panic(err)
   668  	}
   669  
   670  	data = []byte(`
   671  <NotificationConfiguration  xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
   672     <QueueConfiguration>
   673        <Id>1</Id>
   674        <Filter></Filter>
   675        <Queue>arn:minio:sqs:us-east-1:1:webhook</Queue>
   676        <Event>s3:ObjectAccessed:*</Event>
   677        <Event>s3:ObjectCreated:*</Event>
   678        <Event>s3:ObjectRemoved:*</Event>
   679     </QueueConfiguration>
   680     <QueueConfiguration>
   681        <Id>2</Id>
   682         <Filter>
   683             <S3Key>
   684                 <FilterRule>
   685                     <Name>prefix</Name>
   686                     <Value>images/</Value>
   687                 </FilterRule>
   688                 <FilterRule>
   689                     <Name>suffix</Name>
   690                     <Value>jpg</Value>
   691                 </FilterRule>
   692             </S3Key>
   693        </Filter>
   694        <Queue>arn:minio:sqs:us-east-1:2:amqp</Queue>
   695        <Event>s3:ObjectCreated:Put</Event>
   696     </QueueConfiguration>
   697  </NotificationConfiguration>
   698  `)
   699  	config3 := &Config{}
   700  	if err := xml.Unmarshal(data, config3); err != nil {
   701  		panic(err)
   702  	}
   703  
   704  	testCases := []struct {
   705  		config         *Config
   706  		region         string
   707  		expectedResult []ARN
   708  	}{
   709  		{config1, "eu-west-1", []ARN{{TargetID{"1", "webhook"}, "eu-west-1"}}},
   710  		{config1, "", []ARN{{TargetID{"1", "webhook"}, ""}}},
   711  		{config2, "us-east-1", []ARN{{TargetID{"1", "webhook"}, "us-east-1"}}},
   712  		{config2, "", []ARN{{TargetID{"1", "webhook"}, ""}}},
   713  		{config3, "us-east-1", []ARN{{TargetID{"1", "webhook"}, "us-east-1"}, {TargetID{"2", "amqp"}, "us-east-1"}}},
   714  		{config3, "", []ARN{{TargetID{"1", "webhook"}, ""}, {TargetID{"2", "amqp"}, ""}}},
   715  	}
   716  
   717  	for i, testCase := range testCases {
   718  		testCase.config.SetRegion(testCase.region)
   719  		result := []ARN{}
   720  		for _, queue := range testCase.config.QueueList {
   721  			result = append(result, queue.ARN)
   722  		}
   723  
   724  		if !reflect.DeepEqual(result, testCase.expectedResult) {
   725  			t.Fatalf("test %v: data: expected: %v, got: %v", i+1, testCase.expectedResult, result)
   726  		}
   727  	}
   728  }
   729  
   730  func TestConfigToRulesMap(t *testing.T) {
   731  	data := []byte(`
   732  <NotificationConfiguration  xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
   733     <QueueConfiguration>
   734        <Id>1</Id>
   735        <Filter></Filter>
   736        <Queue>arn:minio:sqs:us-east-1:1:webhook</Queue>
   737        <Event>s3:ObjectAccessed:*</Event>
   738        <Event>s3:ObjectCreated:*</Event>
   739        <Event>s3:ObjectRemoved:*</Event>
   740     </QueueConfiguration>
   741  </NotificationConfiguration>
   742  `)
   743  	config1 := &Config{}
   744  	if err := xml.Unmarshal(data, config1); err != nil {
   745  		panic(err)
   746  	}
   747  
   748  	data = []byte(`
   749  <NotificationConfiguration  xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
   750     <QueueConfiguration>
   751        <Id>1</Id>
   752         <Filter>
   753             <S3Key>
   754                 <FilterRule>
   755                     <Name>prefix</Name>
   756                     <Value>images/</Value>
   757                 </FilterRule>
   758                 <FilterRule>
   759                     <Name>suffix</Name>
   760                     <Value>jpg</Value>
   761                 </FilterRule>
   762             </S3Key>
   763        </Filter>
   764        <Queue>arn:minio:sqs::1:webhook</Queue>
   765        <Event>s3:ObjectCreated:Put</Event>
   766     </QueueConfiguration>
   767  </NotificationConfiguration>
   768  `)
   769  	config2 := &Config{}
   770  	if err := xml.Unmarshal(data, config2); err != nil {
   771  		panic(err)
   772  	}
   773  
   774  	data = []byte(`
   775  <NotificationConfiguration  xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
   776     <QueueConfiguration>
   777        <Id>1</Id>
   778        <Filter></Filter>
   779        <Queue>arn:minio:sqs:us-east-1:1:webhook</Queue>
   780        <Event>s3:ObjectAccessed:*</Event>
   781        <Event>s3:ObjectCreated:*</Event>
   782        <Event>s3:ObjectRemoved:*</Event>
   783     </QueueConfiguration>
   784     <QueueConfiguration>
   785        <Id>2</Id>
   786         <Filter>
   787             <S3Key>
   788                 <FilterRule>
   789                     <Name>prefix</Name>
   790                     <Value>images/</Value>
   791                 </FilterRule>
   792                 <FilterRule>
   793                     <Name>suffix</Name>
   794                     <Value>jpg</Value>
   795                 </FilterRule>
   796             </S3Key>
   797        </Filter>
   798        <Queue>arn:minio:sqs:us-east-1:2:amqp</Queue>
   799        <Event>s3:ObjectCreated:Put</Event>
   800     </QueueConfiguration>
   801  </NotificationConfiguration>
   802  `)
   803  	config3 := &Config{}
   804  	if err := xml.Unmarshal(data, config3); err != nil {
   805  		panic(err)
   806  	}
   807  
   808  	rulesMapCase1 := NewRulesMap([]Name{ObjectAccessedAll, ObjectCreatedAll, ObjectRemovedAll}, "*", TargetID{"1", "webhook"})
   809  
   810  	rulesMapCase2 := NewRulesMap([]Name{ObjectCreatedPut}, "images/*jpg", TargetID{"1", "webhook"})
   811  
   812  	rulesMapCase3 := NewRulesMap([]Name{ObjectAccessedAll, ObjectCreatedAll, ObjectRemovedAll}, "*", TargetID{"1", "webhook"})
   813  	rulesMapCase3.add([]Name{ObjectCreatedPut}, "images/*jpg", TargetID{"2", "amqp"})
   814  
   815  	testCases := []struct {
   816  		config         *Config
   817  		expectedResult RulesMap
   818  	}{
   819  		{config1, rulesMapCase1},
   820  		{config2, rulesMapCase2},
   821  		{config3, rulesMapCase3},
   822  	}
   823  
   824  	for i, testCase := range testCases {
   825  		result := testCase.config.ToRulesMap()
   826  
   827  		if !reflect.DeepEqual(result, testCase.expectedResult) {
   828  			t.Fatalf("test %v: data: expected: %v, got: %v", i+1, testCase.expectedResult, result)
   829  		}
   830  	}
   831  }
   832  
   833  func TestParseConfig(t *testing.T) {
   834  	reader1 := strings.NewReader(`
   835  <NotificationConfiguration  xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
   836     <QueueConfiguration>
   837        <Id>1</Id>
   838        <Filter></Filter>
   839        <Queue>arn:minio:sqs:us-east-1:1:webhook</Queue>
   840        <Event>s3:ObjectAccessed:*</Event>
   841        <Event>s3:ObjectCreated:*</Event>
   842        <Event>s3:ObjectRemoved:*</Event>
   843     </QueueConfiguration>
   844  </NotificationConfiguration>
   845  `)
   846  
   847  	reader2 := strings.NewReader(`
   848  <NotificationConfiguration  xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
   849     <QueueConfiguration>
   850        <Id>1</Id>
   851         <Filter>
   852             <S3Key>
   853                 <FilterRule>
   854                     <Name>prefix</Name>
   855                     <Value>images/</Value>
   856                 </FilterRule>
   857                 <FilterRule>
   858                     <Name>suffix</Name>
   859                     <Value>jpg</Value>
   860                 </FilterRule>
   861             </S3Key>
   862        </Filter>
   863        <Queue>arn:minio:sqs:us-east-1:1:webhook</Queue>
   864        <Event>s3:ObjectCreated:Put</Event>
   865     </QueueConfiguration>
   866  </NotificationConfiguration>
   867  `)
   868  
   869  	reader3 := strings.NewReader(`
   870  <NotificationConfiguration  xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
   871     <QueueConfiguration>
   872        <Id>1</Id>
   873        <Filter></Filter>
   874        <Queue>arn:minio:sqs:us-east-1:1:webhook</Queue>
   875        <Event>s3:ObjectAccessed:*</Event>
   876        <Event>s3:ObjectCreated:*</Event>
   877        <Event>s3:ObjectRemoved:*</Event>
   878     </QueueConfiguration>
   879     <QueueConfiguration>
   880        <Id>2</Id>
   881         <Filter>
   882             <S3Key>
   883                 <FilterRule>
   884                     <Name>prefix</Name>
   885                     <Value>images/</Value>
   886                 </FilterRule>
   887                 <FilterRule>
   888                     <Name>suffix</Name>
   889                     <Value>jpg</Value>
   890                 </FilterRule>
   891             </S3Key>
   892        </Filter>
   893        <Queue>arn:minio:sqs:us-east-1:1:webhook</Queue>
   894        <Event>s3:ObjectCreated:Put</Event>
   895     </QueueConfiguration>
   896  </NotificationConfiguration>
   897  `)
   898  
   899  	reader4 := strings.NewReader(`
   900  <NotificationConfiguration  xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
   901     <QueueConfiguration>
   902        <Id>1</Id>
   903        <Filter></Filter>
   904        <Queue>arn:minio:sqs:us-east-1:1:webhook</Queue>
   905        <Event>s3:ObjectAccessed:*</Event>
   906        <Event>s3:ObjectCreated:*</Event>
   907        <Event>s3:ObjectRemoved:*</Event>
   908     </QueueConfiguration>
   909     <CloudFunctionConfiguration>
   910        <Id>1</Id>
   911        <Filter>
   912               <S3Key>
   913                   <FilterRule>
   914                       <Name>suffix</Name>
   915                       <Value>.jpg</Value>
   916                   </FilterRule>
   917               </S3Key>
   918        </Filter>
   919        <Cloudcode>arn:aws:lambda:us-west-2:444455556666:cloud-function-A</Cloudcode>
   920        <Event>s3:ObjectCreated:Put</Event>
   921     </CloudFunctionConfiguration>
   922     <TopicConfiguration>
   923        <Topic>arn:aws:sns:us-west-2:444455556666:sns-notification-one</Topic>
   924        <Event>s3:ObjectCreated:*</Event>
   925    </TopicConfiguration>
   926  </NotificationConfiguration>
   927  `)
   928  
   929  	targetList1 := NewTargetList()
   930  
   931  	targetList2 := NewTargetList()
   932  	if err := targetList2.Add(&ExampleTarget{TargetID{"1", "webhook"}, false, false}); err != nil {
   933  		panic(err)
   934  	}
   935  
   936  	testCases := []struct {
   937  		reader     *strings.Reader
   938  		region     string
   939  		targetList *TargetList
   940  		expectErr  bool
   941  	}{
   942  		{reader1, "eu-west-1", nil, true},
   943  		{reader2, "us-east-1", targetList1, true},
   944  		{reader4, "us-east-1", targetList1, true},
   945  		{reader3, "", targetList2, false},
   946  		{reader2, "us-east-1", targetList2, false},
   947  	}
   948  
   949  	for i, testCase := range testCases {
   950  		if _, err := testCase.reader.Seek(0, 0); err != nil {
   951  			panic(err)
   952  		}
   953  		_, err := ParseConfig(testCase.reader, testCase.region, testCase.targetList)
   954  		expectErr := (err != nil)
   955  
   956  		if expectErr != testCase.expectErr {
   957  			t.Fatalf("test %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
   958  		}
   959  	}
   960  }