From b90550de255396b03d02c8b079d82d8d2c3dab74 Mon Sep 17 00:00:00 2001 From: harry Date: Mon, 22 Feb 2016 15:30:31 +0800 Subject: [PATCH] Implement check for priority --- pkg/util/codeinspector/codeinspector.go | 60 +++++++++++++++++++ .../algorithm/priorities/priorities_test.go | 29 +++++++++ 2 files changed, 89 insertions(+) create mode 100644 pkg/util/codeinspector/codeinspector.go diff --git a/pkg/util/codeinspector/codeinspector.go b/pkg/util/codeinspector/codeinspector.go new file mode 100644 index 0000000000..4f5429831f --- /dev/null +++ b/pkg/util/codeinspector/codeinspector.go @@ -0,0 +1,60 @@ +/* +Copyright 2016 The Kubernetes Authors All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package codeinspector + +import ( + "fmt" + "go/ast" + "go/parser" + "go/token" + "unicode" +) + +// Get all public functions (not methods) from a golang source file. +func GetPulicFunctions(filePath string) ([]string, error) { + var functionNames []string + + // Create the AST by parsing src. + fset := token.NewFileSet() // positions are relative to fset + f, err := parser.ParseFile(fset, filePath, nil, 0) + if err != nil { + return nil, fmt.Errorf("failed parse file to list functions: %v", err) + } + + // Inspect the AST and print all identifiers and literals. + ast.Inspect(f, func(n ast.Node) bool { + var s string + switch x := n.(type) { + case *ast.FuncDecl: + s = x.Name.Name + // It's a function (not method), and is public, record it. + if x.Recv == nil && isPublic(s) { + functionNames = append(functionNames, s) + } + } + return true + }) + + return functionNames, nil +} + +// Check if a given string is a public function name. +func isPublic(myString string) bool { + a := []rune(myString) + a[0] = unicode.ToUpper(a[0]) + return myString == string(a) +} diff --git a/plugin/pkg/scheduler/algorithm/priorities/priorities_test.go b/plugin/pkg/scheduler/algorithm/priorities/priorities_test.go index 65814cb0cb..0793a6e1c0 100644 --- a/plugin/pkg/scheduler/algorithm/priorities/priorities_test.go +++ b/plugin/pkg/scheduler/algorithm/priorities/priorities_test.go @@ -17,6 +17,7 @@ limitations under the License. package priorities import ( + "os/exec" "reflect" "sort" "strconv" @@ -25,6 +26,7 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/resource" "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/util/codeinspector" "k8s.io/kubernetes/plugin/pkg/scheduler" "k8s.io/kubernetes/plugin/pkg/scheduler/algorithm" priorityutil "k8s.io/kubernetes/plugin/pkg/scheduler/algorithm/priorities/util" @@ -884,3 +886,30 @@ func makeImageNode(node string, status api.NodeStatus) api.Node { Status: status, } } + +func TestPriorityRegistered(t *testing.T) { + var functionNames []string + + files := []string{"priorities.go", "node_affinity.go", "selector_spreading.go"} + + for _, filePath := range files { + functions, err := codeinspector.GetPulicFunctions(filePath) + if err == nil { + functionNames = append(functionNames, functions...) + } else { + t.Errorf("unexpected error when parsing %s", filePath) + } + } + + for _, funcionName := range functionNames { + err := exec.Command("grep", "-rl", funcionName, "./../../algorithmprovider/defaults/defaults.go", "./../../factory/plugins.go").Run() + if err != nil { + switch err.Error() { + case "exit status 2": + t.Errorf("unexpected error when checking %s", funcionName) + case "exit status 1": + t.Errorf("priority %s is implemented but seems not registered in any place", funcionName) + } + } + } +}