github.com/googleapis/api-linter@v1.65.2/rules/aip0121/resource_must_support_get_test.go (about) 1 // Copyright 2023 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package aip0121 16 17 import ( 18 "testing" 19 20 "github.com/googleapis/api-linter/lint" 21 "github.com/googleapis/api-linter/rules/internal/testutils" 22 ) 23 24 // TestResourceMustSupportGet tests the resourceMustSupportGet 25 // lint rule by declaring a service proto, then declaring a 26 // google.api.resource message, then declaring non-Get 27 // methods. 28 func TestResourceMustSupportGet(t *testing.T) { 29 for _, test := range []struct { 30 name string 31 RPCs string 32 problems testutils.Problems 33 }{ 34 {"ValidCreateGet", ` 35 rpc GetBook(GetBookRequest) returns (Book) {}; 36 rpc CreateBook(CreateBookRequest) returns (Book) {}; 37 `, nil}, 38 {"ValidCreateGetLRO", ` 39 rpc GetBook(GetBookRequest) returns (Book) {}; 40 rpc CreateBook(CreateBookRequest) returns (google.longrunning.Operation) { 41 option (google.longrunning.operation_info) = { 42 response_type: "Book" 43 }; 44 }; 45 `, nil}, 46 {"ValidListGet", ` 47 rpc GetBook(GetBookRequest) returns (Book) {}; 48 rpc ListBooks(ListBooksRequest) returns (ListBooksResponse) {}; 49 `, nil}, 50 {"ValidUpdateGet", ` 51 rpc GetBook(GetBookRequest) returns (Book) {}; 52 rpc UpdateBook(UpdateBookRequest) returns (Book) {}; 53 `, nil}, 54 {"ValidIgnoreNonResourceUpdate", ` 55 rpc UpdateBook(UpdateBookRequest) returns (Other) {}; 56 `, nil}, 57 {"ValidIgnoreNonResourceCreate", ` 58 rpc CreateBook(CreateBookRequest) returns (Other) {}; 59 `, nil}, 60 {"ValidIgnoreNonResourceList", ` 61 rpc ListBooks(ListBooksRequest) returns (RepeatedOther) {}; 62 `, nil}, 63 {"ValidIgnoreStreamingLookalike", ` 64 rpc CreateBook(CreateBookRequest) returns (stream Book) {}; 65 `, nil}, 66 {"InvalidCreateOnly", ` 67 rpc CreateBook(CreateBookRequest) returns (Book) {}; 68 `, []lint.Problem{ 69 {Message: `resource "library.googleapis.com/Book"`}, 70 }}, 71 {"InvalidCreateOnlyLRO", ` 72 rpc CreateBook(CreateBookRequest) returns (google.longrunning.Operation) { 73 option (google.longrunning.operation_info) = { 74 response_type: "Book" 75 }; 76 }; 77 `, []lint.Problem{ 78 {Message: `resource "library.googleapis.com/Book"`}, 79 }}, 80 {"InvalidUpdateOnly", ` 81 rpc UpdateBook(UpdateBookRequest) returns (Book) {}; 82 `, []lint.Problem{ 83 {Message: `resource "library.googleapis.com/Book"`}, 84 }}, 85 {"InvalidListOnly", ` 86 rpc ListBooks(ListBooksRequest) returns (ListBooksResponse) {}; 87 `, []lint.Problem{ 88 {Message: `resource "library.googleapis.com/Book"`}, 89 }}, 90 } { 91 t.Run(test.name, func(t *testing.T) { 92 file := testutils.ParseProto3Tmpl(t, ` 93 import "google/api/resource.proto"; 94 import "google/longrunning/operations.proto"; 95 import "google/protobuf/field_mask.proto"; 96 service Foo { 97 {{.RPCs}} 98 } 99 100 // This is at the top to make it retrievable 101 // by the test code. 102 message Book { 103 option (google.api.resource) = { 104 type: "library.googleapis.com/Book" 105 pattern: "books/{book}" 106 singular: "book" 107 plural: "books" 108 }; 109 } 110 111 message CreateBookRequest { 112 // The parent resource where this book will be created. 113 // Format: publishers/{publisher} 114 string parent = 1; 115 116 // The book to create. 117 Book book = 2; 118 } 119 120 message GetBookRequest { 121 string name = 1; 122 } 123 124 message UpdateBookRequest { 125 Book book = 1; 126 google.protobuf.FieldMask update_mask = 2; 127 } 128 129 message ListBooksRequest { 130 string parent = 1; 131 int32 page_size = 2; 132 string page_token = 3; 133 } 134 135 message ListBooksResponse { 136 repeated Book books = 1; 137 string next_page_token = 2; 138 } 139 140 message Other {} 141 142 message RepeatedOther { 143 repeated Other others = 1; 144 } 145 `, test) 146 s := file.GetServices()[0] 147 got := resourceMustSupportGet.Lint(file) 148 if diff := test.problems.SetDescriptor(s).Diff(got); diff != "" { 149 t.Error(diff) 150 } 151 }) 152 } 153 }