Change:
I just noticed you forgot to register the image locality priority function in in I also missed it when I reviewed your PR. I have fixed this in . But it would be great if you could figure out a mechanism that would ensure that all predicate/priority functions that are tested (you can assume they will always live under ) are registered, and fail the test if not. That will allow us to prevent this mistake in the future.
Thanks! Will fix this soon!
Seems need to wait for in before I send PR? Otherwise this test will always fail ...

Discussion:
<ins> /* 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" "io/ioutil" "strings" "unicode" ) // GetPublicFunctions lists all public functions (not methods) from a golang source file. func GetPublicFunctions(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 } // isPublic checks 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) } // GetSourceCodeFiles lists golang source code files from directory, excluding sub-directory and tests files. func GetSourceCodeFiles(dir string) ([]string, error) { files, err := ioutil.ReadDir(dir) if err != nil { return nil, err } var filenames []string for _, file := range files { if strings.HasSuffix(file.Name(), ".go") && !strings.HasSuffix(file.Name(), "_test.go") { filenames = append(filenames, file.Name()) } } return filenames, nil } </ins>

return selector.PodSelectorMatches } <del> // NodeMatchesNodeSelectorTerms checks if a node's labels satisfy a list of node selector terms, </del> <ins> // nodeMatchesNodeSelectorTerms checks if a node's labels satisfy a list of node selector terms, </ins> // terms are ORed, and an emtpy a list of terms will match nothing. <del> func NodeMatchesNodeSelectorTerms(node *api.Node, nodeSelectorTerms []api.NodeSelectorTerm) bool { </del> <ins> func nodeMatchesNodeSelectorTerms(node *api.Node, nodeSelectorTerms []api.NodeSelectorTerm) bool { </ins> for _, req := range nodeSelectorTerms { nodeSelector, err := api.NodeSelectorRequirementsAsSelector(req.MatchExpressions) if err != nil {

// if nodeAffinity.RequiredDuringSchedulingRequiredDuringExecution != nil { // 	nodeSelectorTerms := nodeAffinity.RequiredDuringSchedulingRequiredDuringExecution.NodeSelectorTerms // 	glog.V(10).Infof("Match for RequiredDuringSchedulingRequiredDuringExecution node selector terms %+v", nodeSelectorTerms) <del> // 	nodeAffinityMatches = NodeMatchesNodeSelectorTerms(node, nodeSelectorTerms) </del> <ins> // 	nodeAffinityMatches = nodeMatchesNodeSelectorTerms(node, nodeSelectorTerms) </ins> // } // Match node selector for requiredDuringSchedulingIgnoredDuringExecution. if nodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution != nil { nodeSelectorTerms := nodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms glog.V(10).Infof("Match for RequiredDuringSchedulingIgnoredDuringExecution node selector terms %+v", nodeSelectorTerms) <del> nodeAffinityMatches = nodeAffinityMatches && NodeMatchesNodeSelectorTerms(node, nodeSelectorTerms) </del> <ins> nodeAffinityMatches = nodeAffinityMatches && nodeMatchesNodeSelectorTerms(node, nodeSelectorTerms) </ins> } }

import ( "fmt" <ins> "os/exec" </ins> "reflect" "testing" "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/resource" <ins> "k8s.io/kubernetes/pkg/util/codeinspector" </ins> "k8s.io/kubernetes/plugin/pkg/scheduler/algorithm" "k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache" )

} } } <ins> func TestPredicatesRegistered(t *testing.T) { var functionNames []string // Files and directories which predicates may be referenced targetFiles := []string{ "./../../algorithmprovider/defaults/defaults.go", // Default algorithm "./../../factory/plugins.go",                     // Registered in init() "./../../../../../pkg/",                          // kubernetes/pkg, often used by kubelet or controller } // List all golang source files under ./predicates/, excluding test files and sub-directories. files, err := codeinspector.GetSourceCodeFiles(".") if err != nil { t.Errorf("unexpected error: %v when listing files in current directory", err) } // Get all public predicates in files. for _, filePath := range files { functions, err := codeinspector.GetPublicFunctions(filePath) if err == nil { functionNames = append(functionNames, functions...) } else { t.Errorf("unexpected error when parsing %s", filePath) } } // Check if all public predicates are referenced in target files. for _, functionName := range functionNames { args := []string{"-rl", functionName} args = append(args, targetFiles...) err := exec.Command("grep", args...).Run() if err != nil { switch err.Error() { case "exit status 2": t.Errorf("unexpected error when checking %s", functionName) case "exit status 1": t.Errorf("predicate %s is implemented as public but seems not registered or used in any other place", functionName) } } } } </ins>

package priorities import ( <ins> "os/exec" </ins> "reflect" "sort" "strconv"

"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/resource" "k8s.io/kubernetes/pkg/apis/extensions" <ins> "k8s.io/kubernetes/pkg/util/codeinspector" </ins> "k8s.io/kubernetes/plugin/pkg/scheduler" "k8s.io/kubernetes/plugin/pkg/scheduler/algorithm" priorityutil "k8s.io/kubernetes/plugin/pkg/scheduler/algorithm/priorities/util"

Status:     status, } } <ins> func TestPrioritiesRegistered(t *testing.T) { var functionNames []string // Files and directories which priorities may be referenced targetFiles := []string{ "./../../algorithmprovider/defaults/defaults.go", // Default algorithm "./../../factory/plugins.go",                     // Registered in init() } // List all golang source files under ./priorities/, excluding test files and sub-directories. files, err := codeinspector.GetSourceCodeFiles(".") if err != nil { t.Errorf("unexpected error: %v when listing files in current directory", err) } // Get all public priorities in files. for _, filePath := range files { functions, err := codeinspector.GetPublicFunctions(filePath) if err == nil { functionNames = append(functionNames, functions...) } else { t.Errorf("unexpected error when parsing %s", filePath) } } // Check if all public priorities are referenced in target files. for _, functionName := range functionNames { args := []string{"-rl", functionName} args = append(args, targetFiles...) err := exec.Command("grep", args...).Run() if err != nil { switch err.Error() { case "exit status 2": t.Errorf("unexpected error when checking %s", functionName) case "exit status 1": t.Errorf("priority %s is implemented as public but seems not registered or used in any other place", functionName) } } } } </ins>