diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/AiGenerated.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/AiGenerated.kt index 36704512..efd18b58 100644 --- a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/AiGenerated.kt +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/AiGenerated.kt @@ -413,6 +413,32 @@ fun getAllAIGeneratedValidators(): Map { Validator("config_parse_socket_service", "0") to ConfigParseSocketServiceOptionValue() as OptionValueInformation, Validator("config_parse_service_sockets", "0") to ConfigParseServiceSocketsOptionValue() as OptionValueInformation, + // Batch 2026-10: qdisc + Validator("config_parse_fq_codel_usec", "QDISC_KIND_FQ_CODEL") to ConfigParseFqCodelUsecOptionValue() as OptionValueInformation, + Validator("config_parse_tbf_rate", "QDISC_KIND_TBF") to ConfigParseTbfRateOptionValue() as OptionValueInformation, + Validator("config_parse_netem_rate", "QDISC_KIND_NETEM") to ConfigParseNetemRateOptionValue() as OptionValueInformation, + Validator("config_parse_netem_delay", "QDISC_KIND_NETEM") to ConfigParseNetemDelayOptionValue() as OptionValueInformation, + Validator("config_parse_htb_class_rate", "TCLASS_KIND_HTB") to ConfigParseHtbClassRateOptionValue() as OptionValueInformation, + Validator("config_parse_gred_u32", "QDISC_KIND_GRED") to ConfigParseGredU32OptionValue() as OptionValueInformation, + Validator("config_parse_fq_codel_u32", "QDISC_KIND_FQ_CODEL") to ConfigParseFqCodelU32OptionValue() as OptionValueInformation, + Validator("config_parse_teql_id", "QDISC_KIND_TEQL") to ConfigParseTeqlIdOptionValue() as OptionValueInformation, + Validator("config_parse_qfq_max_packet", "TCLASS_KIND_QFQ") to ConfigParseQfqMaxPacketOptionValue() as OptionValueInformation, + Validator("config_parse_pie_packet_limit", "QDISC_KIND_PIE") to ConfigParsePiePacketLimitOptionValue() as OptionValueInformation, + Validator("config_parse_htb_u32", "QDISC_KIND_HTB") to ConfigParseHtbU32OptionValue() as OptionValueInformation, + Validator("config_parse_htb_default_class", "QDISC_KIND_HTB") to ConfigParseHtbDefaultClassOptionValue() as OptionValueInformation, + Validator("config_parse_htb_class_u32", "TCLASS_KIND_HTB") to ConfigParseHtbClassU32OptionValue() as OptionValueInformation, + Validator("config_parse_gred_bool", "QDISC_KIND_GRED") to ConfigParseGredBoolOptionValue() as OptionValueInformation, + Validator("config_parse_fq_usec", "QDISC_KIND_FQ") to ConfigParseFqUsecOptionValue() as OptionValueInformation, + Validator("config_parse_fq_max_rate", "QDISC_KIND_FQ") to ConfigParseFqMaxRateOptionValue() as OptionValueInformation, + Validator("config_parse_fq_codel_bool", "QDISC_KIND_FQ_CODEL") to ConfigParseFqCodelBoolOptionValue() as OptionValueInformation, + Validator("config_parse_ets_quanta", "QDISC_KIND_ETS") to ConfigParseEtsQuantaOptionValue() as OptionValueInformation, + Validator("config_parse_ets_prio", "QDISC_KIND_ETS") to ConfigParseEtsPrioOptionValue() as OptionValueInformation, + Validator("config_parse_drr_size", "TCLASS_KIND_DRR") to ConfigParseDrrSizeOptionValue() as OptionValueInformation, + Validator("config_parse_cake_flow_isolation_mode", "QDISC_KIND_CAKE") to ConfigParseCakeFlowIsolationModeOptionValue() as OptionValueInformation, + Validator("config_parse_cake_bandwidth", "QDISC_KIND_CAKE") to ConfigParseCakeBandwidthOptionValue() as OptionValueInformation, + Validator("config_parse_cake_ack_filter", "QDISC_KIND_CAKE") to ConfigParseCakeAckFilterOptionValue() as OptionValueInformation, + Validator("config_parse_bfifo_size", "QDISC_KIND_BFIFO") to ConfigParseBfifoSizeOptionValue() as OptionValueInformation, + ) return allValidators diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseBfifoSizeOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseBfifoSizeOptionValue.kt new file mode 100644 index 00000000..b6c02e8e --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseBfifoSizeOptionValue.kt @@ -0,0 +1,29 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.* + +/* + * [BFIFO] LimitBytes= (.network) + * + * man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#LimitBytes= + * parser https://github.com/systemd/systemd/blob/0f0682b773/src/network/tc/fifo.c#L103-L160 config_parse_bfifo_size (QDISC_KIND_BFIFO) + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L157-L283 parse_size + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L108-L176 TEST(parse_size_iec) + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L178-L246 TEST(parse_size_si) + * tests https://github.com/systemd/systemd/blob/0f0682b773/test/test-network/conf/25-qdisc-htb-fifo.network#L42 LimitBytes=1000000 + */ + +/** + * Validator for [BFIFO] LimitBytes=. + * + * C function: config_parse_bfifo_size (QDISC_KIND_BFIFO). An empty assignment resets the setting and is + * handled before this grammar runs. + * + * A byte size as parse_size(rvalue, 1024) reads it (see [parseSize]) that must not exceed UINT32_MAX: + * above it the parser logs "Invalid 'LimitBytes=', ignoring assignment". So `4G` is rejected. + */ +class ConfigParseBfifoSizeOptionValue : SimpleGrammarOptionValues( + "config_parse_bfifo_size", + SequenceCombinator(parseSize(1024, maxInclusive = SIZE_UINT32_MAX), EOF()), +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseCakeAckFilterOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseCakeAckFilterOptionValue.kt new file mode 100644 index 00000000..67911f6d --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseCakeAckFilterOptionValue.kt @@ -0,0 +1,37 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.* + +/* + * [CAKE] AckFilter= (.network) + * + * man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#AckFilter= + * parser https://github.com/systemd/systemd/blob/0f0682b773/src/network/tc/cake.c#L680-L730 config_parse_cake_ack_filter (QDISC_KIND_CAKE) + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/network/tc/cake.c#L672-L678 cake_ack_filter_table + DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/string-table.c#L32-L43 string_table_lookup_from_string_with_boolean + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L23-L46 parse_boolean (case-insensitive) + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L13-L37 TEST(parse_boolean) — "YES", "TRUE", "ON" accepted + * tests https://github.com/systemd/systemd/blob/0f0682b773/test/test-network/conf/25-qdisc-cake.network#L25 AckFilter=aggressive + */ + +/** + * Validator for [CAKE] AckFilter=. + * + * C function: config_parse_cake_ack_filter (QDISC_KIND_CAKE). An empty assignment resets the setting and is + * handled before this grammar runs. + * + * A boolean (parse_boolean() is tried first, case-insensitively: `yes` -> filter, `no` -> off) or the + * table word `aggressive`, which is matched exactly (case-sensitive streq). The table's `no`/`yes` + * entries are not listed as names: parse_boolean() already takes them, in any case. + */ +class ConfigParseCakeAckFilterOptionValue : SimpleGrammarOptionValues( + "config_parse_cake_ack_filter", + SequenceCombinator( + PreferValidAlternativeCombinator( + FlexibleLiteralChoiceTerminal("aggressive"), + BOOLEAN, + ), + EOF(), + ), +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseCakeBandwidthOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseCakeBandwidthOptionValue.kt new file mode 100644 index 00000000..e6299ca0 --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseCakeBandwidthOptionValue.kt @@ -0,0 +1,29 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.* + +/* + * [CAKE] Bandwidth= (.network) + * + * man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#Bandwidth= + * parser https://github.com/systemd/systemd/blob/0f0682b773/src/network/tc/cake.c#L141-L193 config_parse_cake_bandwidth (QDISC_KIND_CAKE) + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L157-L283 parse_size + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L108-L176 TEST(parse_size_iec) + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L178-L246 TEST(parse_size_si) + * tests https://github.com/systemd/systemd/blob/0f0682b773/test/test-network/conf/25-qdisc-cake.network#L12 Bandwidth=500M + */ + +/** + * Validator for [CAKE] Bandwidth=. + * + * C function: config_parse_cake_bandwidth (QDISC_KIND_CAKE). An empty assignment resets the setting and is + * handled before this grammar runs. + * + * A rate in bits per second as parse_size(rvalue, 1000) reads it (see [parseSize]); the result is + * divided by 8 and stored as a uint64 with no further bound. + */ +class ConfigParseCakeBandwidthOptionValue : SimpleGrammarOptionValues( + "config_parse_cake_bandwidth", + SequenceCombinator(parseSize(1000), EOF()), +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseCakeFlowIsolationModeOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseCakeFlowIsolationModeOptionValue.kt new file mode 100644 index 00000000..ca8ecee8 --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseCakeFlowIsolationModeOptionValue.kt @@ -0,0 +1,28 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.* + +/* + * [CAKE] FlowIsolationMode= (.network) + * + * man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#FlowIsolationMode= + * parser https://github.com/systemd/systemd/blob/0f0682b773/src/network/tc/cake.c#L442-L492 config_parse_cake_flow_isolation_mode (QDISC_KIND_CAKE) + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/network/tc/cake.c#L429-L438 cake_flow_isolation_mode_table + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/network/tc/cake.c#L440 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING (exact, case-sensitive) + * tests https://github.com/systemd/systemd/blob/0f0682b773/test/test-network/conf/25-qdisc-cake.network#L18 FlowIsolationMode=dual-dst-host + */ + +/** + * Validator for [CAKE] FlowIsolationMode=. + * + * C function: config_parse_cake_flow_isolation_mode (QDISC_KIND_CAKE). An empty assignment resets the setting and is + * handled before this grammar runs. + * + * One of `none`, `src-host`, `dst-host`, `hosts`, `flows`, `dual-src-host`, `dual-dst-host`, `triple`, + * matched exactly (string_table_lookup is case-sensitive, and this table has no boolean fallback). + */ +class ConfigParseCakeFlowIsolationModeOptionValue : SimpleGrammarOptionValues( + "config_parse_cake_flow_isolation_mode", + SequenceCombinator(FlexibleLiteralChoiceTerminal("none", "src-host", "dst-host", "hosts", "flows", "dual-src-host", "dual-dst-host", "triple"), EOF()), +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseDrrSizeOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseDrrSizeOptionValue.kt new file mode 100644 index 00000000..cd52278d --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseDrrSizeOptionValue.kt @@ -0,0 +1,30 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.* + +/* + * [DeficitRoundRobinSchedulerClass] QuantumBytes= (.network) + * + * man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#QuantumBytes= + * parser https://github.com/systemd/systemd/blob/0f0682b773/src/network/tc/drr.c#L45-L102 config_parse_drr_size (TCLASS_KIND_DRR) + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L157-L283 parse_size + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L108-L176 TEST(parse_size_iec) + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L178-L246 TEST(parse_size_si) + * tests https://github.com/systemd/systemd/blob/0f0682b773/test/test-network/conf/25-qdisc-drr.network#L16 QuantumBytes=2000 + */ + +/** + * Validator for [DeficitRoundRobinSchedulerClass] QuantumBytes=. + * + * C function: config_parse_drr_size (TCLASS_KIND_DRR). An empty assignment resets the setting and is + * handled before this grammar runs. + * + * A byte size as parse_size(rvalue, 1024) reads it (see [parseSize]) that must not exceed UINT32_MAX: + * above it the parser logs "Invalid 'QuantumBytes=', ignoring assignment". So `4G` (4294967296) is + * rejected and `4095M` is accepted. + */ +class ConfigParseDrrSizeOptionValue : SimpleGrammarOptionValues( + "config_parse_drr_size", + SequenceCombinator(parseSize(1024, maxInclusive = SIZE_UINT32_MAX), EOF()), +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseEtsPrioOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseEtsPrioOptionValue.kt new file mode 100644 index 00000000..2e27d6cb --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseEtsPrioOptionValue.kt @@ -0,0 +1,51 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.* +import java.math.BigInteger + +/* + * [EnhancedTransmissionSelection] PriorityMap= (.network) + * + * man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#PriorityMap= + * parser https://github.com/systemd/systemd/blob/0f0682b773/src/network/tc/ets.c#L227-L302 config_parse_ets_prio (QDISC_KIND_ETS) + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L429-L478 safe_atou_full + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L403-L427 mangle_base + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.h#L45-L47 safe_atou8 + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L583-L597 safe_atou8_full (rejects > UINT8_MAX) + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/include/uapi/linux/pkt_sched.h#L28 TC_PRIO_MAX = 15 + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L489 safe_atou16("+12345") accepted + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L466-L470 0o6 / 0B101 prefixes (safe_atolli, same mangle_base) + * tests https://github.com/systemd/systemd/blob/0f0682b773/test/test-network/conf/25-qdisc-ets.network#L18-L21 PriorityMap=8 7 6 5 / PriorityMap= / PriorityMap=3 4 5 + */ + +private val ETS_BAND = SafeAtoTerminal( + signed = false, + base = 0, + flags = emptySet(), + minInclusive = BigInteger.ZERO, + maxInclusive = SafeAtoTerminal.UINT8_MAX, + acceptsWhitespace = false, + acceptsMinus = true, +) + +/** + * Validator for [EnhancedTransmissionSelection] PriorityMap=. + * + * C function: config_parse_ets_prio (QDISC_KIND_ETS). An empty assignment resets the setting and is + * handled before this grammar runs. + * + * A whitespace-separated list of band numbers, each read with safe_atou8 (base 0, 0…255), at most + * TC_PRIO_MAX + 1 (16) entries per line. Each entry is a word from extract_first_word(), so the number + * cannot contain a blank: `0b+1` is 1, but `0b 1` is the words `0b` (invalid) and `1`. Out-of-range or unparsable entries are logged and skipped by + * the C, and so are flagged here; so is a 17th entry. + * + * Lenient: enhanced_transmission_selection_verify later rejects the whole section if any entry is not + * below the number of bands (at most 16), so values 16…255 can never actually work; they are accepted + * here because the man page documents 0…255 and that is what the parser itself checks. The 16-entry + * cap is cumulative across lines; only the per-line count is checked. + */ +class ConfigParseEtsPrioOptionValue : SimpleGrammarOptionValues( + "config_parse_ets_prio", + SequenceCombinator(ETS_BAND, Repeat(SequenceCombinator(WhitespaceTerminal(), ETS_BAND), 0, 15), EOF()), +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseEtsQuantaOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseEtsQuantaOptionValue.kt new file mode 100644 index 00000000..c6d3a587 --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseEtsQuantaOptionValue.kt @@ -0,0 +1,41 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai + +import java.math.BigInteger +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.* + +/* + * [EnhancedTransmissionSelection] QuantumBytes= (.network) + * + * man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#QuantumBytes= + * parser https://github.com/systemd/systemd/blob/0f0682b773/src/network/tc/ets.c#L144-L225 config_parse_ets_quanta (QDISC_KIND_ETS) + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L157-L283 parse_size + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/include/uapi/linux/pkt_sched.h#L1210 TCQ_ETS_MAX_BANDS = 16 + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L108-L176 TEST(parse_size_iec) + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L178-L246 TEST(parse_size_si) + * tests https://github.com/systemd/systemd/blob/0f0682b773/test/test-network/conf/25-qdisc-ets.network#L14-L17 QuantumBytes=2 4 6 / QuantumBytes= / QuantumBytes=1001 1002 1003 + */ + +private val ETS_QUANTUM = parseSize(1024, minInclusive = BigInteger.ONE, maxInclusive = SIZE_UINT32_MAX, allowInnerWhitespace = false) + +/** + * Validator for [EnhancedTransmissionSelection] QuantumBytes=. + * + * C function: config_parse_ets_quanta (QDISC_KIND_ETS). An empty assignment resets the setting and is + * handled before this grammar runs. + * + * A whitespace-separated list (extract_first_word, no flags) of byte sizes, each read with + * parse_size(word, 1024) and required to be 1…4294967295; at most TCQ_ETS_MAX_BANDS (16) entries. A + * zero, oversized or unparsable entry is logged and skipped by the C ("ignoring assignment"), and so is + * flagged here; so is a 17th entry on one line. + * + * Because the list is split on whitespace first, each entry is a single word: `1K` or `1K512B` is one + * entry, but `1K 512B` is two. + * + * Lenient: the 16-entry cap is cumulative across repeated QuantumBytes= lines (until an empty + * assignment resets the list); only the per-line count is checked. + */ +class ConfigParseEtsQuantaOptionValue : SimpleGrammarOptionValues( + "config_parse_ets_quanta", + SequenceCombinator(ETS_QUANTUM, Repeat(SequenceCombinator(WhitespaceTerminal(), ETS_QUANTUM), 0, 15), EOF()), +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseFqCodelBoolOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseFqCodelBoolOptionValue.kt new file mode 100644 index 00000000..b04ad462 --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseFqCodelBoolOptionValue.kt @@ -0,0 +1,29 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.* + +/* + * [FairQueueingControlledDelay] ECN= (.network) + * + * man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#ECN= + * parser https://github.com/systemd/systemd/blob/0f0682b773/src/network/tc/fq-codel.c#L222-L265 config_parse_fq_codel_bool (QDISC_KIND_FQ_CODEL) + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L48-L64 parse_tristate_full + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L23-L46 parse_boolean (STRCASE_IN_SET: case-insensitive) + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L13-L37 TEST(parse_boolean) — "YES", "TRUE", "ON" accepted + * tests https://github.com/systemd/systemd/blob/0f0682b773/test/test-network/conf/25-qdisc-fq_codel.network#L18 ECN=yes + */ + +/** + * Validator for [FairQueueingControlledDelay] ECN=. + * + * C function: config_parse_fq_codel_bool (QDISC_KIND_FQ_CODEL). An empty assignment resets the setting and is + * handled before this grammar runs. + * + * A boolean via parse_tristate(): any parse_boolean() spelling, case-insensitively. Empty resets to + * "unset" (handled before the grammar). + */ +class ConfigParseFqCodelBoolOptionValue : SimpleGrammarOptionValues( + "config_parse_fq_codel_bool", + SequenceCombinator(BOOLEAN, EOF()), +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseFqCodelU32OptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseFqCodelU32OptionValue.kt new file mode 100644 index 00000000..6357d525 --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseFqCodelU32OptionValue.kt @@ -0,0 +1,44 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.* +import java.math.BigInteger + +/* + * [FairQueueingControlledDelay] PacketLimit=, Flows= (.network) + * + * man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#PacketLimit= + * man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#Flows= + * parser https://github.com/systemd/systemd/blob/0f0682b773/src/network/tc/fq-codel.c#L97-L155 config_parse_fq_codel_u32 (QDISC_KIND_FQ_CODEL) + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L429-L478 safe_atou_full + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L403-L427 mangle_base + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L489 safe_atou16("+12345") accepted + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L466-L470 0o6 / 0B101 prefixes (safe_atolli, same mangle_base) + * tests https://github.com/systemd/systemd/blob/0f0682b773/test/test-network/conf/25-qdisc-fq_codel.network#L12-L14 PacketLimit=20480, Flows=2048 + */ + +/** + * Validator for [FairQueueingControlledDelay] PacketLimit=, Flows=. + * + * C function: config_parse_fq_codel_u32 (QDISC_KIND_FQ_CODEL). An empty assignment resets the setting and is + * handled before this grammar runs. + * + * An unsigned 32-bit integer read with safe_atou32 (base 0: decimal, `0x` hex, `0o`/leading-zero + * octal, `0b` binary, optional `+`), 0…4294967295. No further bound in the parser. strtoul starts + * afresh after a `0b`/`0o` prefix, so `0b+1` and `0b 1` are 1 (see [SafeAtoTerminal]). + */ +class ConfigParseFqCodelU32OptionValue : SimpleGrammarOptionValues( + "config_parse_fq_codel_u32", + SequenceCombinator( + SafeAtoTerminal( + signed = false, + base = 0, + flags = emptySet(), + minInclusive = BigInteger.ZERO, + maxInclusive = SafeAtoTerminal.UINT32_MAX, + acceptsWhitespace = true, + acceptsMinus = true, + ), + EOF(), + ), +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseFqCodelUsecOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseFqCodelUsecOptionValue.kt new file mode 100644 index 00000000..c6ba5d11 --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseFqCodelUsecOptionValue.kt @@ -0,0 +1,36 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.* + +/* + * [FairQueueingControlledDelay] TargetSec=, IntervalSec=, CEThresholdSec= (.network) + * + * man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#TargetSec= + * man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#IntervalSec= + * man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#CEThresholdSec= + * parser https://github.com/systemd/systemd/blob/0f0682b773/src/network/tc/fq-codel.c#L157-L220 config_parse_fq_codel_usec (QDISC_KIND_FQ_CODEL) + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/time-util.c#L1289 parse_sec + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/time-util.c#L1198-L1287 parse_time + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/time-util.c#L1147-L1196 extract_multiplier + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-time-util.c#L21-L83 TEST(parse_sec) + * tests https://github.com/systemd/systemd/blob/0f0682b773/test/test-network/conf/25-qdisc-fq_codel.network#L15-L19 TargetSec=10ms, IntervalSec=200ms, CEThresholdSec=100ms + */ + +/** + * Validator for [FairQueueingControlledDelay] TargetSec=, IntervalSec=, CEThresholdSec=. + * + * C function: config_parse_fq_codel_usec (QDISC_KIND_FQ_CODEL). An empty assignment resets the setting and is + * handled before this grammar runs. + * + * A time span as parse_sec() reads it: `infinity`, or one or more `number[unit]` elements such as + * `10ms`, `1min30s`, `5s 500ms`, `.5s`, `+3.1s` (see [parseSec]). There is no extra bound: the parsed + * usec_t is stored as is (CEThresholdSec= additionally treats an empty value as USEC_INFINITY). + * + * Overflow is rejected exactly as parse_time() does (ERANGE): an integer part above LLONG_MAX, or a finite + * total reaching USEC_INFINITY (e.g. `18446744073709551615us`). + */ +class ConfigParseFqCodelUsecOptionValue : SimpleGrammarOptionValues( + "config_parse_fq_codel_usec", + SequenceCombinator(parseSec(), EOF()), +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseFqMaxRateOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseFqMaxRateOptionValue.kt new file mode 100644 index 00000000..381bbb81 --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseFqMaxRateOptionValue.kt @@ -0,0 +1,32 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai + +import java.math.BigInteger +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.* + +/* + * [FairQueueing] MaximumRate= (.network) + * + * man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#MaximumRate= + * parser https://github.com/systemd/systemd/blob/0f0682b773/src/network/tc/fq.c#L344-L402 config_parse_fq_max_rate (QDISC_KIND_FQ) + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L157-L283 parse_size + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L108-L176 TEST(parse_size_iec) + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L178-L246 TEST(parse_size_si) + * tests https://github.com/systemd/systemd/blob/0f0682b773/test/test-network/conf/25-qdisc-fq.network#L16 MaximumRate=1M + */ + +/** + * Validator for [FairQueueing] MaximumRate=. + * + * C function: config_parse_fq_max_rate (QDISC_KIND_FQ). An empty assignment resets the setting and is + * handled before this grammar runs. + * + * A rate in bits per second as parse_size(rvalue, 1000) reads it (see [parseSize]) whose byte rate + * (value / 8) must fit a uint32: above it the parser logs "Specified 'MaximumRate=' is too large, + * ignoring assignment". So the largest accepted value is 34359738367 bits/s (≈ 34.35G); `34G` is + * legal and `35G` is not. + */ +class ConfigParseFqMaxRateOptionValue : SimpleGrammarOptionValues( + "config_parse_fq_max_rate", + SequenceCombinator(parseSize(1000, maxInclusive = SIZE_UINT32_MAX * BigInteger.valueOf(8) + BigInteger.valueOf(7)), EOF()), +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseFqUsecOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseFqUsecOptionValue.kt new file mode 100644 index 00000000..d48539d4 --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseFqUsecOptionValue.kt @@ -0,0 +1,32 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.* + +/* + * [FairQueueing] CEThresholdSec= (.network) + * + * man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#CEThresholdSec= + * parser https://github.com/systemd/systemd/blob/0f0682b773/src/network/tc/fq.c#L284-L342 config_parse_fq_usec (QDISC_KIND_FQ) + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/time-util.c#L1289 parse_sec + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/time-util.c#L1198-L1287 parse_time + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/time-util.c#L1147-L1196 extract_multiplier + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-time-util.c#L21-L83 TEST(parse_sec) + * tests https://github.com/systemd/systemd/blob/0f0682b773/test/test-network/conf/25-qdisc-fq.network#L20 CEThresholdSec=100ms + */ + +/** + * Validator for [FairQueueing] CEThresholdSec=. + * + * C function: config_parse_fq_usec (QDISC_KIND_FQ). An empty assignment resets the setting and is + * handled before this grammar runs. + * + * A time span as parse_sec() reads it (see [parseSec]) that must not exceed UINT32_MAX microseconds + * (about 71min 34.967s): above it the parser logs "Specified 'CEThresholdSec=' is too large, ignoring + * assignment". In particular `infinity` (USEC_INFINITY) is rejected — leave the value empty to get the + * "unset/infinity" default. + */ +class ConfigParseFqUsecOptionValue : SimpleGrammarOptionValues( + "config_parse_fq_usec", + SequenceCombinator(parseSec(UINT32_MAX_USEC), EOF()), +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseGredBoolOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseGredBoolOptionValue.kt new file mode 100644 index 00000000..7fa893b7 --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseGredBoolOptionValue.kt @@ -0,0 +1,29 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.* + +/* + * [GenericRandomEarlyDetection] GenericRIO= (.network) + * + * man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#GenericRIO= + * parser https://github.com/systemd/systemd/blob/0f0682b773/src/network/tc/gred.c#L134-L177 config_parse_gred_bool (QDISC_KIND_GRED) + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L48-L64 parse_tristate_full + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L23-L46 parse_boolean (STRCASE_IN_SET: case-insensitive) + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L13-L37 TEST(parse_boolean) — "YES", "TRUE", "ON" accepted + * tests https://github.com/systemd/systemd/blob/0f0682b773/test/test-network/conf/25-qdisc-gred.network#L14 GenericRIO=yes + */ + +/** + * Validator for [GenericRandomEarlyDetection] GenericRIO=. + * + * C function: config_parse_gred_bool (QDISC_KIND_GRED). An empty assignment resets the setting and is + * handled before this grammar runs. + * + * A boolean via parse_tristate(): any parse_boolean() spelling (`yes`/`no`/`1`/`0`/`true`/`false`/ + * `on`/`off`/`y`/`n`/`t`/`f`), case-insensitively. Empty resets to "unset" (handled before the grammar). + */ +class ConfigParseGredBoolOptionValue : SimpleGrammarOptionValues( + "config_parse_gred_bool", + SequenceCombinator(BOOLEAN, EOF()), +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseGredU32OptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseGredU32OptionValue.kt new file mode 100644 index 00000000..fbf483a5 --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseGredU32OptionValue.kt @@ -0,0 +1,49 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.* + +/* + * [GenericRandomEarlyDetection] VirtualQueues=, DefaultVirtualQueue= (.network) + * + * man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#VirtualQueues= + * man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#DefaultVirtualQueue= + * parser https://github.com/systemd/systemd/blob/0f0682b773/src/network/tc/gred.c#L68-L133 config_parse_gred_u32 (QDISC_KIND_GRED) + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L429-L478 safe_atou_full + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L403-L427 mangle_base + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/include/uapi/linux/pkt_sched.h#L305 MAX_DPs = 16 + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L489 safe_atou16("+12345") accepted + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L466-L470 0o6 / 0B101 prefixes (safe_atolli, same mangle_base) + * tests https://github.com/systemd/systemd/blob/0f0682b773/test/test-network/conf/25-qdisc-gred.network#L12-L13 VirtualQueues=12, DefaultVirtualQueue=10 + */ + +/** + * Validator for [GenericRandomEarlyDetection] VirtualQueues=, DefaultVirtualQueue=. + * + * C function: config_parse_gred_u32 (QDISC_KIND_GRED). An empty assignment resets the setting and is + * handled before this grammar runs. + * + * An unsigned integer read with safe_atou32 (base 0: decimal, `0x` hex, `0o`/leading-zero octal, `0b` + * binary, optional `+`; `0b+1` and `0b 1` are 1, see [SafeAtoTerminal]) that must not exceed MAX_DPs (16). Above 16 the parser logs "Invalid ..., ignoring + * assignment" (although, at 0f0682b773, it still stores the value — a C bug; the kernel refuses more than + * 16 DPs anyway), so it is flagged here. + * + * Lenient: both keys share the parser, so 0..16 is accepted for both, although VirtualQueues=0 and + * DefaultVirtualQueue=16 always fail generic_random_early_detection_verify (DefaultVirtualQueue= must + * be less than VirtualQueues=). The man page documents VirtualQueues= as 1…16. + */ +class ConfigParseGredU32OptionValue : SimpleGrammarOptionValues( + "config_parse_gred_u32", + SequenceCombinator( + SafeAtoTerminal( + signed = false, + base = 0, + flags = emptySet(), + minInclusive = 0L, + maxInclusive = 16L, + acceptsWhitespace = true, + acceptsMinus = true, + ), + EOF(), + ), +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseHtbClassRateOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseHtbClassRateOptionValue.kt new file mode 100644 index 00000000..4f027c87 --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseHtbClassRateOptionValue.kt @@ -0,0 +1,30 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.* + +/* + * [HierarchyTokenBucketClass] Rate=, CeilRate= (.network) + * + * man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#Rate= + * man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#CeilRate= + * parser https://github.com/systemd/systemd/blob/0f0682b773/src/network/tc/htb.c#L378-L436 config_parse_htb_class_rate (TCLASS_KIND_HTB) + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L157-L283 parse_size + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L108-L176 TEST(parse_size_iec) + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L178-L246 TEST(parse_size_si) + * tests https://github.com/systemd/systemd/blob/0f0682b773/test/test-network/conf/25-qdisc-htb-fifo.network#L19-L20 Rate=1M, CeilRate=0.5M + */ + +/** + * Validator for [HierarchyTokenBucketClass] Rate=, CeilRate=. + * + * C function: config_parse_htb_class_rate (TCLASS_KIND_HTB). An empty assignment resets the setting and is + * handled before this grammar runs. + * + * A rate in bits per second as parse_size(rvalue, 1000) reads it (see [parseSize]): `1M`, `0.5M`, + * `1G 500M`, `125000`. The result is divided by 8 and stored as a uint64; no further bound. + */ +class ConfigParseHtbClassRateOptionValue : SimpleGrammarOptionValues( + "config_parse_htb_class_rate", + SequenceCombinator(parseSize(1000), EOF()), +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseHtbClassU32OptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseHtbClassU32OptionValue.kt new file mode 100644 index 00000000..da722eda --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseHtbClassU32OptionValue.kt @@ -0,0 +1,42 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.* +import java.math.BigInteger + +/* + * [HierarchyTokenBucketClass] Priority= (.network) + * + * man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#Priority= + * parser https://github.com/systemd/systemd/blob/0f0682b773/src/network/tc/htb.c#L242-L293 config_parse_htb_class_u32 (TCLASS_KIND_HTB) + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L429-L478 safe_atou_full + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L403-L427 mangle_base + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L489 safe_atou16("+12345") accepted + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L466-L470 0o6 / 0B101 prefixes (safe_atolli, same mangle_base) + * tests https://github.com/systemd/systemd/blob/0f0682b773/test/test-network/conf/25-qdisc-htb-fifo.network#L18 Priority=1 + */ + +/** + * Validator for [HierarchyTokenBucketClass] Priority=. + * + * C function: config_parse_htb_class_u32 (TCLASS_KIND_HTB). An empty assignment resets the setting and is + * handled before this grammar runs. + * + * An unsigned 32-bit integer read with safe_atou32 (base 0, so `0b+1` and `0b 1` are 1; see + * [SafeAtoTerminal]), 0…4294967295. No further bound. + */ +class ConfigParseHtbClassU32OptionValue : SimpleGrammarOptionValues( + "config_parse_htb_class_u32", + SequenceCombinator( + SafeAtoTerminal( + signed = false, + base = 0, + flags = emptySet(), + minInclusive = BigInteger.ZERO, + maxInclusive = SafeAtoTerminal.UINT32_MAX, + acceptsWhitespace = true, + acceptsMinus = true, + ), + EOF(), + ), +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseHtbDefaultClassOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseHtbDefaultClassOptionValue.kt new file mode 100644 index 00000000..9ab738f3 --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseHtbDefaultClassOptionValue.kt @@ -0,0 +1,42 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.* +import java.math.BigInteger + +/* + * [HierarchyTokenBucket] DefaultClass= (.network) + * + * man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#DefaultClass= + * parser https://github.com/systemd/systemd/blob/0f0682b773/src/network/tc/htb.c#L48-L98 config_parse_htb_default_class (QDISC_KIND_HTB) + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.h#L61-L64 safe_atou32_full(rvalue, 16, ..) + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L429-L478 safe_atou_full (explicit base: mangle_base is skipped) + * tests https://github.com/systemd/systemd/blob/0f0682b773/test/test-network/conf/25-qdisc-htb-fifo.network#L12 DefaultClass=30 (i.e. 0x30) + */ + +/** + * Validator for [HierarchyTokenBucket] DefaultClass=. + * + * C function: config_parse_htb_default_class (QDISC_KIND_HTB). An empty assignment resets the setting and is + * handled before this grammar runs. + * + * The default class's minor id, always read as HEXADECIMAL (safe_atou32_full(.., 16)): `30` is 0x30, `0x30` + * is the same, `ff` is legal, `0b1` is read as hex 0xb1, and `0o7` is rejected (with an explicit base, + * mangle_base does not run). strtoul skips a leading vertical tab, so `\v5` is 5 (see [SafeAtoTerminal]). + * Range 0…0xffffffff. + */ +class ConfigParseHtbDefaultClassOptionValue : SimpleGrammarOptionValues( + "config_parse_htb_default_class", + SequenceCombinator( + SafeAtoTerminal( + signed = false, + base = 16, + flags = emptySet(), + minInclusive = BigInteger.ZERO, + maxInclusive = SafeAtoTerminal.UINT32_MAX, + acceptsWhitespace = true, + acceptsMinus = true, + ), + EOF(), + ), +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseHtbU32OptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseHtbU32OptionValue.kt new file mode 100644 index 00000000..5470f63a --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseHtbU32OptionValue.kt @@ -0,0 +1,42 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.* +import java.math.BigInteger + +/* + * [HierarchyTokenBucket] RateToQuantum= (.network) + * + * man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#RateToQuantum= + * parser https://github.com/systemd/systemd/blob/0f0682b773/src/network/tc/htb.c#L100-L150 config_parse_htb_u32 (QDISC_KIND_HTB) + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L429-L478 safe_atou_full + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L403-L427 mangle_base + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L489 safe_atou16("+12345") accepted + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L466-L470 0o6 / 0B101 prefixes (safe_atolli, same mangle_base) + * tests https://github.com/systemd/systemd/blob/0f0682b773/test/test-network/conf/25-qdisc-htb-fifo.network#L13 RateToQuantum=20 + */ + +/** + * Validator for [HierarchyTokenBucket] RateToQuantum=. + * + * C function: config_parse_htb_u32 (QDISC_KIND_HTB). An empty assignment resets the setting and is + * handled before this grammar runs. + * + * An unsigned 32-bit integer read with safe_atou32 (base 0, so `0b+1` and `0b 1` are 1; see + * [SafeAtoTerminal]), 0…4294967295. No further bound. + */ +class ConfigParseHtbU32OptionValue : SimpleGrammarOptionValues( + "config_parse_htb_u32", + SequenceCombinator( + SafeAtoTerminal( + signed = false, + base = 0, + flags = emptySet(), + minInclusive = BigInteger.ZERO, + maxInclusive = SafeAtoTerminal.UINT32_MAX, + acceptsWhitespace = true, + acceptsMinus = true, + ), + EOF(), + ), +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseNetemDelayOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseNetemDelayOptionValue.kt new file mode 100644 index 00000000..1989c2a5 --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseNetemDelayOptionValue.kt @@ -0,0 +1,33 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.* + +/* + * [NetworkEmulator] DelaySec=, DelayJitterSec= (.network) + * + * man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#DelaySec= + * man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#DelayJitterSec= + * parser https://github.com/systemd/systemd/blob/0f0682b773/src/network/tc/netem.c#L51-L110 config_parse_netem_delay (QDISC_KIND_NETEM) + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/time-util.c#L1289 parse_sec + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/time-util.c#L1198-L1287 parse_time + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/time-util.c#L1147-L1196 extract_multiplier + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-time-util.c#L21-L83 TEST(parse_sec) + * tests https://github.com/systemd/systemd/blob/0f0682b773/test/test-network/conf/25-qdisc-netem.network#L12-L13 DelaySec=50ms, DelayJitterSec=10ms + */ + +/** + * Validator for [NetworkEmulator] DelaySec=, DelayJitterSec=. + * + * C function: config_parse_netem_delay (QDISC_KIND_NETEM). An empty assignment resets the setting and is + * handled before this grammar runs. + * + * A time span as parse_sec() reads it (see [parseSec]). No further bound in the parser. + * + * Lenient: a delay too large for the kernel's tick conversion only fails later, in + * network_emulator_fill_message, and is not checked here. + */ +class ConfigParseNetemDelayOptionValue : SimpleGrammarOptionValues( + "config_parse_netem_delay", + SequenceCombinator(parseSec(), EOF()), +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseNetemRateOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseNetemRateOptionValue.kt new file mode 100644 index 00000000..64e87776 --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseNetemRateOptionValue.kt @@ -0,0 +1,34 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.* + +/* + * [NetworkEmulator] LossRate=, DuplicateRate= (.network) + * + * man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#LossRate= + * man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#DuplicateRate= + * parser https://github.com/systemd/systemd/blob/0f0682b773/src/network/tc/netem.c#L112-L170 config_parse_netem_rate (QDISC_KIND_NETEM) + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/network/tc/tc-util.c#L63-L75 parse_tc_percent + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/percent-util.c#L135-L157 parse_permyriad / parse_permyriad_unbounded + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/percent-util.c#L57-L99 parse_parts_value_with_hundredths_place + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L497-L519 safe_atoi (base 0) + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-percent-util.c#L87-L130 TEST(parse_permyriad) + * tests https://github.com/systemd/systemd/blob/0f0682b773/test/test-network/conf/25-qdisc-netem.network#L14 LossRate=20% + */ + +/** + * Validator for [NetworkEmulator] LossRate=, DuplicateRate=. + * + * C function: config_parse_netem_rate (QDISC_KIND_NETEM). An empty assignment resets the setting and is + * handled before this grammar runs. + * + * A percentage as parse_tc_percent() -> parse_permyriad() reads it: an integer followed by `%` (up to + * two decimals), `‰` (up to one decimal) or `‱` (no decimals), at most 100% (see [TC_PERCENT]). A + * bare number without a symbol is rejected. The integer part goes through safe_atoi (base 0), so + * `0x10%` is legal; that corner is accepted. + */ +class ConfigParseNetemRateOptionValue : SimpleGrammarOptionValues( + "config_parse_netem_rate", + SequenceCombinator(TC_PERCENT, EOF()), +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParsePiePacketLimitOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParsePiePacketLimitOptionValue.kt new file mode 100644 index 00000000..1e4354ac --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParsePiePacketLimitOptionValue.kt @@ -0,0 +1,43 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.* +import java.math.BigInteger + +/* + * [PIE] PacketLimit= (.network) + * + * man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#PacketLimit= + * parser https://github.com/systemd/systemd/blob/0f0682b773/src/network/tc/pie.c#L40-L90 config_parse_pie_packet_limit (QDISC_KIND_PIE) + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L429-L478 safe_atou_full + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L403-L427 mangle_base + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L489 safe_atou16("+12345") accepted + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L466-L470 0o6 / 0B101 prefixes (safe_atolli, same mangle_base) + * tests https://github.com/systemd/systemd/blob/0f0682b773/test/test-network/conf/25-qdisc-pie.network#L12 PacketLimit=200000 + */ + +/** + * Validator for [PIE] PacketLimit=. + * + * C function: config_parse_pie_packet_limit (QDISC_KIND_PIE). An empty assignment resets the setting and is + * handled before this grammar runs. + * + * An unsigned 32-bit integer read with safe_atou32 (base 0, so `0b+1` and `0b 1` are 1; see + * [SafeAtoTerminal]), 0…4294967295. No further bound in the + * parser (the man page's "1…4294967294" is not enforced by it). + */ +class ConfigParsePiePacketLimitOptionValue : SimpleGrammarOptionValues( + "config_parse_pie_packet_limit", + SequenceCombinator( + SafeAtoTerminal( + signed = false, + base = 0, + flags = emptySet(), + minInclusive = BigInteger.ZERO, + maxInclusive = SafeAtoTerminal.UINT32_MAX, + acceptsWhitespace = true, + acceptsMinus = true, + ), + EOF(), + ), +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseQfqMaxPacketOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseQfqMaxPacketOptionValue.kt new file mode 100644 index 00000000..5b8f40de --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseQfqMaxPacketOptionValue.kt @@ -0,0 +1,32 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai + +import java.math.BigInteger +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.* + +/* + * [QuickFairQueueingClass] MaxPacketBytes= (.network) + * + * man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#MaxPacketBytes= + * parser https://github.com/systemd/systemd/blob/0f0682b773/src/network/tc/qfq.c#L115-L173 config_parse_qfq_max_packet (TCLASS_KIND_QFQ) + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L157-L283 parse_size + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/network/tc/qfq.c#L14-L15 QFQ_MIN_MAX_PACKET 512, QFQ_MAX_MAX_PACKET 1<<16 + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L108-L176 TEST(parse_size_iec) + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L178-L246 TEST(parse_size_si) + * tests https://github.com/systemd/systemd/blob/0f0682b773/test/test-network/conf/25-qdisc-qfq.network#L17 MaxPacketBytes=16000 + */ + +/** + * Validator for [QuickFairQueueingClass] MaxPacketBytes=. + * + * C function: config_parse_qfq_max_packet (TCLASS_KIND_QFQ). An empty assignment resets the setting and is + * handled before this grammar runs. + * + * A byte size as parse_size(rvalue, 1024) reads it (IEC suffixes `K`/`M`/…, see [parseSize]) that + * must lie in 512…65536 bytes (QFQ_MIN_MAX_PACKET…QFQ_MAX_MAX_PACKET); outside it the parser logs + * "Invalid ..., ignoring assignment". So `64K` is accepted and `65K` or `511` are not. + */ +class ConfigParseQfqMaxPacketOptionValue : SimpleGrammarOptionValues( + "config_parse_qfq_max_packet", + SequenceCombinator(parseSize(1024, BigInteger.valueOf(512), BigInteger.valueOf(65_536)), EOF()), +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseTbfRateOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseTbfRateOptionValue.kt new file mode 100644 index 00000000..4a8bd014 --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseTbfRateOptionValue.kt @@ -0,0 +1,32 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.* + +/* + * [TokenBucketFilter] Rate=, PeakRate= (.network) + * + * man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#Rate= + * man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#PeakRate= + * parser https://github.com/systemd/systemd/blob/0f0682b773/src/network/tc/tbf.c#L184-L243 config_parse_tbf_rate (QDISC_KIND_TBF) + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L157-L283 parse_size + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L108-L176 TEST(parse_size_iec) + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L178-L246 TEST(parse_size_si) + * tests https://github.com/systemd/systemd/blob/0f0682b773/test/test-network/conf/25-qdisc-tbf.network#L12-L16 Rate=1G, PeakRate=100G + */ + +/** + * Validator for [TokenBucketFilter] Rate=, PeakRate=. + * + * C function: config_parse_tbf_rate (QDISC_KIND_TBF). An empty assignment resets the setting and is + * handled before this grammar runs. + * + * A rate in bits per second as parse_size(rvalue, 1000) reads it: a number with an optional SI suffix + * `K`/`M`/`G`/`T`/`P`/`E` (upper case only, powers of 1000) or `B`, optionally several descending + * elements (`1G 500M`). The result is divided by 8 and stored as a uint64; there is no further bound. + * Note `10Mbit` / `10mbit` (tc(8) spellings) are NOT accepted by systemd. + */ +class ConfigParseTbfRateOptionValue : SimpleGrammarOptionValues( + "config_parse_tbf_rate", + SequenceCombinator(parseSize(1000), EOF()), +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseTeqlIdOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseTeqlIdOptionValue.kt new file mode 100644 index 00000000..47b289ab --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseTeqlIdOptionValue.kt @@ -0,0 +1,44 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.* +import java.math.BigInteger + +/* + * [TrivialLinkEqualizer] Id= (.network) + * + * man https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#Id= + * parser https://github.com/systemd/systemd/blob/0f0682b773/src/network/tc/teql.c#L44-L100 config_parse_teql_id (QDISC_KIND_TEQL) + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L429-L478 safe_atou_full + * leaf https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L403-L427 mangle_base + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L489 safe_atou16("+12345") accepted + * tests https://github.com/systemd/systemd/blob/0f0682b773/src/test/test-parse-util.c#L466-L470 0o6 / 0B101 prefixes (safe_atolli, same mangle_base) + * tests https://github.com/systemd/systemd/blob/0f0682b773/test/test-network/conf/25-qdisc-teql.network#L12 Id=1 + */ + +/** + * Validator for [TrivialLinkEqualizer] Id=. + * + * C function: config_parse_teql_id (QDISC_KIND_TEQL). An empty assignment resets the setting and is + * handled before this grammar runs. + * + * An unsigned integer read with safe_atou (base 0, so `0b+1` and `0b 1` are 1; see [SafeAtoTerminal]) + * that must not exceed INT_MAX: above it the parser + * logs "'Id=' is too large, ignoring assignment" (and, at 0f0682b773, still stores it — the qdisc kind + * then becomes e.g. "teql4294967295"), so 0…2147483647 is accepted. + */ +class ConfigParseTeqlIdOptionValue : SimpleGrammarOptionValues( + "config_parse_teql_id", + SequenceCombinator( + SafeAtoTerminal( + signed = false, + base = 0, + flags = emptySet(), + minInclusive = BigInteger.ZERO, + maxInclusive = SafeAtoTerminal.INT32_MAX, + acceptsWhitespace = true, + acceptsMinus = true, + ), + EOF(), + ), +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/grammar/BatchQdiscCombinators.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/grammar/BatchQdiscCombinators.kt new file mode 100644 index 00000000..e1797519 --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/grammar/BatchQdiscCombinators.kt @@ -0,0 +1,324 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar + +import java.math.BigDecimal +import java.math.BigInteger + +/* + * Shared grammars for the systemd-networkd traffic-control validators (.network [QDisc]-family and + * [...Class] sections, systemd src/network/tc/), written for the 2026-10 qdisc batch. + * + * Everything here is pinned to systemd 0f0682b773 (systemd-build/build/last_commit_hash): + * https://github.com/systemd/systemd/blob/0f0682b773 + * + * The tc parsers lean on four leaf helpers. safe_atou / safe_atou32 / safe_atou8 / + * safe_atou32_full(.., 16) (https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L429) + * are the shared [SafeAtoTerminal], written out at each call site. The other three are modelled here as + * closely to the C as the combinator framework allows: + * + * - parse_sec / parse_time -> [parseSec] + * https://github.com/systemd/systemd/blob/0f0682b773/src/basic/time-util.c#L1198 + * - parse_size(.., 1000 | 1024) -> [parseSize] + * https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L157 + * - parse_permyriad (via parse_tc_percent) -> [TC_PERCENT] + * https://github.com/systemd/systemd/blob/0f0682b773/src/basic/percent-util.c#L149 + * + * These are more faithful than the older shared terminals in Combinators.kt (TIME_VALUE rejects + * "1min30s"; ByteSizeTerminal rejects "1G 512M"). They live in this file only so the batch does not + * collide with parallel edits to Combinators.kt; see RECOMMENDATIONS.md for promoting + * them. + */ + +// --------------------------------------------------------------------------------------------------- +// Generic helpers + +private val OPT_WS = ZeroOrOne(WhitespaceTerminal()) + +/** + * Wraps [inner] and additionally requires the text it matched to satisfy [accept]. + * + * Used for value-level range checks that no single terminal can see — e.g. a parse_size() value + * written as several elements (`1G 512M`), where the bound applies to the sum. Matching (and so + * syntax highlighting and error localisation) is delegated to [inner] unchanged; only validity is + * narrowed. When [accept] returns null ("could not evaluate") the value is accepted: the grammar has + * already decided it is well-formed, and an evaluator gap must never flag a valid value. + * + * Empty matches are never accepted, so a grammar built only of optional parts (like [parseSize]'s + * chain of optional elements) cannot match the empty string. + */ +class ValueChecked(private val inner: Combinator, private val accept: (String) -> Boolean?) : Combinator { + + private fun ok(text: String): Boolean = accept(text) ?: true + + override fun SyntacticMatch(value: String, offset: Int): MatchResult { + val m = inner.SyntacticMatch(value, offset) + return if (m.matchResult == offset) NoMatch.copy(longestMatch = offset) else m + } + + override fun SemanticMatch(value: String, offset: Int): MatchResult { + val m = inner.SemanticMatch(value, offset) + if (m.matchResult == -1) return m + if (m.matchResult == offset) return NoMatch.copy(longestMatch = offset) + return if (ok(value.substring(offset, m.matchResult))) m else NoMatch.copy(longestMatch = offset) + } + + override fun parse(value: String, offset: Int): Sequence = + inner.parse(value, offset).map { step -> + when (step) { + is Stuck -> step + is Parse -> when { + step.end == offset -> Stuck(offset, setOf(this)) + ok(value.substring(offset, step.end)) -> step + // Out of range: keep the tokens (so the span still highlights) but mark them invalid. + else -> Parse(step.end, step.tokens.map { it.copy(valid = false) }, step.regions) + } + } + } + + override fun toStringIndented(indent: Int): String = " ".repeat(indent) + "Checked(\n" + inner.toStringIndented(indent + 1) + "\n" + " ".repeat(indent) + ")" + + override fun toString(): String = toStringIndented(0) +} + +// --------------------------------------------------------------------------------------------------- +// Bounds + +/** UINT32_MAX, for the size/time range checks. */ +private val UINT32_MAX_BIG: BigInteger = SafeAtoTerminal.UINT32_MAX + +/** ULLONG_MAX: parse_size() and parse_time() return ERANGE above it. */ +private val UINT64_MAX_BIG: BigInteger = SafeAtoTerminal.UINT64_MAX + +// --------------------------------------------------------------------------------------------------- +// parse_sec / parse_time + +// extract_multiplier()'s table, in table order: the C takes the first entry the text starts with, +// and a regex alternation does the same (time-util.c#L1147-L1196). +private const val SEC_SUFFIX_ALTERNATION = + "seconds|second|sec|s|minutes|minute|min|months|month|M|msec|ms|m|hours|hour|hr|h|days|day|d|" + + "weeks|week|w|years|year|y|usec|us|μs|µs" + +private val SEC_SUFFIX = Labeled(Role.ENUM, RegexTerminal(SEC_SUFFIX_ALTERNATION, SEC_SUFFIX_ALTERNATION)) + +// strtoll() digits with an optional '+', then an optional '.digits'; or a bare '.digits' (".5s" is +// legal: strtoll consumes nothing, and the '.' branch takes over). "5." and "+.5" are not. +private const val SEC_NUMBER_RE = """\+?[0-9]+(?:\.[0-9]+)?|\.[0-9]+""" +private val SEC_NUMBER = Labeled(Role.LITERAL, RegexTerminal(SEC_NUMBER_RE, SEC_NUMBER_RE)) + +// After a number comes either a unit (optionally surrounded by whitespace), or whitespace, or the end. +// A unit may be followed directly by the next number ("5s500ms", "3.1s.2"); a bare number may not +// ("12.34.56" is EINVAL). +private val SEC_ELEMENT = SequenceCombinator( + SEC_NUMBER, + AlternativeCombinator( + SequenceCombinator(OPT_WS, SEC_SUFFIX, OPT_WS), + WhitespaceTerminal(), + EOF(), + ), +) + +private val PARSE_SEC = AlternativeCombinator( + LiteralChoiceTerminal("infinity"), + OneOrMore(SEC_ELEMENT), +) + +private val USEC_INFINITY: BigInteger = UINT64_MAX_BIG + +private val LLONG_MAX_BIG: BigInteger = BigInteger.valueOf(Long.MAX_VALUE) + +/** Returned by [evaluateParseSec] when parse_time() would fail with ERANGE; above every accepted bound. */ +private val PARSE_SEC_ERANGE: BigInteger = USEC_INFINITY + BigInteger.ONE + +private val SEC_MULTIPLIERS: Map = run { + val sec = 1_000_000L + val minute = 60 * sec + val hour = 60 * minute + val day = 24 * hour + mapOf( + "seconds" to sec, "second" to sec, "sec" to sec, "s" to sec, + "minutes" to minute, "minute" to minute, "min" to minute, "m" to minute, + "months" to 2_629_800L * sec, "month" to 2_629_800L * sec, "M" to 2_629_800L * sec, + "msec" to 1000L, "ms" to 1000L, + "hours" to hour, "hour" to hour, "hr" to hour, "h" to hour, + "days" to day, "day" to day, "d" to day, + "weeks" to 7 * day, "week" to 7 * day, "w" to 7 * day, + "years" to 31_557_600L * sec, "year" to 31_557_600L * sec, "y" to 31_557_600L * sec, + "usec" to 1L, "us" to 1L, "μs" to 1L, "µs" to 1L, + ).mapValues { BigInteger.valueOf(it.value) } +} + +private val SEC_EVAL_ELEMENT = Regex("""\s*\+?([0-9]*)(?:\.([0-9]+))?\s*($SEC_SUFFIX_ALTERNATION)?""") + +/** + * parse_time(t, USEC_PER_SEC) as a value in microseconds, or null if [text] is not evaluable. Overflow + * (C's ERANGE: an integer part above LLONG_MAX, or a finite total reaching USEC_INFINITY) yields a value + * greater than USEC_INFINITY so that every bound check rejects it. + */ +fun evaluateParseSec(text: String): BigInteger? { + val t = text.trim() + if (t == "infinity") return USEC_INFINITY + var pos = 0 + var total = BigInteger.ZERO + while (pos < t.length) { + while (pos < t.length && t[pos].isWhitespace()) pos++ + if (pos >= t.length) break + val m = SEC_EVAL_ELEMENT.matchAt(t, pos) ?: return null + if (m.value.isEmpty()) return null + pos += m.value.length + val multiplier = m.groupValues[3].takeIf { it.isNotEmpty() }?.let { SEC_MULTIPLIERS[it] } ?: SEC_MULTIPLIERS.getValue("s") + val whole = BigInteger(m.groupValues[1].ifEmpty { "0" }) + // strtoll() sets ERANGE above LLONG_MAX; then `(usec_t) l >= USEC_INFINITY / multiplier` and + // `k >= USEC_INFINITY - usec` are ERANGE too, so a finite total can never reach USEC_INFINITY. + if (whole > LLONG_MAX_BIG || whole >= USEC_INFINITY / multiplier) return PARSE_SEC_ERANGE + val k = whole * multiplier + if (k >= USEC_INFINITY - total) return PARSE_SEC_ERANGE + total += k + // The C adds the fractional digits one by one, each times a truncated multiplier/10^k. + var step = multiplier / BigInteger.TEN + for (digit in m.groupValues[2]) { + val kf = BigInteger.valueOf((digit - '0').toLong()) * step + if (kf >= USEC_INFINITY - total) return PARSE_SEC_ERANGE + total += kf + step /= BigInteger.TEN + } + } + return total +} + +/** + * A whole parse_sec() value: `infinity`, or one or more `number[unit]` elements. + * + * Mirrors parse_time() (https://github.com/systemd/systemd/blob/0f0682b773/src/basic/time-util.c#L1198-L1287) + * including the forms its unit test asserts are legal (test-time-util.c#L21): `5s500ms`, `.22s`, + * `+3.1s`, `3.1s.2`, `3.1 .2`, `23µs`; and rejects what it asserts are not: `5.`, `.s`, `-5s`, + * `3.s`, `3. 1s`, `12.34.56`, `infinity .7`. + * + * @param maxUsec when set, the value (in microseconds, `infinity` counting as USEC_INFINITY) must not + * exceed it. + */ +fun parseSec(maxUsec: BigInteger? = null): Combinator = + ValueChecked(PARSE_SEC) { text -> + evaluateParseSec(text)?.let { it <= (maxUsec ?: USEC_INFINITY) } + } + +/** [maxUsec] for parsers that refuse anything above UINT32_MAX microseconds (and so `infinity`). */ +val UINT32_MAX_USEC: BigInteger = UINT32_MAX_BIG + +// --------------------------------------------------------------------------------------------------- +// parse_size + +// strtoull(base 10) digits with an optional '+', then an optional '.' with optional digits: "3." and +// "10.M" are legal (parse-util.c "Ignore failure. E.g. 10.M is valid"); ".5" is not. +private const val SIZE_NUMBER_RE = """\+?[0-9]+(?:\.[0-9]*)?""" +private val SIZE_NUMBER = Labeled(Role.LITERAL, RegexTerminal(SIZE_NUMBER_RE, SIZE_NUMBER_RE)) + +private val SIZE_SUFFIXES = listOf("E", "P", "T", "G", "M", "K", "B") + +private fun sizeChain(allowInnerWhitespace: Boolean): Combinator { + val parts = mutableListOf() + for (suffix in SIZE_SUFFIXES) { + val element = if (allowInnerWhitespace) { + SequenceCombinator(SIZE_NUMBER, OPT_WS, LiteralChoiceTerminal(suffix), OPT_WS) + } else { + SequenceCombinator(SIZE_NUMBER, LiteralChoiceTerminal(suffix)) + } + parts.add(ZeroOrOne(element)) + } + // The "" entry of the table: a bare number, which can only be the last element. + parts.add(ZeroOrOne(SIZE_NUMBER)) + return SequenceCombinator(*parts.toTypedArray()) +} + +private val SIZE_EVAL_ELEMENT = Regex("""\s*\+?([0-9]+)(?:\.([0-9]*))?\s*([EPTGMKB]?)\s*""") + +/** parse_size(text, base) as a byte count, or null if [text] is not evaluable. */ +fun evaluateParseSize(text: String, base: Int): BigInteger? { + val factorBase = BigInteger.valueOf(base.toLong()) + var pos = 0 + var total = BigInteger.ZERO + while (pos < text.length) { + val m = SIZE_EVAL_ELEMENT.matchAt(text, pos) ?: return null + if (m.value.isEmpty()) return null + pos += m.value.length + val power = when (m.groupValues[3]) { + "E" -> 6; "P" -> 5; "T" -> 4; "G" -> 3; "M" -> 2; "K" -> 1; else -> 0 + } + val factor = factorBase.pow(power) + total += BigInteger(m.groupValues[1]) * factor + val frac = m.groupValues[2] + if (frac.isNotEmpty()) total += BigDecimal("0.$frac").multiply(BigDecimal(factor)).toBigInteger() + } + return total +} + +/** + * A parse_size() value (https://github.com/systemd/systemd/blob/0f0682b773/src/basic/parse-util.c#L157-L283): + * one or more `number[.fraction][suffix]` elements whose suffixes strictly descend through + * `E P T G M K B ""` — `4M 11.5K`, `3.5G3B` and `4T3G3B` are legal; `3B3.5G`, `12P12P`, `12X`, `5k` + * (suffixes are upper-case only) and `-1` are not (test-parse-util.c#L108, #L178). A bare number (the + * `""` entry) must be the last element. + * + * @param base 1000 (SI, for rates) or 1024 (IEC, for sizes); only affects the range check. + * @param minInclusive / maxInclusive bounds on the resulting byte (or bit) count. The upper bound + * defaults to ULLONG_MAX, above which parse_size() itself returns ERANGE. + * @param allowInnerWhitespace false for an element of a whitespace-separated list (each word is + * parsed on its own, so a space would split the size into two words). + */ +fun parseSize( + base: Int, + minInclusive: BigInteger = BigInteger.ZERO, + maxInclusive: BigInteger = UINT64_MAX_BIG, + allowInnerWhitespace: Boolean = true, +): Combinator = + ValueChecked(sizeChain(allowInnerWhitespace)) { text -> + evaluateParseSize(text, base)?.let { it >= minInclusive && it <= maxInclusive } + } + +/** UINT32_MAX, the cap several tc size parsers apply after parse_size(). */ +val SIZE_UINT32_MAX: BigInteger = UINT32_MAX_BIG + +// --------------------------------------------------------------------------------------------------- +// parse_permyriad / parse_tc_percent + +// The integer part goes through safe_atoi() (base 0, mangle_base), so `0x10%` is 16% and `0b 1%` is 1%, +// and parse_parts_value_*() return ERANGE when it is negative (`-0` is fine, and so is `0b-0`). Its +// magnitude is capped by the 100% check below, so int's range on the terminal itself is enough. The +// whole value reaches safe_atoi() up to the '.' or the symbol, so whitespace can reach the parser. +// https://github.com/systemd/systemd/blob/0f0682b773/src/basic/percent-util.c#L7-L23 +private val PCT_INT = SafeAtoTerminal( + signed = true, + base = 0, + flags = emptySet(), + minInclusive = 0L, + maxInclusive = Int.MAX_VALUE.toLong(), + acceptsWhitespace = true, + acceptsMinus = true, +) + +/** + * A percentage as parse_permyriad() reads it + * (https://github.com/systemd/systemd/blob/0f0682b773/src/basic/percent-util.c#L135-L157): an integer + * followed by `%` (up to two decimals), `‰` (up to one decimal) or `‱` (no decimals), at most 100%. + * test-percent-util.c#L87 asserts `55.53%`, `555.5‰` and `1000‱` legal and `3.212%`, `3.22‰`, + * `3.2‱`, `107%`, `-7%` and a bare `50` illegal. + */ +val TC_PERCENT: Combinator = ValueChecked( + AlternativeCombinator( + SequenceCombinator(PCT_INT, ZeroOrOne(SequenceCombinator(DOT, RegexTerminal("[0-9]{1,2}", "[0-9]{1,2}"))), LiteralChoiceTerminal("%")), + SequenceCombinator(PCT_INT, ZeroOrOne(SequenceCombinator(DOT, RegexTerminal("[0-9]", "[0-9]"))), LiteralChoiceTerminal("‰")), + SequenceCombinator(PCT_INT, LiteralChoiceTerminal("‱")), + ), +) { text -> evaluatePermyriad(text)?.let { it in 0..10_000 } } + +private val PCT_EVAL = Regex("""(.*?)(?:\.([0-9]+))?([%‰‱])""") + +/** parse_permyriad_unbounded(text), or null if not evaluable (the integer part is read like [PCT_INT]). */ +fun evaluatePermyriad(text: String): Long? { + val m = PCT_EVAL.matchEntire(text) ?: return null + val n = PCT_INT.valueOf(m.groupValues[1])?.toLong() ?: return null + val frac = m.groupValues[2] + return when (m.groupValues[3]) { + "%" -> n * 100 + (frac.padEnd(2, '0').toLongOrNull() ?: 0) + "‰" -> n * 10 + (frac.toLongOrNull() ?: 0) + else -> n + } +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseBfifoSizeOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseBfifoSizeOptionValueTest.kt new file mode 100644 index 00000000..27920cc0 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseBfifoSizeOptionValueTest.kt @@ -0,0 +1,52 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.inspections.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest +import net.sjrx.intellij.plugins.systemdunitfiles.inspections.InvalidValueInspection +import org.junit.Test + +class ConfigParseBfifoSizeOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // Fixture values from systemd test/test-network/conf plus tricky spellings the C parser accepts. + // language="unit file (systemd)" + val file = """ + [BFIFO] + LimitBytes=1000000 + LimitBytes=1K + LimitBytes=1M + LimitBytes=1.5M + LimitBytes=4095M + LimitBytes=4294967295 + LimitBytes=3G 1023M + LimitBytes= + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // language="unit file (systemd)" + val file = """ + [BFIFO] + LimitBytes=4G + LimitBytes=4294967296 + LimitBytes=1k + LimitBytes=-1 + LimitBytes=abc + LimitBytes=1M 1M + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(6, highlights) + } + +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseCakeAckFilterOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseCakeAckFilterOptionValueTest.kt new file mode 100644 index 00000000..78625491 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseCakeAckFilterOptionValueTest.kt @@ -0,0 +1,62 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.inspections.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest +import net.sjrx.intellij.plugins.systemdunitfiles.inspections.InvalidValueInspection +import org.junit.Test + +class ConfigParseCakeAckFilterOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // Fixture values from systemd test/test-network/conf plus tricky spellings the C parser accepts. + // language="unit file (systemd)" + val file = """ + [CAKE] + AckFilter=aggressive + AckFilter=yes + AckFilter=no + AckFilter=true + AckFilter=false + AckFilter=1 + AckFilter=0 + AckFilter=on + AckFilter=off + AckFilter=YES + AckFilter=No + AckFilter=Yes + AckFilter=TRUE + AckFilter=oFf + AckFilter=tRUE + AckFilter=N + AckFilter= + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // language="unit file (systemd)" + val file = """ + [CAKE] + AckFilter=Aggressive + AckFilter=maybe + AckFilter=aggresive + AckFilter=2 + AckFilter=filter + AckFilter=AGGRESSIVE + AckFilter=aggressivE + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(7, highlights) + } + +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseCakeBandwidthOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseCakeBandwidthOptionValueTest.kt new file mode 100644 index 00000000..2dcedf88 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseCakeBandwidthOptionValueTest.kt @@ -0,0 +1,53 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.inspections.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest +import net.sjrx.intellij.plugins.systemdunitfiles.inspections.InvalidValueInspection +import org.junit.Test + +class ConfigParseCakeBandwidthOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // Fixture values from systemd test/test-network/conf plus tricky spellings the C parser accepts. + // language="unit file (systemd)" + val file = """ + [CAKE] + Bandwidth=500M + Bandwidth=1G + Bandwidth=100K + Bandwidth=1.5M + Bandwidth=1G 500M + Bandwidth=100000 + Bandwidth= + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // language="unit file (systemd)" + val file = """ + [CAKE] + Bandwidth=10Mbit + Bandwidth=1k + Bandwidth=-1M + Bandwidth=3B3.5G + Bandwidth=12P12P + Bandwidth=1M 1M + Bandwidth=abc + Bandwidth=.5M + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(8, highlights) + } + +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseCakeFlowIsolationModeOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseCakeFlowIsolationModeOptionValueTest.kt new file mode 100644 index 00000000..a97157ad --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseCakeFlowIsolationModeOptionValueTest.kt @@ -0,0 +1,52 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.inspections.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest +import net.sjrx.intellij.plugins.systemdunitfiles.inspections.InvalidValueInspection +import org.junit.Test + +class ConfigParseCakeFlowIsolationModeOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // Fixture values from systemd test/test-network/conf plus tricky spellings the C parser accepts. + // language="unit file (systemd)" + val file = """ + [CAKE] + FlowIsolationMode=none + FlowIsolationMode=src-host + FlowIsolationMode=dst-host + FlowIsolationMode=hosts + FlowIsolationMode=flows + FlowIsolationMode=dual-src-host + FlowIsolationMode=dual-dst-host + FlowIsolationMode=triple + FlowIsolationMode= + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // language="unit file (systemd)" + val file = """ + [CAKE] + FlowIsolationMode=None + FlowIsolationMode=dual + FlowIsolationMode=triple-isolate + FlowIsolationMode=src_host + FlowIsolationMode=yes + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(5, highlights) + } + +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseDrrSizeOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseDrrSizeOptionValueTest.kt new file mode 100644 index 00000000..21931169 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseDrrSizeOptionValueTest.kt @@ -0,0 +1,51 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.inspections.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest +import net.sjrx.intellij.plugins.systemdunitfiles.inspections.InvalidValueInspection +import org.junit.Test + +class ConfigParseDrrSizeOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // Fixture values from systemd test/test-network/conf plus tricky spellings the C parser accepts. + // language="unit file (systemd)" + val file = """ + [DeficitRoundRobinSchedulerClass] + QuantumBytes=2000 + QuantumBytes=1K + QuantumBytes=1.5K + QuantumBytes=4095M + QuantumBytes=4294967295 + QuantumBytes=3G 1023M + QuantumBytes= + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // language="unit file (systemd)" + val file = """ + [DeficitRoundRobinSchedulerClass] + QuantumBytes=4G + QuantumBytes=4294967296 + QuantumBytes=1k + QuantumBytes=-1 + QuantumBytes=abc + QuantumBytes=1K 1K + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(6, highlights) + } + +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseEtsPrioOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseEtsPrioOptionValueTest.kt new file mode 100644 index 00000000..5796bcb5 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseEtsPrioOptionValueTest.kt @@ -0,0 +1,58 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.inspections.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest +import net.sjrx.intellij.plugins.systemdunitfiles.inspections.InvalidValueInspection +import org.junit.Test + +class ConfigParseEtsPrioOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // Fixture values from systemd test/test-network/conf plus tricky spellings the C parser accepts. + // sd-check at 0f0682b773 accepts 0b+1 and 0b-0 (a sign may follow the 0b prefix). + // language="unit file (systemd)" + val file = """ + [EnhancedTransmissionSelection] + PriorityMap=8 7 6 5 + PriorityMap=3 4 5 + PriorityMap=6 7 + PriorityMap=0 + PriorityMap=255 + PriorityMap=0x0f 017 0b1 + PriorityMap=0b+1 + PriorityMap=1 0b-0 2 + PriorityMap=0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + PriorityMap= + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // sd-check at 0f0682b773 rejects 0b 1 and 0b +1 (the list splits on blanks, so the word is "0b") and 0b-1 (ERANGE). + // language="unit file (systemd)" + val file = """ + [EnhancedTransmissionSelection] + PriorityMap=256 + PriorityMap=-1 + PriorityMap=1,2 + PriorityMap=a b + PriorityMap=0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0 + PriorityMap=0b 1 + PriorityMap=0b +1 + PriorityMap=0b-1 + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(8, highlights) + } + +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseEtsQuantaOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseEtsQuantaOptionValueTest.kt new file mode 100644 index 00000000..e836feb7 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseEtsQuantaOptionValueTest.kt @@ -0,0 +1,54 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.inspections.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest +import net.sjrx.intellij.plugins.systemdunitfiles.inspections.InvalidValueInspection +import org.junit.Test + +class ConfigParseEtsQuantaOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // Fixture values from systemd test/test-network/conf plus tricky spellings the C parser accepts. + // language="unit file (systemd)" + val file = """ + [EnhancedTransmissionSelection] + QuantumBytes=2 4 6 + QuantumBytes=1001 1002 1003 + QuantumBytes=1004 1005 + QuantumBytes=1K + QuantumBytes=1K512B + QuantumBytes=1.5K 2M + QuantumBytes=4294967295 + QuantumBytes=1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + QuantumBytes= + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // language="unit file (systemd)" + val file = """ + [EnhancedTransmissionSelection] + QuantumBytes=0 + QuantumBytes=4G + QuantumBytes=1 0 2 + QuantumBytes=1K 512 B + QuantumBytes=abc + QuantumBytes=1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 + QuantumBytes=1k + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(7, highlights) + } + +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseFqCodelBoolOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseFqCodelBoolOptionValueTest.kt new file mode 100644 index 00000000..7163924a --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseFqCodelBoolOptionValueTest.kt @@ -0,0 +1,64 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.inspections.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest +import net.sjrx.intellij.plugins.systemdunitfiles.inspections.InvalidValueInspection +import org.junit.Test + +class ConfigParseFqCodelBoolOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // Fixture values from systemd test/test-network/conf plus tricky spellings the C parser accepts. + // language="unit file (systemd)" + val file = """ + [FairQueueingControlledDelay] + ECN=yes + ECN=no + ECN=1 + ECN=0 + ECN=true + ECN=false + ECN=on + ECN=off + ECN=y + ECN=n + ECN=t + ECN=f + ECN=YES + ECN=False + ECN=On + ECN=Yes + ECN=TRUE + ECN=oFf + ECN=Y + ECN= + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // language="unit file (systemd)" + val file = """ + [FairQueueingControlledDelay] + ECN=maybe + ECN=2 + ECN=enable + ECN=nope + ECN=Maybe + ECN=ENABLE + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(6, highlights) + } + +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseFqCodelU32OptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseFqCodelU32OptionValueTest.kt new file mode 100644 index 00000000..bd8d3047 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseFqCodelU32OptionValueTest.kt @@ -0,0 +1,96 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.inspections.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest +import net.sjrx.intellij.plugins.systemdunitfiles.inspections.InvalidValueInspection +import org.junit.Test + +class ConfigParseFqCodelU32OptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // Fixture values from systemd test/test-network/conf plus tricky spellings the C parser accepts. + // sd-check at 0f0682b773 accepts these: strtoul starts afresh after the 0b/0o prefix, so a sign or blank may follow it. + // language="unit file (systemd)" + val file = """ + [FairQueueingControlledDelay] + PacketLimit=0 + Flows=0 + PacketLimit=1 + Flows=1 + PacketLimit=20480 + Flows=20480 + PacketLimit=4294967295 + Flows=4294967295 + PacketLimit=0x10 + Flows=0x10 + PacketLimit=0o17 + Flows=0o17 + PacketLimit=0b101 + Flows=0b101 + PacketLimit=017 + Flows=017 + PacketLimit=+5 + Flows=+5 + PacketLimit=-0 + Flows=-0 + PacketLimit=0b+1 + Flows=0b+1 + PacketLimit=0b-0 + Flows=0b-0 + PacketLimit=0b 1 + Flows=0b 1 + PacketLimit=0o 7 + Flows=0o 7 + PacketLimit=0b +1 + Flows=0b +1 + PacketLimit=0b -0 + Flows=0b -0 + PacketLimit= + Flows= + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // sd-check at 0f0682b773 rejects these: 0b-1 and 0b -1 are -1 (ERANGE), -0b0 is -0 followed by junk (EINVAL). + // language="unit file (systemd)" + val file = """ + [FairQueueingControlledDelay] + PacketLimit=4294967296 + Flows=4294967296 + PacketLimit=-1 + Flows=-1 + PacketLimit=08 + Flows=08 + PacketLimit=0x + Flows=0x + PacketLimit=1.5 + Flows=1.5 + PacketLimit=abc + Flows=abc + PacketLimit=+0b1 + Flows=+0b1 + PacketLimit=12 13 + Flows=12 13 + PacketLimit=0b-1 + Flows=0b-1 + PacketLimit=0b -1 + Flows=0b -1 + PacketLimit=-0b0 + Flows=-0b0 + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(22, highlights) + } + +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseFqCodelUsecOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseFqCodelUsecOptionValueTest.kt new file mode 100644 index 00000000..8ceaf4d8 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseFqCodelUsecOptionValueTest.kt @@ -0,0 +1,130 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.inspections.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest +import net.sjrx.intellij.plugins.systemdunitfiles.inspections.InvalidValueInspection +import org.junit.Test + +class ConfigParseFqCodelUsecOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // Fixture values from systemd test/test-network/conf plus tricky spellings the C parser accepts. + // language="unit file (systemd)" + val file = """ + [FairQueueingControlledDelay] + TargetSec=10ms + IntervalSec=10ms + CEThresholdSec=10ms + TargetSec=200ms + IntervalSec=200ms + CEThresholdSec=200ms + TargetSec=1min30s + IntervalSec=1min30s + CEThresholdSec=1min30s + TargetSec=5s 500ms + IntervalSec=5s 500ms + CEThresholdSec=5s 500ms + TargetSec=5s500ms + IntervalSec=5s500ms + CEThresholdSec=5s500ms + TargetSec=.5s + IntervalSec=.5s + CEThresholdSec=.5s + TargetSec=+3.1s + IntervalSec=+3.1s + CEThresholdSec=+3.1s + TargetSec=3.1s.2 + IntervalSec=3.1s.2 + CEThresholdSec=3.1s.2 + TargetSec=3.1 .2 + IntervalSec=3.1 .2 + CEThresholdSec=3.1 .2 + TargetSec=1.5h + IntervalSec=1.5h + CEThresholdSec=1.5h + TargetSec=23us + IntervalSec=23us + CEThresholdSec=23us + TargetSec=23µs + IntervalSec=23µs + CEThresholdSec=23µs + TargetSec=2 weeks + IntervalSec=2 weeks + CEThresholdSec=2 weeks + TargetSec=100 + IntervalSec=100 + CEThresholdSec=100 + # Largest finite values parse_time() accepts (total < USEC_INFINITY, each integer <= LLONG_MAX). + TargetSec=9223372036854775807us 9223372036854775807us + IntervalSec=9223372036854775807us 9223372036854775807us + CEThresholdSec=9223372036854775807us 9223372036854775807us + TargetSec=18446744073708s + IntervalSec=18446744073708s + CEThresholdSec=18446744073708s + TargetSec=infinity + IntervalSec=infinity + CEThresholdSec=infinity + TargetSec= + IntervalSec= + CEThresholdSec= + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // language="unit file (systemd)" + val file = """ + [FairQueueingControlledDelay] + TargetSec=5. + IntervalSec=5. + CEThresholdSec=5. + TargetSec=-5s + IntervalSec=-5s + CEThresholdSec=-5s + TargetSec=3.s + IntervalSec=3.s + CEThresholdSec=3.s + TargetSec=12.34.56 + IntervalSec=12.34.56 + CEThresholdSec=12.34.56 + TargetSec=5mins + IntervalSec=5mins + CEThresholdSec=5mins + TargetSec=10 foo + IntervalSec=10 foo + CEThresholdSec=10 foo + TargetSec=infinity 5s + IntervalSec=infinity 5s + CEThresholdSec=infinity 5s + TargetSec=Infinity + IntervalSec=Infinity + CEThresholdSec=Infinity + # parse_time() ERANGE: integer above LLONG_MAX, or total reaching USEC_INFINITY. + TargetSec=9223372036854775808us + IntervalSec=9223372036854775808us + CEThresholdSec=9223372036854775808us + TargetSec=18446744073709551615us + IntervalSec=18446744073709551615us + CEThresholdSec=18446744073709551615us + TargetSec=9223372036854775807us 9223372036854775807us 1us + IntervalSec=9223372036854775807us 9223372036854775807us 1us + CEThresholdSec=9223372036854775807us 9223372036854775807us 1us + TargetSec=18446744073709s + IntervalSec=18446744073709s + CEThresholdSec=18446744073709s + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(36, highlights) + } + +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseFqMaxRateOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseFqMaxRateOptionValueTest.kt new file mode 100644 index 00000000..dc9792fe --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseFqMaxRateOptionValueTest.kt @@ -0,0 +1,51 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.inspections.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest +import net.sjrx.intellij.plugins.systemdunitfiles.inspections.InvalidValueInspection +import org.junit.Test + +class ConfigParseFqMaxRateOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // Fixture values from systemd test/test-network/conf plus tricky spellings the C parser accepts. + // language="unit file (systemd)" + val file = """ + [FairQueueing] + MaximumRate=1M + MaximumRate=0.5G + MaximumRate=34G + MaximumRate=34359738367 + MaximumRate=34359738367B + MaximumRate=1G 500M + MaximumRate= + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // language="unit file (systemd)" + val file = """ + [FairQueueing] + MaximumRate=34359738368 + MaximumRate=35G + MaximumRate=1T + MaximumRate=10mbit + MaximumRate=-1M + MaximumRate=1M 2G + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(6, highlights) + } + +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseFqUsecOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseFqUsecOptionValueTest.kt new file mode 100644 index 00000000..818697c5 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseFqUsecOptionValueTest.kt @@ -0,0 +1,51 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.inspections.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest +import net.sjrx.intellij.plugins.systemdunitfiles.inspections.InvalidValueInspection +import org.junit.Test + +class ConfigParseFqUsecOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // Fixture values from systemd test/test-network/conf plus tricky spellings the C parser accepts. + // language="unit file (systemd)" + val file = """ + [FairQueueing] + CEThresholdSec=100ms + CEThresholdSec=1s + CEThresholdSec=4294967295us + CEThresholdSec=71min 34s + CEThresholdSec=1h 11min 34.967295s + CEThresholdSec=0 + CEThresholdSec= + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // language="unit file (systemd)" + val file = """ + [FairQueueing] + CEThresholdSec=4294967296us + CEThresholdSec=72min + CEThresholdSec=infinity + CEThresholdSec=1h 12min + CEThresholdSec=5x + CEThresholdSec=-1s + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(6, highlights) + } + +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseGredBoolOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseGredBoolOptionValueTest.kt new file mode 100644 index 00000000..0f81298a --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseGredBoolOptionValueTest.kt @@ -0,0 +1,64 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.inspections.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest +import net.sjrx.intellij.plugins.systemdunitfiles.inspections.InvalidValueInspection +import org.junit.Test + +class ConfigParseGredBoolOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // Fixture values from systemd test/test-network/conf plus tricky spellings the C parser accepts. + // language="unit file (systemd)" + val file = """ + [GenericRandomEarlyDetection] + GenericRIO=yes + GenericRIO=no + GenericRIO=1 + GenericRIO=0 + GenericRIO=true + GenericRIO=false + GenericRIO=on + GenericRIO=off + GenericRIO=y + GenericRIO=n + GenericRIO=t + GenericRIO=f + GenericRIO=YES + GenericRIO=False + GenericRIO=On + GenericRIO=Yes + GenericRIO=TRUE + GenericRIO=oFf + GenericRIO=Y + GenericRIO= + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // language="unit file (systemd)" + val file = """ + [GenericRandomEarlyDetection] + GenericRIO=maybe + GenericRIO=2 + GenericRIO=enable + GenericRIO=nope + GenericRIO=Maybe + GenericRIO=ENABLE + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(6, highlights) + } + +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseGredU32OptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseGredU32OptionValueTest.kt new file mode 100644 index 00000000..657eee48 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseGredU32OptionValueTest.kt @@ -0,0 +1,88 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.inspections.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest +import net.sjrx.intellij.plugins.systemdunitfiles.inspections.InvalidValueInspection +import org.junit.Test + +class ConfigParseGredU32OptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // Fixture values from systemd test/test-network/conf plus tricky spellings the C parser accepts. + // sd-check at 0f0682b773 accepts these: strtoul starts afresh after the 0b/0o prefix, so a sign or blank may follow it. + // language="unit file (systemd)" + val file = """ + [GenericRandomEarlyDetection] + VirtualQueues=12 + DefaultVirtualQueue=12 + VirtualQueues=10 + DefaultVirtualQueue=10 + VirtualQueues=0 + DefaultVirtualQueue=0 + VirtualQueues=16 + DefaultVirtualQueue=16 + VirtualQueues=0x10 + DefaultVirtualQueue=0x10 + VirtualQueues=0b1 + DefaultVirtualQueue=0b1 + VirtualQueues=020 + DefaultVirtualQueue=020 + VirtualQueues=+3 + DefaultVirtualQueue=+3 + VirtualQueues=0b+1 + DefaultVirtualQueue=0b+1 + VirtualQueues=0b-0 + DefaultVirtualQueue=0b-0 + VirtualQueues=0b 1 + DefaultVirtualQueue=0b 1 + VirtualQueues=0o 7 + DefaultVirtualQueue=0o 7 + VirtualQueues=0b +1 + DefaultVirtualQueue=0b +1 + VirtualQueues=0b -0 + DefaultVirtualQueue=0b -0 + VirtualQueues= + DefaultVirtualQueue= + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // sd-check at 0f0682b773 rejects these: 0b-1 and 0b -1 are -1 (ERANGE), -0b0 is -0 followed by junk (EINVAL). + // language="unit file (systemd)" + val file = """ + [GenericRandomEarlyDetection] + VirtualQueues=17 + DefaultVirtualQueue=17 + VirtualQueues=0x11 + DefaultVirtualQueue=0x11 + VirtualQueues=-1 + DefaultVirtualQueue=-1 + VirtualQueues=abc + DefaultVirtualQueue=abc + VirtualQueues=4294967296 + DefaultVirtualQueue=4294967296 + VirtualQueues=1.0 + DefaultVirtualQueue=1.0 + VirtualQueues=0b-1 + DefaultVirtualQueue=0b-1 + VirtualQueues=0b -1 + DefaultVirtualQueue=0b -1 + VirtualQueues=-0b0 + DefaultVirtualQueue=-0b0 + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(18, highlights) + } + +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseHtbClassRateOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseHtbClassRateOptionValueTest.kt new file mode 100644 index 00000000..a4f3475b --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseHtbClassRateOptionValueTest.kt @@ -0,0 +1,78 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.inspections.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest +import net.sjrx.intellij.plugins.systemdunitfiles.inspections.InvalidValueInspection +import org.junit.Test + +class ConfigParseHtbClassRateOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // Fixture values from systemd test/test-network/conf plus tricky spellings the C parser accepts. + // language="unit file (systemd)" + val file = """ + [HierarchyTokenBucketClass] + Rate=1M + CeilRate=1M + Rate=0.5M + CeilRate=0.5M + Rate=1G + CeilRate=1G + Rate=100G + CeilRate=100G + Rate=1G 500M + CeilRate=1G 500M + Rate=3.5G3B + CeilRate=3.5G3B + Rate=4T3G3B + CeilRate=4T3G3B + Rate=10.M + CeilRate=10.M + Rate=125000 + CeilRate=125000 + Rate=+5K + CeilRate=+5K + Rate=1000 B + CeilRate=1000 B + Rate= + CeilRate= + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // language="unit file (systemd)" + val file = """ + [HierarchyTokenBucketClass] + Rate=10Mbit + CeilRate=10Mbit + Rate=1k + CeilRate=1k + Rate=-1M + CeilRate=-1M + Rate=3B3.5G + CeilRate=3B3.5G + Rate=12P12P + CeilRate=12P12P + Rate=1M 1M + CeilRate=1M 1M + Rate=abc + CeilRate=abc + Rate=.5M + CeilRate=.5M + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(16, highlights) + } + +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseHtbClassU32OptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseHtbClassU32OptionValueTest.kt new file mode 100644 index 00000000..6401d690 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseHtbClassU32OptionValueTest.kt @@ -0,0 +1,68 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.inspections.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest +import net.sjrx.intellij.plugins.systemdunitfiles.inspections.InvalidValueInspection +import org.junit.Test + +class ConfigParseHtbClassU32OptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // Fixture values from systemd test/test-network/conf plus tricky spellings the C parser accepts. + // sd-check at 0f0682b773 accepts these: strtoul starts afresh after the 0b/0o prefix, so a sign or blank may follow it. + // language="unit file (systemd)" + val file = """ + [HierarchyTokenBucketClass] + Priority=0 + Priority=1 + Priority=20480 + Priority=4294967295 + Priority=0x10 + Priority=0o17 + Priority=0b101 + Priority=017 + Priority=+5 + Priority=-0 + Priority=0b+1 + Priority=0b-0 + Priority=0b 1 + Priority=0o 7 + Priority=0b +1 + Priority=0b -0 + Priority= + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // sd-check at 0f0682b773 rejects these: 0b-1 and 0b -1 are -1 (ERANGE), -0b0 is -0 followed by junk (EINVAL). + // language="unit file (systemd)" + val file = """ + [HierarchyTokenBucketClass] + Priority=4294967296 + Priority=-1 + Priority=08 + Priority=0x + Priority=1.5 + Priority=abc + Priority=+0b1 + Priority=12 13 + Priority=0b-1 + Priority=0b -1 + Priority=-0b0 + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(11, highlights) + } + +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseHtbDefaultClassOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseHtbDefaultClassOptionValueTest.kt new file mode 100644 index 00000000..c97135b9 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseHtbDefaultClassOptionValueTest.kt @@ -0,0 +1,55 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.inspections.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest +import net.sjrx.intellij.plugins.systemdunitfiles.inspections.InvalidValueInspection +import org.junit.Test + +class ConfigParseHtbDefaultClassOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // Fixture values from systemd test/test-network/conf plus tricky spellings the C parser accepts. + // language="unit file (systemd)" + val file = """ + [HierarchyTokenBucket] + DefaultClass=30 + DefaultClass=0x30 + DefaultClass=ff + DefaultClass=FFFF + DefaultClass=ffffffff + DefaultClass=0 + DefaultClass=+a + DefaultClass=0b1 + DefaultClass= + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // language="unit file (systemd)" + val file = """ + [HierarchyTokenBucket] + DefaultClass=100000000 + DefaultClass=0x100000000 + DefaultClass=0o7 + DefaultClass=g + DefaultClass=-1 + DefaultClass=1 2 + DefaultClass=0b 1 + DefaultClass=0x 1 + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(8, highlights) + } + +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseHtbU32OptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseHtbU32OptionValueTest.kt new file mode 100644 index 00000000..a09ee769 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseHtbU32OptionValueTest.kt @@ -0,0 +1,68 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.inspections.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest +import net.sjrx.intellij.plugins.systemdunitfiles.inspections.InvalidValueInspection +import org.junit.Test + +class ConfigParseHtbU32OptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // Fixture values from systemd test/test-network/conf plus tricky spellings the C parser accepts. + // sd-check at 0f0682b773 accepts these: strtoul starts afresh after the 0b/0o prefix, so a sign or blank may follow it. + // language="unit file (systemd)" + val file = """ + [HierarchyTokenBucket] + RateToQuantum=0 + RateToQuantum=1 + RateToQuantum=20480 + RateToQuantum=4294967295 + RateToQuantum=0x10 + RateToQuantum=0o17 + RateToQuantum=0b101 + RateToQuantum=017 + RateToQuantum=+5 + RateToQuantum=-0 + RateToQuantum=0b+1 + RateToQuantum=0b-0 + RateToQuantum=0b 1 + RateToQuantum=0o 7 + RateToQuantum=0b +1 + RateToQuantum=0b -0 + RateToQuantum= + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // sd-check at 0f0682b773 rejects these: 0b-1 and 0b -1 are -1 (ERANGE), -0b0 is -0 followed by junk (EINVAL). + // language="unit file (systemd)" + val file = """ + [HierarchyTokenBucket] + RateToQuantum=4294967296 + RateToQuantum=-1 + RateToQuantum=08 + RateToQuantum=0x + RateToQuantum=1.5 + RateToQuantum=abc + RateToQuantum=+0b1 + RateToQuantum=12 13 + RateToQuantum=0b-1 + RateToQuantum=0b -1 + RateToQuantum=-0b0 + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(11, highlights) + } + +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseNetemDelayOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseNetemDelayOptionValueTest.kt new file mode 100644 index 00000000..b9573441 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseNetemDelayOptionValueTest.kt @@ -0,0 +1,100 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.inspections.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest +import net.sjrx.intellij.plugins.systemdunitfiles.inspections.InvalidValueInspection +import org.junit.Test + +class ConfigParseNetemDelayOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // Fixture values from systemd test/test-network/conf plus tricky spellings the C parser accepts. + // language="unit file (systemd)" + val file = """ + [NetworkEmulator] + DelaySec=10ms + DelayJitterSec=10ms + DelaySec=200ms + DelayJitterSec=200ms + DelaySec=1min30s + DelayJitterSec=1min30s + DelaySec=5s 500ms + DelayJitterSec=5s 500ms + DelaySec=5s500ms + DelayJitterSec=5s500ms + DelaySec=.5s + DelayJitterSec=.5s + DelaySec=+3.1s + DelayJitterSec=+3.1s + DelaySec=3.1s.2 + DelayJitterSec=3.1s.2 + DelaySec=3.1 .2 + DelayJitterSec=3.1 .2 + DelaySec=1.5h + DelayJitterSec=1.5h + DelaySec=23us + DelayJitterSec=23us + DelaySec=23µs + DelayJitterSec=23µs + DelaySec=2 weeks + DelayJitterSec=2 weeks + DelaySec=100 + DelayJitterSec=100 + # Largest finite values parse_time() accepts (total < USEC_INFINITY, each integer <= LLONG_MAX). + DelaySec=9223372036854775807us 9223372036854775807us + DelayJitterSec=9223372036854775807us 9223372036854775807us + DelaySec=18446744073708s + DelayJitterSec=18446744073708s + DelaySec=infinity + DelayJitterSec=infinity + DelaySec= + DelayJitterSec= + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // language="unit file (systemd)" + val file = """ + [NetworkEmulator] + DelaySec=5. + DelayJitterSec=5. + DelaySec=-5s + DelayJitterSec=-5s + DelaySec=3.s + DelayJitterSec=3.s + DelaySec=12.34.56 + DelayJitterSec=12.34.56 + DelaySec=5mins + DelayJitterSec=5mins + DelaySec=10 foo + DelayJitterSec=10 foo + DelaySec=infinity 5s + DelayJitterSec=infinity 5s + DelaySec=Infinity + DelayJitterSec=Infinity + # parse_time() ERANGE: integer above LLONG_MAX, or total reaching USEC_INFINITY. + DelaySec=9223372036854775808us + DelayJitterSec=9223372036854775808us + DelaySec=18446744073709551615us + DelayJitterSec=18446744073709551615us + DelaySec=9223372036854775807us 9223372036854775807us 1us + DelayJitterSec=9223372036854775807us 9223372036854775807us 1us + DelaySec=18446744073709s + DelayJitterSec=18446744073709s + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(24, highlights) + } + +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseNetemRateOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseNetemRateOptionValueTest.kt new file mode 100644 index 00000000..5a4ca6ee --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseNetemRateOptionValueTest.kt @@ -0,0 +1,94 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.inspections.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest +import net.sjrx.intellij.plugins.systemdunitfiles.inspections.InvalidValueInspection +import org.junit.Test + +class ConfigParseNetemRateOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // Fixture values from systemd test/test-network/conf plus tricky spellings the C parser accepts. + // sd-check at 0f0682b773 accepts the 0b/0o spellings: the integer part goes through safe_atoi(). + // language="unit file (systemd)" + val file = """ + [NetworkEmulator] + LossRate=20% + DuplicateRate=20% + LossRate=0% + DuplicateRate=0% + LossRate=100% + DuplicateRate=100% + LossRate=55.5% + DuplicateRate=55.5% + LossRate=55.53% + DuplicateRate=55.53% + LossRate=555.5‰ + DuplicateRate=555.5‰ + LossRate=1000‰ + DuplicateRate=1000‰ + LossRate=1000‱ + DuplicateRate=1000‱ + LossRate=0x10% + DuplicateRate=0x10% + LossRate=0b 1% + DuplicateRate=0b 1% + LossRate=0b+1% + DuplicateRate=0b+1% + LossRate=0b-0% + DuplicateRate=0b-0% + LossRate=-0% + DuplicateRate=-0% + LossRate=0b 1.5% + DuplicateRate=0b 1.5% + LossRate=0o 7‰ + DuplicateRate=0o 7‰ + LossRate= + DuplicateRate= + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // sd-check at 0f0682b773 rejects 0b-1% and 0b -1% (the integer part is -1: ERANGE). + // language="unit file (systemd)" + val file = """ + [NetworkEmulator] + LossRate=20 + DuplicateRate=20 + LossRate=107% + DuplicateRate=107% + LossRate=-7% + DuplicateRate=-7% + LossRate=3.212% + DuplicateRate=3.212% + LossRate=3.22‰ + DuplicateRate=3.22‰ + LossRate=3.2‱ + DuplicateRate=3.2‱ + LossRate=abc% + DuplicateRate=abc% + LossRate=% + DuplicateRate=% + LossRate=20 % + DuplicateRate=20 % + LossRate=0b-1% + DuplicateRate=0b-1% + LossRate=0b -1% + DuplicateRate=0b -1% + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(22, highlights) + } + +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParsePiePacketLimitOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParsePiePacketLimitOptionValueTest.kt new file mode 100644 index 00000000..298306d2 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParsePiePacketLimitOptionValueTest.kt @@ -0,0 +1,68 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.inspections.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest +import net.sjrx.intellij.plugins.systemdunitfiles.inspections.InvalidValueInspection +import org.junit.Test + +class ConfigParsePiePacketLimitOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // Fixture values from systemd test/test-network/conf plus tricky spellings the C parser accepts. + // sd-check at 0f0682b773 accepts these: strtoul starts afresh after the 0b/0o prefix, so a sign or blank may follow it. + // language="unit file (systemd)" + val file = """ + [PIE] + PacketLimit=0 + PacketLimit=1 + PacketLimit=20480 + PacketLimit=4294967295 + PacketLimit=0x10 + PacketLimit=0o17 + PacketLimit=0b101 + PacketLimit=017 + PacketLimit=+5 + PacketLimit=-0 + PacketLimit=0b+1 + PacketLimit=0b-0 + PacketLimit=0b 1 + PacketLimit=0o 7 + PacketLimit=0b +1 + PacketLimit=0b -0 + PacketLimit= + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // sd-check at 0f0682b773 rejects these: 0b-1 and 0b -1 are -1 (ERANGE), -0b0 is -0 followed by junk (EINVAL). + // language="unit file (systemd)" + val file = """ + [PIE] + PacketLimit=4294967296 + PacketLimit=-1 + PacketLimit=08 + PacketLimit=0x + PacketLimit=1.5 + PacketLimit=abc + PacketLimit=+0b1 + PacketLimit=12 13 + PacketLimit=0b-1 + PacketLimit=0b -1 + PacketLimit=-0b0 + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(11, highlights) + } + +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseQfqMaxPacketOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseQfqMaxPacketOptionValueTest.kt new file mode 100644 index 00000000..5fd5c2b8 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseQfqMaxPacketOptionValueTest.kt @@ -0,0 +1,55 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.inspections.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest +import net.sjrx.intellij.plugins.systemdunitfiles.inspections.InvalidValueInspection +import org.junit.Test + +class ConfigParseQfqMaxPacketOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // Fixture values from systemd test/test-network/conf plus tricky spellings the C parser accepts. + // language="unit file (systemd)" + val file = """ + [QuickFairQueueingClass] + MaxPacketBytes=512 + MaxPacketBytes=16000 + MaxPacketBytes=8000 + MaxPacketBytes=65536 + MaxPacketBytes=64K + MaxPacketBytes=1K + MaxPacketBytes=0.5K + MaxPacketBytes=1K 512B + MaxPacketBytes=63K1023B + MaxPacketBytes= + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // language="unit file (systemd)" + val file = """ + [QuickFairQueueingClass] + MaxPacketBytes=511 + MaxPacketBytes=65537 + MaxPacketBytes=65K + MaxPacketBytes=1M + MaxPacketBytes=0 + MaxPacketBytes=16000b + MaxPacketBytes=abc + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(7, highlights) + } + +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseTbfRateOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseTbfRateOptionValueTest.kt new file mode 100644 index 00000000..59fd41fd --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseTbfRateOptionValueTest.kt @@ -0,0 +1,78 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.inspections.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest +import net.sjrx.intellij.plugins.systemdunitfiles.inspections.InvalidValueInspection +import org.junit.Test + +class ConfigParseTbfRateOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // Fixture values from systemd test/test-network/conf plus tricky spellings the C parser accepts. + // language="unit file (systemd)" + val file = """ + [TokenBucketFilter] + Rate=1M + PeakRate=1M + Rate=0.5M + PeakRate=0.5M + Rate=1G + PeakRate=1G + Rate=100G + PeakRate=100G + Rate=1G 500M + PeakRate=1G 500M + Rate=3.5G3B + PeakRate=3.5G3B + Rate=4T3G3B + PeakRate=4T3G3B + Rate=10.M + PeakRate=10.M + Rate=125000 + PeakRate=125000 + Rate=+5K + PeakRate=+5K + Rate=1000 B + PeakRate=1000 B + Rate= + PeakRate= + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // language="unit file (systemd)" + val file = """ + [TokenBucketFilter] + Rate=10Mbit + PeakRate=10Mbit + Rate=1k + PeakRate=1k + Rate=-1M + PeakRate=-1M + Rate=3B3.5G + PeakRate=3B3.5G + Rate=12P12P + PeakRate=12P12P + Rate=1M 1M + PeakRate=1M 1M + Rate=abc + PeakRate=abc + Rate=.5M + PeakRate=.5M + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(16, highlights) + } + +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseTeqlIdOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseTeqlIdOptionValueTest.kt new file mode 100644 index 00000000..55c99220 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseTeqlIdOptionValueTest.kt @@ -0,0 +1,60 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.inspections.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest +import net.sjrx.intellij.plugins.systemdunitfiles.inspections.InvalidValueInspection +import org.junit.Test + +class ConfigParseTeqlIdOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // Fixture values from systemd test/test-network/conf plus tricky spellings the C parser accepts. + // sd-check at 0f0682b773 accepts these: strtoul starts afresh after the 0b/0o prefix, so a sign or blank may follow it. + // language="unit file (systemd)" + val file = """ + [TrivialLinkEqualizer] + Id=0 + Id=1 + Id=2147483647 + Id=0x7fffffff + Id=0o7 + Id=0b+1 + Id=0b-0 + Id=0b 1 + Id=0o 7 + Id=0b +1 + Id=0b -0 + Id= + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // sd-check at 0f0682b773 rejects these: 0b-1 and 0b -1 are -1 (ERANGE), -0b0 is -0 followed by junk (EINVAL). + // language="unit file (systemd)" + val file = """ + [TrivialLinkEqualizer] + Id=2147483648 + Id=4294967295 + Id=-1 + Id=abc + Id=teql1 + Id=0b-1 + Id=0b -1 + Id=-0b0 + """.trimIndent() + + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(8, highlights) + } + +}