mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2025-12-31 20:36:25 +00:00
tests: remove low-value tests
These are already dealt with in other ways or just not useful given now we process things now.
This commit is contained in:
@ -1,220 +0,0 @@
|
||||
/* allocs-within-mark.c
|
||||
*
|
||||
* Copyright 2020 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <locale.h>
|
||||
#include <stdlib.h>
|
||||
#include <sysprof.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gint64 begin;
|
||||
gint64 end;
|
||||
gint64 allocated;
|
||||
} Interval;
|
||||
|
||||
static gint
|
||||
compare_interval (gconstpointer a,
|
||||
gconstpointer b)
|
||||
{
|
||||
const Interval *aptr = a;
|
||||
const Interval *bptr = b;
|
||||
|
||||
if (aptr->begin < bptr->begin)
|
||||
return -1;
|
||||
else if (aptr->begin > bptr->begin)
|
||||
return 1;
|
||||
|
||||
if (aptr->end < bptr->end)
|
||||
return -1;
|
||||
else if (aptr->end > bptr->end)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static gint
|
||||
find_time_cb (gconstpointer key,
|
||||
gconstpointer b)
|
||||
{
|
||||
const Interval *keyptr = key;
|
||||
const Interval *bptr = b;
|
||||
|
||||
if (keyptr->begin >= bptr->begin && keyptr->end <= bptr->end)
|
||||
return 0;
|
||||
|
||||
return compare_interval (key, b);
|
||||
}
|
||||
|
||||
static inline Interval *
|
||||
find_time (GArray *ar,
|
||||
gint64 time)
|
||||
{
|
||||
Interval key = {time, time, 0};
|
||||
|
||||
return bsearch (&key, ar->data, ar->len, sizeof (Interval), find_time_cb);
|
||||
}
|
||||
|
||||
static void
|
||||
allocs_within_mark (SysprofCaptureReader *reader,
|
||||
const gchar *category,
|
||||
const gchar *name)
|
||||
{
|
||||
g_autoptr(GArray) intervals = g_array_new (FALSE, FALSE, sizeof (Interval));
|
||||
SysprofCaptureFrameType type;
|
||||
gint64 begin;
|
||||
struct {
|
||||
gint64 total;
|
||||
gint64 min;
|
||||
gint64 max;
|
||||
} st = { 0, G_MAXINT64, G_MININT64 };
|
||||
|
||||
g_assert (reader);
|
||||
g_assert (category);
|
||||
g_assert (name);
|
||||
|
||||
begin = sysprof_capture_reader_get_start_time (reader);
|
||||
|
||||
while (sysprof_capture_reader_peek_type (reader, &type))
|
||||
{
|
||||
if (type == SYSPROF_CAPTURE_FRAME_MARK)
|
||||
{
|
||||
const SysprofCaptureMark *ev;
|
||||
Interval *iv;
|
||||
|
||||
if (!(ev = sysprof_capture_reader_read_mark (reader)))
|
||||
break;
|
||||
|
||||
if (strcmp (category, ev->group) != 0 ||
|
||||
strcmp (name, ev->name) != 0)
|
||||
continue;
|
||||
|
||||
g_array_set_size (intervals, intervals->len + 1);
|
||||
|
||||
iv = &g_array_index (intervals, Interval, intervals->len - 1);
|
||||
iv->begin = ev->frame.time;
|
||||
iv->end = ev->frame.time + ev->duration;
|
||||
iv->allocated = 0;
|
||||
}
|
||||
else if (!sysprof_capture_reader_skip (reader))
|
||||
break;
|
||||
}
|
||||
|
||||
g_array_sort (intervals, compare_interval);
|
||||
|
||||
sysprof_capture_reader_reset (reader);
|
||||
|
||||
while (sysprof_capture_reader_peek_type (reader, &type))
|
||||
{
|
||||
if (type == SYSPROF_CAPTURE_FRAME_ALLOCATION)
|
||||
{
|
||||
const SysprofCaptureAllocation *ev;
|
||||
Interval *iv;
|
||||
|
||||
if (!(ev = sysprof_capture_reader_read_allocation (reader)))
|
||||
break;
|
||||
|
||||
if (ev->alloc_size <= 0)
|
||||
continue;
|
||||
|
||||
if (!(iv = find_time (intervals, ev->frame.time)))
|
||||
continue;
|
||||
|
||||
iv->allocated += ev->alloc_size;
|
||||
}
|
||||
else if (!sysprof_capture_reader_skip (reader))
|
||||
break;
|
||||
}
|
||||
|
||||
for (guint i = 0; i < intervals->len; i++)
|
||||
{
|
||||
const Interval *iv = &g_array_index (intervals, Interval, i);
|
||||
g_autofree gchar *size = NULL;
|
||||
gdouble t1;
|
||||
gdouble t2;
|
||||
|
||||
if (iv->allocated <= 0)
|
||||
continue;
|
||||
|
||||
st.total += iv->allocated;
|
||||
st.min = MIN (st.min, iv->allocated);
|
||||
st.max = MAX (st.max, iv->allocated);
|
||||
|
||||
size = g_format_size_full (iv->allocated, G_FORMAT_SIZE_IEC_UNITS);
|
||||
|
||||
t1 = (iv->begin - begin) / (gdouble)SYSPROF_NSEC_PER_SEC;
|
||||
t2 = (iv->end - begin) / (gdouble)SYSPROF_NSEC_PER_SEC;
|
||||
|
||||
g_print ("%lf-%lf: %s\n", t1, t2, size);
|
||||
}
|
||||
|
||||
if (intervals->len)
|
||||
{
|
||||
const Interval *iv = &g_array_index (intervals, Interval, intervals->len/2);
|
||||
g_autofree gchar *minstr = g_format_size_full (st.min, G_FORMAT_SIZE_IEC_UNITS);
|
||||
g_autofree gchar *maxstr = g_format_size_full (st.max, G_FORMAT_SIZE_IEC_UNITS);
|
||||
g_autofree gchar *avgstr = g_format_size_full (st.total/(gdouble)intervals->len, G_FORMAT_SIZE_IEC_UNITS);
|
||||
g_autofree gchar *medstr = g_format_size_full (iv->allocated, G_FORMAT_SIZE_IEC_UNITS);
|
||||
|
||||
g_print ("Min: %s, Max: %s, Avg: %s, Median: %s\n", minstr, maxstr, avgstr, medstr);
|
||||
}
|
||||
}
|
||||
|
||||
gint
|
||||
main (gint argc,
|
||||
gchar *argv[])
|
||||
{
|
||||
SysprofCaptureReader *reader;
|
||||
const gchar *filename;
|
||||
const gchar *category;
|
||||
const gchar *name;
|
||||
|
||||
if (argc < 4)
|
||||
{
|
||||
g_printerr ("usage: %s FILENAME MARK_CATEGORY MARK_NAME\n", argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
filename = argv[1];
|
||||
category = argv[2];
|
||||
name = argv[3];
|
||||
|
||||
/* Set up gettext translations */
|
||||
setlocale (LC_ALL, "");
|
||||
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
|
||||
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
||||
textdomain (GETTEXT_PACKAGE);
|
||||
|
||||
if (!(reader = sysprof_capture_reader_new (filename)))
|
||||
{
|
||||
int errsv = errno;
|
||||
g_printerr ("%s\n", g_strerror (errsv));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
allocs_within_mark (reader, category, name);
|
||||
|
||||
sysprof_capture_reader_unref (reader);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@ -1,358 +0,0 @@
|
||||
/* list-all-maps.c
|
||||
*
|
||||
* Copyright 2021 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <sysprof.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../libsysprof/sysprof-helpers.h"
|
||||
#include "../libsysprof/sysprof-mountinfo.h"
|
||||
#include "../libsysprof/sysprof-path-resolver.h"
|
||||
#include "../libsysprof/sysprof-podman.h"
|
||||
|
||||
typedef enum {
|
||||
PROCESS_KIND_HOST,
|
||||
PROCESS_KIND_FLATPAK,
|
||||
PROCESS_KIND_PODMAN,
|
||||
} ProcessKind;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ProcessKind kind : 2;
|
||||
int pid : 29;
|
||||
char *kind_identifier;
|
||||
char *mountinfo;
|
||||
char *comm;
|
||||
GArray *maps;
|
||||
GArray *overlays;
|
||||
} ProcessInfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *on_host;
|
||||
char *in_process;
|
||||
} ProcessOverlay;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *file;
|
||||
SysprofCaptureAddress start;
|
||||
SysprofCaptureAddress end;
|
||||
SysprofCaptureAddress offset;
|
||||
ino_t inode;
|
||||
} ProcessMap;
|
||||
|
||||
static const char *
|
||||
kind_to_string (ProcessKind kind)
|
||||
{
|
||||
switch (kind)
|
||||
{
|
||||
case PROCESS_KIND_HOST:
|
||||
return "Host";
|
||||
case PROCESS_KIND_PODMAN:
|
||||
return "Podman";
|
||||
case PROCESS_KIND_FLATPAK:
|
||||
return "Flatpak";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
process_overlay_clear (ProcessOverlay *overlay)
|
||||
{
|
||||
g_free (overlay->on_host);
|
||||
g_free (overlay->in_process);
|
||||
}
|
||||
|
||||
static void
|
||||
process_info_clear (ProcessInfo *info)
|
||||
{
|
||||
g_free (info->kind_identifier);
|
||||
g_free (info->mountinfo);
|
||||
g_free (info->comm);
|
||||
g_clear_pointer (&info->maps, g_array_unref);
|
||||
g_clear_pointer (&info->overlays, g_array_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
process_map_clear (ProcessMap *map)
|
||||
{
|
||||
g_free (map->file);
|
||||
}
|
||||
|
||||
static ProcessKind
|
||||
get_process_kind_from_cgroup (int pid,
|
||||
const char *cgroup,
|
||||
char **identifier)
|
||||
{
|
||||
static GRegex *podman_regex;
|
||||
static GRegex *flatpak_regex;
|
||||
|
||||
g_autoptr(GMatchInfo) podman_match = NULL;
|
||||
g_autoptr(GMatchInfo) flatpak_match = NULL;
|
||||
|
||||
if G_UNLIKELY (podman_regex == NULL)
|
||||
podman_regex = g_regex_new ("libpod-([a-z0-9]{64})\\.scope", G_REGEX_OPTIMIZE, 0, NULL);
|
||||
|
||||
if G_UNLIKELY (flatpak_regex == NULL)
|
||||
flatpak_regex = g_regex_new ("app-flatpak-([a-zA-Z_\\-\\.]+)-[0-9]+\\.scope", G_REGEX_OPTIMIZE, 0, NULL);
|
||||
|
||||
if (g_regex_match (podman_regex, cgroup, 0, &podman_match))
|
||||
{
|
||||
if (identifier != NULL)
|
||||
*identifier = g_match_info_fetch (podman_match, 1);
|
||||
return PROCESS_KIND_PODMAN;
|
||||
}
|
||||
else if (g_regex_match (flatpak_regex, cgroup, 0, &flatpak_match))
|
||||
{
|
||||
if (identifier != NULL)
|
||||
*identifier = g_match_info_fetch (flatpak_match, 1);
|
||||
return PROCESS_KIND_FLATPAK;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (identifier != NULL)
|
||||
*identifier = NULL;
|
||||
return PROCESS_KIND_HOST;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
process_info_populate_podman_overlays (ProcessInfo *proc,
|
||||
SysprofPodman *podman)
|
||||
{
|
||||
g_auto(GStrv) layers = NULL;
|
||||
|
||||
g_assert (proc != NULL);
|
||||
g_assert (proc->kind == PROCESS_KIND_PODMAN);
|
||||
|
||||
if ((layers = sysprof_podman_get_layers (podman, proc->kind_identifier)))
|
||||
{
|
||||
for (guint i = 0; layers[i]; i++)
|
||||
{
|
||||
ProcessOverlay overlay;
|
||||
g_autofree char *path = g_build_filename (g_get_user_data_dir (),
|
||||
"containers",
|
||||
"storage",
|
||||
"overlay",
|
||||
layers[i],
|
||||
"diff",
|
||||
NULL);
|
||||
|
||||
/* XXX: this really only supports one layer */
|
||||
overlay.in_process = g_strdup ("/");
|
||||
overlay.on_host = g_steal_pointer (&path);
|
||||
|
||||
if (proc->overlays == NULL)
|
||||
{
|
||||
proc->overlays = g_array_new (FALSE, FALSE, sizeof (ProcessOverlay));
|
||||
g_array_set_clear_func (proc->overlays, (GDestroyNotify)process_overlay_clear);
|
||||
}
|
||||
|
||||
g_array_append_val (proc->overlays, overlay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
process_info_populate_maps (ProcessInfo *proc,
|
||||
const char *maps)
|
||||
{
|
||||
g_auto(GStrv) lines = NULL;
|
||||
|
||||
g_assert (proc != NULL);
|
||||
g_assert (maps != NULL);
|
||||
|
||||
if (proc->maps == NULL)
|
||||
{
|
||||
proc->maps = g_array_new (FALSE, FALSE, sizeof (ProcessMap));
|
||||
g_array_set_clear_func (proc->maps, (GDestroyNotify)process_map_clear);
|
||||
}
|
||||
|
||||
lines = g_strsplit (maps, "\n", 0);
|
||||
|
||||
for (guint i = 0; lines[i] != NULL; i++)
|
||||
{
|
||||
ProcessMap map;
|
||||
gchar file[512];
|
||||
gulong start;
|
||||
gulong end;
|
||||
gulong offset;
|
||||
gulong inode;
|
||||
int r;
|
||||
|
||||
r = sscanf (lines[i],
|
||||
"%lx-%lx %*15s %lx %*x:%*x %lu %512s",
|
||||
&start, &end, &offset, &inode, file);
|
||||
file[sizeof file - 1] = '\0';
|
||||
|
||||
if (r != 5)
|
||||
continue;
|
||||
|
||||
if (strcmp ("[vdso]", file) == 0)
|
||||
{
|
||||
/*
|
||||
* Søren Sandmann Pedersen says:
|
||||
*
|
||||
* For the vdso, the kernel reports 'offset' as the
|
||||
* the same as the mapping address. This doesn't make
|
||||
* any sense to me, so we just zero it here. There
|
||||
* is code in binfile.c (read_inode) that returns 0
|
||||
* for [vdso].
|
||||
*/
|
||||
offset = 0;
|
||||
inode = 0;
|
||||
}
|
||||
|
||||
map.file = g_strdup (file);
|
||||
map.start = start;
|
||||
map.end = end;
|
||||
map.offset = offset;
|
||||
map.inode = inode;
|
||||
|
||||
g_array_append_val (proc->maps, map);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
process_info_populate (ProcessInfo *proc,
|
||||
GVariant *variant,
|
||||
SysprofPodman *podman)
|
||||
{
|
||||
const char *str;
|
||||
int pid;
|
||||
|
||||
g_assert (proc != NULL);
|
||||
g_assert (proc->pid == 0);
|
||||
g_assert (variant != NULL);
|
||||
g_assert (g_variant_is_of_type (variant, G_VARIANT_TYPE_VARDICT));
|
||||
|
||||
if (g_variant_lookup (variant, "pid", "i", &pid))
|
||||
proc->pid = pid;
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
if (g_variant_lookup (variant, "comm", "&s", &str))
|
||||
proc->comm = g_strdup (str);
|
||||
|
||||
if (g_variant_lookup (variant, "cgroup", "&s", &str))
|
||||
proc->kind = get_process_kind_from_cgroup (pid, str, &proc->kind_identifier);
|
||||
else
|
||||
proc->kind = PROCESS_KIND_HOST;
|
||||
|
||||
if (proc->kind == PROCESS_KIND_PODMAN)
|
||||
process_info_populate_podman_overlays (proc, podman);
|
||||
|
||||
if (g_variant_lookup (variant, "mountinfo", "&s", &str))
|
||||
proc->mountinfo = g_strdup (str);
|
||||
|
||||
if (g_variant_lookup (variant, "maps", "&s", &str))
|
||||
process_info_populate_maps (proc, str);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
list_all_maps (GError **error)
|
||||
{
|
||||
SysprofHelpers *helpers = sysprof_helpers_get_default ();
|
||||
g_autoptr(SysprofPodman) podman = NULL;
|
||||
g_autofree char *mounts = NULL;
|
||||
g_autoptr(GVariant) info = NULL;
|
||||
g_autoptr(GArray) processes = NULL;
|
||||
GVariant *value;
|
||||
GVariantIter iter;
|
||||
|
||||
if (!sysprof_helpers_get_process_info (helpers, "pid,maps,mountinfo,cmdline,comm,cgroup", FALSE, NULL, &info, error))
|
||||
return FALSE;
|
||||
|
||||
if (!sysprof_helpers_get_proc_file (helpers, "/proc/mounts", NULL, &mounts, error))
|
||||
return FALSE;
|
||||
|
||||
podman = sysprof_podman_snapshot_current_user ();
|
||||
|
||||
processes = g_array_new (FALSE, TRUE, sizeof (ProcessInfo));
|
||||
g_array_set_clear_func (processes, (GDestroyNotify)process_info_clear);
|
||||
|
||||
g_variant_iter_init (&iter, info);
|
||||
while (g_variant_iter_loop (&iter, "@a{sv}", &value))
|
||||
{
|
||||
ProcessInfo *proc;
|
||||
|
||||
g_array_set_size (processes, processes->len + 1);
|
||||
proc = &g_array_index (processes, ProcessInfo, processes->len - 1);
|
||||
|
||||
if (!process_info_populate (proc, value, podman))
|
||||
g_array_set_size (processes, processes->len - 1);
|
||||
}
|
||||
|
||||
for (guint i = 0; i < processes->len; i++)
|
||||
{
|
||||
const ProcessInfo *proc = &g_array_index (processes, ProcessInfo, i);
|
||||
g_autoptr(SysprofPathResolver) resolver = _sysprof_path_resolver_new (mounts, proc->mountinfo);
|
||||
|
||||
if (proc->maps == NULL || proc->maps->len == 0)
|
||||
continue;
|
||||
|
||||
g_print ("Process %d", proc->pid);
|
||||
if (proc->kind != PROCESS_KIND_HOST)
|
||||
g_print (" (%s)", kind_to_string (proc->kind));
|
||||
g_print (" %s\n", proc->comm);
|
||||
|
||||
if (proc->overlays != NULL)
|
||||
{
|
||||
for (guint j = 0; j < proc->overlays->len; j++)
|
||||
{
|
||||
const ProcessOverlay *overlay = &g_array_index (proc->overlays, ProcessOverlay, j);
|
||||
_sysprof_path_resolver_add_overlay (resolver, overlay->in_process, overlay->on_host, j);
|
||||
}
|
||||
}
|
||||
|
||||
for (guint j = 0; j < proc->maps->len; j++)
|
||||
{
|
||||
const ProcessMap *map = &g_array_index (proc->maps, ProcessMap, j);
|
||||
g_autofree char *path = _sysprof_path_resolver_resolve (resolver, map->file);
|
||||
|
||||
if (path != NULL)
|
||||
{
|
||||
g_print (" %s", path);
|
||||
if (!g_file_test (path, G_FILE_TEST_EXISTS))
|
||||
g_print (" (missing)");
|
||||
g_print ("\n");
|
||||
}
|
||||
}
|
||||
|
||||
g_print ("\n");
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
if (!list_all_maps (&error))
|
||||
g_printerr ("%s\n", error->message);
|
||||
return error ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
}
|
||||
@ -1,103 +0,0 @@
|
||||
/* list-maps.c
|
||||
*
|
||||
* Copyright 2021 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <sysprof.h>
|
||||
#include <glib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "sysprof-elf-symbol-resolver-private.h"
|
||||
|
||||
static ino_t
|
||||
read_inode (const char *filename)
|
||||
{
|
||||
struct stat statbuf;
|
||||
|
||||
if (filename == NULL)
|
||||
return (ino_t)-1;
|
||||
|
||||
if (strcmp (filename, "[vdso]") == 0)
|
||||
return (ino_t)0;
|
||||
|
||||
if (stat (filename, &statbuf) < 0)
|
||||
return (ino_t)-1;
|
||||
|
||||
return statbuf.st_ino;
|
||||
}
|
||||
|
||||
static void
|
||||
list_maps (const char *filename)
|
||||
{
|
||||
g_autoptr(SysprofCaptureReader) reader = NULL;
|
||||
g_autoptr(SysprofSymbolResolver) resolver = NULL;
|
||||
SysprofCaptureFrameType type;
|
||||
|
||||
if (!(reader = sysprof_capture_reader_new (filename)))
|
||||
return;
|
||||
|
||||
resolver = sysprof_elf_symbol_resolver_new ();
|
||||
sysprof_symbol_resolver_load (resolver, reader);
|
||||
sysprof_capture_reader_reset (reader);
|
||||
|
||||
while (sysprof_capture_reader_peek_type (reader, &type))
|
||||
{
|
||||
if (type == SYSPROF_CAPTURE_FRAME_MAP)
|
||||
{
|
||||
const SysprofCaptureMap *ev = sysprof_capture_reader_read_map (reader);
|
||||
g_autofree char *resolved = _sysprof_elf_symbol_resolver_resolve_path (SYSPROF_ELF_SYMBOL_RESOLVER (resolver), ev->frame.pid, ev->filename);
|
||||
const char *kind = _sysprof_elf_symbol_resolver_get_pid_kind (SYSPROF_ELF_SYMBOL_RESOLVER (resolver), ev->frame.pid);
|
||||
ino_t inode = read_inode (resolved ? resolved : ev->filename);
|
||||
|
||||
g_print ("PID %u (%s): ", ev->frame.pid, kind);
|
||||
g_print ("%s => %s", ev->filename, resolved ? resolved : ev->filename);
|
||||
|
||||
if (inode == (ino_t)-1)
|
||||
g_print (" (missing)");
|
||||
else if (ev->inode != 0 && inode != ev->inode)
|
||||
g_print (" (Inode mismatch, expected %lu got %lu)",
|
||||
(gulong)ev->inode, (gulong)inode);
|
||||
|
||||
g_print ("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!sysprof_capture_reader_skip (reader))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
if (argc == 1)
|
||||
{
|
||||
g_printerr ("usage: %s CAPTURE_FILE...\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (guint i = 1; i < argc; i++)
|
||||
list_maps (argv[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1,91 +0,0 @@
|
||||
/* memory-stack-stash.c
|
||||
*
|
||||
* Copyright 2020 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <locale.h>
|
||||
#include <stddef.h>
|
||||
#include <rax.h>
|
||||
#include <sysprof.h>
|
||||
|
||||
#include "../stackstash.h"
|
||||
|
||||
static void
|
||||
memory_stack_stash (SysprofCaptureReader *reader)
|
||||
{
|
||||
SysprofCaptureFrameType type;
|
||||
StackStash *stash = stack_stash_new (NULL);
|
||||
|
||||
while (sysprof_capture_reader_peek_type (reader, &type))
|
||||
{
|
||||
if (type == SYSPROF_CAPTURE_FRAME_ALLOCATION)
|
||||
{
|
||||
const SysprofCaptureAllocation *ev = sysprof_capture_reader_read_allocation (reader);
|
||||
|
||||
if (ev == NULL)
|
||||
break;
|
||||
|
||||
if (ev->alloc_size > 0)
|
||||
stack_stash_add_trace (stash, ev->addrs, ev->n_addrs, ev->alloc_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!sysprof_capture_reader_skip (reader))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
stack_stash_unref (stash);
|
||||
}
|
||||
|
||||
gint
|
||||
main (gint argc,
|
||||
gchar *argv[])
|
||||
{
|
||||
SysprofCaptureReader *reader;
|
||||
const gchar *filename = argv[1];
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
g_printerr ("usage: %s FILENAME\n", argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Set up gettext translations */
|
||||
setlocale (LC_ALL, "");
|
||||
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
|
||||
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
||||
textdomain (GETTEXT_PACKAGE);
|
||||
|
||||
if (!(reader = sysprof_capture_reader_new (filename)))
|
||||
{
|
||||
int errsv = errno;
|
||||
g_printerr ("%s\n", g_strerror (errsv));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
memory_stack_stash (reader);
|
||||
|
||||
sysprof_capture_reader_unref (reader);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@ -1,198 +0,0 @@
|
||||
/* show-page-usage.c
|
||||
*
|
||||
* Copyright 2020 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <cairo.h>
|
||||
#include <glib.h>
|
||||
#include <stddef.h>
|
||||
#include <rax.h>
|
||||
#include <sysprof.h>
|
||||
|
||||
static GMainLoop *main_loop;
|
||||
|
||||
static gint
|
||||
u64_compare (gconstpointer a,
|
||||
gconstpointer b)
|
||||
{
|
||||
const guint64 *aptr = a;
|
||||
const guint64 *bptr = b;
|
||||
|
||||
if (*aptr < *bptr)
|
||||
return -1;
|
||||
else if (*aptr > *bptr)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
generate_cb (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
SysprofProfile *profile = (SysprofProfile *)object;
|
||||
g_autoptr(GError) error = NULL;
|
||||
GHashTable *seen;
|
||||
GHashTableIter iter;
|
||||
cairo_t *cr;
|
||||
cairo_surface_t *surface;
|
||||
GArray *ar;
|
||||
raxIterator it;
|
||||
rax *r;
|
||||
gpointer k,v;
|
||||
|
||||
g_assert (SYSPROF_IS_MEMPROF_PROFILE (profile));
|
||||
g_assert (G_IS_ASYNC_RESULT (result));
|
||||
|
||||
if (!sysprof_profile_generate_finish (profile, result, &error))
|
||||
{
|
||||
g_printerr ("%s\n", error->message);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
r = sysprof_memprof_profile_get_native (SYSPROF_MEMPROF_PROFILE (profile));
|
||||
seen = g_hash_table_new (NULL, NULL);
|
||||
|
||||
raxStart (&it, r);
|
||||
raxSeek (&it, "^", NULL, 0);
|
||||
while (raxNext (&it))
|
||||
{
|
||||
guint64 page;
|
||||
guint64 addr;
|
||||
|
||||
memcpy (&addr, it.key, sizeof addr);
|
||||
page = addr / 4096;
|
||||
|
||||
if (g_hash_table_contains (seen, GSIZE_TO_POINTER (page)))
|
||||
continue;
|
||||
|
||||
g_hash_table_insert (seen, GSIZE_TO_POINTER (page), NULL);
|
||||
}
|
||||
raxStop (&it);
|
||||
|
||||
ar = g_array_sized_new (FALSE, FALSE, sizeof (guint64), g_hash_table_size (seen));
|
||||
|
||||
g_hash_table_iter_init (&iter, seen);
|
||||
while (g_hash_table_iter_next (&iter, &k, &v))
|
||||
{
|
||||
guint64 key = GPOINTER_TO_SIZE (k);
|
||||
|
||||
g_array_append_val (ar, key);
|
||||
}
|
||||
|
||||
g_array_sort (ar, u64_compare);
|
||||
|
||||
for (guint i = 0; i < ar->len; i++)
|
||||
{
|
||||
guint64 key = g_array_index (ar, guint64, i);
|
||||
|
||||
g_hash_table_insert (seen, GSIZE_TO_POINTER (key), GSIZE_TO_POINTER (i));
|
||||
}
|
||||
|
||||
g_printerr ("We have %u pages to graph\n", ar->len);
|
||||
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, ar->len, (4096/16));
|
||||
cr = cairo_create (surface);
|
||||
|
||||
cairo_set_line_width (cr, 1.0);
|
||||
cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
|
||||
|
||||
cairo_set_source_rgb (cr, 1, 1, 1);
|
||||
cairo_rectangle (cr, 0, 0, ar->len, (4096/16));
|
||||
cairo_fill (cr);
|
||||
|
||||
cairo_set_source_rgb (cr, 0, 0, 0);
|
||||
|
||||
cairo_scale (cr, 1.0, 1.0/16.0);
|
||||
cairo_translate (cr, .5, .5);
|
||||
|
||||
raxStart (&it, r);
|
||||
raxSeek (&it, "^", NULL, 0);
|
||||
while (raxNext (&it))
|
||||
{
|
||||
guint64 page;
|
||||
guint64 addr;
|
||||
guint64 size;
|
||||
guint x;
|
||||
guint y;
|
||||
|
||||
memcpy (&addr, it.key, sizeof addr);
|
||||
page = addr / 4096;
|
||||
size = GPOINTER_TO_SIZE (it.data);
|
||||
|
||||
x = GPOINTER_TO_UINT (g_hash_table_lookup (seen, GSIZE_TO_POINTER (page)));
|
||||
y = addr % 4096;
|
||||
|
||||
/* TODO: Need size */
|
||||
|
||||
cairo_move_to (cr, x, y);
|
||||
cairo_line_to (cr, x, y+size);
|
||||
}
|
||||
raxStop (&it);
|
||||
|
||||
cairo_stroke (cr);
|
||||
|
||||
cairo_surface_write_to_png (surface, "memory.png");
|
||||
|
||||
cairo_destroy (cr);
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
g_array_unref (ar);
|
||||
g_hash_table_unref (seen);
|
||||
|
||||
g_main_loop_quit (main_loop);
|
||||
}
|
||||
|
||||
gint
|
||||
main (gint argc,
|
||||
gchar *argv[])
|
||||
{
|
||||
SysprofCaptureReader *reader;
|
||||
const gchar *filename = argv[1];
|
||||
g_autoptr(SysprofProfile) memprof = NULL;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
g_printerr ("usage: %s FILENAME\n", argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
main_loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
if (!(reader = sysprof_capture_reader_new (filename)))
|
||||
{
|
||||
int errsv = errno;
|
||||
g_printerr ("%s\n", g_strerror (errsv));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
memprof = sysprof_memprof_profile_new ();
|
||||
sysprof_profile_set_reader (memprof, reader);
|
||||
sysprof_profile_generate (memprof, NULL, generate_cb, NULL);
|
||||
|
||||
g_main_loop_run (main_loop);
|
||||
g_main_loop_unref (main_loop);
|
||||
|
||||
sysprof_capture_reader_unref (reader);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@ -1,85 +0,0 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <glib.h>
|
||||
#include <sysprof.h>
|
||||
|
||||
#include "sysprof-platform.h"
|
||||
#include "sysprof-capture-symbol-resolver.h"
|
||||
|
||||
gint
|
||||
main (gint argc,
|
||||
gchar *argv[])
|
||||
{
|
||||
g_autoptr(SysprofCaptureReader) reader = NULL;
|
||||
g_autoptr(SysprofSymbolResolver) resolver = NULL;
|
||||
SysprofCaptureFrameType type;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
g_printerr ("usage: %s CAPTURE_FILE\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(reader = sysprof_capture_reader_new (argv[1])))
|
||||
{
|
||||
int errsv = errno;
|
||||
g_printerr ("%s\n", g_strerror (errsv));
|
||||
return 1;
|
||||
}
|
||||
|
||||
resolver = sysprof_capture_symbol_resolver_new ();
|
||||
sysprof_symbol_resolver_load (resolver, reader);
|
||||
|
||||
sysprof_capture_reader_reset (reader);
|
||||
|
||||
while (sysprof_capture_reader_peek_type (reader, &type))
|
||||
{
|
||||
if (type == SYSPROF_CAPTURE_FRAME_SAMPLE)
|
||||
{
|
||||
const SysprofCaptureSample *sample;
|
||||
SysprofAddressContext last_context = SYSPROF_ADDRESS_CONTEXT_NONE;
|
||||
|
||||
if ((sample = sysprof_capture_reader_read_sample (reader)))
|
||||
{
|
||||
for (guint i = 0; i < sample->n_addrs; i++)
|
||||
{
|
||||
g_autofree gchar *name = NULL;
|
||||
SysprofAddressContext context;
|
||||
GQuark tag = 0;
|
||||
|
||||
if (sysprof_address_is_context_switch (sample->addrs[i], &context))
|
||||
{
|
||||
last_context = context;
|
||||
continue;
|
||||
}
|
||||
|
||||
name = sysprof_symbol_resolver_resolve_with_context (resolver,
|
||||
sample->frame.time,
|
||||
sample->frame.pid,
|
||||
last_context,
|
||||
sample->addrs[i],
|
||||
&tag);
|
||||
|
||||
if (tag)
|
||||
g_print ("%u: %s [%s]\n",
|
||||
i,
|
||||
name ? name : "-- missing --",
|
||||
g_quark_to_string (tag));
|
||||
else
|
||||
g_print ("%u: %s\n",
|
||||
i,
|
||||
name ? name : "-- missing --");
|
||||
}
|
||||
|
||||
g_print ("======\n");
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sysprof_capture_reader_skip (reader))
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1,107 +0,0 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <glib.h>
|
||||
#include <sysprof.h>
|
||||
|
||||
#include "sysprof-platform.h"
|
||||
#include "sysprof-symbol-map.h"
|
||||
|
||||
static GMainLoop *main_loop;
|
||||
|
||||
static void *
|
||||
resolve_in_thread (gpointer data)
|
||||
{
|
||||
SysprofCaptureReader *reader = data;
|
||||
g_autoptr(SysprofSymbolResolver) kernel = NULL;
|
||||
g_autoptr(SysprofSymbolResolver) elf = NULL;
|
||||
SysprofCaptureFrameType type;
|
||||
SysprofSymbolMap *map;
|
||||
gboolean r;
|
||||
int fd;
|
||||
|
||||
g_assert (reader != NULL);
|
||||
|
||||
map = sysprof_symbol_map_new ();
|
||||
kernel = sysprof_kernel_symbol_resolver_new ();
|
||||
elf = sysprof_elf_symbol_resolver_new ();
|
||||
|
||||
sysprof_symbol_map_add_resolver (map, kernel);
|
||||
sysprof_symbol_map_add_resolver (map, elf);
|
||||
|
||||
sysprof_symbol_map_resolve (map, reader);
|
||||
|
||||
fd = sysprof_memfd_create ("decode-test");
|
||||
g_assert_cmpint (fd, !=, -1);
|
||||
|
||||
r = sysprof_symbol_map_serialize (map, fd);
|
||||
g_assert_true (r);
|
||||
sysprof_symbol_map_free (map);
|
||||
|
||||
/* Reset some state */
|
||||
sysprof_capture_reader_reset (reader);
|
||||
lseek (fd, 0, SEEK_SET);
|
||||
|
||||
/* Now desrialize it */
|
||||
map = sysprof_symbol_map_new ();
|
||||
sysprof_symbol_map_deserialize (map, G_BYTE_ORDER, fd);
|
||||
|
||||
/* Now try to print some stack traces */
|
||||
while (sysprof_capture_reader_peek_type (reader, &type))
|
||||
{
|
||||
if (type == SYSPROF_CAPTURE_FRAME_SAMPLE)
|
||||
{
|
||||
const SysprofCaptureSample *sample = NULL;
|
||||
|
||||
if (!(sample = sysprof_capture_reader_read_sample (reader)))
|
||||
break;
|
||||
|
||||
for (guint j = 0; j < sample->n_addrs; j++)
|
||||
{
|
||||
const gchar *name;
|
||||
GQuark tag;
|
||||
|
||||
if (!(name = sysprof_symbol_map_lookup (map, sample->frame.time, sample->frame.pid, sample->addrs[j], &tag)))
|
||||
name = "Unknown symbol";
|
||||
|
||||
g_print ("%u: %s\n", j, name);
|
||||
}
|
||||
|
||||
g_print ("======\n");
|
||||
}
|
||||
else if (!sysprof_capture_reader_skip (reader))
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
sysprof_symbol_map_free (map);
|
||||
|
||||
close (fd);
|
||||
g_main_loop_quit (main_loop);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gint
|
||||
main (gint argc,
|
||||
gchar *argv[])
|
||||
{
|
||||
g_autoptr(SysprofCaptureReader) reader = NULL;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
g_printerr ("usage: %s CAPTURE_FILE\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(reader = sysprof_capture_reader_new (argv[1])))
|
||||
{
|
||||
int errsv = errno;
|
||||
g_printerr ("%s\n", g_strerror (errsv));
|
||||
return 1;
|
||||
}
|
||||
|
||||
main_loop = g_main_loop_new (NULL, FALSE);
|
||||
g_thread_new ("reader-thread", resolve_in_thread, reader);
|
||||
g_main_loop_run (main_loop);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1,66 +0,0 @@
|
||||
/* test-capture-view.c
|
||||
*
|
||||
* Copyright 2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#include <sysprof-ui.h>
|
||||
|
||||
gint
|
||||
main (gint argc,
|
||||
gchar *argv[])
|
||||
{
|
||||
GtkWindow *window;
|
||||
SysprofDisplay *view;
|
||||
SysprofCaptureReader *reader;
|
||||
g_autoptr(GError) error = NULL;
|
||||
GMainLoop *main_loop;
|
||||
|
||||
gtk_init ();
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
g_printerr ("usage: %s CAPTURE.syscap\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(reader = sysprof_capture_reader_new_with_error (argv[1], &error)))
|
||||
{
|
||||
g_printerr ("Failed to load reader: %s\n", error->message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
main_loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
window = g_object_new (GTK_TYPE_WINDOW,
|
||||
"title", "SysprofDisplay",
|
||||
"default-width", 800,
|
||||
"default-height", 600,
|
||||
NULL);
|
||||
view = g_object_new (SYSPROF_TYPE_DISPLAY,
|
||||
"visible", TRUE,
|
||||
NULL);
|
||||
gtk_window_set_child (GTK_WINDOW (window), GTK_WIDGET (view));
|
||||
|
||||
sysprof_display_load_async (view, reader, NULL, NULL, NULL);
|
||||
|
||||
g_signal_connect_swapped (window, "close-request", G_CALLBACK (g_main_loop_quit), main_loop);
|
||||
gtk_window_present (GTK_WINDOW (window));
|
||||
g_main_loop_run (main_loop);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
#include "sysprof-flatpak.h"
|
||||
|
||||
gint
|
||||
main (gint argc,
|
||||
gchar *argv[])
|
||||
{
|
||||
g_auto(GStrv) debug_dirs = sysprof_flatpak_debug_dirs ();
|
||||
|
||||
for (guint i = 0; debug_dirs[i]; i++)
|
||||
g_print ("%s\n", debug_dirs[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
#include <glib.h>
|
||||
#include <stdlib.h>
|
||||
#include <sysprof.h>
|
||||
|
||||
#include "sysprof-kallsyms.h"
|
||||
|
||||
int
|
||||
main (gint argc,
|
||||
gchar *argv[])
|
||||
{
|
||||
g_autoptr(SysprofKallsyms) kallsyms = NULL;
|
||||
const gchar *name;
|
||||
SysprofAddress addr = 0;
|
||||
guint8 type;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
g_printerr ("usage: %s FILE\n", argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
kallsyms = sysprof_kallsyms_new (argv[1]);
|
||||
|
||||
while (sysprof_kallsyms_next (kallsyms, &name, &addr, &type))
|
||||
{
|
||||
g_assert (name != NULL);
|
||||
g_assert (addr != 0);
|
||||
g_assert (type != 0);
|
||||
|
||||
g_print ("%s %"G_GUINT64_FORMAT"x\n", name, addr);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@ -1,251 +0,0 @@
|
||||
#include <sysprof-ui.h>
|
||||
#include <string.h>
|
||||
|
||||
#define TEST_TYPE_ITEM (test_item_get_type())
|
||||
|
||||
struct _TestItem
|
||||
{
|
||||
GObject p;
|
||||
guint n;
|
||||
};
|
||||
|
||||
G_DECLARE_FINAL_TYPE (TestItem, test_item, TEST, ITEM, GObject)
|
||||
G_DEFINE_TYPE (TestItem, test_item, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
test_item_class_init (TestItemClass *klass)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
test_item_init (TestItem *self)
|
||||
{
|
||||
}
|
||||
|
||||
static TestItem *
|
||||
test_item_new (guint n)
|
||||
{
|
||||
TestItem *item;
|
||||
|
||||
item = g_object_new (TEST_TYPE_ITEM, NULL);
|
||||
item->n = n;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
filter_func1 (GObject *object,
|
||||
gpointer user_data)
|
||||
{
|
||||
return (TEST_ITEM (object)->n & 1) == 0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
filter_func2 (GObject *object,
|
||||
gpointer user_data)
|
||||
{
|
||||
return (TEST_ITEM (object)->n & 1) == 1;
|
||||
}
|
||||
|
||||
static void
|
||||
test_basic (void)
|
||||
{
|
||||
GListStore *model;
|
||||
SysprofModelFilter *filter;
|
||||
TestItem *item;
|
||||
guint i;
|
||||
|
||||
model = g_list_store_new (TEST_TYPE_ITEM);
|
||||
g_assert (model);
|
||||
|
||||
filter = sysprof_model_filter_new (G_LIST_MODEL (model));
|
||||
g_assert (filter);
|
||||
|
||||
for (i = 0; i < 1000; i++)
|
||||
{
|
||||
g_autoptr(TestItem) val = test_item_new (i);
|
||||
|
||||
g_list_store_append (model, val);
|
||||
}
|
||||
|
||||
g_assert_cmpint (1000, ==, g_list_model_get_n_items (G_LIST_MODEL (model)));
|
||||
g_assert_cmpint (1000, ==, g_list_model_get_n_items (G_LIST_MODEL (filter)));
|
||||
|
||||
g_assert_cmpint (1000, ==, g_list_model_get_n_items (G_LIST_MODEL (filter)));
|
||||
sysprof_model_filter_set_filter_func (filter, filter_func1, NULL, NULL);
|
||||
g_assert_cmpint (500, ==, g_list_model_get_n_items (G_LIST_MODEL (filter)));
|
||||
|
||||
for (i = 0; i < 500; i++)
|
||||
{
|
||||
g_autoptr(TestItem) ele = g_list_model_get_item (G_LIST_MODEL (filter), i);
|
||||
|
||||
g_assert (TEST_IS_ITEM (ele));
|
||||
g_assert (filter_func1 (G_OBJECT (ele), NULL));
|
||||
}
|
||||
|
||||
for (i = 0; i < 1000; i += 2)
|
||||
g_list_store_remove (model, 998 - i);
|
||||
|
||||
g_assert_cmpint (500, ==, g_list_model_get_n_items (G_LIST_MODEL (model)));
|
||||
g_assert_cmpint (0, ==, g_list_model_get_n_items (G_LIST_MODEL (filter)));
|
||||
|
||||
sysprof_model_filter_set_filter_func (filter, NULL, NULL, NULL);
|
||||
g_assert_cmpint (500, ==, g_list_model_get_n_items (G_LIST_MODEL (filter)));
|
||||
|
||||
sysprof_model_filter_set_filter_func (filter, filter_func2, NULL, NULL);
|
||||
g_assert_cmpint (500, ==, g_list_model_get_n_items (G_LIST_MODEL (filter)));
|
||||
|
||||
{
|
||||
g_autoptr(TestItem) freeme = test_item_new (1001);
|
||||
g_list_store_append (model, freeme);
|
||||
}
|
||||
|
||||
for (i = 0; i < 500; i++)
|
||||
g_list_store_remove (model, 0);
|
||||
|
||||
g_assert_cmpint (1, ==, g_list_model_get_n_items (G_LIST_MODEL (model)));
|
||||
g_assert_cmpint (1, ==, g_list_model_get_n_items (G_LIST_MODEL (filter)));
|
||||
|
||||
sysprof_model_filter_set_filter_func (filter, NULL, NULL, NULL);
|
||||
g_assert_cmpint (1, ==, g_list_model_get_n_items (G_LIST_MODEL (model)));
|
||||
g_assert_cmpint (1, ==, g_list_model_get_n_items (G_LIST_MODEL (filter)));
|
||||
|
||||
item = g_list_model_get_item (G_LIST_MODEL (filter), 0);
|
||||
g_assert (item);
|
||||
g_assert (TEST_IS_ITEM (item));
|
||||
g_assert_cmpint (item->n, ==, 1001);
|
||||
g_clear_object (&item);
|
||||
|
||||
g_clear_object (&model);
|
||||
g_clear_object (&filter);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
filter_keyword_cb (GObject *object,
|
||||
gpointer user_data)
|
||||
{
|
||||
SysprofProcessModelItem *item = SYSPROF_PROCESS_MODEL_ITEM (object);
|
||||
const gchar *haystack = sysprof_process_model_item_get_command_line (item);
|
||||
const gchar *needle = user_data;
|
||||
|
||||
if (haystack && needle)
|
||||
return strstr (haystack, needle) != NULL;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
test_process (void)
|
||||
{
|
||||
SysprofProcessModel *model = sysprof_process_model_new ();
|
||||
SysprofModelFilter *filter;
|
||||
static gchar *searches[] = {
|
||||
"a", "b", "foo", "bar", "gnome", "gnome-test",
|
||||
"libexec", "/", ":", "gsd-",
|
||||
};
|
||||
|
||||
filter = sysprof_model_filter_new (G_LIST_MODEL (model));
|
||||
|
||||
sysprof_process_model_set_no_proxy (model, TRUE);
|
||||
sysprof_process_model_reload (model);
|
||||
|
||||
for (guint i = 0; i < G_N_ELEMENTS (searches); i++)
|
||||
{
|
||||
const gchar *needle = searches[i];
|
||||
guint n_items;
|
||||
|
||||
sysprof_model_filter_set_filter_func (filter, filter_keyword_cb, g_strdup (needle), g_free);
|
||||
|
||||
n_items = g_list_model_get_n_items (G_LIST_MODEL (filter));
|
||||
|
||||
for (guint j = 0; j < n_items; j++)
|
||||
{
|
||||
g_autoptr(SysprofProcessModelItem) item = g_list_model_get_item (G_LIST_MODEL (filter), j);
|
||||
|
||||
g_assert (SYSPROF_IS_PROCESS_MODEL_ITEM (item));
|
||||
g_assert (filter_keyword_cb (G_OBJECT (item), (gchar *)needle));
|
||||
|
||||
//g_print ("%s: %s\n", needle, sysprof_process_model_item_get_command_line (item));
|
||||
}
|
||||
}
|
||||
|
||||
g_object_unref (filter);
|
||||
g_object_unref (model);
|
||||
}
|
||||
|
||||
static guint last_n_added = 0;
|
||||
static guint last_n_removed = 0;
|
||||
static guint last_changed_position = 0;
|
||||
|
||||
static void
|
||||
model_items_changed_cb (SysprofModelFilter *filter,
|
||||
guint position,
|
||||
guint n_removed,
|
||||
guint n_added,
|
||||
GListModel *model)
|
||||
{
|
||||
last_n_added = n_added;
|
||||
last_n_removed = n_removed;
|
||||
last_changed_position = position;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
filter_items_changed_cb (SysprofModelFilter *filter,
|
||||
guint position,
|
||||
guint n_removed,
|
||||
guint n_added,
|
||||
GListModel *model)
|
||||
{
|
||||
g_assert_cmpint (n_added, ==, last_n_added);
|
||||
g_assert_cmpint (n_removed, ==, last_n_removed);
|
||||
g_assert_cmpint (position, ==, last_changed_position);
|
||||
}
|
||||
|
||||
static void
|
||||
test_items_changed (void)
|
||||
{
|
||||
SysprofModelFilter *filter;
|
||||
GListStore *model;
|
||||
guint i;
|
||||
|
||||
model = g_list_store_new (TEST_TYPE_ITEM);
|
||||
g_assert (model);
|
||||
|
||||
g_signal_connect (model, "items-changed", G_CALLBACK (model_items_changed_cb), NULL);
|
||||
|
||||
filter = sysprof_model_filter_new (G_LIST_MODEL (model));
|
||||
g_assert (filter);
|
||||
|
||||
g_signal_connect_after (filter, "items-changed", G_CALLBACK (filter_items_changed_cb), model);
|
||||
|
||||
/* The filter model is not filtered, so it must mirror whatever
|
||||
* the child model does. In this case, test if the position of
|
||||
* items-changed match.
|
||||
*/
|
||||
for (i = 0; i < 100; i++)
|
||||
{
|
||||
g_autoptr (TestItem) val = test_item_new (i);
|
||||
g_list_store_append (model, val);
|
||||
}
|
||||
|
||||
g_assert_cmpint (100, ==, g_list_model_get_n_items (G_LIST_MODEL (model)));
|
||||
g_assert_cmpint (100, ==, g_list_model_get_n_items (G_LIST_MODEL (filter)));
|
||||
|
||||
for (i = 0; i < 100; i++)
|
||||
g_list_store_remove (model, 0);
|
||||
|
||||
g_clear_object (&model);
|
||||
g_clear_object (&filter);
|
||||
}
|
||||
|
||||
gint
|
||||
main (gint argc,
|
||||
gchar *argv[])
|
||||
{
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
g_test_add_func ("/SysprofModelFilter/basic", test_basic);
|
||||
g_test_add_func ("/SysprofModelFilter/process", test_process);
|
||||
g_test_add_func ("/SysprofModelFilter/items-changed", test_items_changed);
|
||||
return g_test_run ();
|
||||
}
|
||||
@ -1,58 +0,0 @@
|
||||
/* test-mountinfo.c
|
||||
*
|
||||
* Copyright 2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#include "sysprof-mountinfo.h"
|
||||
|
||||
gint
|
||||
main (gint argc,
|
||||
gchar *argv[])
|
||||
{
|
||||
g_autoptr(SysprofMountinfo) info = NULL;
|
||||
g_autofree gchar *contents = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autofree gchar *lookup = NULL;
|
||||
gsize len;
|
||||
|
||||
if (argc != 4)
|
||||
{
|
||||
g_printerr ("usage: %s MOUNTS MOUNTINFO_FILE PATH_TO_TRANSLATE\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
info = sysprof_mountinfo_new ();
|
||||
|
||||
if (!g_file_get_contents (argv[1], &contents, &len, &error))
|
||||
g_error ("%s", error->message);
|
||||
sysprof_mountinfo_parse_mounts (info, contents);
|
||||
g_free (g_steal_pointer (&contents));
|
||||
|
||||
if (!g_file_get_contents (argv[2], &contents, &len, &error))
|
||||
g_error ("%s", error->message);
|
||||
sysprof_mountinfo_parse_mountinfo (info, contents);
|
||||
|
||||
lookup = sysprof_mountinfo_translate (info, argv[3]);
|
||||
|
||||
if (lookup)
|
||||
g_print ("%s\n", lookup);
|
||||
else
|
||||
g_print ("%s\n", argv[3]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1,101 +0,0 @@
|
||||
#include <sysprof.h>
|
||||
#include <sysprof-ui.h>
|
||||
#include <string.h>
|
||||
|
||||
static GtkWidget *list;
|
||||
|
||||
static GtkWidget *
|
||||
create_row (gpointer item,
|
||||
gpointer user_data)
|
||||
{
|
||||
return sysprof_process_model_row_new (item);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
filter_cb (GObject *object,
|
||||
gpointer user_data)
|
||||
{
|
||||
const gchar *needle = user_data;
|
||||
const gchar *command = sysprof_process_model_item_get_command_line (SYSPROF_PROCESS_MODEL_ITEM (object));
|
||||
|
||||
return needle == NULL || needle[0] == 0 || strstr (command, needle) != NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
on_entry_changed (GtkEntry *entry,
|
||||
SysprofModelFilter *filter)
|
||||
{
|
||||
const gchar *text;
|
||||
|
||||
g_assert (GTK_IS_ENTRY (entry));
|
||||
g_assert (SYSPROF_IS_MODEL_FILTER (filter));
|
||||
|
||||
text = gtk_editable_get_text (GTK_EDITABLE (entry));
|
||||
sysprof_model_filter_set_filter_func (filter, filter_cb, g_strdup (text), g_free);
|
||||
|
||||
gtk_list_box_bind_model (GTK_LIST_BOX (list), G_LIST_MODEL (filter), create_row, NULL, NULL);
|
||||
}
|
||||
|
||||
gint
|
||||
main (gint argc,
|
||||
gchar *argv[])
|
||||
{
|
||||
SysprofProcessModel *model;
|
||||
SysprofModelFilter *filter;
|
||||
GtkWidget *window;
|
||||
GtkWidget *box;
|
||||
GtkWidget *scroller;
|
||||
GtkWidget *entry;
|
||||
GMainLoop *main_loop;
|
||||
|
||||
gtk_init ();
|
||||
|
||||
main_loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
window = g_object_new (GTK_TYPE_WINDOW,
|
||||
"title", "Sysprof Process List",
|
||||
"default-height", 700,
|
||||
"default-width", 300,
|
||||
NULL);
|
||||
|
||||
box = g_object_new (GTK_TYPE_BOX,
|
||||
"orientation", GTK_ORIENTATION_VERTICAL,
|
||||
"visible", TRUE,
|
||||
NULL);
|
||||
gtk_window_set_child (GTK_WINDOW (window), box);
|
||||
|
||||
entry = g_object_new (GTK_TYPE_ENTRY,
|
||||
"visible", TRUE,
|
||||
NULL);
|
||||
gtk_box_append (GTK_BOX (box), entry);
|
||||
|
||||
scroller = g_object_new (GTK_TYPE_SCROLLED_WINDOW,
|
||||
"visible", TRUE,
|
||||
"vexpand", TRUE,
|
||||
"hexpand", TRUE,
|
||||
NULL);
|
||||
gtk_box_append (GTK_BOX (box), scroller);
|
||||
|
||||
list = g_object_new (GTK_TYPE_LIST_BOX,
|
||||
"visible", TRUE,
|
||||
NULL);
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scroller), list);
|
||||
|
||||
model = sysprof_process_model_new ();
|
||||
sysprof_process_model_set_no_proxy (model, TRUE);
|
||||
filter = sysprof_model_filter_new (G_LIST_MODEL (model));
|
||||
gtk_list_box_bind_model (GTK_LIST_BOX (list), G_LIST_MODEL (filter), create_row, NULL, NULL);
|
||||
|
||||
g_signal_connect (entry,
|
||||
"changed",
|
||||
G_CALLBACK (on_entry_changed),
|
||||
filter);
|
||||
|
||||
g_signal_connect_swapped (window, "close-request", G_CALLBACK (g_main_loop_quit), main_loop);
|
||||
gtk_window_present (GTK_WINDOW (window));
|
||||
g_main_loop_run (main_loop);
|
||||
|
||||
g_object_unref (model);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1,107 +0,0 @@
|
||||
#include <errno.h>
|
||||
#include <glib.h>
|
||||
#include <sysprof.h>
|
||||
|
||||
static const SysprofCaptureSample *
|
||||
read_to_next_sample (SysprofCaptureReader *reader)
|
||||
{
|
||||
SysprofCaptureFrameType type;
|
||||
|
||||
while (sysprof_capture_reader_peek_type (reader, &type))
|
||||
{
|
||||
if (type != SYSPROF_CAPTURE_FRAME_SAMPLE)
|
||||
{
|
||||
if (!sysprof_capture_reader_skip (reader))
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
return sysprof_capture_reader_read_sample (reader);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gint
|
||||
main (gint argc,
|
||||
gchar *argv[])
|
||||
{
|
||||
g_autoptr(GPtrArray) resolvers = NULL;
|
||||
g_autoptr(SysprofCaptureReader) reader = NULL;
|
||||
const SysprofCaptureSample *sample;
|
||||
const gchar *filename;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
g_printerr ("usage: %s capture_file\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
filename = argv[1];
|
||||
resolvers = g_ptr_array_new_with_free_func (g_object_unref);
|
||||
g_ptr_array_add (resolvers, sysprof_elf_symbol_resolver_new ());
|
||||
g_ptr_array_add (resolvers, sysprof_jitmap_symbol_resolver_new ());
|
||||
g_ptr_array_add (resolvers, sysprof_kernel_symbol_resolver_new ());
|
||||
|
||||
if (!(reader = sysprof_capture_reader_new (filename)))
|
||||
{
|
||||
int errsv = errno;
|
||||
g_error ("%s", g_strerror (errsv));
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (guint r = 0; r < resolvers->len; r++)
|
||||
{
|
||||
SysprofSymbolResolver *resolver = g_ptr_array_index (resolvers, r);
|
||||
|
||||
sysprof_symbol_resolver_load (resolver, reader);
|
||||
sysprof_capture_reader_reset (reader);
|
||||
}
|
||||
|
||||
while ((sample = read_to_next_sample (reader)))
|
||||
{
|
||||
SysprofAddressContext last_context = SYSPROF_ADDRESS_CONTEXT_NONE;
|
||||
|
||||
g_print ("Sample: pid=%d depth=%d\n", sample->frame.pid, sample->n_addrs);
|
||||
|
||||
for (guint a = 0; a < sample->n_addrs; a++)
|
||||
{
|
||||
SysprofAddress addr = sample->addrs[a];
|
||||
SysprofAddressContext context;
|
||||
gboolean found = FALSE;
|
||||
|
||||
if (sysprof_address_is_context_switch (addr, &context))
|
||||
{
|
||||
g_print (" %02d: %016"G_GINT64_MODIFIER"x: Context Switch\n", a, addr);
|
||||
last_context = context;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (guint r = 0; r < resolvers->len; r++)
|
||||
{
|
||||
SysprofSymbolResolver *resolver = g_ptr_array_index (resolvers, r);
|
||||
g_autofree gchar *symbol = NULL;
|
||||
GQuark tag;
|
||||
|
||||
symbol = sysprof_symbol_resolver_resolve_with_context (resolver,
|
||||
sample->frame.time,
|
||||
sample->frame.pid,
|
||||
last_context,
|
||||
addr,
|
||||
&tag);
|
||||
|
||||
if (symbol != NULL)
|
||||
{
|
||||
g_print (" %02d: %016"G_GINT64_MODIFIER"x: %s\n", a, addr, symbol);
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
g_print (" %02d: %016"G_GINT64_MODIFIER"x: \n", a, addr);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1,49 +0,0 @@
|
||||
/* test-utils.c
|
||||
*
|
||||
* Copyright 2021 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#include <sysprof-symbol-resolver-private.h>
|
||||
|
||||
static void
|
||||
test_debug_dirs (void)
|
||||
{
|
||||
g_auto(GStrv) test1 = NULL;
|
||||
g_auto(GStrv) test2 = NULL;
|
||||
|
||||
test1 = _sysprof_symbol_resolver_guess_debug_dirs ("/usr/bin/foo");
|
||||
g_assert_nonnull (test1);
|
||||
g_assert_cmpstr (test1[0], ==, "/usr/lib/debug/bin");
|
||||
g_assert_cmpstr (test1[1], ==, "/usr/lib64/debug/bin");
|
||||
g_assert_cmpstr (test1[2], ==, NULL);
|
||||
|
||||
test2 = _sysprof_symbol_resolver_guess_debug_dirs ("/usr/lib64/libc.so.6");
|
||||
g_assert_nonnull (test2);
|
||||
g_assert_cmpstr (test2[0], ==, "/usr/lib/debug/lib64");
|
||||
g_assert_cmpstr (test2[1], ==, "/usr/lib64/debug/lib64");
|
||||
g_assert_cmpstr (test2[2], ==, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
g_test_add_func ("/Sysprof/SymbolResolver/guess_debug_dirs", test_debug_dirs);
|
||||
return g_test_run ();
|
||||
}
|
||||
@ -1,46 +0,0 @@
|
||||
#include <sysprof-ui.h>
|
||||
|
||||
static void
|
||||
test_zoom_manager (void)
|
||||
{
|
||||
SysprofZoomManager *zoom;
|
||||
|
||||
zoom = sysprof_zoom_manager_new ();
|
||||
g_assert_cmpfloat (1.0, ==, sysprof_zoom_manager_get_zoom (zoom));
|
||||
sysprof_zoom_manager_zoom_in (zoom);
|
||||
g_assert_cmpfloat (1.5, ==, sysprof_zoom_manager_get_zoom (zoom));
|
||||
sysprof_zoom_manager_zoom_in (zoom);
|
||||
g_assert_cmpfloat (2.0, ==, sysprof_zoom_manager_get_zoom (zoom));
|
||||
sysprof_zoom_manager_zoom_in (zoom);
|
||||
g_assert_cmpfloat (2.5, ==, sysprof_zoom_manager_get_zoom (zoom));
|
||||
sysprof_zoom_manager_zoom_out (zoom);
|
||||
g_assert_cmpfloat (2.0, ==, sysprof_zoom_manager_get_zoom (zoom));
|
||||
sysprof_zoom_manager_zoom_out (zoom);
|
||||
g_assert_cmpfloat (1.5, ==, sysprof_zoom_manager_get_zoom (zoom));
|
||||
sysprof_zoom_manager_zoom_out (zoom);
|
||||
g_assert_cmpfloat (1.0, ==, sysprof_zoom_manager_get_zoom (zoom));
|
||||
sysprof_zoom_manager_zoom_out (zoom);
|
||||
g_assert_cmpfloat (.9, ==, sysprof_zoom_manager_get_zoom (zoom));
|
||||
sysprof_zoom_manager_zoom_out (zoom);
|
||||
g_assert_cmpfloat (.8, ==, sysprof_zoom_manager_get_zoom (zoom));
|
||||
sysprof_zoom_manager_zoom_out (zoom);
|
||||
g_assert_cmpfloat (.67, ==, sysprof_zoom_manager_get_zoom (zoom));
|
||||
sysprof_zoom_manager_zoom_out (zoom);
|
||||
g_assert_cmpfloat (.5, ==, sysprof_zoom_manager_get_zoom (zoom));
|
||||
sysprof_zoom_manager_zoom_out (zoom);
|
||||
g_assert_cmpfloat (.3, ==, sysprof_zoom_manager_get_zoom (zoom));
|
||||
sysprof_zoom_manager_zoom_out (zoom);
|
||||
g_assert_cmpfloat (.3 / 2, ==, sysprof_zoom_manager_get_zoom (zoom));
|
||||
|
||||
g_object_unref (zoom);
|
||||
}
|
||||
|
||||
|
||||
gint
|
||||
main (gint argc,
|
||||
gchar *argv[])
|
||||
{
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
g_test_add_func ("/ZoomManager/basic", test_zoom_manager);
|
||||
return g_test_run ();
|
||||
}
|
||||
Reference in New Issue
Block a user