|
| 1 | +/* |
| 2 | + * Copyright 2026 the original author or authors. |
| 3 | + * |
| 4 | + * Licensed under the Moderne Source Available License (the "License"); |
| 5 | + * you may not use this file except in compliance with the License. |
| 6 | + * You may obtain a copy of the License at |
| 7 | + * |
| 8 | + * https://docs.moderne.io/licensing/moderne-source-available-license |
| 9 | + * |
| 10 | + * Unless required by applicable law or agreed to in writing, software |
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | + * See the License for the specific language governing permissions and |
| 14 | + * limitations under the License. |
| 15 | + */ |
| 16 | + |
| 17 | +package main |
| 18 | + |
| 19 | +import ( |
| 20 | + "bufio" |
| 21 | + "bytes" |
| 22 | + "encoding/json" |
| 23 | + "fmt" |
| 24 | + "path/filepath" |
| 25 | + "strings" |
| 26 | + "testing" |
| 27 | +) |
| 28 | + |
| 29 | +// TestResolveTidyViaJavaWireProtocol exercises the Go half of the |
| 30 | +// GoModResolveTidy RPC: it feeds a canned Java response and asserts both that |
| 31 | +// resolveTidyViaJava parses it correctly AND that the request it writes carries |
| 32 | +// the exact field names the Java GoModResolveTidyRequest expects. This guards |
| 33 | +// the cross-process contract that the in-Java handler test cannot see. |
| 34 | +func TestResolveTidyViaJavaWireProtocol(t *testing.T) { |
| 35 | + s := newServer(serverConfig{logFile: filepath.Join(t.TempDir(), "server.log")}) |
| 36 | + |
| 37 | + // Canned host response: direct/indirect/complete, JSON-RPC framed. |
| 38 | + respBody := `{"jsonrpc":"2.0","id":"go-GoModResolveTidy","result":` + |
| 39 | + `{"direct":{"github.com/a/x":"v1.2.3"},"indirect":{"github.com/b/y":"v0.4.0"},"complete":true}}` |
| 40 | + framed := fmt.Sprintf("Content-Length: %d\r\n\r\n%s", len(respBody), respBody) |
| 41 | + s.reader = bufio.NewReader(strings.NewReader(framed)) |
| 42 | + var written bytes.Buffer |
| 43 | + s.writer = &written |
| 44 | + |
| 45 | + rs, ok := s.resolveTidyViaJava("module example.com/m\n\ngo 1.21\n", |
| 46 | + []string{"github.com/a/x", "fmt"}, "example.com/m", true) |
| 47 | + |
| 48 | + // Response parsed correctly. |
| 49 | + if !ok { |
| 50 | + t.Fatal("expected ok=true") |
| 51 | + } |
| 52 | + if !rs.Complete { |
| 53 | + t.Error("expected Complete=true") |
| 54 | + } |
| 55 | + if rs.Direct["github.com/a/x"] != "v1.2.3" { |
| 56 | + t.Errorf("direct: got %v", rs.Direct) |
| 57 | + } |
| 58 | + if rs.Indirect["github.com/b/y"] != "v0.4.0" { |
| 59 | + t.Errorf("indirect: got %v", rs.Indirect) |
| 60 | + } |
| 61 | + |
| 62 | + // Request written with the method and param field names the Java side expects. |
| 63 | + body := written.String() |
| 64 | + if i := strings.Index(body, "\r\n\r\n"); i >= 0 { |
| 65 | + body = body[i+4:] |
| 66 | + } |
| 67 | + var req struct { |
| 68 | + Method string `json:"method"` |
| 69 | + Params struct { |
| 70 | + GoMod string `json:"goMod"` |
| 71 | + MainImports []string `json:"mainImports"` |
| 72 | + ModulePath string `json:"modulePath"` |
| 73 | + SeparateIndirect bool `json:"separateIndirect"` |
| 74 | + Goproxy string `json:"goproxy"` |
| 75 | + Gomodcache string `json:"gomodcache"` |
| 76 | + } `json:"params"` |
| 77 | + } |
| 78 | + if err := json.Unmarshal([]byte(body), &req); err != nil { |
| 79 | + t.Fatalf("request JSON: %v\nbody=%s", err, body) |
| 80 | + } |
| 81 | + if req.Method != "GoModResolveTidy" { |
| 82 | + t.Errorf("method: got %q", req.Method) |
| 83 | + } |
| 84 | + if !strings.Contains(req.Params.GoMod, "module example.com/m") { |
| 85 | + t.Errorf("goMod not propagated: %q", req.Params.GoMod) |
| 86 | + } |
| 87 | + if req.Params.ModulePath != "example.com/m" { |
| 88 | + t.Errorf("modulePath: got %q", req.Params.ModulePath) |
| 89 | + } |
| 90 | + if !req.Params.SeparateIndirect { |
| 91 | + t.Error("separateIndirect should be true") |
| 92 | + } |
| 93 | + if len(req.Params.MainImports) != 2 || req.Params.MainImports[0] != "github.com/a/x" { |
| 94 | + t.Errorf("mainImports: got %v", req.Params.MainImports) |
| 95 | + } |
| 96 | + if req.Params.Goproxy == "" || req.Params.Gomodcache == "" { |
| 97 | + t.Errorf("goproxy/gomodcache should be populated from env: %q / %q", |
| 98 | + req.Params.Goproxy, req.Params.Gomodcache) |
| 99 | + } |
| 100 | +} |
0 commit comments