github.com/imran-kn/cilium-fork@v1.6.9/pkg/policy/resolve_test.go (about)

     1  // Copyright 2018-2019 Authors of Cilium
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // +build !privileged_tests
    16  
    17  package policy
    18  
    19  import (
    20  	"fmt"
    21  	"sync"
    22  
    23  	"github.com/cilium/cilium/pkg/checker"
    24  	"github.com/cilium/cilium/pkg/identity"
    25  	"github.com/cilium/cilium/pkg/identity/cache"
    26  	"github.com/cilium/cilium/pkg/labels"
    27  	"github.com/cilium/cilium/pkg/option"
    28  	"github.com/cilium/cilium/pkg/policy/api"
    29  	"github.com/cilium/cilium/pkg/policy/trafficdirection"
    30  	. "gopkg.in/check.v1"
    31  )
    32  
    33  var (
    34  	fooLabel = labels.NewLabel("k8s:foo", "", "")
    35  	lbls     = labels.Labels{
    36  		"foo": fooLabel,
    37  	}
    38  	lblsArray   = lbls.LabelArray()
    39  	fooIdentity = &identity.Identity{
    40  		ID:         303,
    41  		Labels:     lbls,
    42  		LabelArray: lbls.LabelArray(),
    43  	}
    44  	identityCache = cache.IdentityCache{303: lblsArray}
    45  )
    46  
    47  type dummyEndpoint struct {
    48  	ID               uint16
    49  	SecurityIdentity *identity.Identity
    50  }
    51  
    52  func (d *dummyEndpoint) GetID16() uint16 {
    53  	return d.ID
    54  }
    55  
    56  func (d *dummyEndpoint) GetSecurityIdentity() *identity.Identity {
    57  	return d.SecurityIdentity
    58  }
    59  
    60  func (d *dummyEndpoint) PolicyRevisionBumpEvent(rev uint64) {
    61  }
    62  
    63  func (d *dummyEndpoint) RLockAlive() error {
    64  	return nil
    65  }
    66  
    67  func (d *dummyEndpoint) RUnlock() {
    68  }
    69  
    70  func GenerateNumIdentities(numIdentities int) {
    71  	for i := 0; i < numIdentities; i++ {
    72  
    73  		identityLabel := labels.NewLabel(fmt.Sprintf("k8s:foo%d", i), "", "")
    74  		clusterLabel := labels.NewLabel("io.cilium.k8s.policy.cluster=default", "", labels.LabelSourceK8s)
    75  		serviceAccountLabel := labels.NewLabel("io.cilium.k8s.policy.serviceaccount=default", "", labels.LabelSourceK8s)
    76  		namespaceLabel := labels.NewLabel("io.kubernetes.pod.namespace=monitoring", "", labels.LabelSourceK8s)
    77  		funLabel := labels.NewLabel("app=analytics-erneh", "", labels.LabelSourceK8s)
    78  
    79  		identityLabels := labels.Labels{
    80  			fmt.Sprintf("foo%d", i):                           identityLabel,
    81  			"k8s:io.cilium.k8s.policy.cluster=default":        clusterLabel,
    82  			"k8s:io.cilium.k8s.policy.serviceaccount=default": serviceAccountLabel,
    83  			"k8s:io.kubernetes.pod.namespace=monitoring":      namespaceLabel,
    84  			"k8s:app=analytics-erneh":                         funLabel,
    85  		}
    86  
    87  		bumpedIdentity := i + 1000
    88  		numericIdentity := identity.NumericIdentity(bumpedIdentity)
    89  
    90  		identityCache[numericIdentity] = identityLabels.LabelArray()
    91  	}
    92  }
    93  
    94  func GenerateL3IngressRules(numRules int) api.Rules {
    95  	parseFooLabel := labels.ParseSelectLabel("k8s:foo")
    96  	fooSelector := api.NewESFromLabels(parseFooLabel)
    97  	barSelector := api.NewESFromLabels(labels.ParseSelectLabel("bar"))
    98  
    99  	// Change ingRule and rule in the for-loop below to change what type of rules
   100  	// are added into the policy repository.
   101  	ingRule := api.IngressRule{
   102  		FromEndpoints: []api.EndpointSelector{barSelector},
   103  	}
   104  
   105  	var rules api.Rules
   106  	for i := 1; i <= numRules; i++ {
   107  
   108  		rule := api.Rule{
   109  			EndpointSelector: fooSelector,
   110  			Ingress:          []api.IngressRule{ingRule},
   111  		}
   112  		rule.Sanitize()
   113  		rules = append(rules, &rule)
   114  	}
   115  	return rules
   116  }
   117  
   118  func GenerateL3EgressRules(numRules int) api.Rules {
   119  	parseFooLabel := labels.ParseSelectLabel("k8s:foo")
   120  	fooSelector := api.NewESFromLabels(parseFooLabel)
   121  	barSelector := api.NewESFromLabels(labels.ParseSelectLabel("bar"))
   122  
   123  	// Change ingRule and rule in the for-loop below to change what type of rules
   124  	// are added into the policy repository.
   125  	egRule := api.EgressRule{
   126  		ToEndpoints: []api.EndpointSelector{barSelector},
   127  	}
   128  
   129  	var rules api.Rules
   130  	for i := 1; i <= numRules; i++ {
   131  
   132  		rule := api.Rule{
   133  			EndpointSelector: fooSelector,
   134  			Egress:           []api.EgressRule{egRule},
   135  		}
   136  		rule.Sanitize()
   137  		rules = append(rules, &rule)
   138  	}
   139  	return rules
   140  }
   141  
   142  func GenerateCIDRRules(numRules int) api.Rules {
   143  	parseFooLabel := labels.ParseSelectLabel("k8s:foo")
   144  	fooSelector := api.NewESFromLabels(parseFooLabel)
   145  	//barSelector := api.NewESFromLabels(labels.ParseSelectLabel("bar"))
   146  
   147  	// Change ingRule and rule in the for-loop below to change what type of rules
   148  	// are added into the policy repository.
   149  	egRule := api.EgressRule{
   150  		ToCIDR: []api.CIDR{api.CIDR("10.2.3.0/24"), api.CIDR("ff02::/64")},
   151  		/*ToRequires:  []api.EndpointSelector{barSelector},
   152  		ToPorts: []api.PortRule{
   153  			{
   154  				Ports: []api.PortProtocol{
   155  					{
   156  						Port:     "8080",
   157  						Protocol: api.ProtoTCP,
   158  					},
   159  				},
   160  			},
   161  		},*/
   162  	}
   163  
   164  	var rules api.Rules
   165  	for i := 1; i <= numRules; i++ {
   166  
   167  		rule := api.Rule{
   168  			EndpointSelector: fooSelector,
   169  			Egress:           []api.EgressRule{egRule},
   170  		}
   171  		rule.Sanitize()
   172  		rules = append(rules, &rule)
   173  	}
   174  	return rules
   175  }
   176  
   177  type DummyOwner struct{}
   178  
   179  func (d DummyOwner) LookupRedirectPort(l4 *L4Filter) uint16 {
   180  	return 0
   181  }
   182  
   183  func (d DummyOwner) GetSecurityIdentity() *identity.Identity {
   184  	return fooIdentity
   185  }
   186  
   187  func bootstrapRepo(ruleGenFunc func(int) api.Rules, numRules int, c *C) *Repository {
   188  	testRepo := NewPolicyRepository()
   189  
   190  	var wg sync.WaitGroup
   191  	SetPolicyEnabled(option.DefaultEnforcement)
   192  	GenerateNumIdentities(3000)
   193  	testSelectorCache.UpdateIdentities(identityCache, nil)
   194  	testRepo.selectorCache = testSelectorCache
   195  	rulez, _ := testRepo.AddList(ruleGenFunc(numRules))
   196  
   197  	epSet := NewEndpointSet(map[Endpoint]struct{}{
   198  		&dummyEndpoint{
   199  			ID:               9001,
   200  			SecurityIdentity: fooIdentity,
   201  		}: {},
   202  	})
   203  
   204  	epsToRegen := NewEndpointSet(nil)
   205  	rulez.UpdateRulesEndpointsCaches(epSet, epsToRegen, &wg)
   206  	wg.Wait()
   207  
   208  	c.Assert(epSet.Len(), Equals, 0)
   209  	c.Assert(epsToRegen.Len(), Equals, 1)
   210  
   211  	return testRepo
   212  }
   213  
   214  func (ds *PolicyTestSuite) BenchmarkRegenerateCIDRPolicyRules(c *C) {
   215  	testRepo := bootstrapRepo(GenerateCIDRRules, 1000, c)
   216  
   217  	c.ResetTimer()
   218  	for i := 0; i < c.N; i++ {
   219  		ip, _ := testRepo.resolvePolicyLocked(fooIdentity)
   220  		_ = ip.DistillPolicy(DummyOwner{})
   221  		ip.Detach()
   222  	}
   223  }
   224  
   225  func (ds *PolicyTestSuite) BenchmarkRegenerateL3IngressPolicyRules(c *C) {
   226  	testRepo := bootstrapRepo(GenerateL3IngressRules, 1000, c)
   227  	c.ResetTimer()
   228  	for i := 0; i < c.N; i++ {
   229  		ip, _ := testRepo.resolvePolicyLocked(fooIdentity)
   230  		_ = ip.DistillPolicy(DummyOwner{})
   231  		ip.Detach()
   232  	}
   233  }
   234  
   235  func (ds *PolicyTestSuite) BenchmarkRegenerateL3EgressPolicyRules(c *C) {
   236  	testRepo := bootstrapRepo(GenerateL3EgressRules, 1000, c)
   237  	c.ResetTimer()
   238  	for i := 0; i < c.N; i++ {
   239  		ip, _ := testRepo.resolvePolicyLocked(fooIdentity)
   240  		_ = ip.DistillPolicy(DummyOwner{})
   241  		ip.Detach()
   242  	}
   243  }
   244  
   245  func (ds *PolicyTestSuite) TestL7WithIngressWildcard(c *C) {
   246  	repo := bootstrapRepo(GenerateL3IngressRules, 1000, c)
   247  
   248  	idFooSelectLabelArray := labels.ParseSelectLabelArray("id=foo")
   249  	idFooSelectLabels := labels.Labels{}
   250  	for _, lbl := range idFooSelectLabelArray {
   251  		idFooSelectLabels[lbl.Key] = lbl
   252  	}
   253  	fooIdentity := identity.NewIdentity(12345, idFooSelectLabels)
   254  
   255  	selFoo := api.NewESFromLabels(labels.ParseSelectLabel("id=foo"))
   256  	rule1 := api.Rule{
   257  		EndpointSelector: selFoo,
   258  		Ingress: []api.IngressRule{
   259  			{
   260  				ToPorts: []api.PortRule{{
   261  					Ports: []api.PortProtocol{
   262  						{Port: "80", Protocol: api.ProtoTCP},
   263  					},
   264  					Rules: &api.L7Rules{
   265  						HTTP: []api.PortRuleHTTP{
   266  							{Method: "GET", Path: "/good"},
   267  						},
   268  					},
   269  				}},
   270  			},
   271  		},
   272  	}
   273  
   274  	rule1.Sanitize()
   275  	_, _, err := repo.Add(rule1, []Endpoint{})
   276  	c.Assert(err, IsNil)
   277  
   278  	repo.Mutex.RLock()
   279  	defer repo.Mutex.RUnlock()
   280  	selPolicy, err := repo.resolvePolicyLocked(fooIdentity)
   281  	c.Assert(err, IsNil)
   282  	policy := selPolicy.DistillPolicy(DummyOwner{})
   283  
   284  	expectedEndpointPolicy := EndpointPolicy{
   285  		selectorPolicy: &selectorPolicy{
   286  			Revision:      repo.GetRevision(),
   287  			SelectorCache: repo.GetSelectorCache(),
   288  			L4Policy: &L4Policy{
   289  				Revision: repo.GetRevision(),
   290  				Ingress: L4PolicyMap{
   291  					"80/TCP": {
   292  						Port:     80,
   293  						Protocol: api.ProtoTCP,
   294  						U8Proto:  0x6,
   295  						CachedSelectors: CachedSelectorSlice{
   296  							wildcardCachedSelector,
   297  						},
   298  						allowsAllAtL3: true,
   299  						L7Parser:      ParserTypeHTTP,
   300  						Ingress:       true,
   301  						L7RulesPerEp: L7DataMap{
   302  							wildcardCachedSelector: api.L7Rules{
   303  								HTTP: []api.PortRuleHTTP{{Method: "GET", Path: "/good"}},
   304  							},
   305  						},
   306  						DerivedFromRules: labels.LabelArrayList{nil},
   307  					},
   308  				},
   309  				Egress: L4PolicyMap{},
   310  			},
   311  			CIDRPolicy:           policy.CIDRPolicy,
   312  			IngressPolicyEnabled: true,
   313  			EgressPolicyEnabled:  false,
   314  		},
   315  		PolicyOwner: DummyOwner{},
   316  		// inherit this from the result as it is outside of the scope
   317  		// of this test
   318  		PolicyMapState: policy.PolicyMapState,
   319  	}
   320  
   321  	// Have to remove circular reference before testing to avoid an infinite loop
   322  	policy.selectorPolicy.Detach()
   323  
   324  	c.Assert(policy, checker.Equals, &expectedEndpointPolicy)
   325  }
   326  
   327  func (ds *PolicyTestSuite) TestL7WithLocalHostWildcardd(c *C) {
   328  	repo := bootstrapRepo(GenerateL3IngressRules, 1000, c)
   329  
   330  	idFooSelectLabelArray := labels.ParseSelectLabelArray("id=foo")
   331  	idFooSelectLabels := labels.Labels{}
   332  	for _, lbl := range idFooSelectLabelArray {
   333  		idFooSelectLabels[lbl.Key] = lbl
   334  	}
   335  
   336  	fooIdentity := identity.NewIdentity(12345, idFooSelectLabels)
   337  
   338  	// Emulate Kubernetes mode with allow from localhost
   339  	oldLocalhostOpt := option.Config.AllowLocalhost
   340  	option.Config.AllowLocalhost = option.AllowLocalhostAlways
   341  	defer func() { option.Config.AllowLocalhost = oldLocalhostOpt }()
   342  
   343  	selFoo := api.NewESFromLabels(labels.ParseSelectLabel("id=foo"))
   344  	rule1 := api.Rule{
   345  		EndpointSelector: selFoo,
   346  		Ingress: []api.IngressRule{
   347  			{
   348  				ToPorts: []api.PortRule{{
   349  					Ports: []api.PortProtocol{
   350  						{Port: "80", Protocol: api.ProtoTCP},
   351  					},
   352  					Rules: &api.L7Rules{
   353  						HTTP: []api.PortRuleHTTP{
   354  							{Method: "GET", Path: "/good"},
   355  						},
   356  					},
   357  				}},
   358  			},
   359  		},
   360  	}
   361  
   362  	rule1.Sanitize()
   363  	_, _, err := repo.Add(rule1, []Endpoint{})
   364  	c.Assert(err, IsNil)
   365  
   366  	repo.Mutex.RLock()
   367  	defer repo.Mutex.RUnlock()
   368  
   369  	selPolicy, err := repo.resolvePolicyLocked(fooIdentity)
   370  	c.Assert(err, IsNil)
   371  	policy := selPolicy.DistillPolicy(DummyOwner{})
   372  
   373  	cachedSelectorHost := testSelectorCache.FindCachedIdentitySelector(api.ReservedEndpointSelectors[labels.IDNameHost])
   374  	c.Assert(cachedSelectorHost, Not(IsNil))
   375  
   376  	expectedEndpointPolicy := EndpointPolicy{
   377  		selectorPolicy: &selectorPolicy{
   378  			Revision:      repo.GetRevision(),
   379  			SelectorCache: repo.GetSelectorCache(),
   380  			L4Policy: &L4Policy{
   381  				Revision: repo.GetRevision(),
   382  				Ingress: L4PolicyMap{
   383  					"80/TCP": {
   384  						Port:     80,
   385  						Protocol: api.ProtoTCP,
   386  						U8Proto:  0x6,
   387  						CachedSelectors: CachedSelectorSlice{
   388  							wildcardCachedSelector,
   389  							cachedSelectorHost,
   390  						},
   391  						allowsAllAtL3: true,
   392  						L7Parser:      ParserTypeHTTP,
   393  						Ingress:       true,
   394  						L7RulesPerEp: L7DataMap{
   395  							wildcardCachedSelector: api.L7Rules{
   396  								HTTP: []api.PortRuleHTTP{{Method: "GET", Path: "/good"}},
   397  							},
   398  							cachedSelectorHost: api.L7Rules{},
   399  						},
   400  						DerivedFromRules: labels.LabelArrayList{nil},
   401  					},
   402  				},
   403  				Egress: L4PolicyMap{},
   404  			},
   405  			CIDRPolicy:           policy.CIDRPolicy,
   406  			IngressPolicyEnabled: true,
   407  			EgressPolicyEnabled:  false,
   408  		},
   409  		PolicyOwner: DummyOwner{},
   410  		// inherit this from the result as it is outside of the scope
   411  		// of this test
   412  		PolicyMapState: policy.PolicyMapState,
   413  	}
   414  
   415  	// Have to remove circular reference before testing to avoid an infinite loop
   416  	policy.selectorPolicy.Detach()
   417  
   418  	c.Assert(policy, checker.Equals, &expectedEndpointPolicy)
   419  }
   420  
   421  func (ds *PolicyTestSuite) TestMapStateWithIngressWildcard(c *C) {
   422  	repo := bootstrapRepo(GenerateL3IngressRules, 1000, c)
   423  
   424  	idFooSelectLabelArray := labels.ParseSelectLabelArray("id=foo")
   425  	idFooSelectLabels := labels.Labels{}
   426  	for _, lbl := range idFooSelectLabelArray {
   427  		idFooSelectLabels[lbl.Key] = lbl
   428  	}
   429  	fooIdentity := identity.NewIdentity(12345, idFooSelectLabels)
   430  
   431  	selFoo := api.NewESFromLabels(labels.ParseSelectLabel("id=foo"))
   432  	rule1 := api.Rule{
   433  		EndpointSelector: selFoo,
   434  		Ingress: []api.IngressRule{
   435  			{
   436  				ToPorts: []api.PortRule{{
   437  					Ports: []api.PortProtocol{
   438  						{Port: "80", Protocol: api.ProtoTCP},
   439  					},
   440  					Rules: &api.L7Rules{},
   441  				}},
   442  			},
   443  		},
   444  	}
   445  
   446  	rule1.Sanitize()
   447  	_, _, err := repo.Add(rule1, []Endpoint{})
   448  	c.Assert(err, IsNil)
   449  
   450  	repo.Mutex.RLock()
   451  	defer repo.Mutex.RUnlock()
   452  	selPolicy, err := repo.resolvePolicyLocked(fooIdentity)
   453  	c.Assert(err, IsNil)
   454  	policy := selPolicy.DistillPolicy(DummyOwner{})
   455  
   456  	expectedEndpointPolicy := EndpointPolicy{
   457  		selectorPolicy: &selectorPolicy{
   458  			Revision:      repo.GetRevision(),
   459  			SelectorCache: repo.GetSelectorCache(),
   460  			L4Policy: &L4Policy{
   461  				Revision: repo.GetRevision(),
   462  				Ingress: L4PolicyMap{
   463  					"80/TCP": {
   464  						Port:     80,
   465  						Protocol: api.ProtoTCP,
   466  						U8Proto:  0x6,
   467  						CachedSelectors: CachedSelectorSlice{
   468  							wildcardCachedSelector,
   469  						},
   470  						allowsAllAtL3:    true,
   471  						L7Parser:         ParserTypeNone,
   472  						Ingress:          true,
   473  						L7RulesPerEp:     L7DataMap{},
   474  						DerivedFromRules: labels.LabelArrayList{nil},
   475  					},
   476  				},
   477  				Egress: L4PolicyMap{},
   478  			},
   479  			CIDRPolicy:           policy.CIDRPolicy,
   480  			IngressPolicyEnabled: true,
   481  			EgressPolicyEnabled:  false,
   482  		},
   483  		PolicyOwner: DummyOwner{},
   484  		PolicyMapState: MapState{
   485  			{TrafficDirection: trafficdirection.Egress.Uint8()}: {},
   486  			{DestPort: 80, Nexthdr: 6}:                          {},
   487  		},
   488  	}
   489  
   490  	// Add new identity to test accumulation of PolicyMapChanges
   491  	added1 := cache.IdentityCache{
   492  		identity.NumericIdentity(192): labels.ParseSelectLabelArray("id=resolve_test_1"),
   493  	}
   494  	testSelectorCache.UpdateIdentities(added1, nil)
   495  	c.Assert(policy.PolicyMapChanges.adds, HasLen, 0)
   496  	c.Assert(policy.PolicyMapChanges.deletes, HasLen, 0)
   497  
   498  	// Have to remove circular reference before testing to avoid an infinite loop
   499  	policy.selectorPolicy.Detach()
   500  
   501  	c.Assert(policy, checker.Equals, &expectedEndpointPolicy)
   502  }
   503  
   504  func (ds *PolicyTestSuite) TestMapStateWithIngress(c *C) {
   505  	repo := bootstrapRepo(GenerateL3IngressRules, 1000, c)
   506  
   507  	idFooSelectLabelArray := labels.ParseSelectLabelArray("id=foo")
   508  	idFooSelectLabels := labels.Labels{}
   509  	for _, lbl := range idFooSelectLabelArray {
   510  		idFooSelectLabels[lbl.Key] = lbl
   511  	}
   512  	fooIdentity := identity.NewIdentity(12345, idFooSelectLabels)
   513  
   514  	lblTest := labels.ParseLabel("id=resolve_test_1")
   515  
   516  	selFoo := api.NewESFromLabels(labels.ParseSelectLabel("id=foo"))
   517  	rule1 := api.Rule{
   518  		EndpointSelector: selFoo,
   519  		Ingress: []api.IngressRule{
   520  			{
   521  				FromEntities: []api.Entity{api.EntityWorld},
   522  				ToPorts: []api.PortRule{{
   523  					Ports: []api.PortProtocol{
   524  						{Port: "80", Protocol: api.ProtoTCP},
   525  					},
   526  					Rules: &api.L7Rules{},
   527  				}},
   528  			},
   529  			{
   530  				FromEndpoints: []api.EndpointSelector{
   531  					api.NewESFromLabels(lblTest),
   532  				},
   533  				ToPorts: []api.PortRule{{
   534  					Ports: []api.PortProtocol{
   535  						{Port: "80", Protocol: api.ProtoTCP},
   536  					},
   537  					Rules: &api.L7Rules{},
   538  				}},
   539  			},
   540  		},
   541  	}
   542  
   543  	rule1.Sanitize()
   544  	_, _, err := repo.Add(rule1, []Endpoint{})
   545  	c.Assert(err, IsNil)
   546  
   547  	repo.Mutex.RLock()
   548  	defer repo.Mutex.RUnlock()
   549  	selPolicy, err := repo.resolvePolicyLocked(fooIdentity)
   550  	c.Assert(err, IsNil)
   551  	policy := selPolicy.DistillPolicy(DummyOwner{})
   552  
   553  	// Add new identity to test accumulation of PolicyMapChanges
   554  	added1 := cache.IdentityCache{
   555  		identity.NumericIdentity(192): labels.ParseSelectLabelArray("id=resolve_test_1", "num=1"),
   556  		identity.NumericIdentity(193): labels.ParseSelectLabelArray("id=resolve_test_1", "num=2"),
   557  		identity.NumericIdentity(194): labels.ParseSelectLabelArray("id=resolve_test_1", "num=3"),
   558  	}
   559  	testSelectorCache.UpdateIdentities(added1, nil)
   560  	c.Assert(policy.PolicyMapChanges.adds, HasLen, 3)
   561  	c.Assert(policy.PolicyMapChanges.deletes, HasLen, 0)
   562  
   563  	deleted1 := cache.IdentityCache{
   564  		identity.NumericIdentity(193): labels.ParseSelectLabelArray("id=resolve_test_1", "num=2"),
   565  	}
   566  	testSelectorCache.UpdateIdentities(nil, deleted1)
   567  	c.Assert(policy.PolicyMapChanges.adds, HasLen, 2)
   568  	c.Assert(policy.PolicyMapChanges.deletes, HasLen, 1)
   569  
   570  	cachedSelectorWorld := testSelectorCache.FindCachedIdentitySelector(api.ReservedEndpointSelectors[labels.IDNameWorld])
   571  	c.Assert(cachedSelectorWorld, Not(IsNil))
   572  
   573  	cachedSelectorTest := testSelectorCache.FindCachedIdentitySelector(api.NewESFromLabels(lblTest))
   574  	c.Assert(cachedSelectorTest, Not(IsNil))
   575  
   576  	expectedEndpointPolicy := EndpointPolicy{
   577  		selectorPolicy: &selectorPolicy{
   578  			Revision:      repo.GetRevision(),
   579  			SelectorCache: repo.GetSelectorCache(),
   580  			L4Policy: &L4Policy{
   581  				Revision: repo.GetRevision(),
   582  				Ingress: L4PolicyMap{
   583  					"80/TCP": {
   584  						Port:     80,
   585  						Protocol: api.ProtoTCP,
   586  						U8Proto:  0x6,
   587  						CachedSelectors: CachedSelectorSlice{
   588  							cachedSelectorWorld,
   589  							cachedSelectorTest,
   590  						},
   591  						allowsAllAtL3:    false,
   592  						L7Parser:         ParserTypeNone,
   593  						Ingress:          true,
   594  						L7RulesPerEp:     L7DataMap{},
   595  						DerivedFromRules: labels.LabelArrayList{nil, nil},
   596  					},
   597  				},
   598  				Egress: L4PolicyMap{},
   599  			},
   600  			CIDRPolicy:           policy.CIDRPolicy,
   601  			IngressPolicyEnabled: true,
   602  			EgressPolicyEnabled:  false,
   603  		},
   604  		PolicyOwner: DummyOwner{},
   605  		PolicyMapState: MapState{
   606  			{TrafficDirection: trafficdirection.Egress.Uint8()}:                          {},
   607  			{Identity: uint32(identity.ReservedIdentityWorld), DestPort: 80, Nexthdr: 6}: {},
   608  		},
   609  		PolicyMapChanges: MapChanges{
   610  			adds: MapState{
   611  				{Identity: 192, DestPort: 80, Nexthdr: 6}: {},
   612  				{Identity: 194, DestPort: 80, Nexthdr: 6}: {},
   613  			},
   614  			deletes: MapState{
   615  				{Identity: 193, DestPort: 80, Nexthdr: 6}: {},
   616  			},
   617  		},
   618  	}
   619  
   620  	// Have to remove circular reference before testing for Equality to avoid an infinite loop
   621  	policy.selectorPolicy.Detach()
   622  	// Verify that cached selector is not found after Detach().
   623  	// Note that this depends on the other tests NOT using the same selector concurrently!
   624  	cachedSelectorTest = testSelectorCache.FindCachedIdentitySelector(api.NewESFromLabels(lblTest))
   625  	c.Assert(cachedSelectorTest, IsNil)
   626  
   627  	c.Assert(policy, checker.Equals, &expectedEndpointPolicy)
   628  
   629  	adds, deletes := policy.PolicyMapChanges.ConsumeMapChanges()
   630  	// maps on the policy got cleared
   631  	c.Assert(policy.PolicyMapChanges.adds, IsNil)
   632  	c.Assert(policy.PolicyMapChanges.deletes, IsNil)
   633  
   634  	c.Assert(adds, checker.Equals, MapState{
   635  		{Identity: 192, DestPort: 80, Nexthdr: 6}: {},
   636  		{Identity: 194, DestPort: 80, Nexthdr: 6}: {},
   637  	})
   638  	c.Assert(deletes, checker.Equals, MapState{
   639  		{Identity: 193, DestPort: 80, Nexthdr: 6}: {},
   640  	})
   641  }