mirror of
https://github.com/fleetdm/fleet
synced 2026-04-21 13:37:30 +00:00
fix: remove temporary functions in tests (#20615)
> Related issue: #20229 # Checklist for submitter If some of the following don't apply, delete the relevant line. <!-- Note that API documentation changes are now addressed by the product design team. --> See [Changes files](https://fleetdm.com/docs/contributing/committing-changes#changes-files) for more information. - [x] Added/updated tests - [x] Manual QA for all new/changed functionality
This commit is contained in:
parent
80faef8327
commit
caa7fd74e4
7 changed files with 64 additions and 122 deletions
|
|
@ -155,7 +155,7 @@ func (svc *Service) AddAppStoreApp(ctx context.Context, teamID *uint, adamID str
|
|||
Name: assetMD.TrackName,
|
||||
LatestVersion: assetMD.Version,
|
||||
}
|
||||
if err := svc.ds.InsertVPPAppWithTeam(ctx, app, teamID); err != nil {
|
||||
if _, err := svc.ds.InsertVPPAppWithTeam(ctx, app, teamID); err != nil {
|
||||
return ctxerr.Wrap(ctx, err, "writing VPP app to db")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3647,11 +3647,16 @@ func testListHostSoftware(t *testing.T, ds *Datastore) {
|
|||
require.Empty(t, sw)
|
||||
|
||||
// add VPP apps, one for both no team and team, and two for no-team only.
|
||||
vpp1, _ := createVPPApp(t, ds, nil, "vpp1", "com.app.vpp1")
|
||||
createVPPAppTeamOnly(t, ds, &tm.ID, vpp1)
|
||||
vpp2, _ := createVPPApp(t, ds, nil, "vpp2", "com.app.vpp2")
|
||||
vpp3, _ := createVPPApp(t, ds, nil, "vpp3", "com.app.vpp3")
|
||||
require.NotEmpty(t, vpp3)
|
||||
va1, err := ds.InsertVPPAppWithTeam(ctx, &fleet.VPPApp{AdamID: "adam_vpp_1", Name: "vpp1", BundleIdentifier: "com.app.vpp1"}, nil)
|
||||
require.NoError(t, err)
|
||||
_, err = ds.InsertVPPAppWithTeam(ctx, &fleet.VPPApp{AdamID: "adam_vpp_1", Name: "vpp1", BundleIdentifier: "com.app.vpp1"}, &tm.ID)
|
||||
require.NoError(t, err)
|
||||
vpp1 := va1.AdamID
|
||||
va2, err := ds.InsertVPPAppWithTeam(ctx, &fleet.VPPApp{AdamID: "adam_vpp_2", Name: "vpp2", BundleIdentifier: "com.app.vpp2"}, nil)
|
||||
require.NoError(t, err)
|
||||
va3, err := ds.InsertVPPAppWithTeam(ctx, &fleet.VPPApp{AdamID: "adam_vpp_3", Name: "vpp3", BundleIdentifier: "com.app.vpp3"}, nil)
|
||||
require.NoError(t, err)
|
||||
vpp2, vpp3 := va2.AdamID, va3.AdamID
|
||||
|
||||
// create an installation request for vpp1 and vpp2, leaving vpp3 as
|
||||
// available only
|
||||
|
|
|
|||
|
|
@ -2,10 +2,7 @@ package mysql
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"database/sql"
|
||||
"encoding/base64"
|
||||
"io"
|
||||
"sort"
|
||||
"testing"
|
||||
"time"
|
||||
|
|
@ -318,8 +315,8 @@ func testOrderSoftwareTitles(t *testing.T, ds *Datastore) {
|
|||
_, err = ds.InsertSoftwareInstallRequest(ctx, host1.ID, installer2, false)
|
||||
require.NoError(t, err)
|
||||
// create a VPP app not installed anywhere
|
||||
vpp1, _ := createVPPApp(t, ds, nil, "vpp1", "com.app.vpp1")
|
||||
require.NotEmpty(t, vpp1)
|
||||
_, err = ds.InsertVPPAppWithTeam(ctx, &fleet.VPPApp{Name: "vpp1", BundleIdentifier: "com.app.vpp1", AdamID: "adam_vpp_app_1"}, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, ds.SyncHostsSoftware(ctx, time.Now()))
|
||||
require.NoError(t, ds.ReconcileSoftwareTitles(ctx))
|
||||
|
|
@ -617,8 +614,8 @@ func testTeamFilterSoftwareTitles(t *testing.T, ds *Datastore) {
|
|||
require.NoError(t, err)
|
||||
require.NotZero(t, installer2)
|
||||
// create a VPP app for team2
|
||||
vpp2, _ := createVPPApp(t, ds, &team2.ID, "vpp2", "com.app.vpp2")
|
||||
require.NotEmpty(t, vpp2)
|
||||
_, err = ds.InsertVPPAppWithTeam(ctx, &fleet.VPPApp{Name: "vpp2", BundleIdentifier: "com.app.vpp2", AdamID: "adam_vpp_app_2"}, &team2.ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, ds.SyncHostsSoftware(ctx, time.Now()))
|
||||
require.NoError(t, ds.ReconcileSoftwareTitles(ctx))
|
||||
|
|
@ -800,8 +797,8 @@ func testListSoftwareTitlesInstallersOnly(t *testing.T, ds *Datastore) {
|
|||
require.NoError(t, err)
|
||||
require.NotZero(t, installer2)
|
||||
// create a VPP app not installed on a host
|
||||
vpp1, _ := createVPPApp(t, ds, nil, "vpp1", "com.app.vpp1")
|
||||
require.NotEmpty(t, vpp1)
|
||||
_, err = ds.InsertVPPAppWithTeam(ctx, &fleet.VPPApp{Name: "vpp1", BundleIdentifier: "com.app,vpp1", AdamID: "adam_vpp_app_1"}, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
titles, counts, _, err := ds.ListSoftwareTitles(ctx, fleet.SoftwareTitleListOptions{ListOptions: fleet.ListOptions{
|
||||
OrderKey: "name",
|
||||
|
|
@ -887,10 +884,10 @@ func testListSoftwareTitlesAvailableForInstallFilter(t *testing.T, ds *Datastore
|
|||
require.NotZero(t, installer2)
|
||||
|
||||
// create a couple VPP apps
|
||||
vpp1, _ := createVPPApp(t, ds, nil, "vpp1", "com.example.vpp1")
|
||||
require.NotEmpty(t, vpp1)
|
||||
vpp2, _ := createVPPApp(t, ds, nil, "vpp2", "com.example.vpp2")
|
||||
require.NotEmpty(t, vpp2)
|
||||
_, err = ds.InsertVPPAppWithTeam(ctx, &fleet.VPPApp{Name: "vpp1", BundleIdentifier: "com.example.vpp1", AdamID: "adam_vpp_app_1"}, nil)
|
||||
require.NoError(t, err)
|
||||
_, err = ds.InsertVPPAppWithTeam(ctx, &fleet.VPPApp{Name: "vpp2", BundleIdentifier: "com.example.vpp2", AdamID: "adam_vpp_app_2"}, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
host := test.NewHost(t, ds, "host", "", "hostkey", "hostuuid", time.Now())
|
||||
software := []fleet.Software{
|
||||
|
|
@ -947,45 +944,6 @@ func testListSoftwareTitlesAvailableForInstallFilter(t *testing.T, ds *Datastore
|
|||
require.ElementsMatch(t, []string{"installer1", "installer2", "vpp1", "vpp2"}, names)
|
||||
}
|
||||
|
||||
// creates the entry in vpp_apps and vpp_apps_teams, linking to a software
|
||||
// title, creating it if necessary. The source column is always "apps". Returns
|
||||
// the adam_id (auto-generated) and the software title id.
|
||||
// TODO: temporary, until datastore methods are available for VPP apps.
|
||||
func createVPPApp(t *testing.T, ds *Datastore, teamID *uint, name, bundle string) (string, uint) {
|
||||
ctx := context.Background()
|
||||
|
||||
rawBytes := make([]byte, 10)
|
||||
_, err := io.ReadFull(rand.Reader, rawBytes)
|
||||
require.NoError(t, err)
|
||||
adamID := base64.RawStdEncoding.EncodeToString(rawBytes)
|
||||
|
||||
titleID, err := ds.getOrGenerateSoftwareInstallerTitleID(ctx, &fleet.UploadSoftwareInstallerPayload{Title: name, Source: "apps", BundleIdentifier: bundle})
|
||||
require.NoError(t, err)
|
||||
|
||||
ExecAdhocSQL(t, ds, func(q sqlx.ExtContext) error {
|
||||
_, err := q.ExecContext(ctx, `INSERT INTO vpp_apps (adam_id, title_id, name, bundle_identifier) VALUES (?, ?, ?, ?)`,
|
||||
adamID, titleID, name, bundle)
|
||||
return err
|
||||
})
|
||||
|
||||
createVPPAppTeamOnly(t, ds, teamID, adamID)
|
||||
return adamID, titleID
|
||||
}
|
||||
|
||||
func createVPPAppTeamOnly(t *testing.T, ds *Datastore, teamID *uint, adamID string) {
|
||||
ctx := context.Background()
|
||||
|
||||
ExecAdhocSQL(t, ds, func(q sqlx.ExtContext) error {
|
||||
var globalOrTeamID uint
|
||||
if teamID != nil {
|
||||
globalOrTeamID = *teamID
|
||||
}
|
||||
_, err := q.ExecContext(ctx, `INSERT INTO vpp_apps_teams (adam_id, team_id, global_or_team_id) VALUES (?, ?, ?)`,
|
||||
adamID, teamID, globalOrTeamID)
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
func testUploadedSoftwareExists(t *testing.T, ds *Datastore) {
|
||||
ctx := context.Background()
|
||||
|
||||
|
|
|
|||
|
|
@ -141,8 +141,8 @@ func (ds *Datastore) BatchInsertVPPApps(ctx context.Context, apps []*fleet.VPPAp
|
|||
})
|
||||
}
|
||||
|
||||
func (ds *Datastore) InsertVPPAppWithTeam(ctx context.Context, app *fleet.VPPApp, teamID *uint) error {
|
||||
return ds.withRetryTxx(ctx, func(tx sqlx.ExtContext) error {
|
||||
func (ds *Datastore) InsertVPPAppWithTeam(ctx context.Context, app *fleet.VPPApp, teamID *uint) (*fleet.VPPApp, error) {
|
||||
err := ds.withRetryTxx(ctx, func(tx sqlx.ExtContext) error {
|
||||
titleID, err := ds.getOrInsertSoftwareTitleForVPPApp(ctx, tx, app)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -160,6 +160,11 @@ func (ds *Datastore) InsertVPPAppWithTeam(ctx context.Context, app *fleet.VPPApp
|
|||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return app, nil
|
||||
}
|
||||
|
||||
func (ds *Datastore) GetAssignedVPPApps(ctx context.Context, teamID *uint) (map[string]struct{}, error) {
|
||||
|
|
|
|||
|
|
@ -52,7 +52,9 @@ func testVPPAppMetadata(t *testing.T, ds *Datastore) {
|
|||
require.Nil(t, meta)
|
||||
|
||||
// create no-team app
|
||||
vpp1, titleID1 := createVPPApp(t, ds, nil, "vpp1", "com.app.vpp1")
|
||||
va1, err := ds.InsertVPPAppWithTeam(ctx, &fleet.VPPApp{Name: "vpp1", BundleIdentifier: "com.app.vpp1", AdamID: "adam_vpp_app_1"}, nil)
|
||||
require.NoError(t, err)
|
||||
vpp1, titleID1 := va1.AdamID, va1.TitleID
|
||||
|
||||
// get no-team app
|
||||
meta, err = ds.GetVPPAppMetadataByTeamAndTitleID(ctx, nil, titleID1)
|
||||
|
|
@ -60,7 +62,9 @@ func testVPPAppMetadata(t *testing.T, ds *Datastore) {
|
|||
require.Equal(t, &fleet.VPPAppStoreApp{Name: "vpp1", AppStoreID: vpp1}, meta)
|
||||
|
||||
// create team1 app
|
||||
vpp2, titleID2 := createVPPApp(t, ds, &team1.ID, "vpp2", "com.app.vpp2")
|
||||
va2, err := ds.InsertVPPAppWithTeam(ctx, &fleet.VPPApp{Name: "vpp2", BundleIdentifier: "com.app.vpp2", AdamID: "adam_vpp_app_2"}, &team1.ID)
|
||||
require.NoError(t, err)
|
||||
vpp2, titleID2 := va2.AdamID, va2.TitleID
|
||||
|
||||
// get it for team 1
|
||||
meta, err = ds.GetVPPAppMetadataByTeamAndTitleID(ctx, &team1.ID, titleID2)
|
||||
|
|
@ -74,7 +78,8 @@ func testVPPAppMetadata(t *testing.T, ds *Datastore) {
|
|||
require.Nil(t, meta)
|
||||
|
||||
// create the same app for team2
|
||||
createVPPAppTeamOnly(t, ds, &team2.ID, vpp2)
|
||||
_, err = ds.InsertVPPAppWithTeam(ctx, &fleet.VPPApp{Name: "vpp2", BundleIdentifier: "com.app.vpp2", AdamID: "adam_vpp_app_2"}, &team2.ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
// get it for team 1 and team 2, both work
|
||||
meta, err = ds.GetVPPAppMetadataByTeamAndTitleID(ctx, &team1.ID, titleID2)
|
||||
|
|
@ -85,7 +90,9 @@ func testVPPAppMetadata(t *testing.T, ds *Datastore) {
|
|||
require.Equal(t, &fleet.VPPAppStoreApp{Name: "vpp2", AppStoreID: vpp2}, meta)
|
||||
|
||||
// create another no-team app
|
||||
vpp3, titleID3 := createVPPApp(t, ds, nil, "vpp3", "com.app.vpp3")
|
||||
va3, err := ds.InsertVPPAppWithTeam(ctx, &fleet.VPPApp{Name: "vpp3", BundleIdentifier: "com.app.vpp3", AdamID: "adam_vpp_app_3"}, nil)
|
||||
require.NoError(t, err)
|
||||
vpp3, titleID3 := va3.AdamID, va3.TitleID
|
||||
|
||||
// get it for team 2, does not exist
|
||||
meta, err = ds.GetVPPAppMetadataByTeamAndTitleID(ctx, &team2.ID, titleID3)
|
||||
|
|
@ -158,10 +165,17 @@ func testVPPAppStatus(t *testing.T, ds *Datastore) {
|
|||
require.NotNil(t, team1)
|
||||
|
||||
// create some apps, one for no-team, one for team1, and one in both
|
||||
vpp1, _ := createVPPApp(t, ds, nil, "vpp1", "com.app.vpp1")
|
||||
vpp2, _ := createVPPApp(t, ds, &team1.ID, "vpp2", "com.app.vpp2")
|
||||
vpp3, _ := createVPPApp(t, ds, nil, "vpp3", "com.app.vpp3")
|
||||
createVPPAppTeamOnly(t, ds, &team1.ID, vpp3)
|
||||
va1, err := ds.InsertVPPAppWithTeam(ctx, &fleet.VPPApp{Name: "vpp1", BundleIdentifier: "com.app.vpp1", AdamID: "adam_vpp_app_1"}, nil)
|
||||
require.NoError(t, err)
|
||||
vpp1 := va1.AdamID
|
||||
va2, err := ds.InsertVPPAppWithTeam(ctx, &fleet.VPPApp{Name: "vpp2", BundleIdentifier: "com.app.vpp2", AdamID: "adam_vpp_app_2"}, &team1.ID)
|
||||
require.NoError(t, err)
|
||||
vpp2 := va2.AdamID
|
||||
va3, err := ds.InsertVPPAppWithTeam(ctx, &fleet.VPPApp{Name: "vpp3", BundleIdentifier: "com.app.vpp3", AdamID: "adam_vpp_app_3"}, nil)
|
||||
require.NoError(t, err)
|
||||
vpp3 := va3.AdamID
|
||||
_, err = ds.InsertVPPAppWithTeam(ctx, &fleet.VPPApp{Name: "vpp3", BundleIdentifier: "com.app.vpp3", AdamID: "adam_vpp_app_3"}, &team1.ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
// for now they all return zeroes
|
||||
summary, err := ds.GetSummaryHostVPPAppInstalls(ctx, nil, vpp1)
|
||||
|
|
@ -339,18 +353,18 @@ func testVPPApps(t *testing.T, ds *Datastore) {
|
|||
// Insert some VPP apps for the team, "vpp_app_1" should match the existing "foo" title
|
||||
app1 := &fleet.VPPApp{Name: "vpp_app_1", AdamID: "1", BundleIdentifier: "b1"}
|
||||
app2 := &fleet.VPPApp{Name: "vpp_app_2", AdamID: "2", BundleIdentifier: "b2"}
|
||||
err = ds.InsertVPPAppWithTeam(ctx, app1, &team.ID)
|
||||
_, err = ds.InsertVPPAppWithTeam(ctx, app1, &team.ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = ds.InsertVPPAppWithTeam(ctx, app2, &team.ID)
|
||||
_, err = ds.InsertVPPAppWithTeam(ctx, app2, &team.ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Insert some VPP apps for no team
|
||||
appNoTeam1 := &fleet.VPPApp{Name: "vpp_no_team_app_1", AdamID: "3", BundleIdentifier: "b3"}
|
||||
appNoTeam2 := &fleet.VPPApp{Name: "vpp_no_team_app_2", AdamID: "4", BundleIdentifier: "b4"}
|
||||
err = ds.InsertVPPAppWithTeam(ctx, appNoTeam1, nil)
|
||||
_, err = ds.InsertVPPAppWithTeam(ctx, appNoTeam1, nil)
|
||||
require.NoError(t, err)
|
||||
err = ds.InsertVPPAppWithTeam(ctx, appNoTeam2, nil)
|
||||
_, err = ds.InsertVPPAppWithTeam(ctx, appNoTeam2, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Check that host_vpp_software_installs works
|
||||
|
|
@ -414,54 +428,12 @@ func testGetVPPAppByTeamAndTitleID(t *testing.T, ds *Datastore) {
|
|||
team, err := ds.NewTeam(ctx, &fleet.Team{Name: "team 2"})
|
||||
require.NoError(t, err)
|
||||
|
||||
// TODO(roberto): replace with actual datastore method(s) once we have them
|
||||
createVPPApp := func(adamID string, teamID *uint) uint {
|
||||
var titleID int64
|
||||
ExecAdhocSQL(t, ds, func(tx sqlx.ExtContext) error {
|
||||
res, err := tx.ExecContext(
|
||||
ctx,
|
||||
"INSERT INTO software_titles (name, source, browser) VALUES (?, ?, ?)",
|
||||
uuid.NewString(), uuid.NewString(), "",
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
titleID, _ = res.LastInsertId()
|
||||
return nil
|
||||
})
|
||||
|
||||
ExecAdhocSQL(t, ds, func(tx sqlx.ExtContext) error {
|
||||
_, err = tx.ExecContext(
|
||||
ctx,
|
||||
"INSERT INTO vpp_apps (adam_id, title_id) VALUES (?, ?)",
|
||||
adamID,
|
||||
titleID,
|
||||
)
|
||||
return err
|
||||
})
|
||||
|
||||
ExecAdhocSQL(t, ds, func(tx sqlx.ExtContext) error {
|
||||
var tmID uint
|
||||
if teamID != nil {
|
||||
tmID = *teamID
|
||||
}
|
||||
_, err = tx.ExecContext(
|
||||
ctx,
|
||||
"INSERT INTO vpp_apps_teams (adam_id, team_id, global_or_team_id) VALUES (?, ?, ?)",
|
||||
adamID,
|
||||
teamID,
|
||||
tmID,
|
||||
)
|
||||
return err
|
||||
})
|
||||
|
||||
return uint(titleID)
|
||||
}
|
||||
|
||||
var nfe fleet.NotFoundError
|
||||
|
||||
fooTitleID := createVPPApp("foo", &team.ID)
|
||||
fooApp, err := ds.InsertVPPAppWithTeam(ctx, &fleet.VPPApp{AdamID: "foo", BundleIdentifier: "b1", Name: "Foo"}, &team.ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
fooTitleID := fooApp.TitleID
|
||||
gotVPPApp, err := ds.GetVPPAppByTeamAndTitleID(ctx, &team.ID, fooTitleID, true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "foo", gotVPPApp.AdamID)
|
||||
|
|
@ -471,7 +443,9 @@ func testGetVPPAppByTeamAndTitleID(t *testing.T, ds *Datastore) {
|
|||
require.ErrorAs(t, err, &nfe)
|
||||
|
||||
// create an entry for the global team
|
||||
barTitleID := createVPPApp("bar", nil)
|
||||
barApp, err := ds.InsertVPPAppWithTeam(ctx, &fleet.VPPApp{AdamID: "bar", BundleIdentifier: "b2", Name: "Bar"}, nil)
|
||||
require.NoError(t, err)
|
||||
barTitleID := barApp.TitleID
|
||||
// not found providing the team id
|
||||
gotVPPApp, err = ds.GetVPPAppByTeamAndTitleID(ctx, &team.ID, barTitleID, true)
|
||||
require.ErrorAs(t, err, &nfe)
|
||||
|
|
|
|||
|
|
@ -1590,7 +1590,7 @@ type Datastore interface {
|
|||
|
||||
BatchInsertVPPApps(ctx context.Context, apps []*VPPApp) error
|
||||
GetAssignedVPPApps(ctx context.Context, teamID *uint) (map[string]struct{}, error)
|
||||
InsertVPPAppWithTeam(ctx context.Context, app *VPPApp, teamID *uint) error
|
||||
InsertVPPAppWithTeam(ctx context.Context, app *VPPApp, teamID *uint) (*VPPApp, error)
|
||||
InsertHostVPPSoftwareInstall(ctx context.Context, hostID, userID uint, adamID, commandUUID, associatedEventID string) error
|
||||
GetPastActivityDataForVPPAppInstall(ctx context.Context, commandResults *mdm.CommandResults) (*User, *ActivityInstalledAppStoreApp, error)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1004,7 +1004,7 @@ type BatchInsertVPPAppsFunc func(ctx context.Context, apps []*fleet.VPPApp) erro
|
|||
|
||||
type GetAssignedVPPAppsFunc func(ctx context.Context, teamID *uint) (map[string]struct{}, error)
|
||||
|
||||
type InsertVPPAppWithTeamFunc func(ctx context.Context, app *fleet.VPPApp, teamID *uint) error
|
||||
type InsertVPPAppWithTeamFunc func(ctx context.Context, app *fleet.VPPApp, teamID *uint) (*fleet.VPPApp, error)
|
||||
|
||||
type InsertHostVPPSoftwareInstallFunc func(ctx context.Context, hostID uint, userID uint, adamID string, commandUUID string, associatedEventID string) error
|
||||
|
||||
|
|
@ -5943,7 +5943,7 @@ func (s *DataStore) GetAssignedVPPApps(ctx context.Context, teamID *uint) (map[s
|
|||
return s.GetAssignedVPPAppsFunc(ctx, teamID)
|
||||
}
|
||||
|
||||
func (s *DataStore) InsertVPPAppWithTeam(ctx context.Context, app *fleet.VPPApp, teamID *uint) error {
|
||||
func (s *DataStore) InsertVPPAppWithTeam(ctx context.Context, app *fleet.VPPApp, teamID *uint) (*fleet.VPPApp, error) {
|
||||
s.mu.Lock()
|
||||
s.InsertVPPAppWithTeamFuncInvoked = true
|
||||
s.mu.Unlock()
|
||||
|
|
|
|||
Loading…
Reference in a new issue