|  | // Copyright 2022 Google LLC | 
|  | // | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | package exporter | 
|  |  | 
|  | import ( | 
|  | "bytes" | 
|  | "testing" | 
|  |  | 
|  | "github.com/stretchr/testify/assert" | 
|  | "github.com/stretchr/testify/mock" | 
|  | "github.com/stretchr/testify/require" | 
|  | "go.skia.org/infra/go/skerr" | 
|  | "go.skia.org/skia/bazel/exporter/interfaces/mocks" | 
|  | ) | 
|  |  | 
|  | const workspaceTestWorkspaceDir = "/path/to/workspace" | 
|  |  | 
|  | // This input test data (in textproto format) started as output of | 
|  | // a bazel cquery call - like: | 
|  | // | 
|  | //	bazel cquery --noimplicit_deps 'kind("rule", deps(//:skia_public))' --output textproto > out.txt | 
|  | // | 
|  | // and then hand edited to create a small valid query result with specific | 
|  | // files, copts, and other cc_library/cc_binary rule attributes. | 
|  | const workspaceTestTextProto = `results { | 
|  | target { | 
|  | type: RULE | 
|  | rule { | 
|  | name: "//src/libs:sum" | 
|  | rule_class: "cc_library" | 
|  | location: "/path/to/workspace/src/libs/BUILD.bazel:8:11" | 
|  | attribute { | 
|  | name: "copts" | 
|  | type: STRING_LIST | 
|  | string_list_value: "-O2" | 
|  | explicitly_specified: true | 
|  | nodep: false | 
|  | } | 
|  | attribute { | 
|  | name: "defines" | 
|  | type: STRING_LIST | 
|  | string_list_value: "SUMDEF" | 
|  | explicitly_specified: false | 
|  | nodep: false | 
|  | } | 
|  | attribute { | 
|  | name: "includes" | 
|  | type: STRING_LIST | 
|  | string_list_value: "." | 
|  | explicitly_specified: false | 
|  | nodep: false | 
|  | } | 
|  | attribute { | 
|  | name: "linkopts" | 
|  | type: STRING_LIST | 
|  | string_list_value: "-L/library/dir" | 
|  | explicitly_specified: false | 
|  | nodep: false | 
|  | } | 
|  | attribute { | 
|  | name: "name" | 
|  | type: STRING | 
|  | string_value: "sum" | 
|  | explicitly_specified: true | 
|  | nodep: false | 
|  | } | 
|  | attribute { | 
|  | name: "srcs" | 
|  | type: LABEL_LIST | 
|  | string_list_value: "//src/libs:sum.cpp" | 
|  | explicitly_specified: true | 
|  | nodep: false | 
|  | } | 
|  | attribute { | 
|  | name: "hdrs" | 
|  | type: LABEL_LIST | 
|  | string_list_value: "//src/libs:sum.h" | 
|  | explicitly_specified: true | 
|  | nodep: false | 
|  | } | 
|  | attribute { | 
|  | name: "visibility" | 
|  | type: STRING_LIST | 
|  | string_list_value: "//visibility:public" | 
|  | explicitly_specified: true | 
|  | nodep: true | 
|  | } | 
|  | } | 
|  | }, | 
|  | } | 
|  | results { | 
|  | target { | 
|  | type: RULE | 
|  | rule { | 
|  | name: "//src/apps:hello" | 
|  | rule_class: "cc_binary" | 
|  | location: "/path/to/workspace/src/apps/BUILD.bazel:8:11" | 
|  | attribute { | 
|  | name: "copts" | 
|  | type: STRING_LIST | 
|  | string_list_value: "-O1" | 
|  | explicitly_specified: true | 
|  | nodep: false | 
|  | } | 
|  | attribute { | 
|  | name: "defines" | 
|  | type: STRING_LIST | 
|  | string_list_value: "APPDEF" | 
|  | explicitly_specified: false | 
|  | nodep: false | 
|  | } | 
|  | attribute { | 
|  | name: "linkopts" | 
|  | type: STRING_LIST | 
|  | string_list_value: "-L/app/dir" | 
|  | explicitly_specified: false | 
|  | nodep: false | 
|  | } | 
|  | attribute { | 
|  | name: "name" | 
|  | type: STRING | 
|  | string_value: "hello" | 
|  | explicitly_specified: true | 
|  | nodep: false | 
|  | } | 
|  | attribute { | 
|  | name: "srcs" | 
|  | type: LABEL_LIST | 
|  | string_list_value: "//src/apps:hello-world.cpp" | 
|  | explicitly_specified: true | 
|  | nodep: false | 
|  | } | 
|  | attribute { | 
|  | name: "deps" | 
|  | type: LABEL_LIST | 
|  | string_list_value: "//src/libs:sum" | 
|  | explicitly_specified: false | 
|  | nodep: false | 
|  | } | 
|  | attribute { | 
|  | name: "visibility" | 
|  | type: STRING_LIST | 
|  | string_list_value: "//visibility:public" | 
|  | explicitly_specified: true | 
|  | nodep: true | 
|  | } | 
|  | } | 
|  | } | 
|  | }` | 
|  |  | 
|  | // Return the workspace (cmakeWorkspace) for the test data. | 
|  | // | 
|  | // Note: this helper function makes no test assertions as the | 
|  | // Export function is already tested. | 
|  | func getTestWorkspace(t *testing.T) (cmakeWorkspace, error) { | 
|  | protoData, err := textProtoToProtobuf(workspaceTestTextProto) | 
|  | if err != nil { | 
|  | return cmakeWorkspace{}, skerr.Wrap(err) | 
|  | } | 
|  |  | 
|  | // Export to CMake buffer. | 
|  | fs := mocks.NewFileSystem(t) | 
|  | fs.On("OpenFile", mock.Anything).Return(new(bytes.Buffer), nil).Once() | 
|  | e := NewCMakeExporter("projName", workspaceTestWorkspaceDir, "CMakeLists.txt", fs) | 
|  | qcmd := mocks.NewQueryCommand(t) | 
|  | qcmd.On("Read", mock.Anything).Return(protoData, nil) | 
|  | err = e.Export(qcmd) | 
|  | if err != nil { | 
|  | return cmakeWorkspace{}, skerr.Wrap(err) | 
|  | } | 
|  |  | 
|  | return e.workspace, nil | 
|  | } | 
|  |  | 
|  | func TestIsGetRule_ValidName_ReturnsRule(t *testing.T) { | 
|  | workspace, err := getTestWorkspace(t) | 
|  | require.NoError(t, err) | 
|  |  | 
|  | r := workspace.getRule("//src/libs:sum") | 
|  | require.NotNil(t, r) | 
|  | assert.Equal(t, "//src/libs:sum", r.getName()) | 
|  | } | 
|  |  | 
|  | func TestIsGetRule_InvalidName_ReturnsNil(t *testing.T) { | 
|  | workspace, err := getTestWorkspace(t) | 
|  | require.NoError(t, err) | 
|  |  | 
|  | r := workspace.getRule("//non/existent:rule") | 
|  | assert.Nil(t, r) | 
|  | } | 
|  |  | 
|  | func TestCreateRule_ValidBazelRule_NotNil(t *testing.T) { | 
|  | workspace, err := getTestWorkspace(t) | 
|  | require.NoError(t, err) | 
|  |  | 
|  | // Get the rule from the existing workspace (since we can't make one) | 
|  | cmakeRule := workspace.getRule("//src/libs:sum") | 
|  | require.NotNil(t, cmakeRule) | 
|  |  | 
|  | otherWorkspace := newCMakeWorkspace() | 
|  | require.NotNil(t, otherWorkspace) | 
|  | otherCMakeRule := otherWorkspace.createRule(cmakeRule.rule) | 
|  | require.NotNil(t, otherCMakeRule) | 
|  | } | 
|  |  | 
|  | func TestIsRuleWritten_NotWritten_ReturnsFalse(t *testing.T) { | 
|  | var state writeState | 
|  | assert.False(t, state.isRuleWritten("//unwritten:rule")) | 
|  | } | 
|  |  | 
|  | func TestIsRuleWritten_Written_ReturnsTrue(t *testing.T) { | 
|  | var state writeState | 
|  | state.setRuleWritten("//written:rule") | 
|  | assert.True(t, state.isRuleWritten("//written:rule")) | 
|  | } |