From: Nick Porter Date: Thu, 15 Feb 2024 14:34:51 +0000 (+0000) Subject: Add test of sqlcounter module X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ab4ad43da4ed45119161255c2c5e3ed8b03fbbd6;p=thirdparty%2Ffreeradius-server.git Add test of sqlcounter module --- diff --git a/src/tests/modules/sqlcounter/.gitignore b/src/tests/modules/sqlcounter/.gitignore new file mode 100644 index 00000000000..405551a9439 --- /dev/null +++ b/src/tests/modules/sqlcounter/.gitignore @@ -0,0 +1 @@ +rlm_sql_sqlite.db diff --git a/src/tests/modules/sqlcounter/all.mk b/src/tests/modules/sqlcounter/all.mk new file mode 100644 index 00000000000..e08c2366962 --- /dev/null +++ b/src/tests/modules/sqlcounter/all.mk @@ -0,0 +1,3 @@ +# +# Test the sqlippool module using sqlite backend +# diff --git a/src/tests/modules/sqlcounter/module.conf b/src/tests/modules/sqlcounter/module.conf new file mode 100644 index 00000000000..3cf5d72daff --- /dev/null +++ b/src/tests/modules/sqlcounter/module.conf @@ -0,0 +1,65 @@ +sql { + driver = "sqlite" + dialect = "sqlite" + sqlite { + filename = "$ENV{MODULE_TEST_DIR}/sql_sqlite/$ENV{TEST}/rlm_sql_sqlite.db" + bootstrap = "${modconfdir}/${..:name}/main/${..dialect}/schema.sql" + } + radius_db = "radius" + + acct_table1 = "radacct" + acct_table2 = "radacct" + postauth_table = "radpostauth" + authcheck_table = "radcheck" + groupcheck_table = "radgroupcheck" + authreply_table = "radreply" + groupreply_table = "radgroupreply" + usergroup_table = "radusergroup" + read_groups = yes + + pool { + start = 1 + min = 0 + max = 1 + spare = 1 + lifetime = 1 + retry_delay = 1 + } + + group_attribute = "SQL-Group" + + $INCLUDE ${modconfdir}/${.:name}/main/${dialect}/queries.conf +} + +sqlcounter dailycounter { + sql_module_instance = sql + dialect = ${modules.sql.dialect} + counter_name = &control.Daily-Session-Time + check_name = &control.Max-Daily-Session + reply_name = &reply.Session-Timeout + key = "%{&Stripped-User-Name || &User-Name}" + reply_message_name = &Reply-Message + reset = daily + + $INCLUDE ${modconfdir}/sql/counter/${dialect}/${.:instance}.conf +} + +sqlcounter dailycounter_extend { + sql_module_instance = sql + dialect = ${modules.sql.dialect} + counter_name = &control.Daily-Session-Time + check_name = &control.Max-Daily-Session + reply_name = &reply.Session-Timeout + auto_extend = yes + key = "%{&Stripped-User-Name || &User-Name}" + reply_message_name = &Reply-Message + reset = daily + + $INCLUDE ${modconfdir}/sql/counter/${dialect}/dailycounter.conf +} + + +date { + format = "%Y-%m-%dT%H:%M:%SZ" + utc = yes +} diff --git a/src/tests/modules/sqlcounter/test.attrs b/src/tests/modules/sqlcounter/test.attrs new file mode 100644 index 00000000000..b957017b645 --- /dev/null +++ b/src/tests/modules/sqlcounter/test.attrs @@ -0,0 +1,11 @@ +# +# Input packet +# +Packet-Type = Access-Request +User-Name = 'restricted' +User-Password = 'testing123' + +# +# Expected answer +# +Packet-Type == Access-Accept diff --git a/src/tests/modules/sqlcounter/test.unlang b/src/tests/modules/sqlcounter/test.unlang new file mode 100644 index 00000000000..d1a1f351547 --- /dev/null +++ b/src/tests/modules/sqlcounter/test.unlang @@ -0,0 +1,158 @@ +# +# Test sqlcounter. +# +string date_str +uint64 now +uint64 start +uint64 remaining + +# +# Ensure no accounting records for the user +# +%sql("DELETE FROM radacct WHERE username = '%{User-Name}'") + +# +# Calling the module before setting a limit should do nothing +# +dailycounter +if (!noop) { + test_fail +} + +# +# Now set a limit and re-call the module +# +&control.Max-Daily-Session := 100 + +dailycounter +if (!updated) { + test_fail +} + +# +# Check attributes have been set +# +if !(&control.Daily-Session-Time == 0) { + test_fail +} + +if !(&reply.Session-Timeout == 100) { + test_fail +} + +# +# Calculate the start date/time to compare with attribute set by the module +# +&date_str = %date('now') +&now = %date(%{date_str}) +if (&date_str =~ /([0-9]{4}-[0-9]{2}-[0-9]{2}T)[0-9]{2}:[0-9]{2}:[0-9]{2}Z/) { + &date_str := "%{1}" + '00:00:00Z' +} +&start = %date(%{date_str}) + +if !(&control.dailycounter-Reset-Start == &start) { + test_fail +} + +# +# Insert a fake accounting record +# +%sql("INSERT INTO radacct (acctsessionid, acctuniqueid, username, acctstarttime, acctsessiontime) values ('%{User-Name}', '%{User-Name}', '%{User-Name}', DATETIME('now'), 60)") + +# +# Call the module again +# +dailycounter +if (!updated) { + test_fail +} + +# +# Check the attributes have been updated +# +if !(&control.Daily-Session-Time == 60) { + test_fail +} + +if !(&reply.Session-Timeout == 40) { + test_fail +} + +# +# Reduce the session duration in the fake accounting record +# +%sql("UPDATE radacct SET acctsessiontime = 10 WHERE acctuniqueid = '%{User-Name}'") + +# +# Call the module again +# If the reply attribute exists and is smaller than the new value, the old +# value will be kept and the rcode will be `ok` +# +dailycounter +if (!ok) { + test_fail +} + +# +# Check the attributes have been updated correctly. +# +if !(&control.Daily-Session-Time == 10) { + test_fail +} + +if !(&reply.Session-Timeout == 40) { + test_fail +} + +&reply := {} + +# +# Insert a second fake accounting record, which when summed with the existing will exceed the limit. +# +%sql("INSERT INTO radacct (acctsessionid, acctuniqueid, username, acctstarttime, acctsessiontime) values ('%{User-Name}-2', '%{User-Name}-2', '%{User-Name}', DATETIME('now'), 99)") + +dailycounter { + reject = 1 +} +if (!reject) { + test_fail +} + +if !(&reply.Reply-Message == 'Your maximum daily usage has been reached') { + test_fail +} +if !(&control.Daily-Session-Time == 109) { + test_fail +} + +# +# Find how much time is left before the next reset and set the limit +# so the user has enough remaining to get into the next period +# +&remaining = &control.dailycounter-Reset-End - &now +&control.Max-Daily-Session := &remaining + 110 + +&reply := {} + +dailycounter + +if !(&reply.Session-Timeout == (&control.Max-Daily-Session - 109)) { + test_fail +} + +&reply := {} + +# +# Now use module instance with auto_extend = yes +# This sets the reply attribute to include the next period's allocation. +# Allow some jitter in the reply to cope with crossing seconds boundaries during the test. +# +dailycounter_extend + +if !((&reply.Session-Timeout > (&remaining + &control.Max-Daily-Session - 2)) && (&reply.Session-Timeout <= (&remaining + &control.Max-Daily-Session))) { + test_fail +} + +&reply := {} + +test_pass