module StatsD_Checker {

/* Verifies that  StatsD metrics in a test match the expected values
 * Uses StatsD_CodecPort to receive the statsd messages from the DUT
 * and a separate VTY connection to reset and trigger the stats.
 *
 * When using this you should configure your stats reporter to disable
 * interval-based reports and always send all metrics:
 * > stats interval 0
 * > stats reporter statsd
 * >  remote-ip a.b.c.d
 * >  remote-port 8125
 * >  level subscriber
 * >  flush-period 1
 * >  mtu 1024
 * >  enable
 *
 * (C) 2020 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 * All rights reserved.
 *
 * Author: Daniel Willmann <dwillmann@sysmocom.de>
 *
 * Released under the terms of GNU General Public License, Version 2 or
 * (at your option) any later version.
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

import from Misc_Helpers all;
import from Socket_API_Definitions all;

import from StatsD_Types all;
import from StatsD_CodecPort all;
import from StatsD_CodecPort_CtrlFunct all;

import from Osmocom_Types all;
import from Osmocom_VTY_Functions all;
import from TELNETasp_PortType all;

modulepar {
	/* Whether to test stats values */
	boolean mp_enable_stats := false;
}

type record StatsDExpect {
	MetricName	name,
	MetricType	mtype,
	MetricValue	min,
	MetricValue	max
};

type set of StatsDExpect StatsDExpects;

type record StatsDExpectPriv {
	StatsDExpect expect,
	integer seen
}

type set of StatsDExpectPriv StatsDExpectPrivs;

type enumerated StatsDResultType {
	e_Matched,
	e_Mismatched,
	e_NotFound
}

type record StatsDExpectResult {
	StatsDResultType kind,
	integer idx
}

type component StatsD_Checker_CT {
	port TELNETasp_PT STATSVTY;
	port STATSD_PROC_PT STATSD_PROC;
	port STATSD_CODEC_PT STATS;
	timer T_statsd := 5.0;
}

type component StatsD_ConnHdlr {
	port STATSD_PROC_PT STATSD_PROC;
}

signature STATSD_reset();
signature STATSD_expect(in StatsDExpects expects) return boolean;

type port STATSD_PROC_PT procedure {
	inout STATSD_reset, STATSD_expect;
} with {extension "internal"};

/* Expect templates and functions */


/* StatsD checker component */
function main(charstring statsd_host, integer statsd_port) runs on StatsD_Checker_CT {
	var StatsD_ConnHdlr vc_conn;
	var StatsDExpects expects;
	var Result res;

	while (not mp_enable_stats) {
		log("StatsD checker disabled by modulepar");
		f_sleep(3600.0);
	}

	map(self:STATS, system:STATS);
	res := StatsD_CodecPort_CtrlFunct.f_IPL4_listen(STATS, statsd_host, statsd_port, { udp := {} }, {});
	if (not ispresent(res.connId)) {
		Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
					"Could not bind StatsD socket, check your configuration");
	}

	/* Connect to VTY and reset stats */
	map(self:STATSVTY, system:STATSVTY);
	f_vty_set_prompts(STATSVTY);
	f_vty_transceive(STATSVTY, "enable");

	/* Reset the stats system at start */
	f_vty_transceive(STATSVTY, "stats reset");

	while (true) {
		alt {
		[] STATSD_PROC.getcall(STATSD_reset:{}) -> sender vc_conn {
			f_vty_transceive(STATSVTY, "stats reset");
			STATSD_PROC.reply(STATSD_reset:{}) to vc_conn;
			}
		[] STATSD_PROC.getcall(STATSD_expect:{?}) -> param(expects) sender vc_conn {
			var boolean success := f_statsd_checker_expect(expects);
			STATSD_PROC.reply(STATSD_expect:{expects} value success) to vc_conn;
			}
		}
	}
}


/* Return false if the expectation doesn't match the metric, otherwise return true */
private function f_compare_expect(StatsDMetric metric, StatsDExpect expect) return boolean {
	if ((metric.name == expect.name) and (metric.mtype == expect.mtype)
		and (metric.val >= expect.min) and (metric.val <= expect.max)) {
		return true;
	} else {
		return false;
	}
}

