LCOV - code coverage report
Current view: top level - test - test-install-root.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 731 734 99.6 %
Date: 2019-08-22 15:41:25 Functions: 14 14 100.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include <unistd.h>
       4             : 
       5             : #include "alloc-util.h"
       6             : #include "fileio.h"
       7             : #include "install.h"
       8             : #include "mkdir.h"
       9             : #include "rm-rf.h"
      10             : #include "special.h"
      11             : #include "string-util.h"
      12             : #include "tests.h"
      13             : 
      14           1 : static void test_basic_mask_and_enable(const char *root) {
      15             :         const char *p;
      16             :         UnitFileState state;
      17           1 :         UnitFileChange *changes = NULL;
      18           1 :         size_t n_changes = 0;
      19             : 
      20           1 :         test_setup_logging(LOG_DEBUG);
      21             : 
      22           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", NULL) == -ENOENT);
      23           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", NULL) == -ENOENT);
      24           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", NULL) == -ENOENT);
      25           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", NULL) == -ENOENT);
      26             : 
      27           5 :         p = strjoina(root, "/usr/lib/systemd/system/a.service");
      28           1 :         assert_se(write_string_file(p,
      29             :                                     "[Install]\n"
      30             :                                     "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
      31             : 
      32           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", NULL) >= 0);
      33           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
      34             : 
      35           5 :         p = strjoina(root, "/usr/lib/systemd/system/b.service");
      36           1 :         assert_se(symlink("a.service", p) >= 0);
      37             : 
      38           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", NULL) >= 0);
      39           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
      40             : 
      41           5 :         p = strjoina(root, "/usr/lib/systemd/system/c.service");
      42           1 :         assert_se(symlink("/usr/lib/systemd/system/a.service", p) >= 0);
      43             : 
      44           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", NULL) >= 0);
      45           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
      46             : 
      47           5 :         p = strjoina(root, "/usr/lib/systemd/system/d.service");
      48           1 :         assert_se(symlink("c.service", p) >= 0);
      49             : 
      50             :         /* This one is interesting, as d follows a relative, then an absolute symlink */
      51           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", NULL) >= 0);
      52           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
      53             : 
      54           1 :         assert_se(unit_file_mask(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0);
      55           1 :         assert_se(n_changes == 1);
      56           1 :         assert_se(changes[0].type == UNIT_FILE_SYMLINK);
      57           1 :         assert_se(streq(changes[0].source, "/dev/null"));
      58           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/a.service");
      59           1 :         assert_se(streq(changes[0].path, p));
      60             : 
      61           1 :         unit_file_changes_free(changes, n_changes);
      62           1 :         changes = NULL; n_changes = 0;
      63             : 
      64           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_MASKED);
      65           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_MASKED);
      66           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_MASKED);
      67           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_MASKED);
      68             : 
      69             :         /* Enabling a masked unit should fail! */
      70           1 :         assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) == -ERFKILL);
      71           1 :         unit_file_changes_free(changes, n_changes);
      72           1 :         changes = NULL; n_changes = 0;
      73             : 
      74           1 :         assert_se(unit_file_unmask(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0);
      75           1 :         assert_se(n_changes == 1);
      76           1 :         assert_se(changes[0].type == UNIT_FILE_UNLINK);
      77           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/a.service");
      78           1 :         assert_se(streq(changes[0].path, p));
      79           1 :         unit_file_changes_free(changes, n_changes);
      80           1 :         changes = NULL; n_changes = 0;
      81             : 
      82           1 :         assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) == 1);
      83           1 :         assert_se(n_changes == 1);
      84           1 :         assert_se(changes[0].type == UNIT_FILE_SYMLINK);
      85           1 :         assert_se(streq(changes[0].source, "/usr/lib/systemd/system/a.service"));
      86           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service");
      87           1 :         assert_se(streq(changes[0].path, p));
      88           1 :         unit_file_changes_free(changes, n_changes);
      89           1 :         changes = NULL; n_changes = 0;
      90             : 
      91           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
      92           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
      93           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
      94           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
      95             : 
      96             :         /* Enabling it again should succeed but be a NOP */
      97           1 :         assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0);
      98           1 :         assert_se(n_changes == 0);
      99           1 :         unit_file_changes_free(changes, n_changes);
     100           1 :         changes = NULL; n_changes = 0;
     101             : 
     102           1 :         assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0);
     103           1 :         assert_se(n_changes == 1);
     104           1 :         assert_se(changes[0].type == UNIT_FILE_UNLINK);
     105           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service");
     106           1 :         assert_se(streq(changes[0].path, p));
     107           1 :         unit_file_changes_free(changes, n_changes);
     108           1 :         changes = NULL; n_changes = 0;
     109             : 
     110           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     111           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     112           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     113           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     114             : 
     115             :         /* Disabling a disabled unit must succeed but be a NOP */
     116           1 :         assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0);
     117           1 :         assert_se(n_changes == 0);
     118           1 :         unit_file_changes_free(changes, n_changes);
     119           1 :         changes = NULL; n_changes = 0;
     120             : 
     121             :         /* Let's enable this indirectly via a symlink */
     122           1 :         assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("d.service"), &changes, &n_changes) >= 0);
     123           1 :         assert_se(n_changes == 1);
     124           1 :         assert_se(changes[0].type == UNIT_FILE_SYMLINK);
     125           1 :         assert_se(streq(changes[0].source, "/usr/lib/systemd/system/a.service"));
     126           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service");
     127           1 :         assert_se(streq(changes[0].path, p));
     128           1 :         unit_file_changes_free(changes, n_changes);
     129           1 :         changes = NULL; n_changes = 0;
     130             : 
     131           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     132           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     133           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     134           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     135             : 
     136             :         /* Let's try to reenable */
     137             : 
     138           1 :         assert_se(unit_file_reenable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("b.service"), &changes, &n_changes) >= 0);
     139           1 :         assert_se(n_changes == 2);
     140           1 :         assert_se(changes[0].type == UNIT_FILE_UNLINK);
     141           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service");
     142           1 :         assert_se(streq(changes[0].path, p));
     143           1 :         assert_se(changes[1].type == UNIT_FILE_SYMLINK);
     144           1 :         assert_se(streq(changes[1].source, "/usr/lib/systemd/system/a.service"));
     145           1 :         assert_se(streq(changes[1].path, p));
     146           1 :         unit_file_changes_free(changes, n_changes);
     147           1 :         changes = NULL; n_changes = 0;
     148             : 
     149           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     150           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     151           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     152           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     153           1 : }
     154             : 
     155           1 : static void test_linked_units(const char *root) {
     156             :         const char *p, *q;
     157             :         UnitFileState state;
     158           1 :         UnitFileChange *changes = NULL;
     159           1 :         size_t n_changes = 0, i;
     160             : 
     161             :         /*
     162             :          * We'll test three cases here:
     163             :          *
     164             :          * a) a unit file in /opt, that we use "systemctl link" and
     165             :          * "systemctl enable" on to make it available to the system
     166             :          *
     167             :          * b) a unit file in /opt, that is statically linked into
     168             :          * /usr/lib/systemd/system, that "enable" should work on
     169             :          * correctly.
     170             :          *
     171             :          * c) a unit file in /opt, that is linked into
     172             :          * /etc/systemd/system, and where "enable" should result in
     173             :          * -ELOOP, since using information from /etc to generate
     174             :          * information in /etc should not be allowed.
     175             :          */
     176             : 
     177           5 :         p = strjoina(root, "/opt/linked.service");
     178           1 :         assert_se(write_string_file(p,
     179             :                                     "[Install]\n"
     180             :                                     "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
     181             : 
     182           5 :         p = strjoina(root, "/opt/linked2.service");
     183           1 :         assert_se(write_string_file(p,
     184             :                                     "[Install]\n"
     185             :                                     "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
     186             : 
     187           5 :         p = strjoina(root, "/opt/linked3.service");
     188           1 :         assert_se(write_string_file(p,
     189             :                                     "[Install]\n"
     190             :                                     "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
     191             : 
     192           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", NULL) == -ENOENT);
     193           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked2.service", NULL) == -ENOENT);
     194           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked3.service", NULL) == -ENOENT);
     195             : 
     196           5 :         p = strjoina(root, "/usr/lib/systemd/system/linked2.service");
     197           1 :         assert_se(symlink("/opt/linked2.service", p) >= 0);
     198             : 
     199           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked3.service");
     200           1 :         assert_se(symlink("/opt/linked3.service", p) >= 0);
     201             : 
     202           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", &state) == -ENOENT);
     203           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked2.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     204           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked3.service", &state) >= 0 && state == UNIT_FILE_LINKED);
     205             : 
     206             :         /* First, let's link the unit into the search path */
     207           1 :         assert_se(unit_file_link(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("/opt/linked.service"), &changes, &n_changes) >= 0);
     208           1 :         assert_se(n_changes == 1);
     209           1 :         assert_se(changes[0].type == UNIT_FILE_SYMLINK);
     210           1 :         assert_se(streq(changes[0].source, "/opt/linked.service"));
     211           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service");
     212           1 :         assert_se(streq(changes[0].path, p));
     213           1 :         unit_file_changes_free(changes, n_changes);
     214           1 :         changes = NULL; n_changes = 0;
     215             : 
     216           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", &state) >= 0 && state == UNIT_FILE_LINKED);
     217             : 
     218             :         /* Let's unlink it from the search path again */
     219           1 :         assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("linked.service"), &changes, &n_changes) >= 0);
     220           1 :         assert_se(n_changes == 1);
     221           1 :         assert_se(changes[0].type == UNIT_FILE_UNLINK);
     222           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service");
     223           1 :         assert_se(streq(changes[0].path, p));
     224           1 :         unit_file_changes_free(changes, n_changes);
     225           1 :         changes = NULL; n_changes = 0;
     226             : 
     227           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", NULL) == -ENOENT);
     228             : 
     229             :         /* Now, let's not just link it, but also enable it */
     230           1 :         assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("/opt/linked.service"), &changes, &n_changes) >= 0);
     231           1 :         assert_se(n_changes == 2);
     232           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked.service");
     233           5 :         q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service");
     234           3 :         for (i = 0 ; i < n_changes; i++) {
     235           2 :                 assert_se(changes[i].type == UNIT_FILE_SYMLINK);
     236           2 :                 assert_se(streq(changes[i].source, "/opt/linked.service"));
     237             : 
     238           2 :                 if (p && streq(changes[i].path, p))
     239           1 :                         p = NULL;
     240           1 :                 else if (q && streq(changes[i].path, q))
     241           1 :                         q = NULL;
     242             :                 else
     243           0 :                         assert_not_reached("wut?");
     244             :         }
     245           1 :         assert(!p && !q);
     246           1 :         unit_file_changes_free(changes, n_changes);
     247           1 :         changes = NULL; n_changes = 0;
     248             : 
     249           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     250             : 
     251             :         /* And let's unlink it again */
     252           1 :         assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("linked.service"), &changes, &n_changes) >= 0);
     253           1 :         assert_se(n_changes == 2);
     254           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked.service");
     255           5 :         q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service");
     256           3 :         for (i = 0; i < n_changes; i++) {
     257           2 :                 assert_se(changes[i].type == UNIT_FILE_UNLINK);
     258             : 
     259           2 :                 if (p && streq(changes[i].path, p))
     260           1 :                         p = NULL;
     261           1 :                 else if (q && streq(changes[i].path, q))
     262           1 :                         q = NULL;
     263             :                 else
     264           0 :                         assert_not_reached("wut?");
     265             :         }
     266           1 :         assert(!p && !q);
     267           1 :         unit_file_changes_free(changes, n_changes);
     268           1 :         changes = NULL; n_changes = 0;
     269             : 
     270           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", NULL) == -ENOENT);
     271             : 
     272           1 :         assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("linked2.service"), &changes, &n_changes) >= 0);
     273           1 :         assert_se(n_changes == 2);
     274           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked2.service");
     275           5 :         q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked2.service");
     276           3 :         for (i = 0 ; i < n_changes; i++) {
     277           2 :                 assert_se(changes[i].type == UNIT_FILE_SYMLINK);
     278           2 :                 assert_se(streq(changes[i].source, "/opt/linked2.service"));
     279             : 
     280           2 :                 if (p && streq(changes[i].path, p))
     281           1 :                         p = NULL;
     282           1 :                 else if (q && streq(changes[i].path, q))
     283           1 :                         q = NULL;
     284             :                 else
     285           0 :                         assert_not_reached("wut?");
     286             :         }
     287           1 :         assert(!p && !q);
     288           1 :         unit_file_changes_free(changes, n_changes);
     289           1 :         changes = NULL; n_changes = 0;
     290             : 
     291           1 :         assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("linked3.service"), &changes, &n_changes) >= 0);
     292           1 :         assert_se(n_changes == 1);
     293           1 :         assert_se(changes[0].type == UNIT_FILE_SYMLINK);
     294           1 :         assert_se(startswith(changes[0].path, root));
     295           1 :         assert_se(endswith(changes[0].path, "linked3.service"));
     296           1 :         assert_se(streq(changes[0].source, "/opt/linked3.service"));
     297           1 :         unit_file_changes_free(changes, n_changes);
     298           1 :         changes = NULL; n_changes = 0;
     299           1 : }
     300             : 
     301           1 : static void test_default(const char *root) {
     302           1 :         _cleanup_free_ char *def = NULL;
     303           1 :         UnitFileChange *changes = NULL;
     304           1 :         size_t n_changes = 0;
     305             :         const char *p;
     306             : 
     307           5 :         p = strjoina(root, "/usr/lib/systemd/system/test-default-real.target");
     308           1 :         assert_se(write_string_file(p, "# pretty much empty", WRITE_STRING_FILE_CREATE) >= 0);
     309             : 
     310           5 :         p = strjoina(root, "/usr/lib/systemd/system/test-default.target");
     311           1 :         assert_se(symlink("test-default-real.target", p) >= 0);
     312             : 
     313           1 :         assert_se(unit_file_get_default(UNIT_FILE_SYSTEM, root, &def) == -ENOENT);
     314             : 
     315           1 :         assert_se(unit_file_set_default(UNIT_FILE_SYSTEM, 0, root, "idontexist.target", &changes, &n_changes) == -ENOENT);
     316           1 :         assert_se(n_changes == 1);
     317           1 :         assert_se(changes[0].type == -ENOENT);
     318           1 :         assert_se(streq_ptr(changes[0].path, "idontexist.target"));
     319           1 :         unit_file_changes_free(changes, n_changes);
     320           1 :         changes = NULL; n_changes = 0;
     321             : 
     322           1 :         assert_se(unit_file_get_default(UNIT_FILE_SYSTEM, root, &def) == -ENOENT);
     323             : 
     324           1 :         assert_se(unit_file_set_default(UNIT_FILE_SYSTEM, 0, root, "test-default.target", &changes, &n_changes) >= 0);
     325           1 :         assert_se(n_changes == 1);
     326           1 :         assert_se(changes[0].type == UNIT_FILE_SYMLINK);
     327           1 :         assert_se(streq(changes[0].source, "/usr/lib/systemd/system/test-default-real.target"));
     328           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH "/" SPECIAL_DEFAULT_TARGET);
     329           1 :         assert_se(streq(changes[0].path, p));
     330           1 :         unit_file_changes_free(changes, n_changes);
     331           1 :         changes = NULL; n_changes = 0;
     332             : 
     333           1 :         assert_se(unit_file_get_default(UNIT_FILE_SYSTEM, root, &def) >= 0);
     334           1 :         assert_se(streq_ptr(def, "test-default-real.target"));
     335           1 : }
     336             : 
     337           1 : static void test_add_dependency(const char *root) {
     338           1 :         UnitFileChange *changes = NULL;
     339           1 :         size_t n_changes = 0;
     340             :         const char *p;
     341             : 
     342           5 :         p = strjoina(root, "/usr/lib/systemd/system/real-add-dependency-test-target.target");
     343           1 :         assert_se(write_string_file(p, "# pretty much empty", WRITE_STRING_FILE_CREATE) >= 0);
     344             : 
     345           5 :         p = strjoina(root, "/usr/lib/systemd/system/add-dependency-test-target.target");
     346           1 :         assert_se(symlink("real-add-dependency-test-target.target", p) >= 0);
     347             : 
     348           5 :         p = strjoina(root, "/usr/lib/systemd/system/real-add-dependency-test-service.service");
     349           1 :         assert_se(write_string_file(p, "# pretty much empty", WRITE_STRING_FILE_CREATE) >= 0);
     350             : 
     351           5 :         p = strjoina(root, "/usr/lib/systemd/system/add-dependency-test-service.service");
     352           1 :         assert_se(symlink("real-add-dependency-test-service.service", p) >= 0);
     353             : 
     354           1 :         assert_se(unit_file_add_dependency(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("add-dependency-test-service.service"), "add-dependency-test-target.target", UNIT_WANTS, &changes, &n_changes) >= 0);
     355           1 :         assert_se(n_changes == 1);
     356           1 :         assert_se(changes[0].type == UNIT_FILE_SYMLINK);
     357           1 :         assert_se(streq(changes[0].source, "/usr/lib/systemd/system/real-add-dependency-test-service.service"));
     358           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/real-add-dependency-test-target.target.wants/real-add-dependency-test-service.service");
     359           1 :         assert_se(streq(changes[0].path, p));
     360           1 :         unit_file_changes_free(changes, n_changes);
     361           1 :         changes = NULL; n_changes = 0;
     362           1 : }
     363             : 
     364           1 : static void test_template_enable(const char *root) {
     365           1 :         UnitFileChange *changes = NULL;
     366           1 :         size_t n_changes = 0;
     367             :         UnitFileState state;
     368             :         const char *p;
     369             : 
     370           1 :         log_info("== %s ==", __func__);
     371             : 
     372           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) == -ENOENT);
     373           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) == -ENOENT);
     374           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) == -ENOENT);
     375           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) == -ENOENT);
     376             : 
     377           5 :         p = strjoina(root, "/usr/lib/systemd/system/template@.service");
     378           1 :         assert_se(write_string_file(p,
     379             :                                     "[Install]\n"
     380             :                                     "DefaultInstance=def\n"
     381             :                                     "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
     382             : 
     383           5 :         p = strjoina(root, "/usr/lib/systemd/system/template-symlink@.service");
     384           1 :         assert_se(symlink("template@.service", p) >= 0);
     385             : 
     386           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     387           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     388           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     389           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     390           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     391           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     392             : 
     393           1 :         log_info("== %s with template@.service enabled ==", __func__);
     394             : 
     395           1 :         assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("template@.service"), &changes, &n_changes) >= 0);
     396           1 :         assert_se(n_changes == 1);
     397           1 :         assert_se(changes[0].type == UNIT_FILE_SYMLINK);
     398           1 :         assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service"));
     399           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/template@def.service");
     400           1 :         assert_se(streq(changes[0].path, p));
     401           1 :         unit_file_changes_free(changes, n_changes);
     402           1 :         changes = NULL; n_changes = 0;
     403             : 
     404           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     405           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     406           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     407           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     408           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     409           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     410             : 
     411           1 :         assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("template@.service"), &changes, &n_changes) >= 0);
     412           1 :         assert_se(n_changes == 1);
     413           1 :         assert_se(changes[0].type == UNIT_FILE_UNLINK);
     414           1 :         assert_se(streq(changes[0].path, p));
     415           1 :         unit_file_changes_free(changes, n_changes);
     416           1 :         changes = NULL; n_changes = 0;
     417             : 
     418           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     419           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     420           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     421           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     422           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     423           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     424             : 
     425           1 :         log_info("== %s with template@foo.service enabled ==", __func__);
     426             : 
     427           1 :         assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("template@foo.service"), &changes, &n_changes) >= 0);
     428           1 :         assert_se(changes[0].type == UNIT_FILE_SYMLINK);
     429           1 :         assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service"));
     430           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/template@foo.service");
     431           1 :         assert_se(streq(changes[0].path, p));
     432           1 :         unit_file_changes_free(changes, n_changes);
     433           1 :         changes = NULL; n_changes = 0;
     434             : 
     435           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
     436           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     437           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     438           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     439           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     440           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     441             : 
     442           1 :         assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("template@foo.service"), &changes, &n_changes) >= 0);
     443           1 :         assert_se(n_changes == 1);
     444           1 :         assert_se(changes[0].type == UNIT_FILE_UNLINK);
     445           1 :         assert_se(streq(changes[0].path, p));
     446           1 :         unit_file_changes_free(changes, n_changes);
     447           1 :         changes = NULL; n_changes = 0;
     448             : 
     449           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     450           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     451           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     452           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@quux.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     453           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     454           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     455           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     456           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@quux.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     457             : 
     458           1 :         log_info("== %s with template-symlink@quux.service enabled ==", __func__);
     459             : 
     460           1 :         assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("template-symlink@quux.service"), &changes, &n_changes) >= 0);
     461           1 :         assert_se(changes[0].type == UNIT_FILE_SYMLINK);
     462           1 :         assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service"));
     463           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/template@quux.service");
     464           1 :         assert_se(streq(changes[0].path, p));
     465           1 :         unit_file_changes_free(changes, n_changes);
     466           1 :         changes = NULL; n_changes = 0;
     467             : 
     468           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
     469           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     470           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     471           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@quux.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     472           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
     473           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     474           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     475           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@quux.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     476           1 : }
     477             : 
     478           1 : static void test_indirect(const char *root) {
     479           1 :         UnitFileChange *changes = NULL;
     480           1 :         size_t n_changes = 0;
     481             :         UnitFileState state;
     482             :         const char *p;
     483             : 
     484           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirecta.service", &state) == -ENOENT);
     485           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectb.service", &state) == -ENOENT);
     486           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectc.service", &state) == -ENOENT);
     487             : 
     488           5 :         p = strjoina(root, "/usr/lib/systemd/system/indirecta.service");
     489           1 :         assert_se(write_string_file(p,
     490             :                                     "[Install]\n"
     491             :                                     "Also=indirectb.service\n", WRITE_STRING_FILE_CREATE) >= 0);
     492             : 
     493           5 :         p = strjoina(root, "/usr/lib/systemd/system/indirectb.service");
     494           1 :         assert_se(write_string_file(p,
     495             :                                     "[Install]\n"
     496             :                                     "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
     497             : 
     498           5 :         p = strjoina(root, "/usr/lib/systemd/system/indirectc.service");
     499           1 :         assert_se(symlink("indirecta.service", p) >= 0);
     500             : 
     501           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirecta.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
     502           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectb.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     503           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectc.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
     504             : 
     505           1 :         assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("indirectc.service"), &changes, &n_changes) >= 0);
     506           1 :         assert_se(n_changes == 1);
     507           1 :         assert_se(changes[0].type == UNIT_FILE_SYMLINK);
     508           1 :         assert_se(streq(changes[0].source, "/usr/lib/systemd/system/indirectb.service"));
     509           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/indirectb.service");
     510           1 :         assert_se(streq(changes[0].path, p));
     511           1 :         unit_file_changes_free(changes, n_changes);
     512           1 :         changes = NULL; n_changes = 0;
     513             : 
     514           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirecta.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
     515           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectb.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     516           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectc.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
     517             : 
     518           1 :         assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("indirectc.service"), &changes, &n_changes) >= 0);
     519           1 :         assert_se(n_changes == 1);
     520           1 :         assert_se(changes[0].type == UNIT_FILE_UNLINK);
     521           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/indirectb.service");
     522           1 :         assert_se(streq(changes[0].path, p));
     523           1 :         unit_file_changes_free(changes, n_changes);
     524           1 :         changes = NULL; n_changes = 0;
     525           1 : }
     526             : 
     527           1 : static void test_preset_and_list(const char *root) {
     528           1 :         UnitFileChange *changes = NULL;
     529           1 :         size_t n_changes = 0, i;
     530             :         const char *p, *q;
     531             :         UnitFileState state;
     532           1 :         bool got_yes = false, got_no = false;
     533             :         Iterator j;
     534             :         UnitFileList *fl;
     535             :         Hashmap *h;
     536             : 
     537           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) == -ENOENT);
     538           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) == -ENOENT);
     539             : 
     540           5 :         p = strjoina(root, "/usr/lib/systemd/system/preset-yes.service");
     541           1 :         assert_se(write_string_file(p,
     542             :                                     "[Install]\n"
     543             :                                     "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
     544             : 
     545           5 :         p = strjoina(root, "/usr/lib/systemd/system/preset-no.service");
     546           1 :         assert_se(write_string_file(p,
     547             :                                     "[Install]\n"
     548             :                                     "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
     549             : 
     550           5 :         p = strjoina(root, "/usr/lib/systemd/system-preset/test.preset");
     551           1 :         assert_se(write_string_file(p,
     552             :                                     "enable *-yes.*\n"
     553             :                                     "disable *\n", WRITE_STRING_FILE_CREATE) >= 0);
     554             : 
     555           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     556           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     557             : 
     558           1 :         assert_se(unit_file_preset(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("preset-yes.service"), UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0);
     559           1 :         assert_se(n_changes == 1);
     560           1 :         assert_se(changes[0].type == UNIT_FILE_SYMLINK);
     561           1 :         assert_se(streq(changes[0].source, "/usr/lib/systemd/system/preset-yes.service"));
     562           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/preset-yes.service");
     563           1 :         assert_se(streq(changes[0].path, p));
     564           1 :         unit_file_changes_free(changes, n_changes);
     565           1 :         changes = NULL; n_changes = 0;
     566             : 
     567           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     568           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     569             : 
     570           1 :         assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("preset-yes.service"), &changes, &n_changes) >= 0);
     571           1 :         assert_se(n_changes == 1);
     572           1 :         assert_se(changes[0].type == UNIT_FILE_UNLINK);
     573           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/preset-yes.service");
     574           1 :         assert_se(streq(changes[0].path, p));
     575           1 :         unit_file_changes_free(changes, n_changes);
     576           1 :         changes = NULL; n_changes = 0;
     577             : 
     578           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     579           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     580             : 
     581           1 :         assert_se(unit_file_preset(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("preset-no.service"), UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0);
     582           1 :         assert_se(n_changes == 0);
     583           1 :         unit_file_changes_free(changes, n_changes);
     584           1 :         changes = NULL; n_changes = 0;
     585             : 
     586           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     587           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     588             : 
     589           1 :         assert_se(unit_file_preset_all(UNIT_FILE_SYSTEM, 0, root, UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0);
     590             : 
     591           1 :         assert_se(n_changes > 0);
     592             : 
     593           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/preset-yes.service");
     594             : 
     595          10 :         for (i = 0; i < n_changes; i++) {
     596             : 
     597           9 :                 if (changes[i].type == UNIT_FILE_SYMLINK) {
     598           1 :                         assert_se(streq(changes[i].source, "/usr/lib/systemd/system/preset-yes.service"));
     599           1 :                         assert_se(streq(changes[i].path, p));
     600             :                 } else
     601           8 :                         assert_se(changes[i].type == UNIT_FILE_UNLINK);
     602             :         }
     603             : 
     604           1 :         unit_file_changes_free(changes, n_changes);
     605           1 :         changes = NULL; n_changes = 0;
     606             : 
     607           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     608           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     609             : 
     610           1 :         assert_se(h = hashmap_new(&string_hash_ops));
     611           1 :         assert_se(unit_file_get_list(UNIT_FILE_SYSTEM, root, h, NULL, NULL) >= 0);
     612             : 
     613           5 :         p = strjoina(root, "/usr/lib/systemd/system/preset-yes.service");
     614           5 :         q = strjoina(root, "/usr/lib/systemd/system/preset-no.service");
     615             : 
     616          19 :         HASHMAP_FOREACH(fl, h, j) {
     617          18 :                 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, basename(fl->path), &state) >= 0);
     618          18 :                 assert_se(fl->state == state);
     619             : 
     620          18 :                 if (streq(fl->path, p)) {
     621           1 :                         got_yes = true;
     622           1 :                         assert_se(fl->state == UNIT_FILE_ENABLED);
     623          17 :                 } else if (streq(fl->path, q)) {
     624           1 :                         got_no = true;
     625           1 :                         assert_se(fl->state == UNIT_FILE_DISABLED);
     626             :                 } else
     627          16 :                         assert_se(IN_SET(fl->state, UNIT_FILE_DISABLED, UNIT_FILE_STATIC, UNIT_FILE_INDIRECT));
     628             :         }
     629             : 
     630           1 :         unit_file_list_free(h);
     631             : 
     632           1 :         assert_se(got_yes && got_no);
     633           1 : }
     634             : 
     635           1 : static void test_revert(const char *root) {
     636             :         const char *p;
     637             :         UnitFileState state;
     638           1 :         UnitFileChange *changes = NULL;
     639           1 :         size_t n_changes = 0;
     640             : 
     641           1 :         assert(root);
     642             : 
     643           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "xx.service", NULL) == -ENOENT);
     644           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "yy.service", NULL) == -ENOENT);
     645             : 
     646           5 :         p = strjoina(root, "/usr/lib/systemd/system/xx.service");
     647           1 :         assert_se(write_string_file(p, "# Empty\n", WRITE_STRING_FILE_CREATE) >= 0);
     648             : 
     649           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "xx.service", NULL) >= 0);
     650           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "xx.service", &state) >= 0 && state == UNIT_FILE_STATIC);
     651             : 
     652             :         /* Initially there's nothing to revert */
     653           1 :         assert_se(unit_file_revert(UNIT_FILE_SYSTEM, root, STRV_MAKE("xx.service"), &changes, &n_changes) >= 0);
     654           1 :         assert_se(n_changes == 0);
     655           1 :         unit_file_changes_free(changes, n_changes);
     656           1 :         changes = NULL; n_changes = 0;
     657             : 
     658           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/xx.service");
     659           1 :         assert_se(write_string_file(p, "# Empty override\n", WRITE_STRING_FILE_CREATE) >= 0);
     660             : 
     661             :         /* Revert the override file */
     662           1 :         assert_se(unit_file_revert(UNIT_FILE_SYSTEM, root, STRV_MAKE("xx.service"), &changes, &n_changes) >= 0);
     663           1 :         assert_se(n_changes == 1);
     664           1 :         assert_se(changes[0].type == UNIT_FILE_UNLINK);
     665           1 :         assert_se(streq(changes[0].path, p));
     666           1 :         unit_file_changes_free(changes, n_changes);
     667           1 :         changes = NULL; n_changes = 0;
     668             : 
     669           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/xx.service.d/dropin.conf");
     670           1 :         assert_se(mkdir_parents(p, 0755) >= 0);
     671           1 :         assert_se(write_string_file(p, "# Empty dropin\n", WRITE_STRING_FILE_CREATE) >= 0);
     672             : 
     673             :         /* Revert the dropin file */
     674           1 :         assert_se(unit_file_revert(UNIT_FILE_SYSTEM, root, STRV_MAKE("xx.service"), &changes, &n_changes) >= 0);
     675           1 :         assert_se(n_changes == 2);
     676           1 :         assert_se(changes[0].type == UNIT_FILE_UNLINK);
     677           1 :         assert_se(streq(changes[0].path, p));
     678             : 
     679           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/xx.service.d");
     680           1 :         assert_se(changes[1].type == UNIT_FILE_UNLINK);
     681           1 :         assert_se(streq(changes[1].path, p));
     682           1 :         unit_file_changes_free(changes, n_changes);
     683           1 :         changes = NULL; n_changes = 0;
     684           1 : }
     685             : 
     686           1 : static void test_preset_order(const char *root) {
     687           1 :         UnitFileChange *changes = NULL;
     688           1 :         size_t n_changes = 0;
     689             :         const char *p;
     690             :         UnitFileState state;
     691             : 
     692           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-1.service", &state) == -ENOENT);
     693           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-2.service", &state) == -ENOENT);
     694             : 
     695           5 :         p = strjoina(root, "/usr/lib/systemd/system/prefix-1.service");
     696           1 :         assert_se(write_string_file(p,
     697             :                                     "[Install]\n"
     698             :                                     "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
     699             : 
     700           5 :         p = strjoina(root, "/usr/lib/systemd/system/prefix-2.service");
     701           1 :         assert_se(write_string_file(p,
     702             :                                     "[Install]\n"
     703             :                                     "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
     704             : 
     705           5 :         p = strjoina(root, "/usr/lib/systemd/system-preset/test.preset");
     706           1 :         assert_se(write_string_file(p,
     707             :                                     "enable prefix-1.service\n"
     708             :                                     "disable prefix-*.service\n"
     709             :                                     "enable prefix-2.service\n", WRITE_STRING_FILE_CREATE) >= 0);
     710             : 
     711           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-1.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     712           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-2.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     713             : 
     714           1 :         assert_se(unit_file_preset(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("prefix-1.service"), UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0);
     715           1 :         assert_se(n_changes == 1);
     716           1 :         assert_se(changes[0].type == UNIT_FILE_SYMLINK);
     717           1 :         assert_se(streq(changes[0].source, "/usr/lib/systemd/system/prefix-1.service"));
     718           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/prefix-1.service");
     719           1 :         assert_se(streq(changes[0].path, p));
     720           1 :         unit_file_changes_free(changes, n_changes);
     721           1 :         changes = NULL; n_changes = 0;
     722             : 
     723           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-1.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     724           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-2.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     725             : 
     726           1 :         assert_se(unit_file_preset(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("prefix-2.service"), UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0);
     727           1 :         assert_se(n_changes == 0);
     728             : 
     729           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-1.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     730           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-2.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     731           1 : }
     732             : 
     733           1 : static void test_static_instance(const char *root) {
     734             :         UnitFileState state;
     735             :         const char *p;
     736             : 
     737           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "static-instance@.service", &state) == -ENOENT);
     738           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "static-instance@foo.service", &state) == -ENOENT);
     739             : 
     740           5 :         p = strjoina(root, "/usr/lib/systemd/system/static-instance@.service");
     741           1 :         assert_se(write_string_file(p,
     742             :                                     "[Install]\n"
     743             :                                     "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
     744             : 
     745           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "static-instance@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     746           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "static-instance@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     747             : 
     748           5 :         p = strjoina(root, "/usr/lib/systemd/system/static-instance@foo.service");
     749           1 :         assert_se(symlink("static-instance@.service", p) >= 0);
     750             : 
     751           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "static-instance@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     752           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "static-instance@foo.service", &state) >= 0 && state == UNIT_FILE_STATIC);
     753           1 : }
     754             : 
     755           1 : static void test_with_dropin(const char *root) {
     756             :         const char *p;
     757             :         UnitFileState state;
     758           1 :         UnitFileChange *changes = NULL;
     759           1 :         size_t n_changes = 0;
     760             : 
     761           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-1.service", &state) == -ENOENT);
     762           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2.service", &state) == -ENOENT);
     763           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3.service", &state) == -ENOENT);
     764           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-4a.service", &state) == -ENOENT);
     765           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-4b.service", &state) == -ENOENT);
     766             : 
     767           5 :         p = strjoina(root, "/usr/lib/systemd/system/with-dropin-1.service");
     768           1 :         assert_se(write_string_file(p,
     769             :                                     "[Install]\n"
     770             :                                     "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
     771             : 
     772           5 :         p = strjoina(root, "/usr/lib/systemd/system/with-dropin-1.service.d/dropin.conf");
     773           1 :         assert_se(mkdir_parents(p, 0755) >= 0);
     774           1 :         assert_se(write_string_file(p,
     775             :                                     "[Install]\n"
     776             :                                     "WantedBy=graphical.target\n", WRITE_STRING_FILE_CREATE) >= 0);
     777             : 
     778           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-1.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     779             : 
     780           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/with-dropin-2.service");
     781           1 :         assert_se(write_string_file(p,
     782             :                                     "[Install]\n"
     783             :                                     "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
     784             : 
     785           5 :         p = strjoina(root, "/usr/lib/systemd/system/with-dropin-2.service.d/dropin.conf");
     786           1 :         assert_se(mkdir_parents(p, 0755) >= 0);
     787           1 :         assert_se(write_string_file(p,
     788             :                                     "[Install]\n"
     789             :                                     "WantedBy=graphical.target\n", WRITE_STRING_FILE_CREATE) >= 0);
     790             : 
     791           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     792             : 
     793           5 :         p = strjoina(root, "/usr/lib/systemd/system/with-dropin-3.service");
     794           1 :         assert_se(write_string_file(p,
     795             :                                     "[Install]\n"
     796             :                                     "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
     797             : 
     798           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/with-dropin-3.service.d/dropin.conf");
     799           1 :         assert_se(mkdir_parents(p, 0755) >= 0);
     800           1 :         assert_se(write_string_file(p,
     801             :                                     "[Install]\n"
     802             :                                     "WantedBy=graphical.target\n", WRITE_STRING_FILE_CREATE) >= 0);
     803             : 
     804           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     805             : 
     806           5 :         p = strjoina(root, "/usr/lib/systemd/system/with-dropin-4a.service");
     807           1 :         assert_se(write_string_file(p,
     808             :                                     "[Install]\n"
     809             :                                     "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
     810             : 
     811           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/with-dropin-4a.service.d/dropin.conf");
     812           1 :         assert_se(mkdir_parents(p, 0755) >= 0);
     813           1 :         assert_se(write_string_file(p,
     814             :                                     "[Install]\n"
     815             :                                     "Also=with-dropin-4b.service\n", WRITE_STRING_FILE_CREATE) >= 0);
     816             : 
     817           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-4a.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     818             : 
     819           5 :         p = strjoina(root, "/usr/lib/systemd/system/with-dropin-4b.service");
     820           1 :         assert_se(write_string_file(p,
     821             :                                     "[Install]\n"
     822             :                                     "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
     823             : 
     824           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-4b.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     825             : 
     826           1 :         assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-1.service"), &changes, &n_changes) == 1);
     827           1 :         assert_se(n_changes == 2);
     828           1 :         assert_se(changes[0].type == UNIT_FILE_SYMLINK);
     829           1 :         assert_se(changes[1].type == UNIT_FILE_SYMLINK);
     830           1 :         assert_se(streq(changes[0].source, "/usr/lib/systemd/system/with-dropin-1.service"));
     831           1 :         assert_se(streq(changes[1].source, "/usr/lib/systemd/system/with-dropin-1.service"));
     832           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-1.service");
     833           1 :         assert_se(streq(changes[0].path, p));
     834           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/graphical.target.wants/with-dropin-1.service");
     835           1 :         assert_se(streq(changes[1].path, p));
     836           1 :         unit_file_changes_free(changes, n_changes);
     837           1 :         changes = NULL; n_changes = 0;
     838             : 
     839           1 :         assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-2.service"), &changes, &n_changes) == 1);
     840           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     841           1 :         assert_se(n_changes == 2);
     842           1 :         assert_se(changes[0].type == UNIT_FILE_SYMLINK);
     843           1 :         assert_se(changes[1].type == UNIT_FILE_SYMLINK);
     844           1 :         assert_se(streq(changes[0].source, SYSTEM_CONFIG_UNIT_PATH"/with-dropin-2.service"));
     845           1 :         assert_se(streq(changes[1].source, SYSTEM_CONFIG_UNIT_PATH"/with-dropin-2.service"));
     846           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-2.service");
     847           1 :         assert_se(streq(changes[0].path, p));
     848           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/graphical.target.wants/with-dropin-2.service");
     849           1 :         assert_se(streq(changes[1].path, p));
     850           1 :         unit_file_changes_free(changes, n_changes);
     851           1 :         changes = NULL; n_changes = 0;
     852             : 
     853           1 :         assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-3.service"), &changes, &n_changes) == 1);
     854           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     855           1 :         assert_se(n_changes == 2);
     856           1 :         assert_se(changes[0].type == UNIT_FILE_SYMLINK);
     857           1 :         assert_se(changes[1].type == UNIT_FILE_SYMLINK);
     858           1 :         assert_se(streq(changes[0].source, "/usr/lib/systemd/system/with-dropin-3.service"));
     859           1 :         assert_se(streq(changes[1].source, "/usr/lib/systemd/system/with-dropin-3.service"));
     860           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-3.service");
     861           1 :         assert_se(streq(changes[0].path, p));
     862           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/graphical.target.wants/with-dropin-3.service");
     863           1 :         assert_se(streq(changes[1].path, p));
     864           1 :         unit_file_changes_free(changes, n_changes);
     865           1 :         changes = NULL; n_changes = 0;
     866             : 
     867           1 :         assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-4a.service"), &changes, &n_changes) == 2);
     868           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     869           1 :         assert_se(n_changes == 2);
     870           1 :         assert_se(changes[0].type == UNIT_FILE_SYMLINK);
     871           1 :         assert_se(changes[1].type == UNIT_FILE_SYMLINK);
     872           1 :         assert_se(streq(changes[0].source, "/usr/lib/systemd/system/with-dropin-4a.service"));
     873           1 :         assert_se(streq(changes[1].source, "/usr/lib/systemd/system/with-dropin-4b.service"));
     874           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-4a.service");
     875           1 :         assert_se(streq(changes[0].path, p));
     876           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-4b.service");
     877           1 :         assert_se(streq(changes[1].path, p));
     878           1 :         unit_file_changes_free(changes, n_changes);
     879           1 :         changes = NULL; n_changes = 0;
     880             : 
     881           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-1.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     882           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     883           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     884           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-4a.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     885           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-4b.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     886           1 : }
     887             : 
     888           1 : static void test_with_dropin_template(const char *root) {
     889             :         const char *p;
     890             :         UnitFileState state;
     891           1 :         UnitFileChange *changes = NULL;
     892           1 :         size_t n_changes = 0;
     893             : 
     894           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-1@.service", &state) == -ENOENT);
     895           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2@.service", &state) == -ENOENT);
     896           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3@.service", &state) == -ENOENT);
     897             : 
     898           5 :         p = strjoina(root, "/usr/lib/systemd/system/with-dropin-1@.service");
     899           1 :         assert_se(write_string_file(p,
     900             :                                     "[Install]\n"
     901             :                                     "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
     902             : 
     903           5 :         p = strjoina(root, "/usr/lib/systemd/system/with-dropin-1@.service.d/dropin.conf");
     904           1 :         assert_se(mkdir_parents(p, 0755) >= 0);
     905           1 :         assert_se(write_string_file(p,
     906             :                                     "[Install]\n"
     907             :                                     "WantedBy=graphical.target\n", WRITE_STRING_FILE_CREATE) >= 0);
     908             : 
     909           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-1@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     910             : 
     911           5 :         p = strjoina(root, "/usr/lib/systemd/system/with-dropin-2@.service");
     912           1 :         assert_se(write_string_file(p,
     913             :                                     "[Install]\n"
     914             :                                     "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
     915             : 
     916           5 :         p = strjoina(root, "/usr/lib/systemd/system/with-dropin-2@instance-1.service.d/dropin.conf");
     917           1 :         assert_se(mkdir_parents(p, 0755) >= 0);
     918           1 :         assert_se(write_string_file(p,
     919             :                                     "[Install]\n"
     920             :                                     "WantedBy=graphical.target\n", WRITE_STRING_FILE_CREATE) >= 0);
     921             : 
     922           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     923             : 
     924           5 :         p = strjoina(root, "/usr/lib/systemd/system/with-dropin-3@.service");
     925           1 :         assert_se(write_string_file(p,
     926             :                                     "[Install]\n"
     927             :                                     "DefaultInstance=instance-1\n"
     928             :                                     "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
     929             : 
     930           5 :         p = strjoina(root, "/usr/lib/systemd/system/with-dropin-3@.service.d/dropin.conf");
     931           1 :         assert_se(mkdir_parents(p, 0755) >= 0);
     932           1 :         assert_se(write_string_file(p,
     933             :                                     "[Install]\n"
     934             :                                     "DefaultInstance=instance-2\n", WRITE_STRING_FILE_CREATE) >= 0);
     935             : 
     936           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     937             : 
     938           1 :         assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-1@instance-1.service"), &changes, &n_changes) == 1);
     939           1 :         assert_se(n_changes == 2);
     940           1 :         assert_se(changes[0].type == UNIT_FILE_SYMLINK);
     941           1 :         assert_se(changes[1].type == UNIT_FILE_SYMLINK);
     942           1 :         assert_se(streq(changes[0].source, "/usr/lib/systemd/system/with-dropin-1@.service"));
     943           1 :         assert_se(streq(changes[1].source, "/usr/lib/systemd/system/with-dropin-1@.service"));
     944           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-1@instance-1.service");
     945           1 :         assert_se(streq(changes[0].path, p));
     946           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/graphical.target.wants/with-dropin-1@instance-1.service");
     947           1 :         assert_se(streq(changes[1].path, p));
     948           1 :         unit_file_changes_free(changes, n_changes);
     949           1 :         changes = NULL; n_changes = 0;
     950             : 
     951           1 :         assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-2@instance-1.service"), &changes, &n_changes) == 1);
     952           1 :         assert_se(n_changes == 2);
     953           1 :         assert_se(changes[0].type == UNIT_FILE_SYMLINK);
     954           1 :         assert_se(changes[1].type == UNIT_FILE_SYMLINK);
     955           1 :         assert_se(streq(changes[0].source, "/usr/lib/systemd/system/with-dropin-2@.service"));
     956           1 :         assert_se(streq(changes[1].source, "/usr/lib/systemd/system/with-dropin-2@.service"));
     957           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-2@instance-1.service");
     958           1 :         assert_se(streq(changes[0].path, p));
     959           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/graphical.target.wants/with-dropin-2@instance-1.service");
     960           1 :         assert_se(streq(changes[1].path, p));
     961           1 :         unit_file_changes_free(changes, n_changes);
     962           1 :         changes = NULL; n_changes = 0;
     963             : 
     964           1 :         assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-2@instance-2.service"), &changes, &n_changes) == 1);
     965           1 :         assert_se(n_changes == 1);
     966           1 :         assert_se(changes[0].type == UNIT_FILE_SYMLINK);
     967           1 :         assert_se(streq(changes[0].source, "/usr/lib/systemd/system/with-dropin-2@.service"));
     968           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-2@instance-2.service");
     969           1 :         assert_se(streq(changes[0].path, p));
     970           1 :         unit_file_changes_free(changes, n_changes);
     971           1 :         changes = NULL; n_changes = 0;
     972             : 
     973           1 :         assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-3@.service"), &changes, &n_changes) == 1);
     974           1 :         assert_se(n_changes == 1);
     975           1 :         assert_se(changes[0].type == UNIT_FILE_SYMLINK);
     976           1 :         assert_se(streq(changes[0].source, "/usr/lib/systemd/system/with-dropin-3@.service"));
     977           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-3@instance-2.service");
     978           1 :         assert_se(streq(changes[0].path, p));
     979           1 :         unit_file_changes_free(changes, n_changes);
     980           1 :         changes = NULL; n_changes = 0;
     981             : 
     982           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-1@instance-1.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     983           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2@instance-1.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     984           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2@instance-2.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     985           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3@instance-1.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
     986           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3@instance-2.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
     987           1 : }
     988             : 
     989           1 : static void test_preset_multiple_instances(const char *root) {
     990           1 :         UnitFileChange *changes = NULL;
     991           1 :         size_t n_changes = 0;
     992             :         const char *p;
     993             :         UnitFileState state;
     994             : 
     995             :         /* Set up template service files and preset file */
     996           5 :         p = strjoina(root, "/usr/lib/systemd/system/foo@.service");
     997           1 :         assert_se(write_string_file(p,
     998             :                                     "[Install]\n"
     999             :                                     "DefaultInstance=def\n"
    1000             :                                     "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
    1001             : 
    1002           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
    1003             : 
    1004           5 :         p = strjoina(root, "/usr/lib/systemd/system-preset/test.preset");
    1005           1 :         assert_se(write_string_file(p,
    1006             :                                     "enable foo@.service bar0 bar1 bartest\n"
    1007             :                                     "enable emptylist@.service\n" /* This line ensures the old functionality for templated unit still works */
    1008             :                                     "disable *\n" , WRITE_STRING_FILE_CREATE) >= 0);
    1009             : 
    1010           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@bar0.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
    1011             : 
    1012             :         /* Preset a single instantiated unit specified in the list */
    1013           1 :         assert_se(unit_file_preset(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("foo@bar0.service"), UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0);
    1014           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@bar0.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
    1015           1 :         assert_se(n_changes == 1);
    1016           1 :         assert_se(changes[0].type == UNIT_FILE_SYMLINK);
    1017           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/foo@bar0.service");
    1018           1 :         assert_se(streq(changes[0].path, p));
    1019           1 :         unit_file_changes_free(changes, n_changes);
    1020           1 :         changes = NULL; n_changes = 0;
    1021             : 
    1022           1 :         assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("foo@bar0.service"), &changes, &n_changes) >= 0);
    1023           1 :         assert_se(n_changes == 1);
    1024           1 :         assert_se(changes[0].type == UNIT_FILE_UNLINK);
    1025           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/foo@bar0.service");
    1026           1 :         assert_se(streq(changes[0].path, p));
    1027           1 :         unit_file_changes_free(changes, n_changes);
    1028           1 :         changes = NULL; n_changes = 0;
    1029             : 
    1030             :         /* Check for preset-all case, only instances on the list should be enabled, not including the default instance */
    1031           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
    1032           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@bar1.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
    1033           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@bartest.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
    1034             : 
    1035           1 :         assert_se(unit_file_preset_all(UNIT_FILE_SYSTEM, 0, root, UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0);
    1036           1 :         assert_se(n_changes > 0);
    1037             : 
    1038           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
    1039           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@bar0.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
    1040           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@bar1.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
    1041           1 :         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@bartest.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
    1042             : 
    1043           1 :         unit_file_changes_free(changes, n_changes);
    1044           1 : }
    1045             : 
    1046           1 : int main(int argc, char *argv[]) {
    1047           1 :         char root[] = "/tmp/rootXXXXXX";
    1048             :         const char *p;
    1049             : 
    1050           1 :         assert_se(mkdtemp(root));
    1051             : 
    1052           5 :         p = strjoina(root, "/usr/lib/systemd/system/");
    1053           1 :         assert_se(mkdir_p(p, 0755) >= 0);
    1054             : 
    1055           5 :         p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/");
    1056           1 :         assert_se(mkdir_p(p, 0755) >= 0);
    1057             : 
    1058           5 :         p = strjoina(root, "/run/systemd/system/");
    1059           1 :         assert_se(mkdir_p(p, 0755) >= 0);
    1060             : 
    1061           5 :         p = strjoina(root, "/opt/");
    1062           1 :         assert_se(mkdir_p(p, 0755) >= 0);
    1063             : 
    1064           5 :         p = strjoina(root, "/usr/lib/systemd/system-preset/");
    1065           1 :         assert_se(mkdir_p(p, 0755) >= 0);
    1066             : 
    1067           1 :         test_basic_mask_and_enable(root);
    1068           1 :         test_linked_units(root);
    1069           1 :         test_default(root);
    1070           1 :         test_add_dependency(root);
    1071           1 :         test_template_enable(root);
    1072           1 :         test_indirect(root);
    1073           1 :         test_preset_and_list(root);
    1074           1 :         test_preset_order(root);
    1075           1 :         test_preset_multiple_instances(root);
    1076           1 :         test_revert(root);
    1077           1 :         test_static_instance(root);
    1078           1 :         test_with_dropin(root);
    1079           1 :         test_with_dropin_template(root);
    1080             : 
    1081           1 :         assert_se(rm_rf(root, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
    1082             : 
    1083           1 :         return 0;
    1084             : }

Generated by: LCOV version 1.14