github.com/minio/minio@v0.0.0-20240328213742-3f72439b8a27/internal/event/config_test.go (about)

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