github.com/kubewharf/katalyst-core@v0.5.3/pkg/agent/resourcemanager/fetcher/plugin/endpoint_test.go (about) 1 /* 2 Copyright 2022 The Katalyst 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 plugin 18 19 import ( 20 "context" 21 "fmt" 22 "path" 23 "testing" 24 25 "github.com/stretchr/testify/require" 26 v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 28 "github.com/kubewharf/katalyst-api/pkg/plugins/skeleton" 29 "github.com/kubewharf/katalyst-api/pkg/protocol/reporterplugin/v1alpha1" 30 "github.com/kubewharf/katalyst-core/pkg/metrics" 31 ) 32 33 var testGroupVersionKind = v1.GroupVersionKind{ 34 Group: "test-group", 35 Kind: "test-kind", 36 Version: "test-version", 37 } 38 39 func TestNewEndpoint(t *testing.T) { 40 t.Parallel() 41 42 socketDir := path.Join("/tmp/TestNewEndpoint") 43 44 content := []*v1alpha1.ReportContent{ 45 { 46 GroupVersionKind: &testGroupVersionKind, 47 Field: []*v1alpha1.ReportField{}, 48 }, 49 } 50 51 _, gp, e := esetup(t, content, socketDir, "mock", func(n string, d *v1alpha1.GetReportContentResponse) {}) 52 defer ecleanup(t, gp, e) 53 } 54 55 func TestRun(t *testing.T) { 56 t.Parallel() 57 socket := path.Join("/tmp/TestRun") 58 59 content := []*v1alpha1.ReportContent{ 60 { 61 GroupVersionKind: &testGroupVersionKind, 62 Field: []*v1alpha1.ReportField{ 63 { 64 FieldType: v1alpha1.FieldType_Spec, 65 FieldName: "fieldName_a", 66 Value: []byte("Value_a"), 67 }, 68 }, 69 }, 70 { 71 GroupVersionKind: &testGroupVersionKind, 72 Field: []*v1alpha1.ReportField{ 73 { 74 FieldType: v1alpha1.FieldType_Status, 75 FieldName: "fieldName_b", 76 Value: []byte("Value_b"), 77 }, 78 }, 79 }, 80 } 81 82 updated := []*v1alpha1.ReportContent{ 83 { 84 GroupVersionKind: &testGroupVersionKind, 85 Field: []*v1alpha1.ReportField{ 86 { 87 FieldType: v1alpha1.FieldType_Spec, 88 FieldName: "fieldName_a", 89 Value: []byte("Value_a_1"), 90 }, 91 }, 92 }, 93 { 94 GroupVersionKind: &testGroupVersionKind, 95 Field: []*v1alpha1.ReportField{ 96 { 97 FieldType: v1alpha1.FieldType_Status, 98 FieldName: "fieldName_b", 99 Value: []byte("Value_b_1"), 100 }, 101 }, 102 }, 103 } 104 105 callbackCount := 0 106 callbackChan := make(chan int) 107 callback := func(n string, response *v1alpha1.GetReportContentResponse) { 108 // Should be called twice: 109 // one for plugin registration, one for plugin update. 110 if callbackCount > 2 { 111 t.FailNow() 112 } 113 114 // Check plugin registration 115 if callbackCount == 0 { 116 require.Len(t, response.Content, 2) 117 reporterContentsEqual(t, response.Content, content) 118 } 119 120 // Check plugin update 121 if callbackCount == 1 { 122 require.Len(t, response.Content, 2) 123 reporterContentsEqual(t, response.Content, updated) 124 } 125 126 callbackCount++ 127 callbackChan <- callbackCount 128 } 129 130 p, gp, e := esetup(t, content, socket, "mock", callback) 131 defer ecleanup(t, gp, e) 132 133 success := make(chan bool) 134 go e.Run(success) 135 <-success 136 // Wait for the first callback to be issued. 137 <-callbackChan 138 139 p.Update(updated) 140 141 // Wait for the second callback to be issued. 142 <-callbackChan 143 144 require.Equal(t, callbackCount, 2) 145 } 146 147 func TestGetReportContent(t *testing.T) { 148 t.Parallel() 149 150 socket := path.Join("/tmp/TestGetReportContent") 151 152 content := []*v1alpha1.ReportContent{ 153 { 154 GroupVersionKind: &testGroupVersionKind, 155 Field: []*v1alpha1.ReportField{ 156 { 157 FieldType: v1alpha1.FieldType_Spec, 158 FieldName: "fieldName_a", 159 Value: []byte("Value_a"), 160 }, 161 }, 162 }, 163 { 164 GroupVersionKind: &testGroupVersionKind, 165 Field: []*v1alpha1.ReportField{ 166 { 167 FieldType: v1alpha1.FieldType_Status, 168 FieldName: "fieldName_b", 169 Value: []byte("Value_b"), 170 }, 171 }, 172 }, 173 } 174 175 callbackCount := 0 176 callbackChan := make(chan int) 177 _, gp, e := esetup(t, content, socket, "mock", func(n string, response *v1alpha1.GetReportContentResponse) { 178 callbackCount++ 179 callbackChan <- callbackCount 180 }) 181 defer ecleanup(t, gp, e) 182 183 respOut, err := e.GetReportContent(context.TODO()) 184 require.NoError(t, err) 185 require.NotNil(t, respOut) 186 reporterContentsEqual(t, respOut.Content, content) 187 } 188 189 func esetup(t *testing.T, content []*v1alpha1.ReportContent, socket, pluginName string, callback ListAndWatchCallback) (*skeleton.ReporterPluginStub, skeleton.GenericPlugin, Endpoint) { 190 ps := skeleton.NewReporterPluginStub(content, pluginName) 191 p, _ := skeleton.NewRegistrationPluginWrapper(ps, []string{socket}, nil) 192 err := p.Start() 193 require.NoError(t, err) 194 195 e, err := NewRemoteEndpoint(path.Join(socket, fmt.Sprintf("%s.sock", p.Name())), pluginName, nil, metrics.DummyMetrics{}, callback) 196 require.NoError(t, err) 197 198 return ps, p, e 199 } 200 201 func ecleanup(t *testing.T, p skeleton.GenericPlugin, e Endpoint) { 202 err := p.Stop() 203 require.NoError(t, err) 204 e.Stop() 205 } 206 207 func reporterContentsEqual(t *testing.T, expected, actual []*v1alpha1.ReportContent) { 208 require.Equal(t, len(expected), len(actual)) 209 for idx := range expected { 210 require.Equal(t, expected[idx].GroupVersionKind, actual[idx].GroupVersionKind) 211 require.Equal(t, len(expected[idx].Field), len(actual[idx].Field)) 212 for fieldIdx := range expected[idx].Field { 213 require.Equal(t, expected[idx].Field[fieldIdx].FieldType, actual[idx].Field[fieldIdx].FieldType) 214 require.Equal(t, expected[idx].Field[fieldIdx].FieldName, actual[idx].Field[fieldIdx].FieldName) 215 require.Equal(t, expected[idx].Field[fieldIdx].Value, actual[idx].Field[fieldIdx].Value) 216 } 217 } 218 }