summaryrefslogtreecommitdiffstats
path: root/src/test/test-sleep.c
blob: 6bb8ca0874f5902811270abea935c6f9bbdcc04d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/* SPDX-License-Identifier: LGPL-2.1-or-later */

#include <fcntl.h>
#include <inttypes.h>
#include <linux/fiemap.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

#include "efivars.h"
#include "errno-util.h"
#include "fd-util.h"
#include "log.h"
#include "memory-util.h"
#include "sleep-util.h"
#include "strv.h"
#include "tests.h"

TEST(parse_sleep_config) {
        _cleanup_(free_sleep_configp) SleepConfig *sleep_config = NULL;

        assert_se(parse_sleep_config(&sleep_config) == 0);

        _cleanup_free_ char *sum = NULL, *sus = NULL, *him = NULL, *his = NULL, *hym = NULL, *hys = NULL;

        sum = strv_join(sleep_config->modes[SLEEP_SUSPEND], ", ");
        sus = strv_join(sleep_config->states[SLEEP_SUSPEND], ", ");
        him = strv_join(sleep_config->modes[SLEEP_HIBERNATE], ", ");
        his = strv_join(sleep_config->states[SLEEP_HIBERNATE], ", ");
        hym = strv_join(sleep_config->modes[SLEEP_HYBRID_SLEEP], ", ");
        hys = strv_join(sleep_config->states[SLEEP_HYBRID_SLEEP], ", ");
        log_debug("  allow_suspend: %s", yes_no(sleep_config->allow[SLEEP_SUSPEND]));
        log_debug("  allow_hibernate: %s", yes_no(sleep_config->allow[SLEEP_HIBERNATE]));
        log_debug("  allow_s2h: %s", yes_no(sleep_config->allow[SLEEP_SUSPEND_THEN_HIBERNATE]));
        log_debug("  allow_hybrid_sleep: %s", yes_no(sleep_config->allow[SLEEP_HYBRID_SLEEP]));
        log_debug("  suspend modes: %s", sum);
        log_debug("         states: %s", sus);
        log_debug("  hibernate modes: %s", him);
        log_debug("           states: %s", his);
        log_debug("  hybrid modes: %s", hym);
        log_debug("        states: %s", hys);
}

static int test_fiemap_one(const char *path) {
        _cleanup_free_ struct fiemap *fiemap = NULL;
        _cleanup_close_ int fd = -EBADF;
        int r;

        log_info("/* %s */", __func__);

        fd = open(path, O_RDONLY | O_CLOEXEC | O_NONBLOCK);
        if (fd < 0)
                return log_error_errno(errno, "failed to open %s: %m", path);
        r = read_fiemap(fd, &fiemap);
        if (r == -EOPNOTSUPP)
                exit(log_tests_skipped("Not supported"));
        if (r < 0)
                return log_error_errno(r, "Unable to read extent map for '%s': %m", path);
        log_info("extent map information for %s:", path);
        log_info("\t start: %" PRIu64, (uint64_t) fiemap->fm_start);
        log_info("\t length: %" PRIu64, (uint64_t) fiemap->fm_length);
        log_info("\t flags: %" PRIu32, fiemap->fm_flags);
        log_info("\t number of mapped extents: %" PRIu32, fiemap->fm_mapped_extents);
        log_info("\t extent count: %" PRIu32, fiemap->fm_extent_count);
        if (fiemap->fm_extent_count > 0)
                log_info("\t first extent location: %" PRIu64,
                         (uint64_t) (fiemap->fm_extents[0].fe_physical / page_size()));

        return 0;
}

TEST_RET(fiemap) {
        int r = 0;

        assert_se(test_fiemap_one(saved_argv[0]) == 0);
        for (int i = 1; i < saved_argc; i++) {
                int k = test_fiemap_one(saved_argv[i]);
                if (r == 0)
                        r = k;
        }

        return r;
}

TEST(sleep) {
        _cleanup_strv_free_ char
                **standby = strv_new("standby"),
                **mem = strv_new("mem"),
                **disk = strv_new("disk"),
                **suspend = strv_new("suspend"),
                **reboot = strv_new("reboot"),
                **platform = strv_new("platform"),
                **shutdown = strv_new("shutdown"),
                **freeze = strv_new("freeze");
        int r;

        printf("Secure boot: %sd\n", enable_disable(is_efi_secure_boot()));

        log_info("/= individual sleep modes =/");
        log_info("Standby configured: %s", yes_no(can_sleep_state(standby) > 0));
        log_info("Suspend configured: %s", yes_no(can_sleep_state(mem) > 0));
        log_info("Hibernate configured: %s", yes_no(can_sleep_state(disk) > 0));
        log_info("Hibernate+Suspend (Hybrid-Sleep) configured: %s", yes_no(can_sleep_disk(suspend) > 0));
        log_info("Hibernate+Reboot configured: %s", yes_no(can_sleep_disk(reboot) > 0));
        log_info("Hibernate+Platform configured: %s", yes_no(can_sleep_disk(platform) > 0));
        log_info("Hibernate+Shutdown configured: %s", yes_no(can_sleep_disk(shutdown) > 0));
        log_info("Freeze configured: %s", yes_no(can_sleep_state(freeze) > 0));

        log_info("/= high-level sleep verbs =/");
        r = can_sleep(SLEEP_SUSPEND);
        log_info("Suspend configured and possible: %s", r >= 0 ? yes_no(r) : STRERROR(r));
        r = can_sleep(SLEEP_HIBERNATE);
        log_info("Hibernation configured and possible: %s", r >= 0 ? yes_no(r) : STRERROR(r));
        r = can_sleep(SLEEP_HYBRID_SLEEP);
        log_info("Hybrid-sleep configured and possible: %s", r >= 0 ? yes_no(r) : STRERROR(r));
        r = can_sleep(SLEEP_SUSPEND_THEN_HIBERNATE);
        log_info("Suspend-then-Hibernate configured and possible: %s", r >= 0 ? yes_no(r) : STRERROR(r));
}

TEST(fetch_batteries_capacity_by_name) {
        _cleanup_hashmap_free_ Hashmap *capacity = NULL;
        int r;

        assert_se(fetch_batteries_capacity_by_name(&capacity) >= 0);
        log_debug("fetch_batteries_capacity_by_name: %u entries", hashmap_size(capacity));

        const char *name;
        void *cap;
        HASHMAP_FOREACH_KEY(cap, name, capacity) {
                assert(cap);  /* Anything non-null is fine. */
                log_info("Battery %s: capacity = %i", name, get_capacity_by_name(capacity, name));
        }

        for (int i = 0; i < 2; i++) {
                usec_t interval;

                if (i > 0)
                        sleep(1);

                r = get_total_suspend_interval(capacity, &interval);
                assert_se(r >= 0 || r == -ENOENT);
                log_info("%d: get_total_suspend_interval: %s", i,
                         r < 0 ? STRERROR(r) : FORMAT_TIMESPAN(interval, USEC_PER_SEC));
        }
}

static int intro(void) {
        if (getuid() != 0)
                log_warning("This program is unlikely to work for unprivileged users");

        return EXIT_SUCCESS;
}

DEFINE_TEST_MAIN_WITH_INTRO(LOG_DEBUG, intro);