Skip to content
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
28 changes: 27 additions & 1 deletion cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,30 @@ import (
"sync"
)

// NewApp builds the proxycheck CLI application. It is shared by the cmd binary
// and the tests so both exercise the same flag wiring.
func NewApp() *cli.App {
return &cli.App{
Name: "proxycheck",
Description: "Proxy checker tool",
Version: "0.0.5",
Flags: []cli.Flag{
&cli.StringFlag{Name: "judge", Usage: "Set judge", Value: "proxyjudge.us"},
&cli.IntFlag{Name: "threads", Usage: "Count of threads", Value: 10},
},
Action: Action,
}
}

func Action(c *cli.Context) error {

// Resolve the judge from the --judge flag before doing any work; an unknown
// name aborts here, so no proxy is checked.
judge, err := ResolveJudge(c.String("judge"))
if err != nil {
return err
}

// If pass args, use it or read stdin as input file with proxies
var feed Feed

Expand All @@ -28,7 +50,7 @@ func Action(c *cli.Context) error {
go func(proxyAddrs chan string) {
defer wg.Done()
for proxyAddr := range proxyAddrs {
if res := Check(proxyAddr, &AZEnvPhpJudge{}); res.Online {
if res := Check(proxyAddr, judge); res.Online {
fmt.Printf("%s\t%s\t%s\n", proxyAddr, strings.Join(res.Protocols, ","), res.Speed.String())
} else {
fmt.Fprintf(os.Stderr, "invalid proxy %s: %v\n", proxyAddr, res.Err)
Expand All @@ -47,6 +69,10 @@ func Action(c *cli.Context) error {
proxyAddrs <- proxyAddr
}

// Closing the channel lets the workers' range loops finish so wg.Wait
// returns once the feed is exhausted.
close(proxyAddrs)

wg.Wait()
return nil
}
18 changes: 18 additions & 0 deletions cli_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package proxycheck

import (
"testing"

"github.com/stretchr/testify/assert"
)

// TestApp_UnknownJudge is the regression test for the --judge flag: an unknown
// judge name must abort with an error before any proxy is checked. A deliberately
// unparsable address keeps the run off the network if the guard is missing.
func TestApp_UnknownJudge(t *testing.T) {
err := NewApp().Run([]string{"proxycheck", "--judge", "foo", "not-an-addr"})
assert.Error(t, err, "unknown judge must cause a non-nil error")
if err != nil {
assert.Contains(t, err.Error(), "unknown judge: foo")
}
}
12 changes: 1 addition & 11 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,10 @@ import (
"os"

"github.com/memclutter/proxycheck"
cli "github.com/urfave/cli/v2"
)

func main() {
if err := (&cli.App{
Name: "proxycheck",
Description: "Proxy checker tool",
Version: "0.0.5",
Flags: []cli.Flag{
&cli.StringFlag{Name: "judge", Usage: "Set judge", Value: "proxyjudge.us"},
&cli.IntFlag{Name: "threads", Usage: "Count of threads", Value: 10},
},
Action: proxycheck.Action,
}).Run(os.Args); err != nil {
if err := proxycheck.NewApp().Run(os.Args); err != nil {
log.Fatalf("app run failed: %s", err)
}
}
28 changes: 27 additions & 1 deletion judges.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package proxycheck

import "time"
import (
"fmt"
"sort"
"strings"
"time"
)

type AZEnvPhpJudge struct{}

Expand All @@ -16,3 +21,24 @@ var Judges = map[string]Judge{
"azenv.php": AZEnvPhpJudge{},
"proxyjudge.us": ProxyjudgeUsJudge{},
}

// ResolveJudge returns the Judge registered under name. An unknown name yields
// an error that lists the available judge names.
func ResolveJudge(name string) (Judge, error) {
judge, ok := Judges[name]
if !ok {
return nil, fmt.Errorf("unknown judge: %s (available: %s)", name, judgeNames())
}
return judge, nil
}

// judgeNames returns the registered judge names, sorted and comma-joined, so
// error messages are deterministic.
func judgeNames() string {
names := make([]string, 0, len(Judges))
for name := range Judges {
names = append(names, name)
}
sort.Strings(names)
return strings.Join(names, ", ")
}
28 changes: 27 additions & 1 deletion judges_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,37 @@
package proxycheck

import (
"github.com/stretchr/testify/assert"
"net/url"
"testing"

"github.com/stretchr/testify/assert"
)

func TestResolveJudge(t *testing.T) {
t.Run("azenv.php resolves", func(t *testing.T) {
judge, err := ResolveJudge("azenv.php")
assert.NoError(t, err)
assert.IsType(t, AZEnvPhpJudge{}, judge)
})

t.Run("proxyjudge.us resolves", func(t *testing.T) {
judge, err := ResolveJudge("proxyjudge.us")
assert.NoError(t, err)
assert.IsType(t, ProxyjudgeUsJudge{}, judge)
})

t.Run("unknown name errors", func(t *testing.T) {
judge, err := ResolveJudge("foo")
assert.Nil(t, judge)
assert.Error(t, err)
if err != nil {
assert.Contains(t, err.Error(), "unknown judge: foo")
assert.Contains(t, err.Error(), "azenv.php")
assert.Contains(t, err.Error(), "proxyjudge.us")
}
})
}

func TestJudge_TargetURL(t *testing.T) {
testingTable := []struct {
title string
Expand Down
Loading