sbenp.prettier-vscode

This commit is contained in:
duwenxin
2026-02-09 14:28:51 -05:00
parent ce51f8b22a
commit 288cd5acc3
6 changed files with 68 additions and 58 deletions

View File

@@ -361,7 +361,11 @@ func (s *Source) GetOperations(ctx context.Context, project, location, operation
}
}
return string(opBytes), nil
var result any
if err := json.Unmarshal(opBytes, &result); err != nil {
return nil, fmt.Errorf("failed to unmarshal operation bytes: %w", err)
}
return result, nil
}
logger.DebugContext(ctx, fmt.Sprintf("Operation not complete, retrying in %v\n", delay))
}

View File

@@ -253,7 +253,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
op, err := source.GetOperations(ctx, project, location, operation, alloyDBConnectionMessageTemplate, delay, string(accessToken))
if err != nil {
return nil, util.ProcessGcpError(err)
return nil, util.ProcessGeneralError(err)
}
if op != nil {
return op, nil

View File

@@ -1239,8 +1239,8 @@ func TestAlloyDBCreateInstance(t *testing.T) {
{
name: "api failure",
body: `{"project": "p1", "location": "l1", "cluster": "c1", "instance": "i2-api-failure", "instanceType": "PRIMARY", "displayName": "i1-success"}`,
want: "internal api error",
wantStatusCode: http.StatusBadRequest,
want: `{"error":"error processing GCP request: error creating AlloyDB instance: googleapi: Error 500: internal api error"}`,
wantStatusCode: http.StatusOK,
},
{
name: "missing project",
@@ -1269,8 +1269,8 @@ func TestAlloyDBCreateInstance(t *testing.T) {
{
name: "invalid instanceType",
body: `{"project": "p1", "location": "l1", "cluster": "c1", "instance": "i1", "instanceType": "INVALID", "displayName": "invalid"}`,
want: `invalid 'instanceType' parameter; expected 'PRIMARY' or 'READ_POOL'`,
wantStatusCode: http.StatusBadRequest,
want: `{"error":"invalid 'instanceType' parameter; expected 'PRIMARY' or 'READ_POOL'"}`,
wantStatusCode: http.StatusOK,
},
}

View File

@@ -23,7 +23,6 @@ import (
"net/http"
"net/http/httptest"
"net/url"
"reflect"
"regexp"
"strings"
"sync"
@@ -165,13 +164,13 @@ func TestWaitToolEndpoints(t *testing.T) {
name: "successful operation",
toolName: "wait-for-op1",
body: `{"project": "p1", "location": "l1", "operation": "op1"}`,
want: `{"name":"op1","done":true,"response":"success"}`,
want: `{"done":true,"name":"op1","response":"success"}`,
},
{
name: "failed operation",
toolName: "wait-for-op2",
body: `{"project": "p1", "location": "l1", "operation": "op2"}`,
expectError: true,
name: "failed operation",
toolName: "wait-for-op2",
body: `{"project": "p1", "location": "l1", "operation": "op2"}`,
want: `{"error":"error processing request: operation finished with error: {\"code\":1,\"message\":\"failed\"}"}`,
},
}
@@ -189,48 +188,42 @@ func TestWaitToolEndpoints(t *testing.T) {
}
defer resp.Body.Close()
if tc.expectError {
if resp.StatusCode == http.StatusOK {
t.Fatal("expected error but got status 200")
}
return
}
if resp.StatusCode != http.StatusOK {
bodyBytes, _ := io.ReadAll(resp.Body)
t.Fatalf("response status code is not 200, got %d: %s", resp.StatusCode, string(bodyBytes))
}
var result struct {
Result string `json:"result"`
var response struct {
Result any `json:"result"`
}
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
t.Fatalf("failed to decode response: %v", err)
}
var got string
// Check if the result is a string (which contains JSON)
if s, ok := response.Result.(string); ok {
got = s
} else {
b, err := json.Marshal(response.Result)
if err != nil {
t.Fatalf("failed to marshal result object: %v", err)
}
got = string(b)
}
// Clean up both strings to ignore whitespace differences
got = strings.ReplaceAll(strings.ReplaceAll(got, " ", ""), "\n", "")
want := strings.ReplaceAll(strings.ReplaceAll(tc.want, " ", ""), "\n", "")
if tc.wantSubstring {
if !bytes.Contains([]byte(result.Result), []byte(tc.want)) {
t.Fatalf("unexpected result: got %q, want substring %q", result.Result, tc.want)
if !strings.Contains(got, want) {
t.Fatalf("unexpected result: got %q, want substring %q", got, want)
}
return
}
// The result is a JSON-encoded string, so we need to unmarshal it twice.
var tempString string
if err := json.Unmarshal([]byte(result.Result), &tempString); err != nil {
t.Fatalf("failed to unmarshal result string: %v", err)
}
var got, want map[string]any
if err := json.Unmarshal([]byte(tempString), &got); err != nil {
t.Fatalf("failed to unmarshal result: %v", err)
}
if err := json.Unmarshal([]byte(tc.want), &want); err != nil {
t.Fatalf("failed to unmarshal want: %v", err)
}
if !reflect.DeepEqual(got, want) {
t.Fatalf("unexpected result: got %+v, want %+v", got, want)
if got != want {
t.Fatalf("unexpected result: \ngot: %s\nwant: %s", got, want)
}
})
}

View File

@@ -354,6 +354,7 @@ func runToolUpdateInvokeTest(t *testing.T, update1Want, updateManyWant string) {
})
}
}
func runToolAggregateInvokeTest(t *testing.T, aggregate1Want string, aggregateManyWant string) {
// Test tool invoke endpoint
invokeTcs := []struct {
@@ -385,8 +386,8 @@ func runToolAggregateInvokeTest(t *testing.T, aggregate1Want string, aggregateMa
api: "http://127.0.0.1:5000/api/tool/my-read-only-aggregate-tool/invoke",
requestHeader: map[string]string{},
requestBody: bytes.NewBuffer([]byte(`{ "name" : "ToBeAggregated" }`)),
want: "",
isErr: true,
want: `{"error":"error processing request: this is not a read-only pipeline: {\"$out\":\"target_collection\"}"}`,
isErr: false,
},
{
name: "invoke my-read-write-aggregate-tool",

View File

@@ -287,25 +287,37 @@ func TestNeo4jToolEndpoints(t *testing.T) {
},
},
{
name: "invoke my-simple-execute-cypher-tool with dry_run and invalid syntax",
api: "http://127.0.0.1:5000/api/tool/my-simple-execute-cypher-tool/invoke",
requestBody: bytes.NewBuffer([]byte(`{"cypher": "RTN 1", "dry_run": true}`)),
wantStatus: http.StatusBadRequest,
wantErrorSubstring: "unable to execute query",
name: "invoke my-simple-execute-cypher-tool with dry_run and invalid syntax",
api: "http://127.0.0.1:5000/api/tool/my-simple-execute-cypher-tool/invoke",
requestBody: bytes.NewBuffer([]byte(`{"cypher": "RTN 1", "dry_run": true}`)),
wantStatus: http.StatusOK,
validateFunc: func(t *testing.T, body string) {
if !strings.Contains(body, "unable to execute query") {
t.Errorf("expected error message not found in body: %s", body)
}
},
},
{
name: "invoke readonly tool with write query",
api: "http://127.0.0.1:5000/api/tool/my-readonly-execute-cypher-tool/invoke",
requestBody: bytes.NewBuffer([]byte(`{"cypher": "CREATE (n:TestNode)"}`)),
wantStatus: http.StatusBadRequest,
wantErrorSubstring: "this tool is read-only and cannot execute write queries",
name: "invoke readonly tool with write query",
api: "http://127.0.0.1:5000/api/tool/my-readonly-execute-cypher-tool/invoke",
requestBody: bytes.NewBuffer([]byte(`{"cypher": "CREATE (n:TestNode)"}`)),
wantStatus: http.StatusOK,
validateFunc: func(t *testing.T, body string) {
if !strings.Contains(body, "this tool is read-only and cannot execute write queries") {
t.Errorf("expected error message not found in body: %s", body)
}
},
},
{
name: "invoke readonly tool with write query and dry_run",
api: "http://127.0.0.1:5000/api/tool/my-readonly-execute-cypher-tool/invoke",
requestBody: bytes.NewBuffer([]byte(`{"cypher": "CREATE (n:TestNode)", "dry_run": true}`)),
wantStatus: http.StatusBadRequest,
wantErrorSubstring: "this tool is read-only and cannot execute write queries",
name: "invoke readonly tool with write query and dry_run",
api: "http://127.0.0.1:5000/api/tool/my-readonly-execute-cypher-tool/invoke",
requestBody: bytes.NewBuffer([]byte(`{"cypher": "CREATE (n:TestNode)", "dry_run": true}`)),
wantStatus: http.StatusOK,
validateFunc: func(t *testing.T, body string) {
if !strings.Contains(body, "this tool is read-only and cannot execute write queries") {
t.Errorf("expected error message not found in body: %s", body)
}
},
},
{
name: "invoke my-schema-tool",