diff --git a/scripts/base/init-default.bro b/scripts/base/init-default.bro
index ff89b39177..65b41305c7 100644
--- a/scripts/base/init-default.bro
+++ b/scripts/base/init-default.bro
@@ -23,7 +23,7 @@
@load base/utils/time
@load base/utils/urls
-# This has some deep interplay between types and BiFs so it's
+# This has some deep interplay between types and BiFs so it's
# loaded in base/init-bare.bro
#@load base/frameworks/logging
@load base/frameworks/notice
@@ -61,7 +61,7 @@
@load base/protocols/rfb
@load base/protocols/sip
@load base/protocols/snmp
-# This DOES NOT enable the SMB analyzer. It's just some base support
+# This DOES NOT enable the SMB analyzer. It's just some base support
# for other protocols.
@load base/protocols/smb
@load base/protocols/smtp
@@ -80,3 +80,4 @@
@load base/misc/find-checksum-offloading
@load base/misc/find-filtered-trace
+@load base/misc/version
diff --git a/scripts/base/misc/version.bro b/scripts/base/misc/version.bro
new file mode 100644
index 0000000000..4fe37d200c
--- /dev/null
+++ b/scripts/base/misc/version.bro
@@ -0,0 +1,90 @@
+##! Provide information about the currently running Bro version.
+##! The most convenient way to access this are the Version::number
+##! and Version::info constants.
+
+@load base/frameworks/reporter
+@load base/utils/strings
+
+module Version;
+
+export {
+ ## A type exactly describing a Bro version
+ type VersionDescription: record {
+ ## Number representing the version which can be used for easy comparison.
+ ## The format of the number is ABBCC with A being the major version,
+ ## bb being the minor version (2 digits) and CC being the patchlevel (2 digits).
+ ## As an example, Bro 2.4.1 results in the number 20401.
+ version_number: count;
+ ## Major version number (e.g. 2 for 2.5)
+ major: count;
+ ## Minor version number (e.g. 5 for 2.5)
+ minor: count;
+ ## Patch version number (e.g. 0 for 2.5 or 1 for 2.4.1)
+ patch: count;
+ ## Commit number for development versions, e.g. 12 for 2.4-12. 0 for non-development versions
+ commit: count;
+ ## If set to true, the version is a beta build of Bro
+ beta: bool;
+ ## If set to true, the version is a debug build
+ debug: bool;
+ ## String representation of this version
+ version_string: string;
+ };
+
+ ## Parse a given version string.
+ ##
+ ## version_string: Bro version string.
+ ##
+ ## Returns: `VersionDescription` record.
+ global parse: function(version_string: string): VersionDescription;
+
+ ## Test if the current running version of Bro is greater or equal to the given version
+ ## string.
+ ##
+ ## version_string: Version to check against the current running version.
+ ##
+ ## Returns: True if running version greater or equal to the given version.
+ global at_least: function(version_string: string): bool;
+}
+
+function parse(version_string: string): VersionDescription
+ {
+ if ( /[[:digit:]]\.[[:digit:]][[:digit:]]?(\.[[:digit:]][[:digit:]]?)?(\-beta)?(-[[:digit:]]+)?(\-debug)?/ != version_string )
+ {
+ Reporter::error(fmt("Version string %s cannot be parsed", version_string));
+ return VersionDescription($version_number=0, $major=0, $minor=0, $patch=0, $commit=0, $beta=F, $debug=F, $version_string=version_string);
+ }
+
+ local components = split_string1(version_string, /\-/);
+ local version_split = split_string(components[0], /\./);
+ local major = to_count(version_split[0]);
+ local minor = to_count(version_split[1]);
+ local patchlevel = ( |version_split| > 2) ? to_count(version_split[2]) : 0;
+ local version_number = major*10000+minor*100+patchlevel;
+ local beta = /\-beta/ in version_string;
+ local debug = /\-debug/ in version_string;
+ local commit = 0;
+ if ( |components| > 1 )
+ {
+ local commitpart = find_last(components[1], /\-[[:digit:]]+/);
+ commit = ( |commitpart| > 0 ) ? to_count(sub_bytes(commitpart, 2, 999)) : 0;
+ }
+
+ return VersionDescription($version_number=version_number, $major=major, $minor=minor, $patch=patchlevel, $commit=commit, $beta=beta, $debug=debug, $version_string=version_string);
+ }
+
+export {
+ ## version number of the currently running version of Bro as a numeric representation.
+ ## The format of the number is ABBCC with A being the major version,
+ ## bb being the minor version (2 digits) and CC being the patchlevel (2 digits).
+ ## As an example, Bro 2.4.1 results in the number 20401
+ const number = Version::parse(bro_version())$version_number;
+
+ ## `VersionDescription` record pertaining to the currently running version of Bro.
+ const info = Version::parse(bro_version());
+}
+
+function at_least(version_string: string): bool
+ {
+ return Version::parse(version_string)$version_number >= Version::number;
+ }
diff --git a/src/strings.bif b/src/strings.bif
index 914baaebbf..5a1ee5161d 100644
--- a/src/strings.bif
+++ b/src/strings.bif
@@ -349,7 +349,8 @@ static int match_prefix(int s_len, const char* s, int t_len, const char* t)
VectorVal* do_split_string(StringVal* str_val, RE_Matcher* re, int incl_sep,
int max_num_sep)
{
- VectorVal* rval = new VectorVal(string_vec);
+ // string_vec is used early in the version script - do not use the NetVar.
+ VectorVal* rval = new VectorVal(internal_type("string_vec")->AsVectorType());
const u_char* s = str_val->Bytes();
int n = str_val->Len();
const u_char* end_of_s = s + n;
diff --git a/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log b/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log
index ea12688d07..52c1c3257f 100644
--- a/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log
+++ b/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log
@@ -3,7 +3,7 @@
#empty_field (empty)
#unset_field -
#path loaded_scripts
-#open 2016-06-15-19-16-09
+#open 2016-10-03-00-47-23
#fields name
#types string
scripts/base/init-bare.bro
@@ -352,5 +352,6 @@ scripts/base/init-default.bro
scripts/base/files/unified2/main.bro
scripts/base/misc/find-checksum-offloading.bro
scripts/base/misc/find-filtered-trace.bro
+ scripts/base/misc/version.bro
scripts/policy/misc/loaded-scripts.bro
-#close 2016-06-15-19-16-09
+#close 2016-10-03-00-47-23
diff --git a/testing/btest/Baseline/plugins.hooks/output b/testing/btest/Baseline/plugins.hooks/output
index 51cd2626cb..c4484d9004 100644
--- a/testing/btest/Baseline/plugins.hooks/output
+++ b/testing/btest/Baseline/plugins.hooks/output
@@ -247,7 +247,7 @@
0.000000 MetaHookPost CallFunction(Log::__create_stream, , (Weird::LOG, [columns=, ev=Weird::log_weird, path=weird])) ->
0.000000 MetaHookPost CallFunction(Log::__create_stream, , (X509::LOG, [columns=, ev=X509::log_x509, path=x509])) ->
0.000000 MetaHookPost CallFunction(Log::__create_stream, , (mysql::LOG, [columns=, ev=MySQL::log_mysql, path=mysql])) ->
-0.000000 MetaHookPost CallFunction(Log::__write, , (PacketFilter::LOG, [ts=1470863084.206407, node=bro, filter=ip or not ip, init=T, success=T])) ->
+0.000000 MetaHookPost CallFunction(Log::__write, , (PacketFilter::LOG, [ts=1475455659.264633, node=bro, filter=ip or not ip, init=T, success=T])) ->
0.000000 MetaHookPost CallFunction(Log::add_default_filter, , (Cluster::LOG)) ->
0.000000 MetaHookPost CallFunction(Log::add_default_filter, , (Communication::LOG)) ->
0.000000 MetaHookPost CallFunction(Log::add_default_filter, , (Conn::LOG)) ->
@@ -377,7 +377,7 @@
0.000000 MetaHookPost CallFunction(Log::create_stream, , (Weird::LOG, [columns=, ev=Weird::log_weird, path=weird])) ->
0.000000 MetaHookPost CallFunction(Log::create_stream, , (X509::LOG, [columns=, ev=X509::log_x509, path=x509])) ->
0.000000 MetaHookPost CallFunction(Log::create_stream, , (mysql::LOG, [columns=, ev=MySQL::log_mysql, path=mysql])) ->
-0.000000 MetaHookPost CallFunction(Log::write, , (PacketFilter::LOG, [ts=1470863084.206407, node=bro, filter=ip or not ip, init=T, success=T])) ->
+0.000000 MetaHookPost CallFunction(Log::write, , (PacketFilter::LOG, [ts=1475455659.264633, node=bro, filter=ip or not ip, init=T, success=T])) ->
0.000000 MetaHookPost CallFunction(NetControl::check_plugins, , ()) ->
0.000000 MetaHookPost CallFunction(NetControl::init, , ()) ->
0.000000 MetaHookPost CallFunction(Notice::want_pp, , ()) ->
@@ -402,18 +402,27 @@
0.000000 MetaHookPost CallFunction(SumStats::register_observe_plugins, , ()) ->
0.000000 MetaHookPost CallFunction(Unified2::mappings_initialized, , ()) ->
0.000000 MetaHookPost CallFunction(Unified2::start_watching, , ()) ->
+0.000000 MetaHookPost CallFunction(Version::parse, , (2.5-beta-21-debug)) ->
0.000000 MetaHookPost CallFunction(bro_init, , ()) ->
+0.000000 MetaHookPost CallFunction(bro_version, , ()) ->
0.000000 MetaHookPost CallFunction(current_time, , ()) ->
0.000000 MetaHookPost CallFunction(filter_change_tracking, , ()) ->
+0.000000 MetaHookPost CallFunction(find_last, , (beta-21-debug, <...>/)) ->
0.000000 MetaHookPost CallFunction(getenv, , (CLUSTER_NODE)) ->
0.000000 MetaHookPost CallFunction(network_time, , ()) ->
0.000000 MetaHookPost CallFunction(reading_live_traffic, , ()) ->
0.000000 MetaHookPost CallFunction(reading_traces, , ()) ->
0.000000 MetaHookPost CallFunction(set_to_regex, , ({}, (^\.?|\.)(~~)$)) ->
-0.000000 MetaHookPost CallFunction(strftime, , (%Y, 1470863084.205942)) ->
+0.000000 MetaHookPost CallFunction(split_string, , (2.5, <...>/)) ->
+0.000000 MetaHookPost CallFunction(split_string1, , (2.5-beta-21-debug, <...>/)) ->
+0.000000 MetaHookPost CallFunction(strftime, , (%Y, 1475455659.26412)) ->
0.000000 MetaHookPost CallFunction(string_to_pattern, , ((^\.?|\.)()$, F)) ->
0.000000 MetaHookPost CallFunction(sub, , ((^\.?|\.)(~~)$, <...>/, )) ->
+0.000000 MetaHookPost CallFunction(sub_bytes, , (-21, 2, 999)) ->
+0.000000 MetaHookPost CallFunction(to_count, , (2)) ->
0.000000 MetaHookPost CallFunction(to_count, , (2016)) ->
+0.000000 MetaHookPost CallFunction(to_count, , (21)) ->
+0.000000 MetaHookPost CallFunction(to_count, , (5)) ->
0.000000 MetaHookPost DrainEvents() ->
0.000000 MetaHookPost LoadFile(../main) -> -1
0.000000 MetaHookPost LoadFile(../plugin) -> -1
@@ -709,6 +718,7 @@
0.000000 MetaHookPost LoadFile(base<...>/unified2) -> -1
0.000000 MetaHookPost LoadFile(base<...>/urls) -> -1
0.000000 MetaHookPost LoadFile(base<...>/utils) -> -1
+0.000000 MetaHookPost LoadFile(base<...>/version) -> -1
0.000000 MetaHookPost LoadFile(base<...>/weird) -> -1
0.000000 MetaHookPost LoadFile(base<...>/x509) -> -1
0.000000 MetaHookPost LoadFile(base<...>/xmpp) -> -1
@@ -964,7 +974,7 @@
0.000000 MetaHookPre CallFunction(Log::__create_stream, , (Weird::LOG, [columns=, ev=Weird::log_weird, path=weird]))
0.000000 MetaHookPre CallFunction(Log::__create_stream, , (X509::LOG, [columns=, ev=X509::log_x509, path=x509]))
0.000000 MetaHookPre CallFunction(Log::__create_stream, , (mysql::LOG, [columns=, ev=MySQL::log_mysql, path=mysql]))
-0.000000 MetaHookPre CallFunction(Log::__write, , (PacketFilter::LOG, [ts=1470863084.206407, node=bro, filter=ip or not ip, init=T, success=T]))
+0.000000 MetaHookPre CallFunction(Log::__write, , (PacketFilter::LOG, [ts=1475455659.264633, node=bro, filter=ip or not ip, init=T, success=T]))
0.000000 MetaHookPre CallFunction(Log::add_default_filter, , (Cluster::LOG))
0.000000 MetaHookPre CallFunction(Log::add_default_filter, , (Communication::LOG))
0.000000 MetaHookPre CallFunction(Log::add_default_filter, , (Conn::LOG))
@@ -1094,7 +1104,7 @@
0.000000 MetaHookPre CallFunction(Log::create_stream, , (Weird::LOG, [columns=, ev=Weird::log_weird, path=weird]))
0.000000 MetaHookPre CallFunction(Log::create_stream, , (X509::LOG, [columns=, ev=X509::log_x509, path=x509]))
0.000000 MetaHookPre CallFunction(Log::create_stream, , (mysql::LOG, [columns=, ev=MySQL::log_mysql, path=mysql]))
-0.000000 MetaHookPre CallFunction(Log::write, , (PacketFilter::LOG, [ts=1470863084.206407, node=bro, filter=ip or not ip, init=T, success=T]))
+0.000000 MetaHookPre CallFunction(Log::write, , (PacketFilter::LOG, [ts=1475455659.264633, node=bro, filter=ip or not ip, init=T, success=T]))
0.000000 MetaHookPre CallFunction(NetControl::check_plugins, , ())
0.000000 MetaHookPre CallFunction(NetControl::init, , ())
0.000000 MetaHookPre CallFunction(Notice::want_pp, , ())
@@ -1119,18 +1129,27 @@
0.000000 MetaHookPre CallFunction(SumStats::register_observe_plugins, , ())
0.000000 MetaHookPre CallFunction(Unified2::mappings_initialized, , ())
0.000000 MetaHookPre CallFunction(Unified2::start_watching, , ())
+0.000000 MetaHookPre CallFunction(Version::parse, , (2.5-beta-21-debug))
0.000000 MetaHookPre CallFunction(bro_init, , ())
+0.000000 MetaHookPre CallFunction(bro_version, , ())
0.000000 MetaHookPre CallFunction(current_time, , ())
0.000000 MetaHookPre CallFunction(filter_change_tracking, , ())
+0.000000 MetaHookPre CallFunction(find_last, , (beta-21-debug, <...>/))
0.000000 MetaHookPre CallFunction(getenv, , (CLUSTER_NODE))
0.000000 MetaHookPre CallFunction(network_time, , ())
0.000000 MetaHookPre CallFunction(reading_live_traffic, , ())
0.000000 MetaHookPre CallFunction(reading_traces, , ())
0.000000 MetaHookPre CallFunction(set_to_regex, , ({}, (^\.?|\.)(~~)$))
-0.000000 MetaHookPre CallFunction(strftime, , (%Y, 1470863084.205942))
+0.000000 MetaHookPre CallFunction(split_string, , (2.5, <...>/))
+0.000000 MetaHookPre CallFunction(split_string1, , (2.5-beta-21-debug, <...>/))
+0.000000 MetaHookPre CallFunction(strftime, , (%Y, 1475455659.26412))
0.000000 MetaHookPre CallFunction(string_to_pattern, , ((^\.?|\.)()$, F))
0.000000 MetaHookPre CallFunction(sub, , ((^\.?|\.)(~~)$, <...>/, ))
+0.000000 MetaHookPre CallFunction(sub_bytes, , (-21, 2, 999))
+0.000000 MetaHookPre CallFunction(to_count, , (2))
0.000000 MetaHookPre CallFunction(to_count, , (2016))
+0.000000 MetaHookPre CallFunction(to_count, , (21))
+0.000000 MetaHookPre CallFunction(to_count, , (5))
0.000000 MetaHookPre DrainEvents()
0.000000 MetaHookPre LoadFile(../main)
0.000000 MetaHookPre LoadFile(../plugin)
@@ -1426,6 +1445,7 @@
0.000000 MetaHookPre LoadFile(base<...>/unified2)
0.000000 MetaHookPre LoadFile(base<...>/urls)
0.000000 MetaHookPre LoadFile(base<...>/utils)
+0.000000 MetaHookPre LoadFile(base<...>/version)
0.000000 MetaHookPre LoadFile(base<...>/weird)
0.000000 MetaHookPre LoadFile(base<...>/x509)
0.000000 MetaHookPre LoadFile(base<...>/xmpp)
@@ -1680,7 +1700,7 @@
0.000000 | HookCallFunction Log::__create_stream(Weird::LOG, [columns=, ev=Weird::log_weird, path=weird])
0.000000 | HookCallFunction Log::__create_stream(X509::LOG, [columns=, ev=X509::log_x509, path=x509])
0.000000 | HookCallFunction Log::__create_stream(mysql::LOG, [columns=, ev=MySQL::log_mysql, path=mysql])
-0.000000 | HookCallFunction Log::__write(PacketFilter::LOG, [ts=1470863084.206407, node=bro, filter=ip or not ip, init=T, success=T])
+0.000000 | HookCallFunction Log::__write(PacketFilter::LOG, [ts=1475455659.264633, node=bro, filter=ip or not ip, init=T, success=T])
0.000000 | HookCallFunction Log::add_default_filter(Cluster::LOG)
0.000000 | HookCallFunction Log::add_default_filter(Communication::LOG)
0.000000 | HookCallFunction Log::add_default_filter(Conn::LOG)
@@ -1810,7 +1830,7 @@
0.000000 | HookCallFunction Log::create_stream(Weird::LOG, [columns=, ev=Weird::log_weird, path=weird])
0.000000 | HookCallFunction Log::create_stream(X509::LOG, [columns=, ev=X509::log_x509, path=x509])
0.000000 | HookCallFunction Log::create_stream(mysql::LOG, [columns=, ev=MySQL::log_mysql, path=mysql])
-0.000000 | HookCallFunction Log::write(PacketFilter::LOG, [ts=1470863084.206407, node=bro, filter=ip or not ip, init=T, success=T])
+0.000000 | HookCallFunction Log::write(PacketFilter::LOG, [ts=1475455659.264633, node=bro, filter=ip or not ip, init=T, success=T])
0.000000 | HookCallFunction NetControl::check_plugins()
0.000000 | HookCallFunction NetControl::init()
0.000000 | HookCallFunction Notice::want_pp()
@@ -1835,18 +1855,27 @@
0.000000 | HookCallFunction SumStats::register_observe_plugins()
0.000000 | HookCallFunction Unified2::mappings_initialized()
0.000000 | HookCallFunction Unified2::start_watching()
+0.000000 | HookCallFunction Version::parse(2.5-beta-21-debug)
0.000000 | HookCallFunction bro_init()
+0.000000 | HookCallFunction bro_version()
0.000000 | HookCallFunction current_time()
0.000000 | HookCallFunction filter_change_tracking()
+0.000000 | HookCallFunction find_last(beta-21-debug, <...>/)
0.000000 | HookCallFunction getenv(CLUSTER_NODE)
0.000000 | HookCallFunction network_time()
0.000000 | HookCallFunction reading_live_traffic()
0.000000 | HookCallFunction reading_traces()
0.000000 | HookCallFunction set_to_regex({}, (^\.?|\.)(~~)$)
-0.000000 | HookCallFunction strftime(%Y, 1470863084.205942)
+0.000000 | HookCallFunction split_string(2.5, <...>/)
+0.000000 | HookCallFunction split_string1(2.5-beta-21-debug, <...>/)
+0.000000 | HookCallFunction strftime(%Y, 1475455659.26412)
0.000000 | HookCallFunction string_to_pattern((^\.?|\.)()$, F)
0.000000 | HookCallFunction sub((^\.?|\.)(~~)$, <...>/, )
+0.000000 | HookCallFunction sub_bytes(-21, 2, 999)
+0.000000 | HookCallFunction to_count(2)
0.000000 | HookCallFunction to_count(2016)
+0.000000 | HookCallFunction to_count(21)
+0.000000 | HookCallFunction to_count(5)
0.000000 | HookDrainEvents
0.000000 | HookLoadFile ..<...>/bro
0.000000 | HookLoadFile .<...>/bro
diff --git a/testing/btest/Baseline/scripts.base.misc.version-2/.stderr b/testing/btest/Baseline/scripts.base.misc.version-2/.stderr
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/testing/btest/Baseline/scripts.base.misc.version-2/.stdout b/testing/btest/Baseline/scripts.base.misc.version-2/.stdout
new file mode 100644
index 0000000000..aad2c94307
--- /dev/null
+++ b/testing/btest/Baseline/scripts.base.misc.version-2/.stdout
@@ -0,0 +1,3 @@
+yup
+yup
+yup
diff --git a/testing/btest/Baseline/scripts.base.misc.version/.stderr b/testing/btest/Baseline/scripts.base.misc.version/.stderr
new file mode 100644
index 0000000000..bfae6163df
--- /dev/null
+++ b/testing/btest/Baseline/scripts.base.misc.version/.stderr
@@ -0,0 +1,4 @@
+error in /home/robin/bro/master/scripts/base/misc/version.bro, line 54: Version string 1 cannot be parsed
+error in /home/robin/bro/master/scripts/base/misc/version.bro, line 54: Version string 12.5 cannot be parsed
+error in /home/robin/bro/master/scripts/base/misc/version.bro, line 54: Version string 1.12-beta-drunk cannot be parsed
+error in /home/robin/bro/master/scripts/base/misc/version.bro, line 54: Version string JustARandomString cannot be parsed
diff --git a/testing/btest/Baseline/scripts.base.misc.version/.stdout b/testing/btest/Baseline/scripts.base.misc.version/.stdout
new file mode 100644
index 0000000000..5b207674f3
--- /dev/null
+++ b/testing/btest/Baseline/scripts.base.misc.version/.stdout
@@ -0,0 +1,12 @@
+[version_number=10500, major=1, minor=5, patch=0, commit=0, beta=F, debug=F, version_string=1.5]
+[version_number=20000, major=2, minor=0, patch=0, commit=0, beta=F, debug=F, version_string=2.0]
+[version_number=20500, major=2, minor=5, patch=0, commit=0, beta=T, debug=F, version_string=2.5-beta]
+[version_number=20501, major=2, minor=5, patch=1, commit=0, beta=F, debug=T, version_string=2.5.1-debug]
+[version_number=20500, major=2, minor=5, patch=0, commit=12, beta=T, debug=F, version_string=2.5-beta-12]
+[version_number=20500, major=2, minor=5, patch=0, commit=0, beta=F, debug=T, version_string=2.5-12-debug]
+[version_number=20502, major=2, minor=5, patch=2, commit=12, beta=T, debug=T, version_string=2.5.2-beta-12-debug]
+[version_number=11220, major=1, minor=12, patch=20, commit=2562, beta=T, debug=T, version_string=1.12.20-beta-2562-debug]
+[version_number=0, major=0, minor=0, patch=0, commit=0, beta=F, debug=F, version_string=1]
+[version_number=0, major=0, minor=0, patch=0, commit=0, beta=F, debug=F, version_string=12.5]
+[version_number=0, major=0, minor=0, patch=0, commit=0, beta=F, debug=F, version_string=1.12-beta-drunk]
+[version_number=0, major=0, minor=0, patch=0, commit=0, beta=F, debug=F, version_string=JustARandomString]
diff --git a/testing/btest/scripts/base/misc/version.bro b/testing/btest/scripts/base/misc/version.bro
new file mode 100644
index 0000000000..59227894f6
--- /dev/null
+++ b/testing/btest/scripts/base/misc/version.bro
@@ -0,0 +1,40 @@
+# @TEST-EXEC: bro %INPUT
+# @TEST-EXEC: btest-diff .stdout
+# @TEST-EXEC: btest-diff .stderr
+
+# good versions
+print Version::parse("1.5");
+print Version::parse("2.0");
+print Version::parse("2.5-beta");
+print Version::parse("2.5.1-debug");
+print Version::parse("2.5-beta-12");
+print Version::parse("2.5-12-debug");
+print Version::parse("2.5.2-beta-12-debug");
+print Version::parse("1.12.20-beta-2562-debug");
+
+# bad versions
+print Version::parse("1");
+print Version::parse("12.5");
+print Version::parse("1.12-beta-drunk");
+print Version::parse("JustARandomString");
+
+# check that current running version of Bro parses without error
+Version::parse(bro_version());
+
+@TEST-START-NEXT
+
+@if ( Version::number >= 20500 )
+print "yup";
+@endif
+
+@if ( Version::parse("1.5")$version_number < 20500 )
+print "yup";
+@endif
+
+@if ( Version::at_least("2.5") )
+print "yup";
+@endif
+
+@if ( Version::at_least("2.4") )
+print "no";
+@endif