| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345 |
- // Copyright (c) Tailscale Inc & AUTHORS
- // SPDX-License-Identifier: BSD-3-Clause
- package setting
- import (
- "slices"
- "strings"
- "testing"
- "tailscale.com/types/lazy"
- "tailscale.com/types/ptr"
- "tailscale.com/util/syspolicy/internal"
- "tailscale.com/util/syspolicy/pkey"
- )
- func TestSettingDefinition(t *testing.T) {
- tests := []struct {
- name string
- setting *Definition
- osOverride string
- wantKey pkey.Key
- wantScope Scope
- wantType Type
- wantIsSupported bool
- wantSupportedPlatforms PlatformList
- wantString string
- }{
- {
- name: "Nil",
- setting: nil,
- wantKey: "",
- wantScope: 0,
- wantType: InvalidValue,
- wantIsSupported: false,
- wantString: "(nil)",
- },
- {
- name: "Device/Invalid",
- setting: NewDefinition("TestDevicePolicySetting", DeviceSetting, InvalidValue),
- wantKey: "TestDevicePolicySetting",
- wantScope: DeviceSetting,
- wantType: InvalidValue,
- wantIsSupported: true,
- wantString: `Device("TestDevicePolicySetting", Invalid)`,
- },
- {
- name: "Device/Integer",
- setting: NewDefinition("TestDevicePolicySetting", DeviceSetting, IntegerValue),
- wantKey: "TestDevicePolicySetting",
- wantScope: DeviceSetting,
- wantType: IntegerValue,
- wantIsSupported: true,
- wantString: `Device("TestDevicePolicySetting", Integer)`,
- },
- {
- name: "Profile/String",
- setting: NewDefinition("TestProfilePolicySetting", ProfileSetting, StringValue),
- wantKey: "TestProfilePolicySetting",
- wantScope: ProfileSetting,
- wantType: StringValue,
- wantIsSupported: true,
- wantString: `Profile("TestProfilePolicySetting", String)`,
- },
- {
- name: "Device/StringList",
- setting: NewDefinition("AllowedSuggestedExitNodes", DeviceSetting, StringListValue),
- wantKey: "AllowedSuggestedExitNodes",
- wantScope: DeviceSetting,
- wantType: StringListValue,
- wantIsSupported: true,
- wantString: `Device("AllowedSuggestedExitNodes", StringList)`,
- },
- {
- name: "Device/PreferenceOption",
- setting: NewDefinition("AdvertiseExitNode", DeviceSetting, PreferenceOptionValue),
- wantKey: "AdvertiseExitNode",
- wantScope: DeviceSetting,
- wantType: PreferenceOptionValue,
- wantIsSupported: true,
- wantString: `Device("AdvertiseExitNode", PreferenceOption)`,
- },
- {
- name: "User/Boolean",
- setting: NewDefinition("TestUserPolicySetting", UserSetting, BooleanValue),
- wantKey: "TestUserPolicySetting",
- wantScope: UserSetting,
- wantType: BooleanValue,
- wantIsSupported: true,
- wantString: `User("TestUserPolicySetting", Boolean)`,
- },
- {
- name: "User/Visibility",
- setting: NewDefinition("AdminConsole", UserSetting, VisibilityValue),
- wantKey: "AdminConsole",
- wantScope: UserSetting,
- wantType: VisibilityValue,
- wantIsSupported: true,
- wantString: `User("AdminConsole", Visibility)`,
- },
- {
- name: "User/Duration",
- setting: NewDefinition("KeyExpirationNotice", UserSetting, DurationValue),
- wantKey: "KeyExpirationNotice",
- wantScope: UserSetting,
- wantType: DurationValue,
- wantIsSupported: true,
- wantString: `User("KeyExpirationNotice", Duration)`,
- },
- {
- name: "SupportedSetting",
- setting: NewDefinition("DesktopPolicySetting", DeviceSetting, StringValue, "macos", "windows"),
- osOverride: "windows",
- wantKey: "DesktopPolicySetting",
- wantScope: DeviceSetting,
- wantType: StringValue,
- wantIsSupported: true,
- wantSupportedPlatforms: PlatformList{"macos", "windows"},
- wantString: `Device("DesktopPolicySetting", String)`,
- },
- {
- name: "UnsupportedSetting",
- setting: NewDefinition("AndroidPolicySetting", DeviceSetting, StringValue, "android"),
- osOverride: "macos",
- wantKey: "AndroidPolicySetting",
- wantScope: DeviceSetting,
- wantType: StringValue,
- wantIsSupported: false,
- wantSupportedPlatforms: PlatformList{"android"},
- wantString: `Device("AndroidPolicySetting", String)`,
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- if tt.osOverride != "" {
- internal.OSForTesting.SetForTest(t, tt.osOverride, nil)
- }
- if !tt.setting.Equal(tt.setting) {
- t.Errorf("the setting should be equal to itself")
- }
- if tt.setting != nil && !tt.setting.Equal(ptr.To(*tt.setting)) {
- t.Errorf("the setting should be equal to its shallow copy")
- }
- if gotKey := tt.setting.Key(); gotKey != tt.wantKey {
- t.Errorf("Key: got %q, want %q", gotKey, tt.wantKey)
- }
- if gotScope := tt.setting.Scope(); gotScope != tt.wantScope {
- t.Errorf("Scope: got %v, want %v", gotScope, tt.wantScope)
- }
- if gotType := tt.setting.Type(); gotType != tt.wantType {
- t.Errorf("Type: got %v, want %v", gotType, tt.wantType)
- }
- if gotIsSupported := tt.setting.IsSupported(); gotIsSupported != tt.wantIsSupported {
- t.Errorf("IsSupported: got %v, want %v", gotIsSupported, tt.wantIsSupported)
- }
- if gotSupportedPlatforms := tt.setting.SupportedPlatforms(); !slices.Equal(gotSupportedPlatforms, tt.wantSupportedPlatforms) {
- t.Errorf("SupportedPlatforms: got %v, want %v", gotSupportedPlatforms, tt.wantSupportedPlatforms)
- }
- if gotString := tt.setting.String(); gotString != tt.wantString {
- t.Errorf("String: got %v, want %v", gotString, tt.wantString)
- }
- })
- }
- }
- func TestRegisterSettingDefinition(t *testing.T) {
- const testPolicySettingKey pkey.Key = "TestPolicySetting"
- tests := []struct {
- name string
- key pkey.Key
- wantEq *Definition
- wantErr error
- }{
- {
- name: "GetRegistered",
- key: "TestPolicySetting",
- wantEq: NewDefinition(testPolicySettingKey, DeviceSetting, StringValue),
- },
- {
- name: "GetNonRegistered",
- key: "OtherPolicySetting",
- wantEq: nil,
- wantErr: ErrNoSuchKey,
- },
- }
- resetSettingDefinitions(t)
- Register(testPolicySettingKey, DeviceSetting, StringValue)
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- got, gotErr := DefinitionOf(tt.key)
- if gotErr != tt.wantErr {
- t.Errorf("gotErr %v, wantErr %v", gotErr, tt.wantErr)
- }
- if !got.Equal(tt.wantEq) {
- t.Errorf("got %v, want %v", got, tt.wantEq)
- }
- })
- }
- }
- func TestRegisterAfterUsePanics(t *testing.T) {
- resetSettingDefinitions(t)
- Register("TestPolicySetting", DeviceSetting, StringValue)
- DefinitionOf("TestPolicySetting")
- func() {
- defer func() {
- if gotPanic, wantPanic := recover(), "policy definitions are already in use"; gotPanic != wantPanic {
- t.Errorf("gotPanic: %q, wantPanic: %q", gotPanic, wantPanic)
- }
- }()
- Register("TestPolicySetting", DeviceSetting, StringValue)
- }()
- }
- func TestRegisterDuplicateSettings(t *testing.T) {
- tests := []struct {
- name string
- settings []*Definition
- wantEq *Definition
- wantErrStr string
- }{
- {
- name: "NoConflict/Exact",
- settings: []*Definition{
- NewDefinition("TestPolicySetting", DeviceSetting, StringValue),
- NewDefinition("TestPolicySetting", DeviceSetting, StringValue),
- },
- wantEq: NewDefinition("TestPolicySetting", DeviceSetting, StringValue),
- },
- {
- name: "NoConflict/MergeOS-First",
- settings: []*Definition{
- NewDefinition("TestPolicySetting", DeviceSetting, StringValue, "android", "macos"),
- NewDefinition("TestPolicySetting", DeviceSetting, StringValue), // all platforms
- },
- wantEq: NewDefinition("TestPolicySetting", DeviceSetting, StringValue), // all platforms
- },
- {
- name: "NoConflict/MergeOS-Second",
- settings: []*Definition{
- NewDefinition("TestPolicySetting", DeviceSetting, StringValue), // all platforms
- NewDefinition("TestPolicySetting", DeviceSetting, StringValue, "android", "macos"),
- },
- wantEq: NewDefinition("TestPolicySetting", DeviceSetting, StringValue), // all platforms
- },
- {
- name: "NoConflict/MergeOS-Both",
- settings: []*Definition{
- NewDefinition("TestPolicySetting", DeviceSetting, StringValue, "macos"),
- NewDefinition("TestPolicySetting", DeviceSetting, StringValue, "windows"),
- },
- wantEq: NewDefinition("TestPolicySetting", DeviceSetting, StringValue, "macos", "windows"),
- },
- {
- name: "Conflict/Scope",
- settings: []*Definition{
- NewDefinition("TestPolicySetting", DeviceSetting, StringValue),
- NewDefinition("TestPolicySetting", UserSetting, StringValue),
- },
- wantEq: nil,
- wantErrStr: `duplicate policy definition: "TestPolicySetting"`,
- },
- {
- name: "Conflict/Type",
- settings: []*Definition{
- NewDefinition("TestPolicySetting", UserSetting, StringValue),
- NewDefinition("TestPolicySetting", UserSetting, IntegerValue),
- },
- wantEq: nil,
- wantErrStr: `duplicate policy definition: "TestPolicySetting"`,
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- resetSettingDefinitions(t)
- for _, s := range tt.settings {
- Register(s.Key(), s.Scope(), s.Type(), s.SupportedPlatforms()...)
- }
- got, err := DefinitionOf("TestPolicySetting")
- var gotErrStr string
- if err != nil {
- gotErrStr = err.Error()
- }
- if gotErrStr != tt.wantErrStr {
- t.Fatalf("ErrStr: got %q, want %q", gotErrStr, tt.wantErrStr)
- }
- if !got.Equal(tt.wantEq) {
- t.Errorf("Definition got %v, want %v", got, tt.wantEq)
- }
- if !slices.Equal(got.SupportedPlatforms(), tt.wantEq.SupportedPlatforms()) {
- t.Errorf("SupportedPlatforms got %v, want %v", got.SupportedPlatforms(), tt.wantEq.SupportedPlatforms())
- }
- })
- }
- }
- func TestListSettingDefinitions(t *testing.T) {
- definitions := []*Definition{
- NewDefinition("TestDevicePolicySetting", DeviceSetting, IntegerValue),
- NewDefinition("TestProfilePolicySetting", ProfileSetting, StringValue),
- NewDefinition("TestUserPolicySetting", UserSetting, BooleanValue),
- NewDefinition("TestStringListPolicySetting", DeviceSetting, StringListValue),
- }
- if err := SetDefinitionsForTest(t, definitions...); err != nil {
- t.Fatalf("SetDefinitionsForTest failed: %v", err)
- }
- cmp := func(a, b *Definition) int {
- return strings.Compare(string(a.Key()), string(b.Key()))
- }
- want := append([]*Definition{}, definitions...)
- slices.SortFunc(want, cmp)
- got, err := Definitions()
- if err != nil {
- t.Fatalf("Definitions failed: %v", err)
- }
- slices.SortFunc(got, cmp)
- if !slices.Equal(got, want) {
- t.Errorf("got %v, want %v", got, want)
- }
- }
- func resetSettingDefinitions(t *testing.T) {
- t.Cleanup(func() {
- definitionsMu.Lock()
- definitionsList = nil
- definitions = lazy.SyncValue[DefinitionMap]{}
- definitionsUsed = false
- definitionsMu.Unlock()
- })
- definitionsMu.Lock()
- definitionsList = nil
- definitions = lazy.SyncValue[DefinitionMap]{}
- definitionsUsed = false
- definitionsMu.Unlock()
- }
|