test(gopher): add resume coverage for typeInformation
This commit is contained in:
@@ -494,3 +494,103 @@ func TestGopherResumeIgnoredWhenWriterSet(t *testing.T) {
|
||||
t.Error("Output file should not be created when Writer is set")
|
||||
}
|
||||
}
|
||||
|
||||
// TestGopherResumeInformation verifies that resume machinery works for the
|
||||
// informational (type i) response path, which is also routed through
|
||||
// downloadText. Informational lines are passed through verbatim (no
|
||||
// metadata strip), so the resume offset matches the raw line length
|
||||
// including trailing CR/LF.
|
||||
func TestGopherResumeInformation(t *testing.T) {
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer listener.Close()
|
||||
port := listener.Addr().(*net.TCPAddr).Port
|
||||
|
||||
cancelReady := make(chan struct{})
|
||||
connReady := make(chan struct{})
|
||||
go func() {
|
||||
for i := 0; i < 2; i++ {
|
||||
conn, lerr := listener.Accept()
|
||||
if lerr != nil {
|
||||
return
|
||||
}
|
||||
r := bufio.NewReader(conn)
|
||||
r.ReadString('\n')
|
||||
if i == 0 {
|
||||
// First half: send two info lines, then wait
|
||||
// for the client to cancel before closing.
|
||||
conn.Write([]byte("iFirst line.\r\n"))
|
||||
conn.Write([]byte("iSecond line.\r\n"))
|
||||
<-cancelReady
|
||||
conn.Close()
|
||||
connReady <- struct{}{}
|
||||
} else {
|
||||
// Second half: full body.
|
||||
conn.Write([]byte("iFirst line.\r\n"))
|
||||
conn.Write([]byte("iSecond line.\r\n"))
|
||||
conn.Write([]byte(".\r\n"))
|
||||
conn.Close()
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
tmp := t.TempDir()
|
||||
outPath := tmp + "/info.txt"
|
||||
|
||||
proto := NewProtocol()
|
||||
u, _ := url.Parse("gopher://127.0.0.1:" + strconv.Itoa(port) + "/info")
|
||||
|
||||
progress := make(chan int64, 1)
|
||||
ctx1, cancel1 := context.WithCancel(context.Background())
|
||||
errCh := make(chan error, 1)
|
||||
go func() {
|
||||
_, dlErr := proto.Download(ctx1, &core.DownloadRequest{
|
||||
URL: u,
|
||||
Output: outPath,
|
||||
ProgressCallback: func(current, total int64, speed float64) {
|
||||
select {
|
||||
case progress <- current:
|
||||
default:
|
||||
}
|
||||
},
|
||||
})
|
||||
errCh <- dlErr
|
||||
}()
|
||||
<-progress
|
||||
cancel1()
|
||||
cancelReady <- struct{}{}
|
||||
<-connReady
|
||||
if dlErr := <-errCh; dlErr == nil {
|
||||
t.Fatal("expected error from cancelled context")
|
||||
}
|
||||
|
||||
// Resume should append the missing bytes. For informational lines
|
||||
// we do not strip metadata, so the output preserves the server CR/LF.
|
||||
result, resErr := proto.Download(context.Background(), &core.DownloadRequest{
|
||||
URL: u,
|
||||
Output: outPath,
|
||||
Resume: true,
|
||||
})
|
||||
if resErr != nil {
|
||||
t.Fatalf("resume download failed: %v", resErr)
|
||||
}
|
||||
if !result.Resumed {
|
||||
t.Error("expected Resumed=true")
|
||||
}
|
||||
if result.ContentType != "text/plain" {
|
||||
t.Errorf("ContentType = %q, want text/plain", result.ContentType)
|
||||
}
|
||||
|
||||
data, _ := os.ReadFile(outPath)
|
||||
// Informational lines are passed through verbatim: the 'i' item-type
|
||||
// prefix and CR/LF framing from the server survive into the output.
|
||||
want := "iFirst line.\r\niSecond line.\r\n"
|
||||
if string(data) != want {
|
||||
t.Errorf("content = %q, want %q", string(data), want)
|
||||
}
|
||||
if output.FileExists(outPath + output.ResumeMetaFileSuffix) {
|
||||
t.Error("expected .goget.meta to be deleted after successful resume")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user