|
8 | 8 | "bytes" |
9 | 9 | "context" |
10 | 10 | "encoding/json" |
| 11 | + "errors" |
11 | 12 | "fmt" |
12 | 13 | "log" |
13 | 14 | "log/slog" |
@@ -825,6 +826,92 @@ func TestClientRootCapabilities(t *testing.T) { |
825 | 826 | } |
826 | 827 | } |
827 | 828 |
|
| 829 | +func TestServerRejectsDuplicateInitialize(t *testing.T) { |
| 830 | + ctx := context.Background() |
| 831 | + |
| 832 | + server := NewServer(&Implementation{Name: "testServer", Version: "v1.0.0"}, nil) |
| 833 | + cTransport, sTransport := NewInMemoryTransports() |
| 834 | + ss, err := server.Connect(ctx, sTransport, nil) |
| 835 | + if err != nil { |
| 836 | + t.Fatal(err) |
| 837 | + } |
| 838 | + defer ss.Close() |
| 839 | + |
| 840 | + cConn, err := cTransport.Connect(ctx) |
| 841 | + if err != nil { |
| 842 | + t.Fatal(err) |
| 843 | + } |
| 844 | + defer cConn.Close() |
| 845 | + |
| 846 | + firstParams := json.RawMessage(`{ |
| 847 | + "protocolVersion": "2025-11-25", |
| 848 | + "clientInfo": {"name": "first-client", "version": "1.0.0"} |
| 849 | + }`) |
| 850 | + firstReq, err := jsonrpc2.NewCall(jsonrpc2.Int64ID(1), methodInitialize, firstParams) |
| 851 | + if err != nil { |
| 852 | + t.Fatal(err) |
| 853 | + } |
| 854 | + if err := cConn.Write(ctx, firstReq); err != nil { |
| 855 | + t.Fatalf("first initialize write failed: %v", err) |
| 856 | + } |
| 857 | + msg, err := cConn.Read(ctx) |
| 858 | + if err != nil { |
| 859 | + t.Fatalf("first initialize read failed: %v", err) |
| 860 | + } |
| 861 | + resp, ok := msg.(*jsonrpc2.Response) |
| 862 | + if !ok { |
| 863 | + t.Fatalf("expected Response, got %T", msg) |
| 864 | + } |
| 865 | + if resp.Error != nil { |
| 866 | + t.Fatalf("first initialize failed: %v", resp.Error) |
| 867 | + } |
| 868 | + |
| 869 | + initializedReq, err := jsonrpc2.NewNotification(notificationInitialized, &InitializedParams{}) |
| 870 | + if err != nil { |
| 871 | + t.Fatal(err) |
| 872 | + } |
| 873 | + if err := cConn.Write(ctx, initializedReq); err != nil { |
| 874 | + t.Fatalf("initialized notification write failed: %v", err) |
| 875 | + } |
| 876 | + |
| 877 | + secondParams := json.RawMessage(`{ |
| 878 | + "protocolVersion": "2024-11-05", |
| 879 | + "clientInfo": {"name": "second-client", "version": "2.0.0"} |
| 880 | + }`) |
| 881 | + secondReq, err := jsonrpc2.NewCall(jsonrpc2.Int64ID(2), methodInitialize, secondParams) |
| 882 | + if err != nil { |
| 883 | + t.Fatal(err) |
| 884 | + } |
| 885 | + if err := cConn.Write(ctx, secondReq); err != nil { |
| 886 | + t.Fatalf("second initialize write failed: %v", err) |
| 887 | + } |
| 888 | + msg, err = cConn.Read(ctx) |
| 889 | + if err != nil { |
| 890 | + t.Fatalf("second initialize read failed: %v", err) |
| 891 | + } |
| 892 | + resp, ok = msg.(*jsonrpc2.Response) |
| 893 | + if !ok { |
| 894 | + t.Fatalf("expected Response, got %T", msg) |
| 895 | + } |
| 896 | + if resp.Error == nil { |
| 897 | + t.Fatal("second initialize unexpectedly succeeded") |
| 898 | + } |
| 899 | + if !errors.Is(resp.Error, jsonrpc2.ErrInvalidRequest) { |
| 900 | + t.Fatalf("second initialize error = %v, want invalid request", resp.Error) |
| 901 | + } |
| 902 | + |
| 903 | + got := ss.InitializeParams() |
| 904 | + if got == nil { |
| 905 | + t.Fatal("InitializeParams is nil") |
| 906 | + } |
| 907 | + if got.ProtocolVersion != "2025-11-25" { |
| 908 | + t.Fatalf("ProtocolVersion = %q, want first initialize value", got.ProtocolVersion) |
| 909 | + } |
| 910 | + if got.ClientInfo == nil || got.ClientInfo.Name != "first-client" { |
| 911 | + t.Fatalf("ClientInfo = %#v, want first initialize value", got.ClientInfo) |
| 912 | + } |
| 913 | +} |
| 914 | + |
828 | 915 | // TODO: move this to tool_test.go |
829 | 916 | func TestToolForSchemas(t *testing.T) { |
830 | 917 | // Validate that toolForErr handles schemas properly. |
|
0 commit comments