gitee.com/mysnapcore/mysnapd@v0.1.0/interfaces/ifacetest/testiface.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2015-2017 Canonical Ltd
     5   *
     6   * This program is free software: you can redistribute it and/or modify
     7   * it under the terms of the GNU General Public License version 3 as
     8   * published by the Free Software Foundation.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  package ifacetest
    21  
    22  import (
    23  	"gitee.com/mysnapcore/mysnapd/interfaces"
    24  	"gitee.com/mysnapcore/mysnapd/interfaces/apparmor"
    25  	"gitee.com/mysnapcore/mysnapd/interfaces/dbus"
    26  	"gitee.com/mysnapcore/mysnapd/interfaces/hotplug"
    27  	"gitee.com/mysnapcore/mysnapd/interfaces/kmod"
    28  	"gitee.com/mysnapcore/mysnapd/interfaces/mount"
    29  	"gitee.com/mysnapcore/mysnapd/interfaces/polkit"
    30  	"gitee.com/mysnapcore/mysnapd/interfaces/seccomp"
    31  	"gitee.com/mysnapcore/mysnapd/interfaces/systemd"
    32  	"gitee.com/mysnapcore/mysnapd/interfaces/udev"
    33  	"gitee.com/mysnapcore/mysnapd/snap"
    34  )
    35  
    36  // TestInterface is a interface for various kind of tests.
    37  // It is public so that it can be consumed from other packages.
    38  type TestInterface struct {
    39  	// InterfaceName is the name of this interface
    40  	InterfaceName       string
    41  	InterfaceStaticInfo interfaces.StaticInfo
    42  	// AutoConnectCallback is the callback invoked inside AutoConnect
    43  	AutoConnectCallback func(*snap.PlugInfo, *snap.SlotInfo) bool
    44  	// BeforePreparePlugCallback is the callback invoked inside BeforePreparePlug()
    45  	BeforePreparePlugCallback func(plug *snap.PlugInfo) error
    46  	// BeforePrepareSlotCallback is the callback invoked inside BeforePrepareSlot()
    47  	BeforePrepareSlotCallback func(slot *snap.SlotInfo) error
    48  
    49  	BeforeConnectPlugCallback func(plug *interfaces.ConnectedPlug) error
    50  	BeforeConnectSlotCallback func(slot *interfaces.ConnectedSlot) error
    51  
    52  	// Support for interacting with the test backend.
    53  
    54  	TestConnectedPlugCallback func(spec *Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error
    55  	TestConnectedSlotCallback func(spec *Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error
    56  	TestPermanentPlugCallback func(spec *Specification, plug *snap.PlugInfo) error
    57  	TestPermanentSlotCallback func(spec *Specification, slot *snap.SlotInfo) error
    58  
    59  	// Support for interacting with the mount backend.
    60  
    61  	MountConnectedPlugCallback func(spec *mount.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error
    62  	MountConnectedSlotCallback func(spec *mount.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error
    63  	MountPermanentPlugCallback func(spec *mount.Specification, plug *snap.PlugInfo) error
    64  	MountPermanentSlotCallback func(spec *mount.Specification, slot *snap.SlotInfo) error
    65  
    66  	// Support for interacting with the udev backend.
    67  
    68  	UDevConnectedPlugCallback func(spec *udev.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error
    69  	UDevConnectedSlotCallback func(spec *udev.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error
    70  	UDevPermanentPlugCallback func(spec *udev.Specification, plug *snap.PlugInfo) error
    71  	UDevPermanentSlotCallback func(spec *udev.Specification, slot *snap.SlotInfo) error
    72  
    73  	// Support for interacting with the apparmor backend.
    74  
    75  	AppArmorConnectedPlugCallback func(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error
    76  	AppArmorConnectedSlotCallback func(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error
    77  	AppArmorPermanentPlugCallback func(spec *apparmor.Specification, plug *snap.PlugInfo) error
    78  	AppArmorPermanentSlotCallback func(spec *apparmor.Specification, slot *snap.SlotInfo) error
    79  
    80  	// Support for interacting with the kmod backend.
    81  
    82  	KModConnectedPlugCallback func(spec *kmod.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error
    83  	KModConnectedSlotCallback func(spec *kmod.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error
    84  	KModPermanentPlugCallback func(spec *kmod.Specification, plug *snap.PlugInfo) error
    85  	KModPermanentSlotCallback func(spec *kmod.Specification, slot *snap.SlotInfo) error
    86  
    87  	// Support for interacting with the seccomp backend.
    88  
    89  	SecCompConnectedPlugCallback func(spec *seccomp.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error
    90  	SecCompConnectedSlotCallback func(spec *seccomp.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error
    91  	SecCompPermanentPlugCallback func(spec *seccomp.Specification, plug *snap.PlugInfo) error
    92  	SecCompPermanentSlotCallback func(spec *seccomp.Specification, slot *snap.SlotInfo) error
    93  
    94  	// Support for interacting with the dbus backend.
    95  
    96  	DBusConnectedPlugCallback func(spec *dbus.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error
    97  	DBusConnectedSlotCallback func(spec *dbus.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error
    98  	DBusPermanentPlugCallback func(spec *dbus.Specification, plug *snap.PlugInfo) error
    99  	DBusPermanentSlotCallback func(spec *dbus.Specification, slot *snap.SlotInfo) error
   100  
   101  	// Support for interacting with the systemd backend.
   102  
   103  	SystemdConnectedPlugCallback func(spec *systemd.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error
   104  	SystemdConnectedSlotCallback func(spec *systemd.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error
   105  	SystemdPermanentPlugCallback func(spec *systemd.Specification, plug *snap.PlugInfo) error
   106  	SystemdPermanentSlotCallback func(spec *systemd.Specification, slot *snap.SlotInfo) error
   107  
   108  	// Support for interacting with the polkit backend.
   109  
   110  	PolkitConnectedPlugCallback func(spec *polkit.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error
   111  	PolkitConnectedSlotCallback func(spec *polkit.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error
   112  	PolkitPermanentPlugCallback func(spec *polkit.Specification, plug *snap.PlugInfo) error
   113  	PolkitPermanentSlotCallback func(spec *polkit.Specification, slot *snap.SlotInfo) error
   114  }
   115  
   116  // TestHotplugInterface is an interface for various kinds of tests
   117  // needing a hotplug-aware interface.  It is public so that it can be
   118  // consumed from other packages.
   119  type TestHotplugInterface struct {
   120  	TestInterface
   121  
   122  	// Support for interacting with hotplug subsystem.
   123  	HotplugKeyCallback            func(deviceInfo *hotplug.HotplugDeviceInfo) (snap.HotplugKey, error)
   124  	HandledByGadgetCallback       func(deviceInfo *hotplug.HotplugDeviceInfo, slot *snap.SlotInfo) bool
   125  	HotplugDeviceDetectedCallback func(deviceInfo *hotplug.HotplugDeviceInfo) (*hotplug.ProposedSlot, error)
   126  }
   127  
   128  // String() returns the same value as Name().
   129  func (t *TestInterface) String() string {
   130  	return t.Name()
   131  }
   132  
   133  // Name returns the name of the test interface.
   134  func (t *TestInterface) Name() string {
   135  	return t.InterfaceName
   136  }
   137  
   138  func (t *TestInterface) StaticInfo() interfaces.StaticInfo {
   139  	return t.InterfaceStaticInfo
   140  }
   141  
   142  // BeforePreparePlug checks and possibly modifies a plug.
   143  func (t *TestInterface) BeforePreparePlug(plug *snap.PlugInfo) error {
   144  	if t.BeforePreparePlugCallback != nil {
   145  		return t.BeforePreparePlugCallback(plug)
   146  	}
   147  	return nil
   148  }
   149  
   150  // BeforePrepareSlot checks and possibly modifies a slot.
   151  func (t *TestInterface) BeforePrepareSlot(slot *snap.SlotInfo) error {
   152  	if t.BeforePrepareSlotCallback != nil {
   153  		return t.BeforePrepareSlotCallback(slot)
   154  	}
   155  	return nil
   156  }
   157  
   158  func (t *TestInterface) BeforeConnectPlug(plug *interfaces.ConnectedPlug) error {
   159  	if t.BeforeConnectPlugCallback != nil {
   160  		return t.BeforeConnectPlugCallback(plug)
   161  	}
   162  	return nil
   163  }
   164  
   165  func (t *TestInterface) BeforeConnectSlot(slot *interfaces.ConnectedSlot) error {
   166  	if t.BeforeConnectSlotCallback != nil {
   167  		return t.BeforeConnectSlotCallback(slot)
   168  	}
   169  	return nil
   170  }
   171  
   172  // AutoConnect returns whether plug and slot should be implicitly
   173  // auto-connected assuming they will be an unambiguous connection
   174  // candidate.
   175  func (t *TestInterface) AutoConnect(plug *snap.PlugInfo, slot *snap.SlotInfo) bool {
   176  	if t.AutoConnectCallback != nil {
   177  		return t.AutoConnectCallback(plug, slot)
   178  	}
   179  	return true
   180  }
   181  
   182  // Support for interacting with the test backend.
   183  
   184  func (t *TestInterface) TestConnectedPlug(spec *Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   185  	if t.TestConnectedPlugCallback != nil {
   186  		return t.TestConnectedPlugCallback(spec, plug, slot)
   187  	}
   188  	return nil
   189  }
   190  
   191  func (t *TestInterface) TestConnectedSlot(spec *Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   192  	if t.TestConnectedSlotCallback != nil {
   193  		return t.TestConnectedSlotCallback(spec, plug, slot)
   194  	}
   195  	return nil
   196  }
   197  
   198  func (t *TestInterface) TestPermanentPlug(spec *Specification, plug *snap.PlugInfo) error {
   199  	if t.TestPermanentPlugCallback != nil {
   200  		return t.TestPermanentPlugCallback(spec, plug)
   201  	}
   202  	return nil
   203  }
   204  
   205  func (t *TestInterface) TestPermanentSlot(spec *Specification, slot *snap.SlotInfo) error {
   206  	if t.TestPermanentSlotCallback != nil {
   207  		return t.TestPermanentSlotCallback(spec, slot)
   208  	}
   209  	return nil
   210  }
   211  
   212  // Support for interacting with the mount backend.
   213  
   214  func (t *TestInterface) MountConnectedPlug(spec *mount.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   215  	if t.MountConnectedPlugCallback != nil {
   216  		return t.MountConnectedPlugCallback(spec, plug, slot)
   217  	}
   218  	return nil
   219  }
   220  
   221  func (t *TestInterface) MountConnectedSlot(spec *mount.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   222  	if t.MountConnectedSlotCallback != nil {
   223  		return t.MountConnectedSlotCallback(spec, plug, slot)
   224  	}
   225  	return nil
   226  }
   227  
   228  func (t *TestInterface) MountPermanentPlug(spec *mount.Specification, plug *snap.PlugInfo) error {
   229  	if t.MountPermanentPlugCallback != nil {
   230  		return t.MountPermanentPlugCallback(spec, plug)
   231  	}
   232  	return nil
   233  }
   234  
   235  func (t *TestInterface) MountPermanentSlot(spec *mount.Specification, slot *snap.SlotInfo) error {
   236  	if t.MountPermanentSlotCallback != nil {
   237  		return t.MountPermanentSlotCallback(spec, slot)
   238  	}
   239  	return nil
   240  }
   241  
   242  // Support for interacting with the udev backend.
   243  
   244  func (t *TestInterface) UDevConnectedPlug(spec *udev.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   245  	if t.UDevConnectedPlugCallback != nil {
   246  		return t.UDevConnectedPlugCallback(spec, plug, slot)
   247  	}
   248  	return nil
   249  }
   250  
   251  func (t *TestInterface) UDevPermanentPlug(spec *udev.Specification, plug *snap.PlugInfo) error {
   252  	if t.UDevPermanentPlugCallback != nil {
   253  		return t.UDevPermanentPlugCallback(spec, plug)
   254  	}
   255  	return nil
   256  }
   257  
   258  func (t *TestInterface) UDevPermanentSlot(spec *udev.Specification, slot *snap.SlotInfo) error {
   259  	if t.UDevPermanentSlotCallback != nil {
   260  		return t.UDevPermanentSlotCallback(spec, slot)
   261  	}
   262  	return nil
   263  }
   264  
   265  func (t *TestInterface) UDevConnectedSlot(spec *udev.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   266  	if t.UDevConnectedSlotCallback != nil {
   267  		return t.UDevConnectedSlotCallback(spec, plug, slot)
   268  	}
   269  	return nil
   270  }
   271  
   272  // Support for interacting with the apparmor backend.
   273  
   274  func (t *TestInterface) AppArmorConnectedPlug(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   275  	if t.AppArmorConnectedPlugCallback != nil {
   276  		return t.AppArmorConnectedPlugCallback(spec, plug, slot)
   277  	}
   278  	return nil
   279  }
   280  
   281  func (t *TestInterface) AppArmorPermanentSlot(spec *apparmor.Specification, slot *snap.SlotInfo) error {
   282  	if t.AppArmorPermanentSlotCallback != nil {
   283  		return t.AppArmorPermanentSlotCallback(spec, slot)
   284  	}
   285  	return nil
   286  }
   287  
   288  func (t *TestInterface) AppArmorConnectedSlot(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   289  	if t.AppArmorConnectedSlotCallback != nil {
   290  		return t.AppArmorConnectedSlotCallback(spec, plug, slot)
   291  
   292  	}
   293  	return nil
   294  }
   295  
   296  func (t *TestInterface) AppArmorPermanentPlug(spec *apparmor.Specification, plug *snap.PlugInfo) error {
   297  	if t.AppArmorPermanentPlugCallback != nil {
   298  		return t.AppArmorPermanentPlugCallback(spec, plug)
   299  	}
   300  	return nil
   301  }
   302  
   303  // Support for interacting with the seccomp backend.
   304  
   305  func (t *TestInterface) SecCompConnectedPlug(spec *seccomp.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   306  	if t.SecCompConnectedPlugCallback != nil {
   307  		return t.SecCompConnectedPlugCallback(spec, plug, slot)
   308  	}
   309  	return nil
   310  }
   311  
   312  func (t *TestInterface) SecCompConnectedSlot(spec *seccomp.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   313  	if t.SecCompConnectedSlotCallback != nil {
   314  		return t.SecCompConnectedSlotCallback(spec, plug, slot)
   315  	}
   316  	return nil
   317  }
   318  
   319  func (t *TestInterface) SecCompPermanentSlot(spec *seccomp.Specification, slot *snap.SlotInfo) error {
   320  	if t.SecCompPermanentSlotCallback != nil {
   321  		return t.SecCompPermanentSlotCallback(spec, slot)
   322  	}
   323  	return nil
   324  }
   325  
   326  func (t *TestInterface) SecCompPermanentPlug(spec *seccomp.Specification, plug *snap.PlugInfo) error {
   327  	if t.SecCompPermanentPlugCallback != nil {
   328  		return t.SecCompPermanentPlugCallback(spec, plug)
   329  	}
   330  	return nil
   331  }
   332  
   333  // Support for interacting with the kmod backend.
   334  
   335  func (t *TestInterface) KModConnectedPlug(spec *kmod.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   336  	if t.KModConnectedPlugCallback != nil {
   337  		return t.KModConnectedPlugCallback(spec, plug, slot)
   338  	}
   339  	return nil
   340  }
   341  
   342  func (t *TestInterface) KModConnectedSlot(spec *kmod.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   343  	if t.KModConnectedSlotCallback != nil {
   344  		return t.KModConnectedSlotCallback(spec, plug, slot)
   345  	}
   346  	return nil
   347  }
   348  
   349  func (t *TestInterface) KModPermanentPlug(spec *kmod.Specification, plug *snap.PlugInfo) error {
   350  	if t.KModPermanentPlugCallback != nil {
   351  		return t.KModPermanentPlugCallback(spec, plug)
   352  	}
   353  	return nil
   354  }
   355  
   356  func (t *TestInterface) KModPermanentSlot(spec *kmod.Specification, slot *snap.SlotInfo) error {
   357  	if t.KModPermanentSlotCallback != nil {
   358  		return t.KModPermanentSlotCallback(spec, slot)
   359  	}
   360  	return nil
   361  }
   362  
   363  // Support for interacting with the dbus backend.
   364  
   365  func (t *TestInterface) DBusConnectedPlug(spec *dbus.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   366  	if t.DBusConnectedPlugCallback != nil {
   367  		return t.DBusConnectedPlugCallback(spec, plug, slot)
   368  	}
   369  	return nil
   370  }
   371  
   372  func (t *TestInterface) DBusConnectedSlot(spec *dbus.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   373  	if t.DBusConnectedSlotCallback != nil {
   374  		return t.DBusConnectedSlotCallback(spec, plug, slot)
   375  	}
   376  	return nil
   377  }
   378  
   379  func (t *TestInterface) DBusPermanentSlot(spec *dbus.Specification, slot *snap.SlotInfo) error {
   380  	if t.DBusPermanentSlotCallback != nil {
   381  		return t.DBusPermanentSlotCallback(spec, slot)
   382  	}
   383  	return nil
   384  }
   385  
   386  func (t *TestInterface) DBusPermanentPlug(spec *dbus.Specification, plug *snap.PlugInfo) error {
   387  	if t.DBusPermanentPlugCallback != nil {
   388  		return t.DBusPermanentPlugCallback(spec, plug)
   389  	}
   390  	return nil
   391  }
   392  
   393  // Support for interacting with the systemd backend.
   394  
   395  func (t *TestInterface) SystemdConnectedPlug(spec *systemd.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   396  	if t.SystemdConnectedPlugCallback != nil {
   397  		return t.SystemdConnectedPlugCallback(spec, plug, slot)
   398  	}
   399  	return nil
   400  }
   401  
   402  func (t *TestInterface) SystemdConnectedSlot(spec *systemd.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   403  	if t.SystemdConnectedSlotCallback != nil {
   404  		return t.SystemdConnectedSlotCallback(spec, plug, slot)
   405  	}
   406  	return nil
   407  }
   408  
   409  func (t *TestInterface) SystemdPermanentSlot(spec *systemd.Specification, slot *snap.SlotInfo) error {
   410  	if t.SystemdPermanentSlotCallback != nil {
   411  		return t.SystemdPermanentSlotCallback(spec, slot)
   412  	}
   413  	return nil
   414  }
   415  
   416  func (t *TestInterface) SystemdPermanentPlug(spec *systemd.Specification, plug *snap.PlugInfo) error {
   417  	if t.SystemdPermanentPlugCallback != nil {
   418  		return t.SystemdPermanentPlugCallback(spec, plug)
   419  	}
   420  	return nil
   421  }
   422  
   423  // Support for interacting with the polkit backend.
   424  
   425  func (t *TestInterface) PolkitConnectedPlug(spec *polkit.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   426  	if t.PolkitConnectedPlugCallback != nil {
   427  		return t.PolkitConnectedPlugCallback(spec, plug, slot)
   428  	}
   429  	return nil
   430  }
   431  
   432  func (t *TestInterface) PolkitConnectedSlot(spec *polkit.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   433  	if t.PolkitConnectedSlotCallback != nil {
   434  		return t.PolkitConnectedSlotCallback(spec, plug, slot)
   435  	}
   436  	return nil
   437  }
   438  
   439  func (t *TestInterface) PolkitPermanentSlot(spec *polkit.Specification, slot *snap.SlotInfo) error {
   440  	if t.PolkitPermanentSlotCallback != nil {
   441  		return t.PolkitPermanentSlotCallback(spec, slot)
   442  	}
   443  	return nil
   444  }
   445  
   446  func (t *TestInterface) PolkitPermanentPlug(spec *polkit.Specification, plug *snap.PlugInfo) error {
   447  	if t.PolkitPermanentPlugCallback != nil {
   448  		return t.PolkitPermanentPlugCallback(spec, plug)
   449  	}
   450  	return nil
   451  }
   452  
   453  // Support for interacting with hotplug subsystem.
   454  
   455  func (t *TestHotplugInterface) HotplugKey(deviceInfo *hotplug.HotplugDeviceInfo) (snap.HotplugKey, error) {
   456  	if t.HotplugKeyCallback != nil {
   457  		return t.HotplugKeyCallback(deviceInfo)
   458  	}
   459  	return "", nil
   460  }
   461  
   462  func (t *TestHotplugInterface) HotplugDeviceDetected(deviceInfo *hotplug.HotplugDeviceInfo) (*hotplug.ProposedSlot, error) {
   463  	if t.HotplugDeviceDetectedCallback != nil {
   464  		return t.HotplugDeviceDetectedCallback(deviceInfo)
   465  	}
   466  	return nil, nil
   467  }
   468  
   469  func (t *TestHotplugInterface) HandledByGadget(deviceInfo *hotplug.HotplugDeviceInfo, slot *snap.SlotInfo) bool {
   470  	if t.HandledByGadgetCallback != nil {
   471  		return t.HandledByGadgetCallback(deviceInfo, slot)
   472  	}
   473  	return false
   474  }