diff options
Diffstat (limited to 'protocol/v0v1/server/receivepack/parse_test.go')
| -rw-r--r-- | protocol/v0v1/server/receivepack/parse_test.go | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/protocol/v0v1/server/receivepack/parse_test.go b/protocol/v0v1/server/receivepack/parse_test.go new file mode 100644 index 00000000..f304ac44 --- /dev/null +++ b/protocol/v0v1/server/receivepack/parse_test.go @@ -0,0 +1,255 @@ +package receivepack_test + +import ( + "errors" + "strings" + "testing" + + "codeberg.org/lindenii/furgit/format/pktline" + "codeberg.org/lindenii/furgit/internal/testgit" + "codeberg.org/lindenii/furgit/objectid" + common "codeberg.org/lindenii/furgit/protocol/v0v1/server" + receivepack "codeberg.org/lindenii/furgit/protocol/v0v1/server/receivepack" +) + +func TestReadRequestParsesCommandsAndPushOptions(t *testing.T) { + t.Parallel() + + //nolint:thelper + testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { + t.Parallel() + + oldZero := objectid.Zero(algo).String() + oneID := mustHexID(t, algo, "1") + + var wire bufferWriteFlusher + + enc := pktline.NewEncoder(&wire) + + err := enc.WriteData([]byte( + oldZero + " " + oneID.String() + " refs/heads/main\x00report-status push-options object-format=" + algo.String() + "\n", + )) + if err != nil { + t.Fatalf("WriteData(first): %v", err) + } + + err = enc.WriteData([]byte( + oneID.String() + " " + oldZero + " refs/heads/old\n", + )) + if err != nil { + t.Fatalf("WriteData(second): %v", err) + } + + err = enc.WriteFlush() + if err != nil { + t.Fatalf("WriteFlush(commands): %v", err) + } + + err = enc.WriteData([]byte("ci.skip\n")) + if err != nil { + t.Fatalf("WriteData(push-option): %v", err) + } + + err = enc.WriteFlush() + if err != nil { + t.Fatalf("WriteFlush(push-options): %v", err) + } + + base := common.NewSession(strings.NewReader(wire.String()), &bufferWriteFlusher{}, common.Options{ + Algorithm: algo, + }) + session := receivepack.NewSession(base, receivepack.Capabilities{ + ReportStatus: true, + PushOptions: true, + ObjectFormat: algo, + }) + + req, err := session.ReadRequest() + if err != nil { + t.Fatalf("ReadRequest: %v", err) + } + + if len(req.Commands) != 2 { + t.Fatalf("len(req.Commands) = %d, want 2", len(req.Commands)) + } + + if !req.Capabilities.ReportStatus || !req.Capabilities.PushOptions { + t.Fatalf("capabilities = %#v", req.Capabilities) + } + + if len(req.PushOptions) != 1 || req.PushOptions[0] != "ci.skip" { + t.Fatalf("push options = %#v", req.PushOptions) + } + + if !req.PackExpected { + t.Fatalf("PackExpected = false, want true") + } + + if req.DeleteOnly { + t.Fatalf("DeleteOnly = true, want false") + } + }) +} + +func TestReadRequestDeleteOnlyDoesNotExpectPack(t *testing.T) { + t.Parallel() + + //nolint:thelper + testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { + t.Parallel() + + oneID := mustHexID(t, algo, "1") + + var wire bufferWriteFlusher + + enc := pktline.NewEncoder(&wire) + + err := enc.WriteData([]byte( + oneID.String() + " " + objectid.Zero(algo).String() + " refs/heads/old\x00delete-refs object-format=" + algo.String() + "\n", + )) + if err != nil { + t.Fatalf("WriteData: %v", err) + } + + err = enc.WriteFlush() + if err != nil { + t.Fatalf("WriteFlush: %v", err) + } + + base := common.NewSession(strings.NewReader(wire.String()), &bufferWriteFlusher{}, common.Options{ + Algorithm: algo, + }) + session := receivepack.NewSession(base, receivepack.Capabilities{ + DeleteRefs: true, + ObjectFormat: algo, + }) + + req, err := session.ReadRequest() + if err != nil { + t.Fatalf("ReadRequest: %v", err) + } + + if req.PackExpected { + t.Fatalf("PackExpected = true, want false") + } + + if !req.DeleteOnly { + t.Fatalf("DeleteOnly = false, want true") + } + }) +} + +func TestReadRequestRejectsUnsupportedCapability(t *testing.T) { + t.Parallel() + + //nolint:thelper + testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { + t.Parallel() + + oneID := mustHexID(t, algo, "1") + + var wire bufferWriteFlusher + + enc := pktline.NewEncoder(&wire) + + err := enc.WriteData([]byte( + objectid.Zero(algo).String() + " " + oneID.String() + " refs/heads/main\x00atomic object-format=" + algo.String() + "\n", + )) + if err != nil { + t.Fatalf("WriteData: %v", err) + } + + err = enc.WriteFlush() + if err != nil { + t.Fatalf("WriteFlush: %v", err) + } + + base := common.NewSession(strings.NewReader(wire.String()), &bufferWriteFlusher{}, common.Options{ + Algorithm: algo, + }) + session := receivepack.NewSession(base, receivepack.Capabilities{ObjectFormat: algo}) + + _, err = session.ReadRequest() + if err == nil { + t.Fatalf("ReadRequest error = nil, want error") + } + + protocolErr, ok := errors.AsType[*receivepack.ProtocolError](err) + if !ok { + t.Fatalf("errors.AsType[*receivepack.ProtocolError](%T) = false", err) + } + + if !strings.Contains(protocolErr.Reason, "unsupported capability") { + t.Fatalf("ProtocolError.Reason = %q", protocolErr.Reason) + } + }) +} + +func TestReadRequestParsesPushCertificate(t *testing.T) { + t.Parallel() + + //nolint:thelper + testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { + t.Parallel() + + oneID := mustHexID(t, algo, "1") + + var wire bufferWriteFlusher + + enc := pktline.NewEncoder(&wire) + + err := enc.WriteData([]byte("push-cert\x00push-cert=nonce object-format=" + algo.String() + "\n")) + if err != nil { + t.Fatalf("WriteData(push-cert): %v", err) + } + + lines := []string{ + "certificate version 0.1\n", + "pusher Example <example@example.com>\n", + "nonce nonce\n", + "push-option ci.skip\n", + "\n", + objectid.Zero(algo).String() + " " + oneID.String() + " refs/heads/main\n", + "-----BEGIN PGP SIGNATURE-----\n", + "abcdef\n", + "push-cert-end\n", + } + + for _, line := range lines { + err = enc.WriteData([]byte(line)) + if err != nil { + t.Fatalf("WriteData(%q): %v", line, err) + } + } + + err = enc.WriteFlush() + if err != nil { + t.Fatalf("WriteFlush: %v", err) + } + + base := common.NewSession(strings.NewReader(wire.String()), &bufferWriteFlusher{}, common.Options{ + Algorithm: algo, + }) + session := receivepack.NewSession(base, receivepack.Capabilities{ + PushCertNonce: "server-nonce", + ObjectFormat: algo, + }) + + req, err := session.ReadRequest() + if err != nil { + t.Fatalf("ReadRequest: %v", err) + } + + if req.PushCert == nil { + t.Fatalf("PushCert = nil, want parsed certificate") + } + + if len(req.Commands) != 1 { + t.Fatalf("len(req.Commands) = %d, want 1", len(req.Commands)) + } + + if len(req.PushCert.EmbeddedOption) != 1 || req.PushCert.EmbeddedOption[0] != "ci.skip" { + t.Fatalf("embedded options = %#v", req.PushCert.EmbeddedOption) + } + }) +} |