private function f_statsd_checker_metric_expects(StatsDExpectPrivs exp_seen, StatsDMetric metric)
return StatsDExpectResult {
	var StatsDExpectResult result := {
		kind := e_NotFound,
		idx := -1
	};

	for (var integer i := 0; i < lengthof(exp_seen); i := i + 1) {
		var StatsDExpectPriv exp := exp_seen[i];
		if (exp.expect.name != metric.name) {
			continue;
		}
		if (not f_compare_expect(metric, exp.expect)) {
			log("EXP mismatch: ", metric, exp.expect);
			result := {
				kind := e_Mismatched,
				idx := i
			};
			break;
		} else {
			log("EXP match: ", metric, exp.expect);
			result := {
				kind := e_Matched,
				idx := i
			};
			break;
		}
	}
	return result;
}

template StatsDExpectPriv t_statsd_expect_priv(template StatsDExpect expect) := {
	expect := expect,
	seen := 0
}

private function f_statsd_checker_expect(StatsDExpects expects) runs on StatsD_Checker_CT return boolean {
	var default t;
	var StatsDMessage msg;
	var StatsDExpectResult res;
	var StatsDExpectPrivs exp_seen := {};

	for (var integer i := 0; i < lengthof(expects); i := i + 1) {
		exp_seen := exp_seen & {valueof(t_statsd_expect_priv(expects[i]))};
	}

	/* Dismiss any messages we might have skipped from the last report */
	STATS.clear;

	f_vty_transceive(STATSVTY, "stats report");

	var boolean seen_all := false;
	T_statsd.start;
	while (not seen_all) {
		var StatsD_RecvFrom rf;
		alt {
		[] STATS.receive(tr_StatsD_RecvFrom(?, ?)) -> value rf {
			msg := rf.msg;
			}
		[] T_statsd.timeout {
			for (var integer i := 0; i < lengthof(exp_seen); i := i + 1) {
				/* We're still missing some expects, keep looking */
				if (exp_seen[i].seen == 0) {
					log("Timeout waiting for ", exp_seen[i].expect.name, " (min: ", exp_seen[i].expect.min,
						", max: ", exp_seen[i].expect.max, ")");
				}
			}
			setverdict(fail, "Timeout waiting for metrics");
			return false;
		}
		}

		for (var integer i := 0; i < lengthof(msg); i := i + 1) {
			var StatsDMetric metric := msg[i];

			res := f_statsd_checker_metric_expects(exp_seen, metric);
			if (res.kind == e_NotFound) {
				continue;
			}

			if (res.kind == e_Mismatched) {
				log("Metric: ", metric);
				log("Expect: ", exp_seen[res.idx].expect);
				setverdict(fail, "Metric failed expectation ", metric, " vs ", exp_seen[res.idx].expect);
				return false;
			} else if (res.kind == e_Matched) {
				exp_seen[res.idx].seen := exp_seen[res.idx].seen + 1;
			}
		}

		/* Check if all expected metrics were received */
		seen_all := true;
		for (var integer i := 0; i < lengthof(exp_seen); i := i + 1) {
			/* We're still missing some expects, keep looking */
			if (exp_seen[i].seen == 0) {
				seen_all := false;
				break;
			}
		}
	}

	T_statsd.stop;
	return seen_all;
}

function f_init_statsd(charstring id, inout StatsD_Checker_CT vc_STATSD, charstring dst_addr, integer dst_port) {
	id := id & "-STATS";

	vc_STATSD := StatsD_Checker_CT.create(id);
	vc_STATSD.start(StatsD_Checker.main(dst_addr, dst_port));
}


/* StatsD connhdlr */
function f_statsd_reset() runs on StatsD_ConnHdlr {
	if (not mp_enable_stats) {
		return;
	}

	STATSD_PROC.call(STATSD_reset:{}) {
		[] STATSD_PROC.getreply(STATSD_reset:{}) {}
	}
}

function f_statsd_expect(StatsDExpects expects) runs on StatsD_ConnHdlr return boolean {
	var boolean res;

	if (not mp_enable_stats) {
		return true;
	}

	STATSD_PROC.call(STATSD_expect:{expects}) {
		[] STATSD_PROC.getreply(STATSD_expect:{expects}) -> value res;
	}
	return res;
}

}
