Skip to content

Commit e86f76f

Browse files
authored
refactor(sidekick): make createModel testable (#1594)
Moving the function to the `parser` package where we can test it and use it in other tests.
1 parent 51e1e24 commit e86f76f

File tree

3 files changed

+161
-44
lines changed

3 files changed

+161
-44
lines changed

internal/sidekick/internal/parser/parser.go

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,58 @@
1414

1515
package parser
1616

17-
import "strings"
17+
import (
18+
"fmt"
19+
"strings"
20+
21+
"github.com/googleapis/librarian/internal/sidekick/internal/api"
22+
"github.com/googleapis/librarian/internal/sidekick/internal/config"
23+
)
24+
25+
// CreateModel parses the service specification referenced in `config`,
26+
// cross-references the model, and applies any transformations or overrides
27+
// required by the configuration.
28+
func CreateModel(config *config.Config) (*api.API, error) {
29+
var err error
30+
var model *api.API
31+
switch config.General.SpecificationFormat {
32+
case "openapi":
33+
model, err = ParseOpenAPI(config.General.SpecificationSource, config.General.ServiceConfig, config.Source)
34+
case "protobuf":
35+
model, err = ParseProtobuf(config.General.SpecificationSource, config.General.ServiceConfig, config.Source)
36+
case "none":
37+
return nil, nil
38+
default:
39+
return nil, fmt.Errorf("unknown parser %q", config.General.SpecificationFormat)
40+
}
41+
if err != nil {
42+
return nil, err
43+
}
44+
api.LabelRecursiveFields(model)
45+
if err := api.CrossReference(model); err != nil {
46+
return nil, err
47+
}
48+
if err := api.SkipModelElements(model, config.Source); err != nil {
49+
return nil, err
50+
}
51+
if err := api.PatchDocumentation(model, config); err != nil {
52+
return nil, err
53+
}
54+
// Verify all the services, messages and enums are in the same package.
55+
if err := api.Validate(model); err != nil {
56+
return nil, err
57+
}
58+
if name, ok := config.Source["name-override"]; ok {
59+
model.Name = name
60+
}
61+
if title, ok := config.Source["title-override"]; ok {
62+
model.Title = title
63+
}
64+
if description, ok := config.Source["description-override"]; ok {
65+
model.Description = description
66+
}
67+
return model, nil
68+
}
1869

1970
func splitApiName(name string) (string, string) {
2071
li := strings.LastIndex(name, ".")

internal/sidekick/internal/parser/parser_test.go

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,121 @@
1515
package parser
1616

1717
import (
18+
"path"
19+
"path/filepath"
1820
"testing"
1921

2022
"github.com/google/go-cmp/cmp"
2123
"github.com/google/go-cmp/cmp/cmpopts"
2224
"github.com/googleapis/librarian/internal/sidekick/internal/api"
25+
"github.com/googleapis/librarian/internal/sidekick/internal/config"
2326
)
2427

28+
var (
29+
testdataDir, _ = filepath.Abs("../../testdata")
30+
)
31+
32+
func TestCreateModelOpenAPI(t *testing.T) {
33+
cfg := &config.Config{
34+
General: config.GeneralConfig{
35+
SpecificationFormat: "openapi",
36+
ServiceConfig: path.Join(testdataDir, "googleapis/google/cloud/secretmanager/v1/secretmanager_v1.yaml"),
37+
SpecificationSource: path.Join(testdataDir, "openapi/secretmanager_openapi_v1.json"),
38+
},
39+
}
40+
model, err := CreateModel(cfg)
41+
if err != nil {
42+
t.Fatal(err)
43+
}
44+
_, ok := model.State.ServiceByID[".google.cloud.secretmanager.v1.SecretManagerService"]
45+
if !ok {
46+
t.Errorf("missing service (.google.cloud.secretmanager.v1.SecretManagerService) in ServiceByID index")
47+
return
48+
}
49+
}
50+
51+
func TestCreateModelProtobuf(t *testing.T) {
52+
requireProtoc(t)
53+
cfg := &config.Config{
54+
General: config.GeneralConfig{
55+
SpecificationFormat: "protobuf",
56+
ServiceConfig: "google/cloud/secretmanager/v1/secretmanager_v1.yaml",
57+
SpecificationSource: "google/cloud/secretmanager/v1",
58+
},
59+
Source: map[string]string{
60+
"googleapis-root": path.Join(testdataDir, "googleapis"),
61+
},
62+
}
63+
model, err := CreateModel(cfg)
64+
if err != nil {
65+
t.Fatal(err)
66+
}
67+
_, ok := model.State.ServiceByID[".google.cloud.secretmanager.v1.SecretManagerService"]
68+
if !ok {
69+
t.Errorf("missing service (.google.cloud.secretmanager.v1.SecretManagerService) in ServiceByID index")
70+
return
71+
}
72+
}
73+
74+
func TestCreateModelOverrides(t *testing.T) {
75+
requireProtoc(t)
76+
cfg := &config.Config{
77+
General: config.GeneralConfig{
78+
SpecificationFormat: "protobuf",
79+
ServiceConfig: "google/cloud/secretmanager/v1/secretmanager_v1.yaml",
80+
SpecificationSource: "google/cloud/secretmanager/v1",
81+
},
82+
Source: map[string]string{
83+
"googleapis-root": path.Join(testdataDir, "googleapis"),
84+
"name-override": "Name Override",
85+
"title-override": "Title Override",
86+
"description-override": "Description Override",
87+
},
88+
}
89+
model, err := CreateModel(cfg)
90+
if err != nil {
91+
t.Fatal(err)
92+
}
93+
type TestCase struct {
94+
got string
95+
want string
96+
}
97+
testCases := []TestCase{
98+
{model.Name, "Name Override"},
99+
{model.Title, "Title Override"},
100+
{model.Description, "Description Override"},
101+
}
102+
for _, c := range testCases {
103+
if c.got != c.want {
104+
t.Errorf("mimatched override got=%q, want=%q", c.got, c.want)
105+
}
106+
}
107+
}
108+
109+
func TestCreateModelNone(t *testing.T) {
110+
requireProtoc(t)
111+
cfg := &config.Config{
112+
General: config.GeneralConfig{
113+
SpecificationFormat: "none",
114+
ServiceConfig: "google/cloud/secretmanager/v1/secretmanager_v1.yaml",
115+
SpecificationSource: "none",
116+
},
117+
Source: map[string]string{
118+
"googleapis-root": path.Join(testdataDir, "googleapis"),
119+
"name-override": "Name Override",
120+
"title-override": "Title Override",
121+
"description-override": "Description Override",
122+
},
123+
}
124+
model, err := CreateModel(cfg)
125+
if err != nil {
126+
t.Fatal(err)
127+
}
128+
if model != nil {
129+
t.Errorf("expected `nil` model with source format == none")
130+
}
131+
}
132+
25133
func checkMessage(t *testing.T, got *api.Message, want *api.Message) {
26134
t.Helper()
27135
// Checking Parent, Messages, Fields, and OneOfs requires special handling.

internal/sidekick/refresh.go

Lines changed: 1 addition & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -61,55 +61,13 @@ func loadDir(rootConfig *config.Config, output string) (*api.API, *config.Config
6161
if config.General.SpecificationSource == "" {
6262
return nil, nil, fmt.Errorf("must provide general.specification-source")
6363
}
64-
model, err := createModel(config)
64+
model, err := parser.CreateModel(config)
6565
if err != nil {
6666
return nil, nil, err
6767
}
6868
return model, config, nil
6969
}
7070

71-
func createModel(config *config.Config) (*api.API, error) {
72-
var err error
73-
var model *api.API
74-
switch config.General.SpecificationFormat {
75-
case "openapi":
76-
model, err = parser.ParseOpenAPI(config.General.SpecificationSource, config.General.ServiceConfig, config.Source)
77-
case "protobuf":
78-
model, err = parser.ParseProtobuf(config.General.SpecificationSource, config.General.ServiceConfig, config.Source)
79-
case "none":
80-
return nil, nil
81-
default:
82-
return nil, fmt.Errorf("unknown parser %q", config.General.SpecificationFormat)
83-
}
84-
if err != nil {
85-
return nil, err
86-
}
87-
api.LabelRecursiveFields(model)
88-
if err := api.CrossReference(model); err != nil {
89-
return nil, err
90-
}
91-
if err := api.SkipModelElements(model, config.Source); err != nil {
92-
return nil, err
93-
}
94-
if err := api.PatchDocumentation(model, config); err != nil {
95-
return nil, err
96-
}
97-
// Verify all the services, messages and enums are in the same package.
98-
if err := api.Validate(model); err != nil {
99-
return nil, err
100-
}
101-
if name, ok := config.Source["name-override"]; ok {
102-
model.Name = name
103-
}
104-
if title, ok := config.Source["title-override"]; ok {
105-
model.Title = title
106-
}
107-
if description, ok := config.Source["description-override"]; ok {
108-
model.Description = description
109-
}
110-
return model, nil
111-
}
112-
11371
func refreshDir(rootConfig *config.Config, cmdLine *CommandLine, output string) error {
11472
model, config, err := loadDir(rootConfig, output)
11573
if err != nil {

0 commit comments

Comments
 (0)