github.com/netdata/go.d.plugin@v0.58.1/modules/systemdunits/systemdunits_test.go (about)

     1  // SPDX-License-Identifier: GPL-3.0-or-later
     2  
     3  //go:build linux
     4  // +build linux
     5  
     6  package systemdunits
     7  
     8  import (
     9  	"context"
    10  	"errors"
    11  	"fmt"
    12  	"path/filepath"
    13  	"testing"
    14  
    15  	"github.com/netdata/go.d.plugin/agent/module"
    16  
    17  	"github.com/coreos/go-systemd/v22/dbus"
    18  	"github.com/stretchr/testify/assert"
    19  	"github.com/stretchr/testify/require"
    20  )
    21  
    22  func TestNew(t *testing.T) {
    23  	assert.Implements(t, (*module.Module)(nil), New())
    24  }
    25  
    26  func TestSystemdUnits_Init(t *testing.T) {
    27  	tests := map[string]struct {
    28  		config   Config
    29  		wantFail bool
    30  	}{
    31  		"success on default config": {
    32  			config: New().Config,
    33  		},
    34  		"success when 'include' option set": {
    35  			config: Config{
    36  				Include: []string{"*"},
    37  			},
    38  		},
    39  		"fails when 'include' option not set": {
    40  			wantFail: true,
    41  			config:   Config{Include: []string{}},
    42  		},
    43  	}
    44  
    45  	for name, test := range tests {
    46  		t.Run(name, func(t *testing.T) {
    47  			systemd := New()
    48  			systemd.Config = test.config
    49  
    50  			if test.wantFail {
    51  				assert.False(t, systemd.Init())
    52  			} else {
    53  				assert.True(t, systemd.Init())
    54  			}
    55  		})
    56  	}
    57  }
    58  
    59  func TestSystemdUnits_Check(t *testing.T) {
    60  	tests := map[string]struct {
    61  		prepare  func() *SystemdUnits
    62  		wantFail bool
    63  	}{
    64  		"success on systemd v230+": {
    65  			prepare: func() *SystemdUnits {
    66  				systemd := New()
    67  				systemd.Include = []string{"*"}
    68  				systemd.client = prepareOKClient(230)
    69  				return systemd
    70  			},
    71  		},
    72  		"success on systemd v230-": {
    73  			prepare: func() *SystemdUnits {
    74  				systemd := New()
    75  				systemd.Include = []string{"*"}
    76  				systemd.client = prepareOKClient(220)
    77  				return systemd
    78  			},
    79  		},
    80  		"fails when all unites are filtered": {
    81  			wantFail: true,
    82  			prepare: func() *SystemdUnits {
    83  				systemd := New()
    84  				systemd.Include = []string{"*.not_exists"}
    85  				systemd.client = prepareOKClient(230)
    86  				return systemd
    87  			},
    88  		},
    89  		"fails on error on connect": {
    90  			wantFail: true,
    91  			prepare: func() *SystemdUnits {
    92  				systemd := New()
    93  				systemd.client = prepareClientErrOnConnect()
    94  				return systemd
    95  			},
    96  		},
    97  		"fails on error on get manager property": {
    98  			wantFail: true,
    99  			prepare: func() *SystemdUnits {
   100  				systemd := New()
   101  				systemd.client = prepareClientErrOnGetManagerProperty()
   102  				return systemd
   103  			},
   104  		},
   105  		"fails on error on list units": {
   106  			wantFail: true,
   107  			prepare: func() *SystemdUnits {
   108  				systemd := New()
   109  				systemd.client = prepareClientErrOnListUnits()
   110  				return systemd
   111  			},
   112  		},
   113  	}
   114  
   115  	for name, test := range tests {
   116  		t.Run(name, func(t *testing.T) {
   117  			systemd := test.prepare()
   118  			require.True(t, systemd.Init())
   119  
   120  			if test.wantFail {
   121  				assert.False(t, systemd.Check())
   122  			} else {
   123  				assert.True(t, systemd.Check())
   124  			}
   125  		})
   126  	}
   127  }
   128  
   129  func TestSystemdUnits_Charts(t *testing.T) {
   130  	systemd := New()
   131  	require.True(t, systemd.Init())
   132  	assert.NotNil(t, systemd.Charts())
   133  }
   134  
   135  func TestSystemdUnits_Cleanup(t *testing.T) {
   136  	systemd := New()
   137  	systemd.Include = []string{"*"}
   138  	client := prepareOKClient(230)
   139  	systemd.client = client
   140  
   141  	require.True(t, systemd.Init())
   142  	require.NotNil(t, systemd.Collect())
   143  	conn := systemd.conn
   144  	systemd.Cleanup()
   145  
   146  	assert.Nil(t, systemd.conn)
   147  	v, _ := conn.(*mockConn)
   148  	assert.True(t, v.closeCalled)
   149  }
   150  
   151  func TestSystemdUnits_Collect(t *testing.T) {
   152  	tests := map[string]struct {
   153  		prepare       func() *SystemdUnits
   154  		wantCollected map[string]int64
   155  	}{
   156  		"success on systemd v230+ on collecting all unit type": {
   157  			prepare: func() *SystemdUnits {
   158  				systemd := New()
   159  				systemd.Include = []string{"*"}
   160  				systemd.client = prepareOKClient(230)
   161  				return systemd
   162  			},
   163  			wantCollected: map[string]int64{
   164  				"unit_dbus_socket_state_activating":                                0,
   165  				"unit_dbus_socket_state_active":                                    1,
   166  				"unit_dbus_socket_state_deactivating":                              0,
   167  				"unit_dbus_socket_state_failed":                                    0,
   168  				"unit_dbus_socket_state_inactive":                                  0,
   169  				"unit_dev-disk-by-uuid-DE44-CEE0_device_state_activating":          0,
   170  				"unit_dev-disk-by-uuid-DE44-CEE0_device_state_active":              1,
   171  				"unit_dev-disk-by-uuid-DE44-CEE0_device_state_deactivating":        0,
   172  				"unit_dev-disk-by-uuid-DE44-CEE0_device_state_failed":              0,
   173  				"unit_dev-disk-by-uuid-DE44-CEE0_device_state_inactive":            0,
   174  				"unit_dev-nvme0n1_device_state_activating":                         0,
   175  				"unit_dev-nvme0n1_device_state_active":                             1,
   176  				"unit_dev-nvme0n1_device_state_deactivating":                       0,
   177  				"unit_dev-nvme0n1_device_state_failed":                             0,
   178  				"unit_dev-nvme0n1_device_state_inactive":                           0,
   179  				"unit_docker_socket_state_activating":                              0,
   180  				"unit_docker_socket_state_active":                                  1,
   181  				"unit_docker_socket_state_deactivating":                            0,
   182  				"unit_docker_socket_state_failed":                                  0,
   183  				"unit_docker_socket_state_inactive":                                0,
   184  				"unit_getty-pre_target_state_activating":                           0,
   185  				"unit_getty-pre_target_state_active":                               0,
   186  				"unit_getty-pre_target_state_deactivating":                         0,
   187  				"unit_getty-pre_target_state_failed":                               0,
   188  				"unit_getty-pre_target_state_inactive":                             1,
   189  				"unit_init_scope_state_activating":                                 0,
   190  				"unit_init_scope_state_active":                                     1,
   191  				"unit_init_scope_state_deactivating":                               0,
   192  				"unit_init_scope_state_failed":                                     0,
   193  				"unit_init_scope_state_inactive":                                   0,
   194  				"unit_logrotate_timer_state_activating":                            0,
   195  				"unit_logrotate_timer_state_active":                                1,
   196  				"unit_logrotate_timer_state_deactivating":                          0,
   197  				"unit_logrotate_timer_state_failed":                                0,
   198  				"unit_logrotate_timer_state_inactive":                              0,
   199  				"unit_lvm2-lvmetad_socket_state_activating":                        0,
   200  				"unit_lvm2-lvmetad_socket_state_active":                            1,
   201  				"unit_lvm2-lvmetad_socket_state_deactivating":                      0,
   202  				"unit_lvm2-lvmetad_socket_state_failed":                            0,
   203  				"unit_lvm2-lvmetad_socket_state_inactive":                          0,
   204  				"unit_lvm2-lvmpolld_socket_state_activating":                       0,
   205  				"unit_lvm2-lvmpolld_socket_state_active":                           1,
   206  				"unit_lvm2-lvmpolld_socket_state_deactivating":                     0,
   207  				"unit_lvm2-lvmpolld_socket_state_failed":                           0,
   208  				"unit_lvm2-lvmpolld_socket_state_inactive":                         0,
   209  				"unit_man-db_timer_state_activating":                               0,
   210  				"unit_man-db_timer_state_active":                                   1,
   211  				"unit_man-db_timer_state_deactivating":                             0,
   212  				"unit_man-db_timer_state_failed":                                   0,
   213  				"unit_man-db_timer_state_inactive":                                 0,
   214  				"unit_org.cups.cupsd_path_state_activating":                        0,
   215  				"unit_org.cups.cupsd_path_state_active":                            1,
   216  				"unit_org.cups.cupsd_path_state_deactivating":                      0,
   217  				"unit_org.cups.cupsd_path_state_failed":                            0,
   218  				"unit_org.cups.cupsd_path_state_inactive":                          0,
   219  				"unit_pamac-cleancache_timer_state_activating":                     0,
   220  				"unit_pamac-cleancache_timer_state_active":                         1,
   221  				"unit_pamac-cleancache_timer_state_deactivating":                   0,
   222  				"unit_pamac-cleancache_timer_state_failed":                         0,
   223  				"unit_pamac-cleancache_timer_state_inactive":                       0,
   224  				"unit_pamac-mirrorlist_timer_state_activating":                     0,
   225  				"unit_pamac-mirrorlist_timer_state_active":                         1,
   226  				"unit_pamac-mirrorlist_timer_state_deactivating":                   0,
   227  				"unit_pamac-mirrorlist_timer_state_failed":                         0,
   228  				"unit_pamac-mirrorlist_timer_state_inactive":                       0,
   229  				"unit_proc-sys-fs-binfmt_misc_automount_state_activating":          0,
   230  				"unit_proc-sys-fs-binfmt_misc_automount_state_active":              1,
   231  				"unit_proc-sys-fs-binfmt_misc_automount_state_deactivating":        0,
   232  				"unit_proc-sys-fs-binfmt_misc_automount_state_failed":              0,
   233  				"unit_proc-sys-fs-binfmt_misc_automount_state_inactive":            0,
   234  				"unit_remote-fs-pre_target_state_activating":                       0,
   235  				"unit_remote-fs-pre_target_state_active":                           0,
   236  				"unit_remote-fs-pre_target_state_deactivating":                     0,
   237  				"unit_remote-fs-pre_target_state_failed":                           0,
   238  				"unit_remote-fs-pre_target_state_inactive":                         1,
   239  				"unit_rpc_pipefs_target_state_activating":                          0,
   240  				"unit_rpc_pipefs_target_state_active":                              0,
   241  				"unit_rpc_pipefs_target_state_deactivating":                        0,
   242  				"unit_rpc_pipefs_target_state_failed":                              0,
   243  				"unit_rpc_pipefs_target_state_inactive":                            1,
   244  				"unit_run-user-1000-gvfs_mount_state_activating":                   0,
   245  				"unit_run-user-1000-gvfs_mount_state_active":                       1,
   246  				"unit_run-user-1000-gvfs_mount_state_deactivating":                 0,
   247  				"unit_run-user-1000-gvfs_mount_state_failed":                       0,
   248  				"unit_run-user-1000-gvfs_mount_state_inactive":                     0,
   249  				"unit_run-user-1000_mount_state_activating":                        0,
   250  				"unit_run-user-1000_mount_state_active":                            1,
   251  				"unit_run-user-1000_mount_state_deactivating":                      0,
   252  				"unit_run-user-1000_mount_state_failed":                            0,
   253  				"unit_run-user-1000_mount_state_inactive":                          0,
   254  				"unit_session-1_scope_state_activating":                            0,
   255  				"unit_session-1_scope_state_active":                                1,
   256  				"unit_session-1_scope_state_deactivating":                          0,
   257  				"unit_session-1_scope_state_failed":                                0,
   258  				"unit_session-1_scope_state_inactive":                              0,
   259  				"unit_session-2_scope_state_activating":                            0,
   260  				"unit_session-2_scope_state_active":                                1,
   261  				"unit_session-2_scope_state_deactivating":                          0,
   262  				"unit_session-2_scope_state_failed":                                0,
   263  				"unit_session-2_scope_state_inactive":                              0,
   264  				"unit_session-3_scope_state_activating":                            0,
   265  				"unit_session-3_scope_state_active":                                1,
   266  				"unit_session-3_scope_state_deactivating":                          0,
   267  				"unit_session-3_scope_state_failed":                                0,
   268  				"unit_session-3_scope_state_inactive":                              0,
   269  				"unit_session-6_scope_state_activating":                            0,
   270  				"unit_session-6_scope_state_active":                                1,
   271  				"unit_session-6_scope_state_deactivating":                          0,
   272  				"unit_session-6_scope_state_failed":                                0,
   273  				"unit_session-6_scope_state_inactive":                              0,
   274  				"unit_shadow_timer_state_activating":                               0,
   275  				"unit_shadow_timer_state_active":                                   1,
   276  				"unit_shadow_timer_state_deactivating":                             0,
   277  				"unit_shadow_timer_state_failed":                                   0,
   278  				"unit_shadow_timer_state_inactive":                                 0,
   279  				"unit_sound_target_state_activating":                               0,
   280  				"unit_sound_target_state_active":                                   1,
   281  				"unit_sound_target_state_deactivating":                             0,
   282  				"unit_sound_target_state_failed":                                   0,
   283  				"unit_sound_target_state_inactive":                                 0,
   284  				"unit_sys-devices-virtual-net-loopback1_device_state_activating":   0,
   285  				"unit_sys-devices-virtual-net-loopback1_device_state_active":       1,
   286  				"unit_sys-devices-virtual-net-loopback1_device_state_deactivating": 0,
   287  				"unit_sys-devices-virtual-net-loopback1_device_state_failed":       0,
   288  				"unit_sys-devices-virtual-net-loopback1_device_state_inactive":     0,
   289  				"unit_sys-module-fuse_device_state_activating":                     0,
   290  				"unit_sys-module-fuse_device_state_active":                         1,
   291  				"unit_sys-module-fuse_device_state_deactivating":                   0,
   292  				"unit_sys-module-fuse_device_state_failed":                         0,
   293  				"unit_sys-module-fuse_device_state_inactive":                       0,
   294  				"unit_sysinit_target_state_activating":                             0,
   295  				"unit_sysinit_target_state_active":                                 1,
   296  				"unit_sysinit_target_state_deactivating":                           0,
   297  				"unit_sysinit_target_state_failed":                                 0,
   298  				"unit_sysinit_target_state_inactive":                               0,
   299  				"unit_system-getty_slice_state_activating":                         0,
   300  				"unit_system-getty_slice_state_active":                             1,
   301  				"unit_system-getty_slice_state_deactivating":                       0,
   302  				"unit_system-getty_slice_state_failed":                             0,
   303  				"unit_system-getty_slice_state_inactive":                           0,
   304  				"unit_system-netctl_slice_state_activating":                        0,
   305  				"unit_system-netctl_slice_state_active":                            1,
   306  				"unit_system-netctl_slice_state_deactivating":                      0,
   307  				"unit_system-netctl_slice_state_failed":                            0,
   308  				"unit_system-netctl_slice_state_inactive":                          0,
   309  				"unit_system-systemd-fsck_slice_state_activating":                  0,
   310  				"unit_system-systemd-fsck_slice_state_active":                      1,
   311  				"unit_system-systemd-fsck_slice_state_deactivating":                0,
   312  				"unit_system-systemd-fsck_slice_state_failed":                      0,
   313  				"unit_system-systemd-fsck_slice_state_inactive":                    0,
   314  				"unit_system_slice_state_activating":                               0,
   315  				"unit_system_slice_state_active":                                   1,
   316  				"unit_system_slice_state_deactivating":                             0,
   317  				"unit_system_slice_state_failed":                                   0,
   318  				"unit_system_slice_state_inactive":                                 0,
   319  				"unit_systemd-ask-password-console_path_state_activating":          0,
   320  				"unit_systemd-ask-password-console_path_state_active":              1,
   321  				"unit_systemd-ask-password-console_path_state_deactivating":        0,
   322  				"unit_systemd-ask-password-console_path_state_failed":              0,
   323  				"unit_systemd-ask-password-console_path_state_inactive":            0,
   324  				"unit_systemd-ask-password-wall_path_state_activating":             0,
   325  				"unit_systemd-ask-password-wall_path_state_active":                 1,
   326  				"unit_systemd-ask-password-wall_path_state_deactivating":           0,
   327  				"unit_systemd-ask-password-wall_path_state_failed":                 0,
   328  				"unit_systemd-ask-password-wall_path_state_inactive":               0,
   329  				"unit_systemd-ask-password-wall_service_state_activating":          0,
   330  				"unit_systemd-ask-password-wall_service_state_active":              0,
   331  				"unit_systemd-ask-password-wall_service_state_deactivating":        0,
   332  				"unit_systemd-ask-password-wall_service_state_failed":              0,
   333  				"unit_systemd-ask-password-wall_service_state_inactive":            1,
   334  				"unit_systemd-fsck-root_service_state_activating":                  0,
   335  				"unit_systemd-fsck-root_service_state_active":                      0,
   336  				"unit_systemd-fsck-root_service_state_deactivating":                0,
   337  				"unit_systemd-fsck-root_service_state_failed":                      0,
   338  				"unit_systemd-fsck-root_service_state_inactive":                    1,
   339  				"unit_systemd-udevd-kernel_socket_state_activating":                0,
   340  				"unit_systemd-udevd-kernel_socket_state_active":                    1,
   341  				"unit_systemd-udevd-kernel_socket_state_deactivating":              0,
   342  				"unit_systemd-udevd-kernel_socket_state_failed":                    0,
   343  				"unit_systemd-udevd-kernel_socket_state_inactive":                  0,
   344  				"unit_tmp_mount_state_activating":                                  0,
   345  				"unit_tmp_mount_state_active":                                      1,
   346  				"unit_tmp_mount_state_deactivating":                                0,
   347  				"unit_tmp_mount_state_failed":                                      0,
   348  				"unit_tmp_mount_state_inactive":                                    0,
   349  				"unit_user-runtime-dir@1000_service_state_activating":              0,
   350  				"unit_user-runtime-dir@1000_service_state_active":                  1,
   351  				"unit_user-runtime-dir@1000_service_state_deactivating":            0,
   352  				"unit_user-runtime-dir@1000_service_state_failed":                  0,
   353  				"unit_user-runtime-dir@1000_service_state_inactive":                0,
   354  				"unit_user@1000_service_state_activating":                          0,
   355  				"unit_user@1000_service_state_active":                              1,
   356  				"unit_user@1000_service_state_deactivating":                        0,
   357  				"unit_user@1000_service_state_failed":                              0,
   358  				"unit_user@1000_service_state_inactive":                            0,
   359  				"unit_user_slice_state_activating":                                 0,
   360  				"unit_user_slice_state_active":                                     1,
   361  				"unit_user_slice_state_deactivating":                               0,
   362  				"unit_user_slice_state_failed":                                     0,
   363  				"unit_user_slice_state_inactive":                                   0,
   364  				"unit_var-lib-nfs-rpc_pipefs_mount_state_activating":               0,
   365  				"unit_var-lib-nfs-rpc_pipefs_mount_state_active":                   0,
   366  				"unit_var-lib-nfs-rpc_pipefs_mount_state_deactivating":             0,
   367  				"unit_var-lib-nfs-rpc_pipefs_mount_state_failed":                   0,
   368  				"unit_var-lib-nfs-rpc_pipefs_mount_state_inactive":                 1,
   369  			},
   370  		},
   371  		"success on systemd v230- on collecting all unit types": {
   372  			prepare: func() *SystemdUnits {
   373  				systemd := New()
   374  				systemd.Include = []string{"*"}
   375  				systemd.client = prepareOKClient(220)
   376  				return systemd
   377  			},
   378  			wantCollected: map[string]int64{
   379  				"unit_dbus_socket_state_activating":                                0,
   380  				"unit_dbus_socket_state_active":                                    1,
   381  				"unit_dbus_socket_state_deactivating":                              0,
   382  				"unit_dbus_socket_state_failed":                                    0,
   383  				"unit_dbus_socket_state_inactive":                                  0,
   384  				"unit_dev-disk-by-uuid-DE44-CEE0_device_state_activating":          0,
   385  				"unit_dev-disk-by-uuid-DE44-CEE0_device_state_active":              1,
   386  				"unit_dev-disk-by-uuid-DE44-CEE0_device_state_deactivating":        0,
   387  				"unit_dev-disk-by-uuid-DE44-CEE0_device_state_failed":              0,
   388  				"unit_dev-disk-by-uuid-DE44-CEE0_device_state_inactive":            0,
   389  				"unit_dev-nvme0n1_device_state_activating":                         0,
   390  				"unit_dev-nvme0n1_device_state_active":                             1,
   391  				"unit_dev-nvme0n1_device_state_deactivating":                       0,
   392  				"unit_dev-nvme0n1_device_state_failed":                             0,
   393  				"unit_dev-nvme0n1_device_state_inactive":                           0,
   394  				"unit_docker_socket_state_activating":                              0,
   395  				"unit_docker_socket_state_active":                                  1,
   396  				"unit_docker_socket_state_deactivating":                            0,
   397  				"unit_docker_socket_state_failed":                                  0,
   398  				"unit_docker_socket_state_inactive":                                0,
   399  				"unit_getty-pre_target_state_activating":                           0,
   400  				"unit_getty-pre_target_state_active":                               0,
   401  				"unit_getty-pre_target_state_deactivating":                         0,
   402  				"unit_getty-pre_target_state_failed":                               0,
   403  				"unit_getty-pre_target_state_inactive":                             1,
   404  				"unit_init_scope_state_activating":                                 0,
   405  				"unit_init_scope_state_active":                                     1,
   406  				"unit_init_scope_state_deactivating":                               0,
   407  				"unit_init_scope_state_failed":                                     0,
   408  				"unit_init_scope_state_inactive":                                   0,
   409  				"unit_logrotate_timer_state_activating":                            0,
   410  				"unit_logrotate_timer_state_active":                                1,
   411  				"unit_logrotate_timer_state_deactivating":                          0,
   412  				"unit_logrotate_timer_state_failed":                                0,
   413  				"unit_logrotate_timer_state_inactive":                              0,
   414  				"unit_lvm2-lvmetad_socket_state_activating":                        0,
   415  				"unit_lvm2-lvmetad_socket_state_active":                            1,
   416  				"unit_lvm2-lvmetad_socket_state_deactivating":                      0,
   417  				"unit_lvm2-lvmetad_socket_state_failed":                            0,
   418  				"unit_lvm2-lvmetad_socket_state_inactive":                          0,
   419  				"unit_lvm2-lvmpolld_socket_state_activating":                       0,
   420  				"unit_lvm2-lvmpolld_socket_state_active":                           1,
   421  				"unit_lvm2-lvmpolld_socket_state_deactivating":                     0,
   422  				"unit_lvm2-lvmpolld_socket_state_failed":                           0,
   423  				"unit_lvm2-lvmpolld_socket_state_inactive":                         0,
   424  				"unit_man-db_timer_state_activating":                               0,
   425  				"unit_man-db_timer_state_active":                                   1,
   426  				"unit_man-db_timer_state_deactivating":                             0,
   427  				"unit_man-db_timer_state_failed":                                   0,
   428  				"unit_man-db_timer_state_inactive":                                 0,
   429  				"unit_org.cups.cupsd_path_state_activating":                        0,
   430  				"unit_org.cups.cupsd_path_state_active":                            1,
   431  				"unit_org.cups.cupsd_path_state_deactivating":                      0,
   432  				"unit_org.cups.cupsd_path_state_failed":                            0,
   433  				"unit_org.cups.cupsd_path_state_inactive":                          0,
   434  				"unit_pamac-cleancache_timer_state_activating":                     0,
   435  				"unit_pamac-cleancache_timer_state_active":                         1,
   436  				"unit_pamac-cleancache_timer_state_deactivating":                   0,
   437  				"unit_pamac-cleancache_timer_state_failed":                         0,
   438  				"unit_pamac-cleancache_timer_state_inactive":                       0,
   439  				"unit_pamac-mirrorlist_timer_state_activating":                     0,
   440  				"unit_pamac-mirrorlist_timer_state_active":                         1,
   441  				"unit_pamac-mirrorlist_timer_state_deactivating":                   0,
   442  				"unit_pamac-mirrorlist_timer_state_failed":                         0,
   443  				"unit_pamac-mirrorlist_timer_state_inactive":                       0,
   444  				"unit_proc-sys-fs-binfmt_misc_automount_state_activating":          0,
   445  				"unit_proc-sys-fs-binfmt_misc_automount_state_active":              1,
   446  				"unit_proc-sys-fs-binfmt_misc_automount_state_deactivating":        0,
   447  				"unit_proc-sys-fs-binfmt_misc_automount_state_failed":              0,
   448  				"unit_proc-sys-fs-binfmt_misc_automount_state_inactive":            0,
   449  				"unit_remote-fs-pre_target_state_activating":                       0,
   450  				"unit_remote-fs-pre_target_state_active":                           0,
   451  				"unit_remote-fs-pre_target_state_deactivating":                     0,
   452  				"unit_remote-fs-pre_target_state_failed":                           0,
   453  				"unit_remote-fs-pre_target_state_inactive":                         1,
   454  				"unit_rpc_pipefs_target_state_activating":                          0,
   455  				"unit_rpc_pipefs_target_state_active":                              0,
   456  				"unit_rpc_pipefs_target_state_deactivating":                        0,
   457  				"unit_rpc_pipefs_target_state_failed":                              0,
   458  				"unit_rpc_pipefs_target_state_inactive":                            1,
   459  				"unit_run-user-1000-gvfs_mount_state_activating":                   0,
   460  				"unit_run-user-1000-gvfs_mount_state_active":                       1,
   461  				"unit_run-user-1000-gvfs_mount_state_deactivating":                 0,
   462  				"unit_run-user-1000-gvfs_mount_state_failed":                       0,
   463  				"unit_run-user-1000-gvfs_mount_state_inactive":                     0,
   464  				"unit_run-user-1000_mount_state_activating":                        0,
   465  				"unit_run-user-1000_mount_state_active":                            1,
   466  				"unit_run-user-1000_mount_state_deactivating":                      0,
   467  				"unit_run-user-1000_mount_state_failed":                            0,
   468  				"unit_run-user-1000_mount_state_inactive":                          0,
   469  				"unit_session-1_scope_state_activating":                            0,
   470  				"unit_session-1_scope_state_active":                                1,
   471  				"unit_session-1_scope_state_deactivating":                          0,
   472  				"unit_session-1_scope_state_failed":                                0,
   473  				"unit_session-1_scope_state_inactive":                              0,
   474  				"unit_session-2_scope_state_activating":                            0,
   475  				"unit_session-2_scope_state_active":                                1,
   476  				"unit_session-2_scope_state_deactivating":                          0,
   477  				"unit_session-2_scope_state_failed":                                0,
   478  				"unit_session-2_scope_state_inactive":                              0,
   479  				"unit_session-3_scope_state_activating":                            0,
   480  				"unit_session-3_scope_state_active":                                1,
   481  				"unit_session-3_scope_state_deactivating":                          0,
   482  				"unit_session-3_scope_state_failed":                                0,
   483  				"unit_session-3_scope_state_inactive":                              0,
   484  				"unit_session-6_scope_state_activating":                            0,
   485  				"unit_session-6_scope_state_active":                                1,
   486  				"unit_session-6_scope_state_deactivating":                          0,
   487  				"unit_session-6_scope_state_failed":                                0,
   488  				"unit_session-6_scope_state_inactive":                              0,
   489  				"unit_shadow_timer_state_activating":                               0,
   490  				"unit_shadow_timer_state_active":                                   1,
   491  				"unit_shadow_timer_state_deactivating":                             0,
   492  				"unit_shadow_timer_state_failed":                                   0,
   493  				"unit_shadow_timer_state_inactive":                                 0,
   494  				"unit_sound_target_state_activating":                               0,
   495  				"unit_sound_target_state_active":                                   1,
   496  				"unit_sound_target_state_deactivating":                             0,
   497  				"unit_sound_target_state_failed":                                   0,
   498  				"unit_sound_target_state_inactive":                                 0,
   499  				"unit_sys-devices-virtual-net-loopback1_device_state_activating":   0,
   500  				"unit_sys-devices-virtual-net-loopback1_device_state_active":       1,
   501  				"unit_sys-devices-virtual-net-loopback1_device_state_deactivating": 0,
   502  				"unit_sys-devices-virtual-net-loopback1_device_state_failed":       0,
   503  				"unit_sys-devices-virtual-net-loopback1_device_state_inactive":     0,
   504  				"unit_sys-module-fuse_device_state_activating":                     0,
   505  				"unit_sys-module-fuse_device_state_active":                         1,
   506  				"unit_sys-module-fuse_device_state_deactivating":                   0,
   507  				"unit_sys-module-fuse_device_state_failed":                         0,
   508  				"unit_sys-module-fuse_device_state_inactive":                       0,
   509  				"unit_sysinit_target_state_activating":                             0,
   510  				"unit_sysinit_target_state_active":                                 1,
   511  				"unit_sysinit_target_state_deactivating":                           0,
   512  				"unit_sysinit_target_state_failed":                                 0,
   513  				"unit_sysinit_target_state_inactive":                               0,
   514  				"unit_system-getty_slice_state_activating":                         0,
   515  				"unit_system-getty_slice_state_active":                             1,
   516  				"unit_system-getty_slice_state_deactivating":                       0,
   517  				"unit_system-getty_slice_state_failed":                             0,
   518  				"unit_system-getty_slice_state_inactive":                           0,
   519  				"unit_system-netctl_slice_state_activating":                        0,
   520  				"unit_system-netctl_slice_state_active":                            1,
   521  				"unit_system-netctl_slice_state_deactivating":                      0,
   522  				"unit_system-netctl_slice_state_failed":                            0,
   523  				"unit_system-netctl_slice_state_inactive":                          0,
   524  				"unit_system-systemd-fsck_slice_state_activating":                  0,
   525  				"unit_system-systemd-fsck_slice_state_active":                      1,
   526  				"unit_system-systemd-fsck_slice_state_deactivating":                0,
   527  				"unit_system-systemd-fsck_slice_state_failed":                      0,
   528  				"unit_system-systemd-fsck_slice_state_inactive":                    0,
   529  				"unit_system_slice_state_activating":                               0,
   530  				"unit_system_slice_state_active":                                   1,
   531  				"unit_system_slice_state_deactivating":                             0,
   532  				"unit_system_slice_state_failed":                                   0,
   533  				"unit_system_slice_state_inactive":                                 0,
   534  				"unit_systemd-ask-password-console_path_state_activating":          0,
   535  				"unit_systemd-ask-password-console_path_state_active":              1,
   536  				"unit_systemd-ask-password-console_path_state_deactivating":        0,
   537  				"unit_systemd-ask-password-console_path_state_failed":              0,
   538  				"unit_systemd-ask-password-console_path_state_inactive":            0,
   539  				"unit_systemd-ask-password-wall_path_state_activating":             0,
   540  				"unit_systemd-ask-password-wall_path_state_active":                 1,
   541  				"unit_systemd-ask-password-wall_path_state_deactivating":           0,
   542  				"unit_systemd-ask-password-wall_path_state_failed":                 0,
   543  				"unit_systemd-ask-password-wall_path_state_inactive":               0,
   544  				"unit_systemd-ask-password-wall_service_state_activating":          0,
   545  				"unit_systemd-ask-password-wall_service_state_active":              0,
   546  				"unit_systemd-ask-password-wall_service_state_deactivating":        0,
   547  				"unit_systemd-ask-password-wall_service_state_failed":              0,
   548  				"unit_systemd-ask-password-wall_service_state_inactive":            1,
   549  				"unit_systemd-fsck-root_service_state_activating":                  0,
   550  				"unit_systemd-fsck-root_service_state_active":                      0,
   551  				"unit_systemd-fsck-root_service_state_deactivating":                0,
   552  				"unit_systemd-fsck-root_service_state_failed":                      0,
   553  				"unit_systemd-fsck-root_service_state_inactive":                    1,
   554  				"unit_systemd-udevd-kernel_socket_state_activating":                0,
   555  				"unit_systemd-udevd-kernel_socket_state_active":                    1,
   556  				"unit_systemd-udevd-kernel_socket_state_deactivating":              0,
   557  				"unit_systemd-udevd-kernel_socket_state_failed":                    0,
   558  				"unit_systemd-udevd-kernel_socket_state_inactive":                  0,
   559  				"unit_tmp_mount_state_activating":                                  0,
   560  				"unit_tmp_mount_state_active":                                      1,
   561  				"unit_tmp_mount_state_deactivating":                                0,
   562  				"unit_tmp_mount_state_failed":                                      0,
   563  				"unit_tmp_mount_state_inactive":                                    0,
   564  				"unit_user-runtime-dir@1000_service_state_activating":              0,
   565  				"unit_user-runtime-dir@1000_service_state_active":                  1,
   566  				"unit_user-runtime-dir@1000_service_state_deactivating":            0,
   567  				"unit_user-runtime-dir@1000_service_state_failed":                  0,
   568  				"unit_user-runtime-dir@1000_service_state_inactive":                0,
   569  				"unit_user@1000_service_state_activating":                          0,
   570  				"unit_user@1000_service_state_active":                              1,
   571  				"unit_user@1000_service_state_deactivating":                        0,
   572  				"unit_user@1000_service_state_failed":                              0,
   573  				"unit_user@1000_service_state_inactive":                            0,
   574  				"unit_user_slice_state_activating":                                 0,
   575  				"unit_user_slice_state_active":                                     1,
   576  				"unit_user_slice_state_deactivating":                               0,
   577  				"unit_user_slice_state_failed":                                     0,
   578  				"unit_user_slice_state_inactive":                                   0,
   579  				"unit_var-lib-nfs-rpc_pipefs_mount_state_activating":               0,
   580  				"unit_var-lib-nfs-rpc_pipefs_mount_state_active":                   0,
   581  				"unit_var-lib-nfs-rpc_pipefs_mount_state_deactivating":             0,
   582  				"unit_var-lib-nfs-rpc_pipefs_mount_state_failed":                   0,
   583  				"unit_var-lib-nfs-rpc_pipefs_mount_state_inactive":                 1,
   584  			},
   585  		},
   586  		"success on systemd v230+ on collecting only 'service' unit type": {
   587  			prepare: func() *SystemdUnits {
   588  				systemd := New()
   589  				systemd.Include = []string{"*.service"}
   590  				systemd.client = prepareOKClient(230)
   591  				return systemd
   592  			},
   593  			wantCollected: map[string]int64{
   594  				"unit_systemd-ask-password-wall_service_state_activating":   0,
   595  				"unit_systemd-ask-password-wall_service_state_active":       0,
   596  				"unit_systemd-ask-password-wall_service_state_deactivating": 0,
   597  				"unit_systemd-ask-password-wall_service_state_failed":       0,
   598  				"unit_systemd-ask-password-wall_service_state_inactive":     1,
   599  				"unit_systemd-fsck-root_service_state_activating":           0,
   600  				"unit_systemd-fsck-root_service_state_active":               0,
   601  				"unit_systemd-fsck-root_service_state_deactivating":         0,
   602  				"unit_systemd-fsck-root_service_state_failed":               0,
   603  				"unit_systemd-fsck-root_service_state_inactive":             1,
   604  				"unit_user-runtime-dir@1000_service_state_activating":       0,
   605  				"unit_user-runtime-dir@1000_service_state_active":           1,
   606  				"unit_user-runtime-dir@1000_service_state_deactivating":     0,
   607  				"unit_user-runtime-dir@1000_service_state_failed":           0,
   608  				"unit_user-runtime-dir@1000_service_state_inactive":         0,
   609  				"unit_user@1000_service_state_activating":                   0,
   610  				"unit_user@1000_service_state_active":                       1,
   611  				"unit_user@1000_service_state_deactivating":                 0,
   612  				"unit_user@1000_service_state_failed":                       0,
   613  				"unit_user@1000_service_state_inactive":                     0,
   614  			},
   615  		},
   616  		"success on systemd v230- on collecting only 'service' unit type": {
   617  			prepare: func() *SystemdUnits {
   618  				systemd := New()
   619  				systemd.Include = []string{"*.service"}
   620  				systemd.client = prepareOKClient(220)
   621  				return systemd
   622  			},
   623  			wantCollected: map[string]int64{
   624  				"unit_systemd-ask-password-wall_service_state_activating":   0,
   625  				"unit_systemd-ask-password-wall_service_state_active":       0,
   626  				"unit_systemd-ask-password-wall_service_state_deactivating": 0,
   627  				"unit_systemd-ask-password-wall_service_state_failed":       0,
   628  				"unit_systemd-ask-password-wall_service_state_inactive":     1,
   629  				"unit_systemd-fsck-root_service_state_activating":           0,
   630  				"unit_systemd-fsck-root_service_state_active":               0,
   631  				"unit_systemd-fsck-root_service_state_deactivating":         0,
   632  				"unit_systemd-fsck-root_service_state_failed":               0,
   633  				"unit_systemd-fsck-root_service_state_inactive":             1,
   634  				"unit_user-runtime-dir@1000_service_state_activating":       0,
   635  				"unit_user-runtime-dir@1000_service_state_active":           1,
   636  				"unit_user-runtime-dir@1000_service_state_deactivating":     0,
   637  				"unit_user-runtime-dir@1000_service_state_failed":           0,
   638  				"unit_user-runtime-dir@1000_service_state_inactive":         0,
   639  				"unit_user@1000_service_state_activating":                   0,
   640  				"unit_user@1000_service_state_active":                       1,
   641  				"unit_user@1000_service_state_deactivating":                 0,
   642  				"unit_user@1000_service_state_failed":                       0,
   643  				"unit_user@1000_service_state_inactive":                     0,
   644  			},
   645  		},
   646  		"fails when all unites are filtered": {
   647  			prepare: func() *SystemdUnits {
   648  				systemd := New()
   649  				systemd.Include = []string{"*.not_exists"}
   650  				systemd.client = prepareOKClient(230)
   651  				return systemd
   652  			},
   653  			wantCollected: nil,
   654  		},
   655  		"fails on error on connect": {
   656  			prepare: func() *SystemdUnits {
   657  				systemd := New()
   658  				systemd.client = prepareClientErrOnConnect()
   659  				return systemd
   660  			},
   661  			wantCollected: nil,
   662  		},
   663  		"fails on error on get manager property": {
   664  			prepare: func() *SystemdUnits {
   665  				systemd := New()
   666  				systemd.client = prepareClientErrOnGetManagerProperty()
   667  				return systemd
   668  			},
   669  			wantCollected: nil,
   670  		},
   671  		"fails on error on list units": {
   672  			prepare: func() *SystemdUnits {
   673  				systemd := New()
   674  				systemd.client = prepareClientErrOnListUnits()
   675  				return systemd
   676  			},
   677  			wantCollected: nil,
   678  		},
   679  	}
   680  
   681  	for name, test := range tests {
   682  		t.Run(name, func(t *testing.T) {
   683  			systemd := test.prepare()
   684  			require.True(t, systemd.Init())
   685  
   686  			var collected map[string]int64
   687  
   688  			for i := 0; i < 10; i++ {
   689  				collected = systemd.Collect()
   690  			}
   691  
   692  			assert.Equal(t, test.wantCollected, collected)
   693  			if len(test.wantCollected) > 0 {
   694  				ensureCollectedHasAllChartsDimsVarsIDs(t, systemd, collected)
   695  			}
   696  		})
   697  	}
   698  }
   699  
   700  func TestSystemdUnits_connectionReuse(t *testing.T) {
   701  	systemd := New()
   702  	systemd.Include = []string{"*"}
   703  	client := prepareOKClient(230)
   704  	systemd.client = client
   705  	require.True(t, systemd.Init())
   706  
   707  	var collected map[string]int64
   708  	for i := 0; i < 10; i++ {
   709  		collected = systemd.Collect()
   710  	}
   711  
   712  	assert.NotEmpty(t, collected)
   713  	assert.Equal(t, 1, client.connectCalls)
   714  }
   715  
   716  func ensureCollectedHasAllChartsDimsVarsIDs(t *testing.T, sd *SystemdUnits, collected map[string]int64) {
   717  	for _, chart := range *sd.Charts() {
   718  		if chart.Obsolete {
   719  			continue
   720  		}
   721  		for _, dim := range chart.Dims {
   722  			_, ok := collected[dim.ID]
   723  			assert.Truef(t, ok, "collected metrics has no data for dim '%s' chart '%s'", dim.ID, chart.ID)
   724  		}
   725  		for _, v := range chart.Vars {
   726  			_, ok := collected[v.ID]
   727  			assert.Truef(t, ok, "collected metrics has no data for var '%s' chart '%s'", v.ID, chart.ID)
   728  		}
   729  	}
   730  }
   731  
   732  func prepareOKClient(ver int) *mockClient {
   733  	return &mockClient{
   734  		conn: &mockConn{
   735  			version: ver,
   736  			units:   mockSystemdUnits,
   737  		},
   738  	}
   739  }
   740  
   741  func prepareClientErrOnConnect() *mockClient {
   742  	return &mockClient{
   743  		errOnConnect: true,
   744  	}
   745  }
   746  
   747  func prepareClientErrOnGetManagerProperty() *mockClient {
   748  	return &mockClient{
   749  		conn: &mockConn{
   750  			version:                 230,
   751  			errOnGetManagerProperty: true,
   752  			units:                   mockSystemdUnits,
   753  		},
   754  	}
   755  }
   756  
   757  func prepareClientErrOnListUnits() *mockClient {
   758  	return &mockClient{
   759  		conn: &mockConn{
   760  			version:        230,
   761  			errOnListUnits: true,
   762  			units:          mockSystemdUnits,
   763  		},
   764  	}
   765  }
   766  
   767  type mockClient struct {
   768  	conn         systemdConnection
   769  	connectCalls int
   770  	errOnConnect bool
   771  }
   772  
   773  func (m *mockClient) connect() (systemdConnection, error) {
   774  	m.connectCalls++
   775  	if m.errOnConnect {
   776  		return nil, errors.New("mock 'connect' error")
   777  	}
   778  	return m.conn, nil
   779  }
   780  
   781  type mockConn struct {
   782  	version                 int
   783  	units                   []dbus.UnitStatus
   784  	errOnGetManagerProperty bool
   785  	errOnListUnits          bool
   786  	closeCalled             bool
   787  }
   788  
   789  func (m *mockConn) Close() {
   790  	m.closeCalled = true
   791  }
   792  
   793  func (m *mockConn) GetManagerProperty(prop string) (string, error) {
   794  	if m.errOnGetManagerProperty {
   795  		return "", errors.New("'GetManagerProperty' call error")
   796  	}
   797  	if prop != versionProperty {
   798  		return "", fmt.Errorf("'GetManagerProperty' unkown property: %s", prop)
   799  	}
   800  	return fmt.Sprintf("%d.6-1-manjaro", m.version), nil
   801  }
   802  
   803  func (m *mockConn) ListUnitsContext(_ context.Context) ([]dbus.UnitStatus, error) {
   804  	if m.errOnListUnits {
   805  		return nil, errors.New("'ListUnits' call error")
   806  	}
   807  	if m.version >= 230 {
   808  		return nil, errors.New("'ListUnits' unsupported function error")
   809  	}
   810  	return append([]dbus.UnitStatus{}, m.units...), nil
   811  }
   812  
   813  func (m *mockConn) ListUnitsByPatternsContext(_ context.Context, _ []string, ps []string) ([]dbus.UnitStatus, error) {
   814  	if m.errOnListUnits {
   815  		return nil, errors.New("'ListUnitsByPatterns' call error")
   816  	}
   817  	if m.version < 230 {
   818  		return nil, errors.New("'ListUnitsByPatterns' unsupported function error")
   819  	}
   820  
   821  	matches := func(name string) bool {
   822  		for _, p := range ps {
   823  			if ok, _ := filepath.Match(p, name); ok {
   824  				return true
   825  			}
   826  		}
   827  		return false
   828  	}
   829  
   830  	var units []dbus.UnitStatus
   831  	for _, unit := range m.units {
   832  		if matches(unit.Name) {
   833  			units = append(units, unit)
   834  		}
   835  	}
   836  	return units, nil
   837  }
   838  
   839  var mockSystemdUnits = []dbus.UnitStatus{
   840  	{Name: `proc-sys-fs-binfmt_misc.automount`, LoadState: "loaded", ActiveState: "active"},
   841  	{Name: `dev-nvme0n1.device`, LoadState: "loaded", ActiveState: "active"},
   842  	{Name: `sys-devices-virtual-net-loopback1.device`, LoadState: "loaded", ActiveState: "active"},
   843  	{Name: `sys-module-fuse.device`, LoadState: "loaded", ActiveState: "active"},
   844  	{Name: `dev-disk-by\x2duuid-DE44\x2dCEE0.device`, LoadState: "loaded", ActiveState: "active"},
   845  
   846  	{Name: `var-lib-nfs-rpc_pipefs.mount`, LoadState: "loaded", ActiveState: "inactive"},
   847  	{Name: `var.mount`, LoadState: "not-found", ActiveState: "inactive"},
   848  	{Name: `run-user-1000.mount`, LoadState: "loaded", ActiveState: "active"},
   849  	{Name: `tmp.mount`, LoadState: "loaded", ActiveState: "active"},
   850  	{Name: `run-user-1000-gvfs.mount`, LoadState: "loaded", ActiveState: "active"},
   851  
   852  	{Name: `org.cups.cupsd.path`, LoadState: "loaded", ActiveState: "active"},
   853  	{Name: `systemd-ask-password-wall.path`, LoadState: "loaded", ActiveState: "active"},
   854  	{Name: `systemd-ask-password-console.path`, LoadState: "loaded", ActiveState: "active"},
   855  
   856  	{Name: `init.scope`, LoadState: "loaded", ActiveState: "active"},
   857  	{Name: `session-3.scope`, LoadState: "loaded", ActiveState: "active"},
   858  	{Name: `session-6.scope`, LoadState: "loaded", ActiveState: "active"},
   859  	{Name: `session-1.scope`, LoadState: "loaded", ActiveState: "active"},
   860  	{Name: `session-2.scope`, LoadState: "loaded", ActiveState: "active"},
   861  
   862  	{Name: `systemd-fsck-root.service`, LoadState: "loaded", ActiveState: "inactive"},
   863  	{Name: `httpd.service`, LoadState: "not-found", ActiveState: "inactive"},
   864  	{Name: `user-runtime-dir@1000.service`, LoadState: "loaded", ActiveState: "active"},
   865  	{Name: `systemd-ask-password-wall.service`, LoadState: "loaded", ActiveState: "inactive"},
   866  	{Name: `user@1000.service`, LoadState: "loaded", ActiveState: "active"},
   867  
   868  	{Name: `user.slice`, LoadState: "loaded", ActiveState: "active"},
   869  	{Name: `system-getty.slice`, LoadState: "loaded", ActiveState: "active"},
   870  	{Name: `system-netctl.slice`, LoadState: "loaded", ActiveState: "active"},
   871  	{Name: `system.slice`, LoadState: "loaded", ActiveState: "active"},
   872  	{Name: `system-systemd\x2dfsck.slice`, LoadState: "loaded", ActiveState: "active"},
   873  
   874  	{Name: `lvm2-lvmpolld.socket`, LoadState: "loaded", ActiveState: "active"},
   875  	{Name: `docker.socket`, LoadState: "loaded", ActiveState: "active"},
   876  	{Name: `systemd-udevd-kernel.socket`, LoadState: "loaded", ActiveState: "active"},
   877  	{Name: `dbus.socket`, LoadState: "loaded", ActiveState: "active"},
   878  	{Name: `lvm2-lvmetad.socket`, LoadState: "loaded", ActiveState: "active"},
   879  
   880  	{Name: `getty-pre.target`, LoadState: "loaded", ActiveState: "inactive"},
   881  	{Name: `rpc_pipefs.target`, LoadState: "loaded", ActiveState: "inactive"},
   882  	{Name: `remote-fs-pre.target`, LoadState: "loaded", ActiveState: "inactive"},
   883  	{Name: `sysinit.target`, LoadState: "loaded", ActiveState: "active"},
   884  	{Name: `sound.target`, LoadState: "loaded", ActiveState: "active"},
   885  
   886  	{Name: `man-db.timer`, LoadState: "loaded", ActiveState: "active"},
   887  	{Name: `pamac-mirrorlist.timer`, LoadState: "loaded", ActiveState: "active"},
   888  	{Name: `pamac-cleancache.timer`, LoadState: "loaded", ActiveState: "active"},
   889  	{Name: `shadow.timer`, LoadState: "loaded", ActiveState: "active"},
   890  	{Name: `logrotate.timer`, LoadState: "loaded", ActiveState: "active"},
   891  }