/* Copyright 2016 The Kubernetes Authors. 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 main import ( "fmt" "reflect" "testing" ) func TestConformance(t *testing.T) { for _, tc := range []struct { desc string filename string code string targetFrame frame output *ConformanceData }{ { desc: "Grabs comment above test", filename: "test/list/main_test.go", code: `package test var num = 3 func Helper(x int) { return x / 0 } var _ = Describe("Feature", func() { /* Testname: Kubelet-OutputToLogs Description: By default the stdout and stderr from the process being executed in a pod MUST be sent to the pod's logs. */ framework.ConformanceIt("validates describe with ConformanceIt", func() {}) })`, output: &ConformanceData{ URL: "https://github.com/kubernetes/kubernetes/tree/master/test/list/main_test.go#L11", TestName: "Kubelet-OutputToLogs", Description: `By default the stdout and stderr from the process being executed in a pod MUST be sent to the pod's logs.`, File: "test/list/main_test.go", }, targetFrame: frame{File: "test/list/main_test.go", Line: 11}, }, { desc: "Handles extra spaces", filename: "e2e/foo.go", code: `package test var _ = SIGDescribe("Feature", func() { Context("with context and extra spaces before It block should still pick up Testname", func() { // Testname: Test with spaces //Description: Should pick up testname even if it is not within 3 spaces //even when executed from memory. framework.ConformanceIt("should work", func() {}) }) })`, output: &ConformanceData{ URL: "https://github.com/kubernetes/kubernetes/tree/master/e2e/foo.go#L8", TestName: "Test with spaces", Description: `Should pick up testname even if it is not within 3 spaces even when executed from memory.`, File: "e2e/foo.go", }, targetFrame: frame{File: "e2e/foo.go", Line: 8}, }, { desc: "Should target the correct comment based on the line numbers (second)", filename: "e2e/foo.go", code: `package test var _ = SIGDescribe("Feature", func() { Context("with context and extra spaces before It block should still pick up Testname", func() { // Testname: First test // Description: Should pick up testname even if it is not within 3 spaces // even when executed from memory. framework.ConformanceIt("should work", func() {}) // Testname: Second test // Description: Should target the correct test/comment based on the line numbers framework.ConformanceIt("should work", func() {}) }) })`, output: &ConformanceData{ URL: "https://github.com/kubernetes/kubernetes/tree/master/e2e/foo.go#L13", TestName: "Second test", Description: `Should target the correct test/comment based on the line numbers`, File: "e2e/foo.go", }, targetFrame: frame{File: "e2e/foo.go", Line: 13}, }, { desc: "Should target the correct comment based on the line numbers (first)", filename: "e2e/foo.go", code: `package test var _ = SIGDescribe("Feature", func() { Context("with context and extra spaces before It block should still pick up Testname", func() { // Testname: First test // Description: Should target the correct test/comment based on the line numbers framework.ConformanceIt("should work", func() {}) // Testname: Second test // Description: Should target the correct test/comment based on the line numbers framework.ConformanceIt("should work", func() {}) }) })`, output: &ConformanceData{ URL: "https://github.com/kubernetes/kubernetes/tree/master/e2e/foo.go#L8", TestName: "First test", Description: `Should target the correct test/comment based on the line numbers`, File: "e2e/foo.go", }, targetFrame: frame{File: "e2e/foo.go", Line: 8}, }, } { t.Run(tc.desc, func(t *testing.T) { *confDoc = true cd, err := scanFileForFrame(tc.filename, tc.code, tc.targetFrame) if err != nil { panic(err) } if !reflect.DeepEqual(cd, tc.output) { t.Errorf("code:\n%s\ngot %+v\nwant %+v", tc.code, cd, tc.output) } }) } } func TestCommentToConformanceData(t *testing.T) { tcs := []struct { desc string input string expected *ConformanceData }{ { desc: "Empty comment leads to nil", }, { desc: "No Release or Testname leads to nil", input: "Description: foo", }, { desc: "Release but no Testname should result in nil", input: "Release: v1.1\nDescription: foo", }, { desc: "Testname but no Release does not result in nil", input: "Testname: mytest\nDescription: foo", expected: &ConformanceData{TestName: "mytest", Description: "foo"}, }, { desc: "All fields parsed and newlines and whitespace removed from description", input: "Release: v1.1\n\t\tTestname: mytest\n\t\tDescription: foo\n\t\tbar\ndone", expected: &ConformanceData{TestName: "mytest", Release: "v1.1", Description: "foo bar done"}, }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { out := commentToConformanceData(tc.input) if !reflect.DeepEqual(out, tc.expected) { t.Errorf("Expected %#v but got %#v", tc.expected, out) } }) } } func TestValidateTestName(t *testing.T) { testCases := []struct { testName string tagString string }{ { "a test case with no tags", "", }, { "a test case with valid tags [LinuxOnly] [NodeConformance] [Serial] [Disruptive]", "", }, { "a flaky test case that is invalid [Flaky]", "[Flaky]", }, { "a feature test case that is invalid [Feature:Awesome]", "[Feature:Awesome]", }, { "an alpha test case that is invalid [Alpha]", "[Alpha]", }, { "a test case with multiple invalid tags [Flaky] [Feature:Awesome] [Alpha]", "[Flaky],[Feature:Awesome],[Alpha]", }, { "[sig-awesome] [Alpha] [Disruptive] a test case with valid and invalid tags [Serial] [Flaky]", "[Alpha],[Flaky]", }, } for i, tc := range testCases { err := validateTestName(tc.testName) if err != nil { if tc.tagString == "" { t.Errorf("test case[%d]: expected no validate error, got %q", i, err.Error()) } else { expectedMsg := fmt.Sprintf("'%s' cannot have invalid tags %s", tc.testName, tc.tagString) actualMsg := err.Error() if actualMsg != expectedMsg { t.Errorf("test case[%d]: expected error message %q, got %q", i, expectedMsg, actualMsg) } } } } }