github.com/googleapis/api-linter@v1.65.2/rules/aip0121/resource_must_support_list_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 // TestResourceMustSupportList tests the resourceMustSupportList 25 // lint rule by declaring a service proto, then declaring a 26 // google.api.resource message, then declaring non-List 27 // methods. 28 func TestResourceMustSupportList(t *testing.T) { 29 for _, test := range []struct { 30 name string 31 RPCs string 32 problems testutils.Problems 33 }{ 34 {"ValidCreateList", ` 35 rpc ListBooks(ListBooksRequest) returns (ListBooksResponse) {}; 36 rpc CreateBook(CreateBookRequest) returns (Book) {}; 37 `, nil}, 38 {"ValidCreateListLRO", ` 39 rpc ListBooks(ListBooksRequest) returns (ListBooksResponse) {}; 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 {"ValidUpdateList", ` 51 rpc ListBooks(ListBooksRequest) returns (ListBooksResponse) {}; 52 rpc UpdateBook(UpdateBookRequest) returns (Book) {}; 53 `, nil}, 54 {"InvalidCreateOnly", ` 55 rpc CreateBook(CreateBookRequest) returns (Book) {}; 56 `, []lint.Problem{ 57 {Message: `resource "library.googleapis.com/Book"`}, 58 }}, 59 {"InvalidCreateOnlyLRO", ` 60 rpc CreateBook(CreateBookRequest) returns (google.longrunning.Operation) { 61 option (google.longrunning.operation_info) = { 62 response_type: "Book" 63 }; 64 }; 65 `, []lint.Problem{ 66 {Message: `resource "library.googleapis.com/Book"`}, 67 }}, 68 {"InvalidUpdateOnly", ` 69 rpc UpdateBook(UpdateBookRequest) returns (Book) {}; 70 `, []lint.Problem{ 71 {Message: `resource "library.googleapis.com/Book"`}, 72 }}, 73 {"InvalidGetOnly", ` 74 rpc GetBook(GetBookRequest) returns (Book) {}; 75 `, []lint.Problem{ 76 {Message: `resource "library.googleapis.com/Book"`}, 77 }}, 78 {"ValidIgnoreSingleton", ` 79 rpc GetBookCover(GetBookCoverRequest) returns (BookCover) {}; 80 `, nil}, 81 {"ValidIgnoreNonResource", ` 82 rpc GetBookCover(GetBookCoverRequest) returns (Other) {}; 83 `, nil}, 84 {"ValidIgnoreStreamingLookalike", ` 85 rpc GetBook(GetBookRequest) returns (stream Book) {}; 86 `, nil}, 87 } { 88 t.Run(test.name, func(t *testing.T) { 89 file := testutils.ParseProto3Tmpl(t, ` 90 import "google/api/resource.proto"; 91 import "google/longrunning/operations.proto"; 92 import "google/protobuf/field_mask.proto"; 93 service Foo { 94 {{.RPCs}} 95 } 96 97 // This is at the top to make it retrievable 98 // by the test code. 99 message Book { 100 option (google.api.resource) = { 101 type: "library.googleapis.com/Book" 102 pattern: "books/{book}" 103 singular: "book" 104 plural: "books" 105 }; 106 } 107 108 message BookCover { 109 option (google.api.resource) = { 110 type: "library.googleapis.com/BookCover" 111 pattern: "books/{book}/bookCover" 112 singular: "bookCover" 113 }; 114 } 115 116 message GetBookCoverRequest { 117 string name = 1; 118 } 119 120 message CreateBookRequest { 121 // The parent resource where this book will be created. 122 // Format: publishers/{publisher} 123 string parent = 1; 124 125 // The book to create. 126 Book book = 2; 127 } 128 129 message GetBookRequest { 130 string name = 1; 131 } 132 133 message UpdateBookRequest { 134 Book book = 1; 135 google.protobuf.FieldMask update_mask = 2; 136 } 137 138 message ListBooksRequest { 139 string parent = 1; 140 int32 page_size = 2; 141 string page_token = 3; 142 } 143 144 message ListBooksResponse { 145 repeated Book books = 1; 146 string next_page_token = 2; 147 } 148 149 message Other { 150 string other = 1; 151 } 152 `, test) 153 s := file.GetServices()[0] 154 got := resourceMustSupportList.Lint(file) 155 if diff := test.problems.SetDescriptor(s).Diff(got); diff != "" { 156 t.Error(diff) 157 } 158 }) 159 } 160 }