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 := true;
}

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, " vs ", exp.expect);
			result := {
				kind := e_Mismatched,
				idx := i
			};
			break;
		} else {
			log("EXP match: ", metric, " vs ", 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 local_addr, integer local_port) {
	id := id & "-STATS";

	vc_STATSD := StatsD_Checker_CT.create(id);
	vc_STATSD.start(StatsD_Checker.main(local_addr, local_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;
}

}
