Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Functional test #436

Merged
merged 6 commits into from
Nov 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .github/workflows/functional-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: 🧪 Functional Test
on:
push:
pull_request:
workflow_dispatch:


jobs:
functional:
name: Functional Test
runs-on: ubuntu-latest
steps:
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.17

- name: Check out code
uses: actions/checkout@v2

- name: Functional Tests
run: |
chmod +x run.sh
bash run.sh
working-directory: cmd/functional-test
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@

cmd/httpx/httpx
integration_tests/httpx
integration_tests/integration-test
integration_tests/integration-test
cmd/functional-test/httpx_dev
cmd/functional-test/functional-test
cmd/functional-test/httpx
cmd/functional-test/*.cfg

83 changes: 83 additions & 0 deletions cmd/functional-test/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package main

import (
"bufio"
"flag"
"fmt"
"log"
"os"
"strings"

"github.com/logrusorgru/aurora"
"github.com/pkg/errors"

"github.com/projectdiscovery/httpx/internal/testutils"
)

var (
debug = os.Getenv("DEBUG") == "true"
success = aurora.Green("[✓]").String()
failed = aurora.Red("[✘]").String()
errored = false

mainHttpxBinary = flag.String("main", "", "Main Branch Httpx Binary")
devHttpxBinary = flag.String("dev", "", "Dev Branch Httpx Binary")
testcases = flag.String("testcases", "", "Test cases file for Httpx functional tests")
)

func main() {
flag.Parse()

if err := runFunctionalTests(); err != nil {
log.Fatalf("Could not run functional tests: %s\n", err)
}
if errored {
os.Exit(1)
}
}

func runFunctionalTests() error {
file, err := os.Open(*testcases)
if err != nil {
return errors.Wrap(err, "could not open test cases")
}
defer file.Close()

scanner := bufio.NewScanner(file)
for scanner.Scan() {
text := strings.TrimSpace(scanner.Text())
if text == "" {
continue
}
if err := runIndividualTestCase(text); err != nil {
errored = true
fmt.Fprintf(os.Stderr, "%s Test \"%s\" failed: %s\n", failed, text, err)
} else {
fmt.Printf("%s Test \"%s\" passed!\n", success, text)
}
}
return nil
}

func runIndividualTestCase(testcase string) error {
parts := strings.Fields(testcase)

var finalArgs []string
var target string
if len(parts) > 1 {
finalArgs = parts[2:]
target = parts[0]
}
mainOutput, err := testutils.RunHttpxBinaryAndGetResults(target, *mainHttpxBinary, debug, finalArgs)
if err != nil {
return errors.Wrap(err, "could not run httpx main test")
}
devOutput, err := testutils.RunHttpxBinaryAndGetResults(target, *devHttpxBinary, debug, finalArgs)
if err != nil {
return errors.Wrap(err, "could not run httpx dev test")
}
if len(mainOutput) == len(devOutput) {
return nil
}
return fmt.Errorf("%s main is not equal to %s dev", mainOutput, devOutput)
}
13 changes: 13 additions & 0 deletions cmd/functional-test/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/bash

echo 'Building functional-test binary'
go build

echo 'Building HTTPX binary from current branch'
go build -o httpx_dev ../httpx

echo 'Installing latest release of HTTPX'
GO111MODULE=on go build -v github.com/projectdiscovery/httpx/cmd/httpx

echo 'Starting HTTPX functional test'
./functional-test -main ./httpx -dev ./httpx_dev -testcases testcases.txt
1 change: 1 addition & 0 deletions cmd/functional-test/test-data/raw-request.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
GET /search?q=test HTTP/2
1 change: 1 addition & 0 deletions cmd/functional-test/test-data/request.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
https://www.example.com
16 changes: 16 additions & 0 deletions cmd/functional-test/testcases.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
www.example.com {{binary}} -silent
www.example.com {{binary}} -silent -l test-data/request.txt
www.example.com {{binary}} -silent -request test-data/raw-request.txt
www.example.com {{binary}} -silent -title
www.example.com {{binary}} -silent -sc
www.example.com {{binary}} -silent -td
www.example.com {{binary}} -silent -probe
www.example.com {{binary}} -silent -no-fallback
www.example.com {{binary}} -silent -cl
www.example.com {{binary}} -silent -server
www.example.com {{binary}} -silent -ip
www.example.com {{binary}} -silent -tls-grab
www.example.com {{binary}} -silent -unsafe
www.example.com {{binary}} -silent -x all
www.example.com {{binary}} -silent -body 'a=b'
www.example.com {{binary}} -silent -exclude-cdn
26 changes: 26 additions & 0 deletions internal/testutils/integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"os"
"os/exec"
"strings"
"fmt"
)

// RunNucleiAndGetResults returns a list of results for a template
Expand Down Expand Up @@ -33,6 +34,31 @@ func RunHttpxAndGetResults(url string, debug bool, extra ...string) ([]string, e
}
return parts, nil
}
func RunHttpxBinaryAndGetResults(target string, httpxBinary string, debug bool, args []string) ([]string, error) {
cmd := exec.Command("bash", "-c")
cmdLine := fmt.Sprintf(`echo %s | %s `, target, httpxBinary)
cmdLine += strings.Join(args, " ")
if debug {
cmdLine += " -debug"
cmd.Stderr = os.Stderr
} else {
cmdLine += " -silent"
}

cmd.Args = append(cmd.Args, cmdLine)
data, err := cmd.Output()
if err != nil {
return nil, err
}
parts := []string{}
items := strings.Split(string(data), "\n")
for _, i := range items {
if i != "" {
parts = append(parts, i)
}
}
return parts,nil
}

// TestCase is a single integration test case
type TestCase interface {
Expand Down