From 59d162bef863369e127aa99063690dc408bca8de Mon Sep 17 00:00:00 2001 From: Steve Ramage Date: Sat, 23 May 2026 11:19:23 -0700 Subject: [PATCH] feat: add 6 validators - exec_input, exec_memory_thp, exec_cpu_affinity, syscall_archs, colon_separated_paths, user_group_strv_compat (Resolves #452) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Batch 5/5 — final batch of the burn-down extension. Each grammar mirrors the systemd C parser: - config_parse_exec_input: fd:NAME | file:/PATH | enum from exec_input_table - config_parse_exec_memory_thp: inherit/disable/madvise/system enum - config_parse_exec_cpu_affinity: "numa" OR CPU set list (integers and N-M ranges, whitespace or comma separated) - config_parse_syscall_archs: list of arch names from seccomp_arch_from_string (~22 entries, includes loongarch64/riscv64 unconditionally) - config_parse_colon_separated_paths: colon-separated absolute paths (specifier-aware) - config_parse_user_group_strv_compat: relaxed user/group names, no colon/slash/whitespace, not "."/"..", specifier-aware OptionValueTest missing-function count drops 376 -> 370; found-key count rises 1870 -> 1900. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../semanticdata/optionvalues/AiGenerated.kt | 6 +++ ...nfigParseColonSeparatedPathsOptionValue.kt | 28 +++++++++++ .../ConfigParseExecCpuAffinityOptionValue.kt | 38 ++++++++++++++ .../ai/ConfigParseExecInputOptionValue.kt | 32 ++++++++++++ .../ai/ConfigParseExecMemoryThpOptionValue.kt | 19 +++++++ .../ai/ConfigParseSyscallArchsOptionValue.kt | 35 +++++++++++++ ...nfigParseUserGroupStrvCompatOptionValue.kt | 39 +++++++++++++++ ...ParseColonSeparatedPathsOptionValueTest.kt | 43 ++++++++++++++++ ...nfigParseExecCpuAffinityOptionValueTest.kt | 46 +++++++++++++++++ .../ai/ConfigParseExecInputOptionValueTest.kt | 50 +++++++++++++++++++ ...ConfigParseExecMemoryThpOptionValueTest.kt | 43 ++++++++++++++++ .../ConfigParseSyscallArchsOptionValueTest.kt | 46 +++++++++++++++++ ...ParseUserGroupStrvCompatOptionValueTest.kt | 48 ++++++++++++++++++ 13 files changed, 473 insertions(+) create mode 100644 src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseColonSeparatedPathsOptionValue.kt create mode 100644 src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseExecCpuAffinityOptionValue.kt create mode 100644 src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseExecInputOptionValue.kt create mode 100644 src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseExecMemoryThpOptionValue.kt create mode 100644 src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseSyscallArchsOptionValue.kt create mode 100644 src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseUserGroupStrvCompatOptionValue.kt create mode 100644 src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseColonSeparatedPathsOptionValueTest.kt create mode 100644 src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseExecCpuAffinityOptionValueTest.kt create mode 100644 src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseExecInputOptionValueTest.kt create mode 100644 src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseExecMemoryThpOptionValueTest.kt create mode 100644 src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseSyscallArchsOptionValueTest.kt create mode 100644 src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseUserGroupStrvCompatOptionValueTest.kt 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 e2ed319..c2cc5b9 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 @@ -56,6 +56,7 @@ fun getAllAIGeneratedValidators(): Map { Validator("config_parse_codel_bool", "QDISC_KIND_CODEL") to ConfigParseCodelBoolOptionValue() as OptionValueInformation, Validator("config_parse_codel_u32", "QDISC_KIND_CODEL") to ConfigParseCodelU32OptionValue() as OptionValueInformation, Validator("config_parse_collect_mode", "0") to ConfigParseCollectModeOptionValue() as OptionValueInformation, + Validator("config_parse_colon_separated_paths", "0") to ConfigParseColonSeparatedPathsOptionValue() as OptionValueInformation, Validator("config_parse_cpu_quota", "0") to ConfigParseCpuQuotaOptionValue() as OptionValueInformation, Validator("config_parse_cpuset_partition", "0") to ConfigParseCpusetPartitionOptionValue() as OptionValueInformation, Validator("config_parse_delegate", "0") to ConfigParseDelegateOptionValue() as OptionValueInformation, @@ -80,9 +81,12 @@ fun getAllAIGeneratedValidators(): Map { Validator("config_parse_erspan_index", "0") to ConfigParseErspanIndexOptionValue() as OptionValueInformation, Validator("config_parse_erspan_version", "0") to ConfigParseErspanVersionOptionValue() as OptionValueInformation, Validator("config_parse_ets_u8", "QDISC_KIND_ETS") to ConfigParseEtsU8OptionValue() as OptionValueInformation, + Validator("config_parse_exec_cpu_affinity", "0") to ConfigParseExecCpuAffinityOptionValue() as OptionValueInformation, Validator("config_parse_exec_cpu_sched_prio", "0") to ConfigParseExecCpuSchedPrioOptionValue() as OptionValueInformation, + Validator("config_parse_exec_input", "0") to ConfigParseExecInputOptionValue() as OptionValueInformation, Validator("config_parse_exec_input_text", "0") to ConfigParseExecInputTextOptionValue() as OptionValueInformation, Validator("config_parse_exec_io_priority", "0") to ConfigParseExecIoPriorityOptionValue() as OptionValueInformation, + Validator("config_parse_exec_memory_thp", "0") to ConfigParseExecMemoryThpOptionValue() as OptionValueInformation, Validator("config_parse_exec_mount_propagation_flag", "0") to ConfigParseExecMountPropagationFlagOptionValue() as OptionValueInformation, Validator("config_parse_exec_nice", "0") to ConfigParseExecNiceOptionValue() as OptionValueInformation, Validator("config_parse_exec_oom_score_adjust", "0") to ConfigParseExecOomScoreAdjustOptionValue() as OptionValueInformation, @@ -189,6 +193,7 @@ fun getAllAIGeneratedValidators(): Map { Validator("config_parse_sr_iov_uint32", "0") to ConfigParseSrIovUint32OptionValue() as OptionValueInformation, Validator("config_parse_sr_iov_vlan_proto", "0") to ConfigParseSrIovVlanProtoOptionValue() as OptionValueInformation, Validator("config_parse_swap_priority", "0") to ConfigParseSwapPriorityOptionValue() as OptionValueInformation, + Validator("config_parse_syscall_archs", "0") to ConfigParseSyscallArchsOptionValue() as OptionValueInformation, Validator("config_parse_syscall_errno", "0") to ConfigParseSyscallErrnoOptionValue() as OptionValueInformation, Validator("config_parse_tasks_max", "0") to ConfigParseTasksMaxOptionValue() as OptionValueInformation, Validator("config_parse_tbf_size", "QDISC_KIND_TBF") to ConfigParseTbfSizeOptionValue() as OptionValueInformation, @@ -205,6 +210,7 @@ fun getAllAIGeneratedValidators(): Map { Validator("config_parse_unit_mounts_for", "0") to ConfigParseUnitMountsForOptionValue() as OptionValueInformation, Validator("config_parse_unit_slice", "0") to ConfigParseUnitSliceOptionValue() as OptionValueInformation, Validator("config_parse_use_domains", "0") to ConfigParseUseDomainsOptionValue() as OptionValueInformation, + Validator("config_parse_user_group_strv_compat", "0") to ConfigParseUserGroupStrvCompatOptionValue() as OptionValueInformation, Validator("config_parse_userns_chown", "0") to ConfigParseUsernsChownOptionValue() as OptionValueInformation, Validator("config_parse_userns_ownership", "0") to ConfigParseUsernsOwnershipOptionValue() as OptionValueInformation, Validator("config_parse_vlanid", "0") to ConfigParseVlanidOptionValue() as OptionValueInformation, diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseColonSeparatedPathsOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseColonSeparatedPathsOptionValue.kt new file mode 100644 index 0000000..6df91f9 --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseColonSeparatedPathsOptionValue.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.* + +/** + * Validator for ExecSearchPath= (and similar colon-separated path lists). + * + * C function: config_parse_colon_separated_paths in src/core/load-fragment.c. Tokenizes with + * extract_first_word using ":" as the separator (no coalescing), expands specifiers via + * unit_path_printf, then requires each path to be absolute via path_simplify_and_warn with + * PATH_CHECK_ABSOLUTE. + * + * Grammar matches one or more absolute paths (each starting with "/") separated by ":". + * Per-path content excludes ":" since that's the separator. "%X" specifiers are allowed + * inline since the C parser expands them before the absolute-path check. + */ +class ConfigParseColonSeparatedPathsOptionValue : SimpleGrammarOptionValues( + "config_parse_colon_separated_paths", + SequenceCombinator( + RegexTerminal("/[^\\s:]*", "/[^\\s:]*"), + ZeroOrMore(SequenceCombinator( + LiteralChoiceTerminal(":"), + RegexTerminal("/[^\\s:]*", "/[^\\s:]*") + )), + EOF() + ) +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseExecCpuAffinityOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseExecCpuAffinityOptionValue.kt new file mode 100644 index 0000000..118f3bd --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseExecCpuAffinityOptionValue.kt @@ -0,0 +1,38 @@ +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.* + +/** + * Validator for CPUAffinity=. + * + * C function: config_parse_exec_cpu_affinity in src/core/load-fragment.c. Either the literal + * "numa" (use NUMA-derived CPU set) or a CPU set list parsed by the same code path as + * NUMAMask= / AllowedCPUs=: whitespace- or comma-separated integers and `N-M` ranges. + * + * The "numa" literal goes first explicitly; otherwise the CPU set grammar matches integers + * and ranges. Note the existing AllowedCpuSetOptionValue handles the same syntax for + * config_parse_unit_cpu_set — duplicated here as a grammar so it composes with the "numa" + * alternative. + */ +class ConfigParseExecCpuAffinityOptionValue : SimpleGrammarOptionValues( + "config_parse_exec_cpu_affinity", + SequenceCombinator( + AlternativeCombinator( + LiteralChoiceTerminal("numa"), + SequenceCombinator( + CPU_RANGE, + ZeroOrMore(SequenceCombinator( + AlternativeCombinator(WhitespaceTerminal(), LiteralChoiceTerminal(",")), + CPU_RANGE + )) + ) + ), + EOF() + ) +) { + companion object { + // `N` or `N-M` (each side a non-negative integer) + private val CPU_RANGE = RegexTerminal("[0-9]+(-[0-9]+)?", "[0-9]+(-[0-9]+)?") + } +} diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseExecInputOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseExecInputOptionValue.kt new file mode 100644 index 0000000..6be9a61 --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseExecInputOptionValue.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.* + +/** + * Validator for StandardInput=. + * + * C function: config_parse_exec_input in src/core/load-fragment.c. Accepts: + * - "fd:NAME" — fdname_is_valid name (alphanumerics-ish, specifier-aware) + * - "file:/PATH" — absolute path (specifier-aware) + * - one of the bare enum names from exec_input_table in src/core/execute.c: + * null, tty, tty-force, tty-fail, socket, data + * (fd / file appear as prefixes above; their bare form isn't accepted) + * + * The structured branches (fd:/file:) come before the enum so that a literal "fd"/"file" + * (which aren't in the enum table anyway) wouldn't accidentally match. Order also matters + * because LiteralChoiceTerminal does first-match-by-length. + */ +class ConfigParseExecInputOptionValue : SimpleGrammarOptionValues( + "config_parse_exec_input", + SequenceCombinator( + AlternativeCombinator( + // fd:NAME (NAME is allowed to be empty per the C code's isempty check) + SequenceCombinator(LiteralChoiceTerminal("fd:"), RegexTerminal("\\S*", "\\S*")), + // file:/PATH + SequenceCombinator(LiteralChoiceTerminal("file:"), RegexTerminal("/\\S*", "/\\S*")), + LiteralChoiceTerminal("null", "tty", "tty-force", "tty-fail", "socket", "data") + ), + EOF() + ) +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseExecMemoryThpOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseExecMemoryThpOptionValue.kt new file mode 100644 index 0000000..8e8c296 --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseExecMemoryThpOptionValue.kt @@ -0,0 +1,19 @@ +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.* + +/** + * Validator for MemoryTHP=. + * + * C function: config_parse_exec_memory_thp, expanded via DEFINE_CONFIG_PARSE_ENUM in + * src/core/load-fragment.c. Accepts exactly the entries of exec_memory_thp_table in + * src/core/execute.c. + */ +class ConfigParseExecMemoryThpOptionValue : SimpleGrammarOptionValues( + "config_parse_exec_memory_thp", + SequenceCombinator( + LiteralChoiceTerminal("inherit", "disable", "madvise", "system"), + EOF() + ) +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseSyscallArchsOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseSyscallArchsOptionValue.kt new file mode 100644 index 0000000..f382078 --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseSyscallArchsOptionValue.kt @@ -0,0 +1,35 @@ +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.* + +/** + * Validator for SystemCallArchitectures=. + * + * C function: config_parse_syscall_archs in src/core/load-fragment.c → seccomp_arch_from_string + * in src/shared/seccomp-util.c. Whitespace-separated list of architecture names — the table + * below mirrors the streq checks in the C source, including arches gated by libseccomp build + * options (loongarch64, riscv64): they're always accepted by the validator since users won't + * know which seccomp build the host has, and the runtime check is what's authoritative anyway. + */ +class ConfigParseSyscallArchsOptionValue : SimpleGrammarOptionValues( + "config_parse_syscall_archs", + SequenceCombinator( + ARCH, + ZeroOrMore(SequenceCombinator(WhitespaceTerminal(), ARCH)), + EOF() + ) +) { + companion object { + private val ARCH = LiteralChoiceTerminal( + "native", "x86", "x86-64", "x32", + "arm", "arm64", + "loongarch64", + "mips", "mips64", "mips64-n32", "mips-le", "mips64-le", "mips64-le-n32", + "parisc", "parisc64", + "ppc", "ppc64", "ppc64-le", + "riscv64", + "s390", "s390x" + ) + } +} diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseUserGroupStrvCompatOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseUserGroupStrvCompatOptionValue.kt new file mode 100644 index 0000000..37acc4b --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseUserGroupStrvCompatOptionValue.kt @@ -0,0 +1,39 @@ +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.* + +/** + * Validator for SupplementaryGroups= (and any other key parsed by config_parse_user_group_strv_compat). + * + * C function: config_parse_user_group_strv_compat in src/core/load-fragment.c → valid_user_group_name + * with VALID_USER_ALLOW_NUMERIC | VALID_USER_RELAX | VALID_USER_WARN. The relaxed mode accepts a wide + * range of user/group names because real-world auth stacks (SSSD, Samba, …) are permissive. Per + * src/basic/user-util.c the constraints are: + * - non-empty + * - no leading/trailing whitespace + * - no colons (/etc/passwd field separator), no slashes + * - no control characters + * - not fully numeric (UID is allowed via numeric parse, but mixed numeric+text isn't) + * - not "." / ".." + * + * Pre-expansion, words may also contain "%X" specifiers (unit_full_printf expands before the + * validity check), so the grammar tolerates "%" inline. + */ +class ConfigParseUserGroupStrvCompatOptionValue : SimpleGrammarOptionValues( + "config_parse_user_group_strv_compat", + SequenceCombinator( + NAME, + ZeroOrMore(SequenceCombinator(WhitespaceTerminal(), NAME)), + EOF() + ) +) { + companion object { + // No colon, slash, whitespace, or shell metacharacters. Length unbounded in relaxed mode. + // Negative lookahead excludes "." and ".." as literal entries. + private val NAME = RegexTerminal( + "(?!\\.{1,2}\\Z)[^\\s:/]+", + "(?!\\.{1,2}\\Z)[^\\s:/]+" + ) + } +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseColonSeparatedPathsOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseColonSeparatedPathsOptionValueTest.kt new file mode 100644 index 0000000..086d745 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseColonSeparatedPathsOptionValueTest.kt @@ -0,0 +1,43 @@ +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 ConfigParseColonSeparatedPathsOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // language="unit file (systemd)" + val file = """ + [Service] + ExecSearchPath=/usr/local/bin + ExecSearchPath=/usr/local/bin:/usr/bin + ExecSearchPath=/opt/app/bin:/usr/local/bin:/usr/bin:/bin + ExecSearchPath=/var/lib/%n + """.trimIndent() + + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // language="unit file (systemd)" + val file = """ + [Service] + ExecSearchPath=relative/bin + ExecSearchPath=/usr/bin relative/bin + ExecSearchPath=/usr/bin:relative/bin + """.trimIndent() + + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(3, highlights) + } +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseExecCpuAffinityOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseExecCpuAffinityOptionValueTest.kt new file mode 100644 index 0000000..b66a8c9 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseExecCpuAffinityOptionValueTest.kt @@ -0,0 +1,46 @@ +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 ConfigParseExecCpuAffinityOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // language="unit file (systemd)" + val file = """ + [Service] + CPUAffinity=numa + CPUAffinity=0 + CPUAffinity=0-3 + CPUAffinity=0,2,4 + CPUAffinity=0-3 5 + CPUAffinity=0-3,5,8-11 + """.trimIndent() + + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // language="unit file (systemd)" + val file = """ + [Service] + CPUAffinity=all + CPUAffinity=numa 0 + CPUAffinity=-1 + CPUAffinity=0- + """.trimIndent() + + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(4, highlights) + } +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseExecInputOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseExecInputOptionValueTest.kt new file mode 100644 index 0000000..191ffb4 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseExecInputOptionValueTest.kt @@ -0,0 +1,50 @@ +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 ConfigParseExecInputOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // language="unit file (systemd)" + val file = """ + [Service] + StandardInput=null + StandardInput=tty + StandardInput=tty-force + StandardInput=tty-fail + StandardInput=socket + StandardInput=data + StandardInput=fd:stdin + StandardInput=fd: + StandardInput=file:/var/log/input.log + StandardInput=file:/dev/null + """.trimIndent() + + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // language="unit file (systemd)" + val file = """ + [Service] + StandardInput=stdin + StandardInput=file:relative/path + StandardInput=file: + StandardInput=FD:stdin + """.trimIndent() + + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(4, highlights) + } +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseExecMemoryThpOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseExecMemoryThpOptionValueTest.kt new file mode 100644 index 0000000..f0298d8 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseExecMemoryThpOptionValueTest.kt @@ -0,0 +1,43 @@ +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 ConfigParseExecMemoryThpOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // language="unit file (systemd)" + val file = """ + [Service] + MemoryTHP=inherit + MemoryTHP=disable + MemoryTHP=madvise + MemoryTHP=system + """.trimIndent() + + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // language="unit file (systemd)" + val file = """ + [Service] + MemoryTHP=never + MemoryTHP=always + MemoryTHP=Disable + """.trimIndent() + + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(3, highlights) + } +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseSyscallArchsOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseSyscallArchsOptionValueTest.kt new file mode 100644 index 0000000..69c6ce4 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseSyscallArchsOptionValueTest.kt @@ -0,0 +1,46 @@ +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 ConfigParseSyscallArchsOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // language="unit file (systemd)" + val file = """ + [Service] + SystemCallArchitectures=native + SystemCallArchitectures=x86-64 + SystemCallArchitectures=native x86 x86-64 + SystemCallArchitectures=arm arm64 + SystemCallArchitectures=mips64-le-n32 + SystemCallArchitectures=ppc64-le riscv64 s390x + """.trimIndent() + + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // language="unit file (systemd)" + val file = """ + [Service] + SystemCallArchitectures=amd64 + SystemCallArchitectures=x86_64 + SystemCallArchitectures=aarch64 + SystemCallArchitectures=native,x86 + """.trimIndent() + + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(4, highlights) + } +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseUserGroupStrvCompatOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseUserGroupStrvCompatOptionValueTest.kt new file mode 100644 index 0000000..0cdd9af --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseUserGroupStrvCompatOptionValueTest.kt @@ -0,0 +1,48 @@ +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 ConfigParseUserGroupStrvCompatOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // language="unit file (systemd)" + val file = """ + [Service] + SupplementaryGroups=wheel + SupplementaryGroups=wheel adm + SupplementaryGroups=users + SupplementaryGroups=1000 + SupplementaryGroups=group-with-dash + SupplementaryGroups=group_with_underscore + SupplementaryGroups=%n + SupplementaryGroups=app-%i wheel + """.trimIndent() + + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // language="unit file (systemd)" + val file = """ + [Service] + SupplementaryGroups=. + SupplementaryGroups=.. + SupplementaryGroups=group/with/slash + SupplementaryGroups=group:with:colon + """.trimIndent() + + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(4, highlights) + } +}