mirror of
https://github.com/shadow1ng/fscan.git
synced 2026-09-22 03:10:42 +08:00
169 lines
4.3 KiB
Go
169 lines
4.3 KiB
Go
package parsers
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"os"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestHostIteratorCIDRBatch(t *testing.T) {
|
|
iter, err := NewHostIterator("192.168.1.0/30", "", "")
|
|
if err != nil {
|
|
t.Fatalf("NewHostIterator error = %v", err)
|
|
}
|
|
defer iter.Close()
|
|
|
|
batch, err := iter.NextBatch(context.Background(), 10)
|
|
if err != nil {
|
|
t.Fatalf("NextBatch error = %v", err)
|
|
}
|
|
|
|
want := []string{"192.168.1.1", "192.168.1.2"}
|
|
if !reflect.DeepEqual(batch, want) {
|
|
t.Fatalf("batch = %#v, want %#v", batch, want)
|
|
}
|
|
}
|
|
|
|
func TestHostIteratorDoesNotExpandWholeRangeAtOnce(t *testing.T) {
|
|
iter, err := NewHostIterator("10", "", "")
|
|
if err != nil {
|
|
t.Fatalf("NewHostIterator error = %v", err)
|
|
}
|
|
defer iter.Close()
|
|
|
|
batch, err := iter.NextBatch(context.Background(), 3)
|
|
if err != nil {
|
|
t.Fatalf("NextBatch error = %v", err)
|
|
}
|
|
|
|
want := []string{"10.0.0.1", "10.0.0.2", "10.0.0.3"}
|
|
if !reflect.DeepEqual(batch, want) {
|
|
t.Fatalf("batch = %#v, want %#v", batch, want)
|
|
}
|
|
}
|
|
|
|
func TestHostIteratorExcludeCIDR(t *testing.T) {
|
|
iter, err := NewHostIterator("192.168.1.0/29", "", "192.168.1.2-192.168.1.4")
|
|
if err != nil {
|
|
t.Fatalf("NewHostIterator error = %v", err)
|
|
}
|
|
defer iter.Close()
|
|
|
|
batch, err := iter.NextBatch(context.Background(), 10)
|
|
if err != nil {
|
|
t.Fatalf("NextBatch error = %v", err)
|
|
}
|
|
|
|
want := []string{"192.168.1.1", "192.168.1.5", "192.168.1.6"}
|
|
if !reflect.DeepEqual(batch, want) {
|
|
t.Fatalf("batch = %#v, want %#v", batch, want)
|
|
}
|
|
}
|
|
|
|
func TestHostIteratorAcceptsMultipleExcludeSources(t *testing.T) {
|
|
iter, err := NewHostIterator("192.168.1.0/29", "", "192.168.1.2", "192.168.1.5")
|
|
if err != nil {
|
|
t.Fatalf("NewHostIterator error = %v", err)
|
|
}
|
|
defer iter.Close()
|
|
|
|
batch, err := iter.NextBatch(context.Background(), 10)
|
|
if err != nil {
|
|
t.Fatalf("NextBatch error = %v", err)
|
|
}
|
|
|
|
want := []string{"192.168.1.1", "192.168.1.3", "192.168.1.4", "192.168.1.6"}
|
|
if !reflect.DeepEqual(batch, want) {
|
|
t.Fatalf("batch = %#v, want %#v", batch, want)
|
|
}
|
|
}
|
|
|
|
func TestHostIteratorReadsLongHostFileLine(t *testing.T) {
|
|
dir := t.TempDir()
|
|
path := dir + "/hosts.txt"
|
|
longPrefix := strings.Repeat("a", 70*1024)
|
|
host := longPrefix + ".example.com"
|
|
if err := os.WriteFile(path, []byte(host+"\n"), 0o600); err != nil {
|
|
t.Fatalf("WriteFile error = %v", err)
|
|
}
|
|
|
|
iter, err := NewHostIterator("", path)
|
|
if err != nil {
|
|
t.Fatalf("NewHostIterator error = %v", err)
|
|
}
|
|
defer iter.Close()
|
|
|
|
batch, err := iter.NextBatch(context.Background(), 1)
|
|
if err != nil {
|
|
t.Fatalf("NextBatch error = %v", err)
|
|
}
|
|
if !reflect.DeepEqual(batch, []string{host}) {
|
|
t.Fatalf("batch = %#v, want long host", batch)
|
|
}
|
|
}
|
|
|
|
func TestMultiHostSourceAndMatcherCIDR(t *testing.T) {
|
|
src := &multiHostSource{sources: []hostSource{
|
|
&singleHostSource{host: "192.168.1.1"},
|
|
&singleHostSource{host: "192.168.1.2"},
|
|
}}
|
|
|
|
host, ok, err := src.Next()
|
|
if err != nil || !ok || host != "192.168.1.1" {
|
|
t.Fatalf("first Next = %q/%v/%v", host, ok, err)
|
|
}
|
|
host, ok, err = src.Next()
|
|
if err != nil || !ok || host != "192.168.1.2" {
|
|
t.Fatalf("second Next = %q/%v/%v", host, ok, err)
|
|
}
|
|
host, ok, err = src.Next()
|
|
if err != nil || ok || host != "" {
|
|
t.Fatalf("exhausted Next = %q/%v/%v", host, ok, err)
|
|
}
|
|
if err := src.Close(); err != nil {
|
|
t.Fatalf("Close error = %v", err)
|
|
}
|
|
|
|
matcher := newHostMatcher()
|
|
if err := matcher.add("192.168.1.0/30,example.com"); err != nil {
|
|
t.Fatalf("matcher add error = %v", err)
|
|
}
|
|
if !matcher.match("192.168.1.1") || !matcher.match("192.168.1.2") || !matcher.match("example.com") {
|
|
t.Fatal("matcher should match CIDR hosts and exact host")
|
|
}
|
|
if matcher.match("192.168.1.3") || matcher.match("nope.example") {
|
|
t.Fatal("matcher matched hosts outside its rules")
|
|
}
|
|
if err := matcher.add("2001:db8::/126"); err == nil {
|
|
t.Fatal("IPv6 CIDR should be rejected by IPv4-only matcher")
|
|
}
|
|
}
|
|
|
|
func TestCloseHostSourcesIgnoresCloseErrors(t *testing.T) {
|
|
first := &closeTrackingSource{err: errors.New("close failed")}
|
|
second := &closeTrackingSource{}
|
|
|
|
closeHostSources([]hostSource{first, second})
|
|
|
|
if !first.closed || !second.closed {
|
|
t.Fatalf("sources closed = %v/%v, want both true", first.closed, second.closed)
|
|
}
|
|
}
|
|
|
|
type closeTrackingSource struct {
|
|
closed bool
|
|
err error
|
|
}
|
|
|
|
func (s *closeTrackingSource) Next() (string, bool, error) {
|
|
return "", false, nil
|
|
}
|
|
|
|
func (s *closeTrackingSource) Close() error {
|
|
s.closed = true
|
|
return s.err
|
|
}
|