Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
projectdiscovery
GitHub Repository: projectdiscovery/nuclei
Path: blob/dev/cmd/functional-test/main.go
2070 views
1
package main
2
3
import (
4
"bufio"
5
"flag"
6
"fmt"
7
"log"
8
"os"
9
"strings"
10
11
"github.com/kitabisa/go-ci"
12
"github.com/logrusorgru/aurora"
13
"github.com/pkg/errors"
14
15
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
16
)
17
18
var (
19
success = aurora.Green("[✓]").String()
20
failed = aurora.Red("[✘]").String()
21
22
mainNucleiBinary = flag.String("main", "", "Main Branch Nuclei Binary")
23
devNucleiBinary = flag.String("dev", "", "Dev Branch Nuclei Binary")
24
testcases = flag.String("testcases", "", "Test cases file for nuclei functional tests")
25
)
26
27
func main() {
28
flag.Parse()
29
30
debug := os.Getenv("DEBUG") == "true" || os.Getenv("RUNNER_DEBUG") == "1"
31
32
if err, errored := runFunctionalTests(debug); err != nil {
33
log.Fatalf("Could not run functional tests: %s\n", err)
34
} else if errored {
35
os.Exit(1)
36
}
37
}
38
39
func runFunctionalTests(debug bool) (error, bool) {
40
file, err := os.Open(*testcases)
41
if err != nil {
42
return errors.Wrap(err, "could not open test cases"), true
43
}
44
defer func() {
45
_ = file.Close()
46
}()
47
48
errored, failedTestCases := runTestCases(file, debug)
49
50
if ci.IsCI() {
51
fmt.Println("::group::Failed tests with debug")
52
for _, failedTestCase := range failedTestCases {
53
_ = runTestCase(failedTestCase, true)
54
}
55
fmt.Println("::endgroup::")
56
}
57
58
return nil, errored
59
}
60
61
func runTestCases(file *os.File, debug bool) (bool, []string) {
62
errored := false
63
var failedTestCases []string
64
65
scanner := bufio.NewScanner(file)
66
for scanner.Scan() {
67
testCase := strings.TrimSpace(scanner.Text())
68
if testCase == "" {
69
continue
70
}
71
// skip comments
72
if strings.HasPrefix(testCase, "#") {
73
continue
74
}
75
if runTestCase(testCase, debug) {
76
errored = true
77
failedTestCases = append(failedTestCases, testCase)
78
}
79
}
80
return errored, failedTestCases
81
}
82
83
func runTestCase(testCase string, debug bool) bool {
84
if err := runIndividualTestCase(testCase, debug); err != nil {
85
fmt.Fprintf(os.Stderr, "%s Test \"%s\" failed: %s\n", failed, testCase, err)
86
return true
87
} else {
88
fmt.Printf("%s Test \"%s\" passed!\n", success, testCase)
89
}
90
return false
91
}
92
93
func runIndividualTestCase(testcase string, debug bool) error {
94
quoted := false
95
96
// split upon unquoted spaces
97
parts := strings.FieldsFunc(testcase, func(r rune) bool {
98
if r == '"' {
99
quoted = !quoted
100
}
101
return !quoted && r == ' '
102
})
103
104
// Quoted strings containing spaces are expressions and must have trailing \" removed
105
for index, part := range parts {
106
if strings.Contains(part, " ") {
107
parts[index] = strings.Trim(part, "\"")
108
}
109
}
110
111
var finalArgs []string
112
if len(parts) > 1 {
113
finalArgs = parts[1:]
114
}
115
mainOutput, err := testutils.RunNucleiBinaryAndGetLoadedTemplates(*mainNucleiBinary, debug, finalArgs)
116
if err != nil {
117
return errors.Wrap(err, "could not run nuclei main test")
118
}
119
devOutput, err := testutils.RunNucleiBinaryAndGetLoadedTemplates(*devNucleiBinary, debug, finalArgs)
120
if err != nil {
121
return errors.Wrap(err, "could not run nuclei dev test")
122
}
123
if mainOutput == devOutput {
124
return nil
125
}
126
return fmt.Errorf("%s main is not equal to %s dev", mainOutput, devOutput)
127
}
128
129