2020-05-05 21:29:43 +03:00
// SPDX-License-Identifier: GPL-2.0
/*
* Test support for libpfm4 event encodings .
*
* Copyright 2020 Google LLC .
*/
# include "tests.h"
# include "util/debug.h"
# include "util/evlist.h"
# include "util/pfm.h"
# include <linux/kernel.h>
# ifdef HAVE_LIBPFM
static int test__pfm_events ( void ) ;
static int test__pfm_group ( void ) ;
# endif
static const struct {
int ( * func ) ( void ) ;
const char * desc ;
} pfm_testcase_table [ ] = {
# ifdef HAVE_LIBPFM
{
. func = test__pfm_events ,
. desc = " test of individual --pfm-events " ,
} ,
{
. func = test__pfm_group ,
. desc = " test groups of --pfm-events " ,
} ,
# endif
} ;
# ifdef HAVE_LIBPFM
static int count_pfm_events ( struct perf_evlist * evlist )
{
struct perf_evsel * evsel ;
int count = 0 ;
perf_evlist__for_each_entry ( evlist , evsel ) {
count + + ;
}
return count ;
}
static int test__pfm_events ( void )
{
struct evlist * evlist ;
struct option opt ;
size_t i ;
const struct {
const char * events ;
int nr_events ;
} table [ ] = {
{
. events = " " ,
. nr_events = 0 ,
} ,
{
. events = " instructions " ,
. nr_events = 1 ,
} ,
{
. events = " instructions,cycles " ,
. nr_events = 2 ,
} ,
{
. events = " stereolab " ,
. nr_events = 0 ,
} ,
{
. events = " instructions,instructions " ,
. nr_events = 2 ,
} ,
{
. events = " stereolab,instructions " ,
. nr_events = 0 ,
} ,
{
. events = " instructions,stereolab " ,
. nr_events = 1 ,
} ,
} ;
for ( i = 0 ; i < ARRAY_SIZE ( table ) ; i + + ) {
evlist = evlist__new ( ) ;
if ( evlist = = NULL )
return - ENOMEM ;
opt . value = evlist ;
parse_libpfm_events_option ( & opt ,
table [ i ] . events ,
0 ) ;
TEST_ASSERT_EQUAL ( table [ i ] . events ,
count_pfm_events ( & evlist - > core ) ,
table [ i ] . nr_events ) ;
TEST_ASSERT_EQUAL ( table [ i ] . events ,
2021-07-06 18:17:01 +03:00
evlist - > core . nr_groups ,
2020-05-05 21:29:43 +03:00
0 ) ;
evlist__delete ( evlist ) ;
}
return 0 ;
}
static int test__pfm_group ( void )
{
struct evlist * evlist ;
struct option opt ;
size_t i ;
const struct {
const char * events ;
int nr_events ;
int nr_groups ;
} table [ ] = {
{
. events = " {}, " ,
. nr_events = 0 ,
. nr_groups = 0 ,
} ,
{
. events = " {instructions} " ,
. nr_events = 1 ,
. nr_groups = 1 ,
} ,
{
. events = " {instructions},{} " ,
. nr_events = 1 ,
. nr_groups = 1 ,
} ,
{
. events = " {},{instructions} " ,
perf test: Fix libpfm4 support (63) test error for nested event groups
Compiling perf with make LIBPFM4=1 includes libpfm support and
enables test case 63 'Test libpfm4 support'. This test reports an error
on all platforms for subtest 63.2 'test groups of --pfm-events'.
The reported error message is 'nested event groups not supported'
# ./perf test -F 63
63: Test libpfm4 support :
63.1: test of individual --pfm-events :
Error:
failed to parse event stereolab : event not found
Error:
failed to parse event stereolab,instructions : event not found
Error:
failed to parse event instructions,stereolab : event not found
Ok
63.2: test groups of --pfm-events :
Error:
nested event groups not supported <------ Error message here
Error:
failed to parse event {stereolab} : event not found
Error:
failed to parse event {instructions,cycles},{instructions,stereolab} :\
event not found
Ok
#
This patch addresses the error message 'nested event groups not supported'.
The root cause is function parse_libpfm_events_option() which parses the
event string '{},{instructions}' and can not handle a leading empty
group notation '{},...'.
The code detects the first (empty) group indicator '{' but does not
terminate group processing on the following group closing character '}'.
So when the second group indicator '{' is detected, the code assumes
a nested group and returns an error.
With the error message fixed, also change the expected event number to
one for the test case to succeed.
While at it also fix a memory leak. In good case the function does not
free the duplicated string given as first parameter.
Output after:
# ./perf test -F 63
63: Test libpfm4 support :
63.1: test of individual --pfm-events :
Error:
failed to parse event stereolab : event not found
Error:
failed to parse event stereolab,instructions : event not found
Error:
failed to parse event instructions,stereolab : event not found
Ok
63.2: test groups of --pfm-events :
Error:
failed to parse event {stereolab} : event not found
Error:
failed to parse event {instructions,cycles},{instructions,stereolab} : \
event not found
Ok
#
Error message 'nested event groups not supported' is gone.
Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Acked-By: Ian Rogers <irogers@google.com>
Acked-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Cc: Heiko Carstens <hca@linux.ibm.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Sven Schnelle <svens@linux.ibm.com>
Cc: Vasily Gorbik <gor@linux.ibm.com>
Link: http://lore.kernel.org/lkml/20210517140931.2559364-1-tmricht@linux.ibm.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2021-05-17 17:09:31 +03:00
. nr_events = 1 ,
. nr_groups = 1 ,
2020-05-05 21:29:43 +03:00
} ,
{
. events = " {instructions},{instructions} " ,
. nr_events = 2 ,
. nr_groups = 2 ,
} ,
{
. events = " {instructions,cycles},{instructions,cycles} " ,
. nr_events = 4 ,
. nr_groups = 2 ,
} ,
{
. events = " {stereolab} " ,
. nr_events = 0 ,
. nr_groups = 0 ,
} ,
{
. events =
" {instructions,cycles},{instructions,stereolab} " ,
. nr_events = 3 ,
. nr_groups = 1 ,
} ,
2021-05-19 18:12:13 +03:00
{
. events = " instructions} " ,
. nr_events = 1 ,
. nr_groups = 0 ,
} ,
{
. events = " {{instructions}} " ,
. nr_events = 0 ,
. nr_groups = 0 ,
} ,
2020-05-05 21:29:43 +03:00
} ;
for ( i = 0 ; i < ARRAY_SIZE ( table ) ; i + + ) {
evlist = evlist__new ( ) ;
if ( evlist = = NULL )
return - ENOMEM ;
opt . value = evlist ;
parse_libpfm_events_option ( & opt ,
table [ i ] . events ,
0 ) ;
TEST_ASSERT_EQUAL ( table [ i ] . events ,
count_pfm_events ( & evlist - > core ) ,
table [ i ] . nr_events ) ;
TEST_ASSERT_EQUAL ( table [ i ] . events ,
2021-07-06 18:17:01 +03:00
evlist - > core . nr_groups ,
2020-05-05 21:29:43 +03:00
table [ i ] . nr_groups ) ;
evlist__delete ( evlist ) ;
}
return 0 ;
}
# endif
const char * test__pfm_subtest_get_desc ( int i )
{
if ( i < 0 | | i > = ( int ) ARRAY_SIZE ( pfm_testcase_table ) )
return NULL ;
return pfm_testcase_table [ i ] . desc ;
}
int test__pfm_subtest_get_nr ( void )
{
return ( int ) ARRAY_SIZE ( pfm_testcase_table ) ;
}
int test__pfm ( struct test * test __maybe_unused , int i __maybe_unused )
{
# ifdef HAVE_LIBPFM
if ( i < 0 | | i > = ( int ) ARRAY_SIZE ( pfm_testcase_table ) )
return TEST_FAIL ;
return pfm_testcase_table [ i ] . func ( ) ;
# else
return TEST_SKIP ;
# endif
}