github.com/stackb/rules_proto@v0.0.0-20240221195024-5428336c51f1/pkg/protoc/file_test.go (about)

     1  package protoc
     2  
     3  import (
     4  	"strings"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/assert"
     8  )
     9  
    10  func mustParseTestFile(t *testing.T, in string) *File {
    11  	f := &File{}
    12  	if err := f.ParseReader(strings.NewReader(in)); err != nil {
    13  		t.Fatalf("mustTestFile: %v", err)
    14  	}
    15  	return f
    16  }
    17  
    18  func TestHas(t *testing.T) {
    19  	tests := map[string]struct {
    20  		in            string
    21  		hasMessages   bool
    22  		hasServices   bool
    23  		hasEnumOption string
    24  		hasRPCOption  string
    25  	}{
    26  		"empty file": {},
    27  		"has services": {
    28  			in: `
    29  syntax = "proto3";
    30  
    31  service Greeter {
    32  	rpc Greet(GreetRequest) returns (GreetResponse);
    33  }
    34  `,
    35  			hasServices: true,
    36  		},
    37  		"has enum option": {
    38  			in: `
    39  syntax = "proto3";
    40  import "google/api/visibility.proto";
    41  enum MyEnum {
    42      UNKNOWN = 0;
    43  	PRIVATE = 1 [(google.api.value_visibility).restriction = "HIDDEN"];
    44  }
    45  `,
    46  			hasEnumOption: "(google.api.value_visibility).restriction",
    47  		},
    48  		"has rpc option": {
    49  			in: `
    50  syntax = "proto3";
    51  import "google/api/annotations.proto";
    52  
    53  service Greeter {
    54  	rpc Greet(GreetRequest) returns (GreetResponse) {
    55  		option (google.api.http) = {
    56  			get: "/greet"
    57  		};
    58  	}
    59  }
    60  `,
    61  			hasServices:  true,
    62  			hasRPCOption: "(google.api.http)",
    63  		},
    64  	}
    65  
    66  	for name, tc := range tests {
    67  		t.Run(name, func(t *testing.T) {
    68  			f := mustParseTestFile(t, tc.in)
    69  			if tc.hasMessages != f.HasMessages() {
    70  				t.Errorf("hasMessages: want %t, got %t", tc.hasMessages, f.HasMessages())
    71  			}
    72  			if tc.hasServices != f.HasServices() {
    73  				t.Errorf("hasServices: want %t, got %t", tc.hasServices, f.HasServices())
    74  			}
    75  			if tc.hasEnumOption != "" && !f.HasEnumOption(tc.hasEnumOption) {
    76  				t.Errorf("hasEnumOption: expected %s",
    77  					tc.hasEnumOption)
    78  			}
    79  			if tc.hasRPCOption != "" && !f.HasRPCOption(tc.hasRPCOption) {
    80  				t.Errorf("hasRPCOption: expected %s",
    81  					tc.hasRPCOption)
    82  			}
    83  		})
    84  	}
    85  }
    86  
    87  func TestRelativeFileNameWithExtensions(t *testing.T) {
    88  	tests := map[string]struct {
    89  		dir  string
    90  		name string
    91  		rel  string
    92  		exts []string
    93  		want []string
    94  	}{
    95  		"empty": {
    96  			want: []string{},
    97  		},
    98  		"single": {
    99  			name: "a",
   100  			rel:  "proto",
   101  			exts: []string{".cc"},
   102  			want: []string{
   103  				"proto/a.cc",
   104  			},
   105  		},
   106  		"multiple": {
   107  			name: "a",
   108  			rel:  "proto",
   109  			exts: []string{".cc", ".h"},
   110  			want: []string{
   111  				"proto/a.cc",
   112  				"proto/a.h",
   113  			},
   114  		},
   115  	}
   116  
   117  	for name, tc := range tests {
   118  		t.Run(name, func(t *testing.T) {
   119  			fn := RelativeFileNameWithExtensions(tc.rel, tc.exts...)
   120  			got := fn(&File{
   121  				Dir:  tc.dir,
   122  				Name: tc.name,
   123  			})
   124  			assert.Equal(t, got, tc.want, "generated filenames")
   125  		})
   126  	}
   127  }
   128  
   129  func TestImportPrefixRelativeFileNameWithExtensions(t *testing.T) {
   130  	tests := map[string]struct {
   131  		stripImportPrefix string
   132  		dir               string
   133  		name              string
   134  		rel               string
   135  		exts              []string
   136  		want              []string
   137  	}{
   138  		"empty": {
   139  			want: []string{},
   140  		},
   141  		"single": {
   142  			name: "a",
   143  			rel:  "proto",
   144  			exts: []string{".cc"},
   145  			want: []string{
   146  				"proto/a.cc",
   147  			},
   148  		},
   149  		"multiple": {
   150  			name: "a",
   151  			rel:  "proto",
   152  			exts: []string{".cc", ".h"},
   153  			want: []string{
   154  				"proto/a.cc",
   155  				"proto/a.h",
   156  			},
   157  		},
   158  		"strip": {
   159  			stripImportPrefix: "foo/bar",
   160  			name:              "a",
   161  			rel:               "foo/bar/baz",
   162  			exts:              []string{".cc", ".h"},
   163  			want: []string{
   164  				"baz/a.cc",
   165  				"baz/a.h",
   166  			},
   167  		},
   168  		"strip-abs": {
   169  			stripImportPrefix: "/foo/bar",
   170  			name:              "a",
   171  			rel:               "foo/bar/baz",
   172  			exts:              []string{".cc", ".h"},
   173  			want: []string{
   174  				"baz/a.cc",
   175  				"baz/a.h",
   176  			},
   177  		},
   178  		"strip-abs-with-trailing-slash": {
   179  			stripImportPrefix: "/foo/bar/",
   180  			name:              "a",
   181  			rel:               "foo/bar/baz",
   182  			exts:              []string{".cc", ".h"},
   183  			want: []string{
   184  				"baz/a.cc",
   185  				"baz/a.h",
   186  			},
   187  		},
   188  	}
   189  
   190  	for name, tc := range tests {
   191  		t.Run(name, func(t *testing.T) {
   192  			fn := ImportPrefixRelativeFileNameWithExtensions(tc.stripImportPrefix, tc.rel, tc.exts...)
   193  			got := fn(&File{
   194  				Dir:  tc.dir,
   195  				Name: tc.name,
   196  			})
   197  			assert.Equal(t, got, tc.want, "generated filenames")
   198  		})
   199  	}
   200  }