]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Add test of sqlcounter module
authorNick Porter <nick@portercomputing.co.uk>
Thu, 15 Feb 2024 14:34:51 +0000 (14:34 +0000)
committerNick Porter <nick@portercomputing.co.uk>
Thu, 15 Feb 2024 18:32:02 +0000 (18:32 +0000)
src/tests/modules/sqlcounter/.gitignore [new file with mode: 0644]
src/tests/modules/sqlcounter/all.mk [new file with mode: 0644]
src/tests/modules/sqlcounter/module.conf [new file with mode: 0644]
src/tests/modules/sqlcounter/test.attrs [new file with mode: 0644]
src/tests/modules/sqlcounter/test.unlang [new file with mode: 0644]

diff --git a/src/tests/modules/sqlcounter/.gitignore b/src/tests/modules/sqlcounter/.gitignore
new file mode 100644 (file)
index 0000000..405551a
--- /dev/null
@@ -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 (file)
index 0000000..e08c236
--- /dev/null
@@ -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 (file)
index 0000000..3cf5d72
--- /dev/null
@@ -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 (file)
index 0000000..b957017
--- /dev/null
@@ -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 (file)
index 0000000..d1a1f35
--- /dev/null
@@ -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