github.com/googleapis/api-linter@v1.65.2/rules/internal/testutils/parse_test.go (about)

     1  // Copyright 2019 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 testutils
    16  
    17  import (
    18  	"sync"
    19  	"testing"
    20  
    21  	"github.com/jhump/protoreflect/desc"
    22  )
    23  
    24  func TestParseProtoStrings(t *testing.T) {
    25  	fd := ParseProtoStrings(t, map[string]string{"test.proto": `
    26  		syntax = "proto3";
    27  
    28  		import "google/protobuf/timestamp.proto";
    29  
    30  		message Foo {
    31  			int32 bar = 1;
    32  			int64 baz = 2;
    33  		}
    34  
    35  		message Spam {
    36  			string eggs = 2;
    37  			google.protobuf.Timestamp create_time = 3;
    38  		}
    39  	`})["test.proto"]
    40  	if !fd.IsProto3() {
    41  		t.Errorf("Expected a proto3 file descriptor.")
    42  	}
    43  	tests := []struct {
    44  		name       string
    45  		descriptor desc.Descriptor
    46  	}{
    47  		{"Foo", fd.GetMessageTypes()[0]},
    48  		{"bar", fd.GetMessageTypes()[0].GetFields()[0]},
    49  		{"baz", fd.GetMessageTypes()[0].GetFields()[1]},
    50  		{"Spam", fd.GetMessageTypes()[1]},
    51  		{"eggs", fd.GetMessageTypes()[1].GetFields()[0]},
    52  		{"create_time", fd.GetMessageTypes()[1].GetFields()[1]},
    53  	}
    54  	for _, test := range tests {
    55  		t.Run(test.name, func(t *testing.T) {
    56  			if got, want := test.descriptor.GetName(), test.name; got != want {
    57  				t.Errorf("Got %q, expected %q.", got, want)
    58  			}
    59  		})
    60  	}
    61  }
    62  
    63  func TestParseProtoStringError(t *testing.T) {
    64  	canary := &testing.T{}
    65  
    66  	// t.Fatalf will exit the goroutine, so to test this,
    67  	// we run the test in a different goroutine.
    68  	wg := &sync.WaitGroup{}
    69  	wg.Add(1)
    70  	go func() {
    71  		defer wg.Done()
    72  		ParseProtoStrings(canary, map[string]string{"test.proto": `
    73  			syntax = "proto3";
    74  			message Foo {}
    75  			The quick brown fox jumped over the lazy dogs.
    76  		`})
    77  	}()
    78  	wg.Wait()
    79  
    80  	// Verify that the testing.T object was given a failure.
    81  	if !canary.Failed() {
    82  		t.Errorf("Expected syntax error to cause a fatal error.")
    83  	}
    84  }
    85  
    86  func TestParseProto3String(t *testing.T) {
    87  	fd := ParseProto3String(t, `
    88  		message Foo {
    89  			int32 bar = 1;
    90  			int64 baz = 2;
    91  		}
    92  
    93  		message Spam {
    94  			string eggs = 2;
    95  		}
    96  	`)
    97  	if !fd.IsProto3() {
    98  		t.Errorf("Expected a proto3 file descriptor.")
    99  	}
   100  }
   101  
   102  func TestParseProto3Tmpl(t *testing.T) {
   103  	tests := []struct {
   104  		MessageName string
   105  		Field1Name  string
   106  		Field2Name  string
   107  	}{
   108  		{"Book", "title", "author"},
   109  		{"Foo", "bar", "baz"},
   110  	}
   111  	for _, test := range tests {
   112  		t.Run(test.MessageName, func(t *testing.T) {
   113  			fd := ParseProto3Tmpl(t, `
   114  				message {{.MessageName}} {
   115  					string {{.Field1Name}} = 1;
   116  					string {{.Field2Name}} = 2;
   117  				}
   118  			`, test)
   119  			if !fd.IsProto3() {
   120  				t.Errorf("Expected a proto3 file descriptor.")
   121  			}
   122  			msg := fd.GetMessageTypes()[0]
   123  			if got, want := msg.GetName(), test.MessageName; got != want {
   124  				t.Errorf("Got %q for message name, expected %q.", got, want)
   125  			}
   126  			for i, fn := range []string{test.Field1Name, test.Field2Name} {
   127  				if got, want := msg.GetFields()[i].GetName(), fn; got != want {
   128  					t.Errorf("Got %q for field name %d; expected %q.", got, i+1, want)
   129  				}
   130  			}
   131  		})
   132  	}
   133  }
   134  
   135  func TestParseProto3TmplSyntaxError(t *testing.T) {
   136  	canary := &testing.T{}
   137  
   138  	// t.Fatalf will exit the goroutine, so to test this,
   139  	// we run the test in a different goroutine.
   140  	wg := &sync.WaitGroup{}
   141  	wg.Add(1)
   142  	go func() {
   143  		defer wg.Done()
   144  		ParseProto3Tmpl(canary, `
   145  			message {{.InvalidTmplVariable[0]}} {}
   146  		`, struct{}{})
   147  	}()
   148  	wg.Wait()
   149  
   150  	// Verify that the testing.T object was given a failure.
   151  	if !canary.Failed() {
   152  		t.Errorf("Expected syntax error to cause a fatal error.")
   153  	}
   154  }
   155  
   156  func TestParseProto3TmplDataError(t *testing.T) {
   157  	canary := &testing.T{}
   158  
   159  	// t.Fatalf will exit the goroutine, so to test this,
   160  	// we run the test in a different goroutine.
   161  	wg := &sync.WaitGroup{}
   162  	wg.Add(1)
   163  	go func() {
   164  		defer wg.Done()
   165  		ParseProto3Tmpl(canary, `
   166  			message {{.MissingVariable}} {}
   167  		`, struct{}{})
   168  	}()
   169  	wg.Wait()
   170  
   171  	// Verify that the testing.T object was given a failure.
   172  	if !canary.Failed() {
   173  		t.Errorf("Expected missing data to cause a fatal error.")
   174  	}
   175  }