...

Source file src/k8s.io/kubernetes/test/e2e/network/netpol/truthtable.go

Documentation: k8s.io/kubernetes/test/e2e/network/netpol

     1  /*
     2  Copyright 2020 The Kubernetes Authors.
     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 netpol
    18  
    19  import (
    20  	"strings"
    21  
    22  	"k8s.io/kubernetes/test/e2e/framework"
    23  )
    24  
    25  // TruthTable takes in n items and maintains an n x n table of booleans for each ordered pair
    26  type TruthTable struct {
    27  	Froms  []string
    28  	Tos    []string
    29  	toSet  map[string]bool
    30  	Values map[string]map[string]bool
    31  }
    32  
    33  // NewTruthTableFromItems creates a new truth table with items
    34  func NewTruthTableFromItems(items []string, defaultValue *bool) *TruthTable {
    35  	return NewTruthTable(items, items, defaultValue)
    36  }
    37  
    38  // NewTruthTable creates a new truth table with froms and tos
    39  func NewTruthTable(froms []string, tos []string, defaultValue *bool) *TruthTable {
    40  	values := map[string]map[string]bool{}
    41  	for _, from := range froms {
    42  		values[from] = map[string]bool{}
    43  		for _, to := range tos {
    44  			if defaultValue != nil {
    45  				values[from][to] = *defaultValue
    46  			}
    47  		}
    48  	}
    49  	toSet := map[string]bool{}
    50  	for _, to := range tos {
    51  		toSet[to] = true
    52  	}
    53  	return &TruthTable{
    54  		Froms:  froms,
    55  		Tos:    tos,
    56  		toSet:  toSet,
    57  		Values: values,
    58  	}
    59  }
    60  
    61  // IsComplete returns true if there's a value set for every single pair of items, otherwise it returns false.
    62  func (tt *TruthTable) IsComplete() bool {
    63  	for _, from := range tt.Froms {
    64  		for _, to := range tt.Tos {
    65  			if _, ok := tt.Values[from][to]; !ok {
    66  				return false
    67  			}
    68  		}
    69  	}
    70  	return true
    71  }
    72  
    73  // Set sets the value for from->to
    74  func (tt *TruthTable) Set(from string, to string, value bool) {
    75  	dict, ok := tt.Values[from]
    76  	if !ok {
    77  		framework.Failf("from-key %s not found", from)
    78  	}
    79  	if _, ok := tt.toSet[to]; !ok {
    80  		framework.Failf("to-key %s not allowed", to)
    81  	}
    82  	dict[to] = value
    83  }
    84  
    85  // SetAllFrom sets all values where from = 'from'
    86  func (tt *TruthTable) SetAllFrom(from string, value bool) {
    87  	dict, ok := tt.Values[from]
    88  	if !ok {
    89  		framework.Failf("from-key %s not found", from)
    90  	}
    91  	for _, to := range tt.Tos {
    92  		dict[to] = value
    93  	}
    94  }
    95  
    96  // SetAllTo sets all values where to = 'to'
    97  func (tt *TruthTable) SetAllTo(to string, value bool) {
    98  	if _, ok := tt.toSet[to]; !ok {
    99  		framework.Failf("to-key %s not found", to)
   100  	}
   101  	for _, from := range tt.Froms {
   102  		tt.Values[from][to] = value
   103  	}
   104  }
   105  
   106  // Get gets the specified value
   107  func (tt *TruthTable) Get(from string, to string) bool {
   108  	dict, ok := tt.Values[from]
   109  	if !ok {
   110  		framework.Failf("from-key %s not found", from)
   111  	}
   112  	val, ok := dict[to]
   113  	if !ok {
   114  		framework.Failf("to-key %s not found in map (%+v)", to, dict)
   115  	}
   116  	return val
   117  }
   118  
   119  // Compare is used to check two truth tables for equality, returning its
   120  // result in the form of a third truth table.  Both tables are expected to
   121  // have identical items.
   122  func (tt *TruthTable) Compare(other *TruthTable) *TruthTable {
   123  	if len(tt.Froms) != len(other.Froms) || len(tt.Tos) != len(other.Tos) {
   124  		framework.Failf("cannot compare tables of different dimensions")
   125  	}
   126  	for i, fr := range tt.Froms {
   127  		if other.Froms[i] != fr {
   128  			framework.Failf("cannot compare: from keys at index %d do not match (%s vs %s)", i, other.Froms[i], fr)
   129  		}
   130  	}
   131  	for i, to := range tt.Tos {
   132  		if other.Tos[i] != to {
   133  			framework.Failf("cannot compare: to keys at index %d do not match (%s vs %s)", i, other.Tos[i], to)
   134  		}
   135  	}
   136  
   137  	values := map[string]map[string]bool{}
   138  	for from, dict := range tt.Values {
   139  		values[from] = map[string]bool{}
   140  		for to, val := range dict {
   141  			values[from][to] = val == other.Values[from][to]
   142  		}
   143  	}
   144  	return &TruthTable{
   145  		Froms:  tt.Froms,
   146  		Tos:    tt.Tos,
   147  		toSet:  tt.toSet,
   148  		Values: values,
   149  	}
   150  }
   151  
   152  // PrettyPrint produces a nice visual representation.
   153  func (tt *TruthTable) PrettyPrint(indent string) string {
   154  	header := indent + strings.Join(append([]string{"-\t"}, tt.Tos...), "\t")
   155  	lines := []string{header}
   156  	for _, from := range tt.Froms {
   157  		line := []string{from}
   158  		for _, to := range tt.Tos {
   159  			mark := "X"
   160  			val, ok := tt.Values[from][to]
   161  			if !ok {
   162  				mark = "?"
   163  			} else if val {
   164  				mark = "."
   165  			}
   166  			line = append(line, mark+"\t")
   167  		}
   168  		lines = append(lines, indent+strings.Join(line, "\t"))
   169  	}
   170  	return strings.Join(lines, "\n")
   171  }
   172  

View as plain text