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 6f5b38d..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 @@ -12,6 +12,7 @@ fun getAllAIGeneratedValidators(): Map { Validator("config_parse_6rd_prefix", "0") to ConfigParse6rdPrefixOptionValue() as OptionValueInformation, Validator("config_parse_ad_actor_sys_prio", "0") to ConfigParseAdActorSysPrioOptionValue() as OptionValueInformation, Validator("config_parse_ad_user_port_key", "0") to ConfigParseAdUserPortKeyOptionValue() as OptionValueInformation, + Validator("config_parse_address_families", "0") to ConfigParseAddressFamiliesOptionValue() as OptionValueInformation, Validator("config_parse_address_section", "ADDRESS_ADD_PREFIX_ROUTE") to ConfigParseAddressSectionOptionValue() as OptionValueInformation, Validator("config_parse_address_section", "ADDRESS_AUTO_JOIN") to ConfigParseAddressSectionOptionValue() as OptionValueInformation, Validator("config_parse_address_section", "ADDRESS_DAD") to ConfigParseAddressSectionOptionValue() as OptionValueInformation, @@ -24,6 +25,7 @@ fun getAllAIGeneratedValidators(): Map { Validator("config_parse_bare_udp_iftype", "0") to ConfigParseBareUdpIftypeOptionValue() as OptionValueInformation, Validator("config_parse_batadv_gateway_mode", "0") to ConfigParseBatadvGatewayModeOptionValue() as OptionValueInformation, Validator("config_parse_batadv_routing_algorithm", "0") to ConfigParseBatadvRoutingAlgorithmOptionValue() as OptionValueInformation, + Validator("config_parse_bind_network_interface", "0") to ConfigParseBindNetworkInterfaceOptionValue() as OptionValueInformation, Validator("config_parse_bond_ad_select", "0") to ConfigParseBondAdSelectOptionValue() as OptionValueInformation, Validator("config_parse_bond_arp_all_targets", "0") to ConfigParseBondArpAllTargetsOptionValue() as OptionValueInformation, Validator("config_parse_bond_arp_validate", "0") to ConfigParseBondArpValidateOptionValue() as OptionValueInformation, @@ -54,7 +56,10 @@ 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, Validator("config_parse_df", "0") to ConfigParseDfOptionValue() as OptionValueInformation, Validator("config_parse_dhcp6_client_start_mode", "0") to ConfigParseDhcp6ClientStartModeOptionValue() as OptionValueInformation, Validator("config_parse_dhcp6_pd_prefix_hint", "0") to ConfigParseDhcp6PdPrefixHintOptionValue() as OptionValueInformation, @@ -76,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, @@ -90,14 +98,18 @@ fun getAllAIGeneratedValidators(): Map { Validator("config_parse_flow_label", "0") to ConfigParseFlowLabelOptionValue() as OptionValueInformation, Validator("config_parse_fou_encap_type", "0") to ConfigParseFouEncapTypeOptionValue() as OptionValueInformation, Validator("config_parse_fou_tunnel_address", "0") to ConfigParseFouTunnelAddressOptionValue() as OptionValueInformation, + Validator("config_parse_fq_codel_size", "QDISC_KIND_FQ_CODEL") to ConfigParseFqCodelSizeOptionValue() as OptionValueInformation, Validator("config_parse_fq_pie_packet_limit", "QDISC_KIND_FQ_PIE") to ConfigParseFqPiePacketLimitOptionValue() as OptionValueInformation, Validator("config_parse_geneve_df", "0") to ConfigParseGeneveDfOptionValue() as OptionValueInformation, Validator("config_parse_geneve_flow_label", "0") to ConfigParseGeneveFlowLabelOptionValue() as OptionValueInformation, Validator("config_parse_geneve_ttl", "0") to ConfigParseGeneveTtlOptionValue() as OptionValueInformation, Validator("config_parse_geneve_vni", "0") to ConfigParseGeneveVniOptionValue() as OptionValueInformation, Validator("config_parse_hhf_packet_limit", "QDISC_KIND_HHF") to ConfigParseHhfPacketLimitOptionValue() as OptionValueInformation, + Validator("config_parse_htb_class_size", "TCLASS_KIND_HTB") to ConfigParseHtbClassSizeOptionValue() as OptionValueInformation, Validator("config_parse_iaid", "AF_INET6") to ConfigParseIaidOptionValue() as OptionValueInformation, Validator("config_parse_iaid", "AF_INET") to ConfigParseIaidOptionValue() as OptionValueInformation, + Validator("config_parse_iec_size", "0") to ConfigParseIecSizeOptionValue() as OptionValueInformation, + Validator("config_parse_int", "0") to ConfigParseIntOptionValue() as OptionValueInformation, Validator("config_parse_in_addr_non_null", "AF_INET") to ConfigParseInAddrNonNullOptionValue() as OptionValueInformation, Validator("config_parse_ip_masquerade", "0") to ConfigParseIpMasqueradeOptionValue() as OptionValueInformation, Validator("config_parse_ip_protocol", "true") to ConfigParseIpProtocolOptionValue() as OptionValueInformation, @@ -108,6 +120,7 @@ fun getAllAIGeneratedValidators(): Map { Validator("config_parse_ipv6_privacy_extensions", "0") to ConfigParseIpv6PrivacyExtensionsOptionValue() as OptionValueInformation, Validator("config_parse_ipvlan_flags", "0") to ConfigParseIpvlanFlagsOptionValue() as OptionValueInformation, Validator("config_parse_ipvlan_mode", "0") to ConfigParseIpvlanModeOptionValue() as OptionValueInformation, + Validator("config_parse_job_mode", "0") to ConfigParseJobModeOptionValue() as OptionValueInformation, Validator("config_parse_job_mode_isolate", "0") to ConfigParseJobModeIsolateOptionValue() as OptionValueInformation, Validator("config_parse_keep_configuration", "0") to ConfigParseKeepConfigurationOptionValue() as OptionValueInformation, Validator("config_parse_l2tp_encap_type", "0") to ConfigParseL2tpEncapTypeOptionValue() as OptionValueInformation, @@ -126,6 +139,7 @@ fun getAllAIGeneratedValidators(): Map { Validator("config_parse_macvlan_mode", "0") to ConfigParseMacvlanModeOptionValue() as OptionValueInformation, Validator("config_parse_managed_oom_mem_pressure_duration_sec", "0") to ConfigParseManagedOomMemPressureDurationSecOptionValue() as OptionValueInformation, Validator("config_parse_managed_oom_mem_pressure_limit", "0") to ConfigParseManagedOomMemPressureLimitOptionValue() as OptionValueInformation, + Validator("config_parse_managed_oom_rules", "1") to ConfigParseManagedOomRulesOptionValue() as OptionValueInformation, Validator("config_parse_mdi", "0") to ConfigParseMdiOptionValue() as OptionValueInformation, Validator("config_parse_pressure_watch", "0") to ConfigParseMemoryPressureWatchOptionValue() as OptionValueInformation, Validator("config_parse_mtu", "AF_INET6") to ConfigParseMtuOptionValue() as OptionValueInformation, @@ -138,6 +152,7 @@ fun getAllAIGeneratedValidators(): Map { Validator("config_parse_nexthop_section", "NEXTHOP_ID") to ConfigParseNexthopSectionOptionValue() as OptionValueInformation, Validator("config_parse_nexthop_section", "NEXTHOP_ONLINK") to ConfigParseNexthopSectionOptionValue() as OptionValueInformation, Validator("config_parse_nsec", "0") to ConfigParseNsecOptionValue() as OptionValueInformation, + Validator("config_parse_pass_environ", "0") to ConfigParsePassEnvironOptionValue() as OptionValueInformation, Validator("config_parse_permille", "0") to ConfigParsePermilleOptionValue() as OptionValueInformation, Validator("config_parse_pfifo_size", "QDISC_KIND_PFIFO") to ConfigParsePfifoSizeOptionValue() as OptionValueInformation, Validator("config_parse_pfifo_size", "QDISC_KIND_PFIFO_HEAD_DROP") to ConfigParsePfifoSizeOptionValue() as OptionValueInformation, @@ -150,10 +165,13 @@ fun getAllAIGeneratedValidators(): Map { Validator("config_parse_prefix_metric", "0") to ConfigParsePrefixMetricOptionValue() as OptionValueInformation, Validator("config_parse_private_pids", "0") to ConfigParsePrivatePidsOptionValue() as OptionValueInformation, Validator("config_parse_private_tmp", "0") to ConfigParsePrivateTmpOptionValue() as OptionValueInformation, + Validator("config_parse_private_users", "0") to ConfigParsePrivateUsersOptionValue() as OptionValueInformation, Validator("config_parse_protect_control_groups", "0") to ConfigParseProtectControlGroupsOptionValue() as OptionValueInformation, Validator("config_parse_protect_home", "0") to ConfigParseProtectHomeOptionValue() as OptionValueInformation, Validator("config_parse_protect_system", "0") to ConfigParseProtectSystemOptionValue() as OptionValueInformation, Validator("config_parse_qfq_weight", "TCLASS_KIND_QFQ") to ConfigParseQfqWeightOptionValue() as OptionValueInformation, + Validator("config_parse_reboot_parameter", "0") to ConfigParseRebootParameterOptionValue() as OptionValueInformation, + Validator("config_parse_restrict_network_interfaces", "0") to ConfigParseRestrictNetworkInterfacesOptionValue() as OptionValueInformation, Validator("config_parse_ring_buffer_or_channel", "0") to ConfigParseRingBufferOrChannelOptionValue() as OptionValueInformation, Validator("config_parse_route_prefix_preference", "0") to ConfigParseRoutePrefixPreferenceOptionValue() as OptionValueInformation, Validator("config_parse_route_section", "ROUTE_METRIC_FASTOPEN_NO_COOKIE") to ConfigParseRouteSectionOptionValue() as OptionValueInformation, @@ -175,6 +193,8 @@ 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, Validator("config_parse_tcp_window", "0") to ConfigParseTcpWindowOptionValue() as OptionValueInformation, @@ -186,12 +206,16 @@ fun getAllAIGeneratedValidators(): Map { Validator("config_parse_unit_condition_string", "CONDITION_CONTROL_GROUP_CONTROLLER") to ConfigParseUnitConditionStringOptionValue() as OptionValueInformation, Validator("config_parse_unit_condition_string", "CONDITION_CPU_FEATURE") to ConfigParseUnitConditionStringOptionValue() as OptionValueInformation, Validator("config_parse_unit_condition_string", "CONDITION_FIRST_BOOT") to ConfigParseUnitConditionStringOptionValue() as OptionValueInformation, + Validator("config_parse_unit_env_file", "0") to ConfigParseUnitEnvFileOptionValue() as OptionValueInformation, + 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, Validator("config_parse_vxlan_ttl", "0") to ConfigParseVxlanTtlOptionValue() as OptionValueInformation, + Validator("config_parse_working_directory", "0") to ConfigParseWorkingDirectoryOptionValue() as OptionValueInformation, Validator("config_parse_wireguard_keepalive", "0") to ConfigParseWireguardKeepaliveOptionValue() as OptionValueInformation, Validator("config_parse_wireguard_listen_port", "0") to ConfigParseWireguardListenPortOptionValue() as OptionValueInformation, Validator("config_parse_wireguard_peer_route_priority", "0") to ConfigParseWireguardPeerRoutePriorityOptionValue() as OptionValueInformation, diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseAddressFamiliesOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseAddressFamiliesOptionValue.kt new file mode 100644 index 0000000..186890f --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseAddressFamiliesOptionValue.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 RestrictAddressFamilies=. + * + * C function: config_parse_address_families in src/core/load-fragment.c → parse_address_families + * in src/shared/parse-helpers.c:90. Accepts: + * - "none" (clears the set, sets allowlist) + * - optional leading "~" (invert / denylist mode), followed by a whitespace-separated list + * of address family names from af_from_name (AF_UNIX, AF_INET, AF_INET6, AF_NETLINK, + * AF_PACKET, …) + * + * The grammar matches the "AF_" prefix loosely (any uppercase/digit/underscore tail); unknown + * names slip past the grammar but fail at runtime. This is the same tradeoff as syscall_errno. + */ +class ConfigParseAddressFamiliesOptionValue : SimpleGrammarOptionValues( + "config_parse_address_families", + SequenceCombinator( + AlternativeCombinator( + LiteralChoiceTerminal("none"), + SequenceCombinator( + ZeroOrOne(LiteralChoiceTerminal("~")), + RegexTerminal("AF_[A-Z0-9_]+", "AF_[A-Z0-9_]+"), + ZeroOrMore(SequenceCombinator( + WhitespaceTerminal(), + RegexTerminal("AF_[A-Z0-9_]+", "AF_[A-Z0-9_]+") + )) + ) + ), + EOF() + ) +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseBindNetworkInterfaceOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseBindNetworkInterfaceOptionValue.kt new file mode 100644 index 0000000..e1f92c5 --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseBindNetworkInterfaceOptionValue.kt @@ -0,0 +1,23 @@ +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 BindNetworkInterface=. + * + * C function: config_parse_bind_network_interface in src/core/load-fragment.c. After + * unit_full_printf specifier expansion, the result must pass ifname_valid_full( + * IFNAME_VALID_ALTERNATIVE) — same rules as RestrictNetworkInterfaces= entries but the value + * is a single interface name (no whitespace-separated list, no leading "~"). + */ +class ConfigParseBindNetworkInterfaceOptionValue : SimpleGrammarOptionValues( + "config_parse_bind_network_interface", + SequenceCombinator( + RegexTerminal( + "(?!(?:all|default|\\.{1,2}|0[xX][0-9a-fA-F]+|[0-9]+)\\Z)[^\\s:/%]{1,127}", + "(?!(?:all|default|\\.{1,2}|0[xX][0-9a-fA-F]+|[0-9]+)\\Z)[^\\s:/%]{1,127}" + ), + EOF() + ) +) 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/ConfigParseCpuQuotaOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseCpuQuotaOptionValue.kt new file mode 100644 index 0000000..e8d25ab --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseCpuQuotaOptionValue.kt @@ -0,0 +1,25 @@ +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 CPUQuota=. + * + * C function: config_parse_cpu_quota in src/core/load-fragment.c. After the empty-input check + * it calls parse_permyriad_unbounded(rvalue), which accepts N% / N.N% / N.NN% (with no upper + * bound — values over 100% are meaningful here, e.g. "200%" means 2 cores). The result must + * be strictly greater than zero, so "0%", "0.0%", "0.00%" are rejected at the C semantic + * layer; the grammar accepts them but the runtime parser will warn. + * + * Only the ASCII percent form is matched here; the ‰/‱ Unicode suffixes are vanishingly rare + * in unit files. + */ +class ConfigParseCpuQuotaOptionValue : SimpleGrammarOptionValues( + "config_parse_cpu_quota", + SequenceCombinator( + RegexTerminal("[0-9]+(\\.[0-9]{1,2})?", "[0-9]+(\\.[0-9]{1,2})?"), + LiteralChoiceTerminal("%"), + EOF() + ) +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseDelegateOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseDelegateOptionValue.kt new file mode 100644 index 0000000..ce1db4f --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseDelegateOptionValue.kt @@ -0,0 +1,41 @@ +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 Delegate=. + * + * C function: config_parse_delegate in src/core/load-fragment.c. Either a boolean (toggles + * delegation for all controllers) or a whitespace-separated list of cgroup controller names + * from cgroup_controller_table in src/basic/cgroup-util.c. + * + * Note: the controller list is the first alternative because BOOLEAN is a + * FlexibleLiteralChoiceTerminal whose syntactic phase accepts any short alphanumeric token — + * if it ran first, single-controller inputs like "cpu" would syntactically consume the value + * as a (fake) boolean and AlternativeCombinator would short-circuit there. + */ +class ConfigParseDelegateOptionValue : SimpleGrammarOptionValues( + "config_parse_delegate", + SequenceCombinator( + AlternativeCombinator( + SequenceCombinator( + LiteralChoiceTerminal( + "cpu", "cpuacct", "cpuset", "io", "blkio", "memory", "devices", "pids", + "bpf-firewall", "bpf-devices", "bpf-foreign", "bpf-socket-bind", + "bpf-restrict-network-interfaces", "bpf-bind-network-interface" + ), + ZeroOrMore(SequenceCombinator( + WhitespaceTerminal(), + LiteralChoiceTerminal( + "cpu", "cpuacct", "cpuset", "io", "blkio", "memory", "devices", "pids", + "bpf-firewall", "bpf-devices", "bpf-foreign", "bpf-socket-bind", + "bpf-restrict-network-interfaces", "bpf-bind-network-interface" + ) + )) + ), + BOOLEAN + ), + 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/ConfigParseFqCodelSizeOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseFqCodelSizeOptionValue.kt new file mode 100644 index 0000000..19add4d --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseFqCodelSizeOptionValue.kt @@ -0,0 +1,20 @@ +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 the [FairQueueingControlledDelay] size-style options: MemoryLimitBytes=, + * QuantumBytes= (and the deprecated MemoryLimit / Quantum aliases). + * + * C function: config_parse_fq_codel_size(QDISC_KIND_FQ_CODEL) in src/network/tc/fq-codel.c. + * After branching on the lvalue it calls parse_size(rvalue, 1024, &sz). Same IEC byte shape + * as the other parse_size-based validators. + */ +class ConfigParseFqCodelSizeOptionValue : SimpleGrammarOptionValues( + "config_parse_fq_codel_size", + SequenceCombinator( + OptionalWhitespacePrefix(BYTES), + EOF() + ) +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseHtbClassSizeOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseHtbClassSizeOptionValue.kt new file mode 100644 index 0000000..5e4a561 --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseHtbClassSizeOptionValue.kt @@ -0,0 +1,24 @@ +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 the HTB class size-style options: QuantumBytes=, MTUBytes=, OverheadBytes=, + * BufferBytes=, CeilBufferBytes=. + * + * C function: config_parse_htb_class_size(TCLASS_KIND_HTB) in src/network/tc/htb.c. After + * branching on the lvalue, it calls parse_size(rvalue, 1024, &v), so the value is a decimal + * byte count optionally suffixed with an IEC unit. Same shape as config_parse_tbf_size and + * config_parse_fq_size. + * + * The per-lvalue OverheadBytes <= UINT16_MAX bound and the general v <= UINT32_MAX bound are + * semantic checks that can't be expressed at the grammar level without lvalue access. + */ +class ConfigParseHtbClassSizeOptionValue : SimpleGrammarOptionValues( + "config_parse_htb_class_size", + SequenceCombinator( + OptionalWhitespacePrefix(BYTES), + EOF() + ) +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseIecSizeOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseIecSizeOptionValue.kt new file mode 100644 index 0000000..7739bc4 --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseIecSizeOptionValue.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 generic IEC byte-size options parsed by config_parse_iec_size. + * + * C function: config_parse_iec_size in src/shared/conf-parser.c. Delegates to + * parse_size(rvalue, 1024, &v) and additionally requires the result to fit in a size_t. + * Same IEC byte syntax used by tbf_size / fq_size / htb_class_size. + */ +class ConfigParseIecSizeOptionValue : SimpleGrammarOptionValues( + "config_parse_iec_size", + SequenceCombinator( + OptionalWhitespacePrefix(BYTES), + EOF() + ) +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseIntOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseIntOptionValue.kt new file mode 100644 index 0000000..78db652 --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseIntOptionValue.kt @@ -0,0 +1,18 @@ +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 generic signed-integer options parsed by config_parse_int. + * + * C function: defined via DEFINE_PARSER(int, int, safe_atoi) in src/shared/conf-parser.c. + * Accepts a signed 32-bit integer. + */ +class ConfigParseIntOptionValue : SimpleGrammarOptionValues( + "config_parse_int", + SequenceCombinator( + IntegerTerminal(Int.MIN_VALUE.toLong(), Int.MAX_VALUE.toLong() + 1L), + EOF() + ) +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseJobModeOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseJobModeOptionValue.kt new file mode 100644 index 0000000..19a5037 --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseJobModeOptionValue.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.* + +/** + * Validator for job-mode options (e.g. OnFailureJobMode=, OnSuccessJobMode=). + * + * C function: config_parse_job_mode, expanded via DEFINE_CONFIG_PARSE_ENUM in + * src/core/load-fragment.c. Accepts exactly the entries of job_mode_table in + * src/basic/unit-def.c. + */ +class ConfigParseJobModeOptionValue : SimpleGrammarOptionValues( + "config_parse_job_mode", + SequenceCombinator( + LiteralChoiceTerminal( + "fail", + "lenient", + "replace", + "replace-irreversibly", + "isolate", + "flush", + "ignore-dependencies", + "ignore-requirements", + "triggering", + "restart-dependencies" + ), + EOF() + ) +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseManagedOomRulesOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseManagedOomRulesOptionValue.kt new file mode 100644 index 0000000..997c72e --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseManagedOomRulesOptionValue.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 ManagedOOMRulesets= and friends. + * + * C function: config_parse_managed_oom_rules in src/core/load-fragment.c. After an + * unsupported-unit-type check it tokenizes rvalue with extract_first_word and accepts each + * token that passes string_is_safe(STRING_FILENAME) — i.e. filename-safe characters, not + * "." / "..", no slashes, no whitespace, no shell metacharacters. The rules themselves are + * loaded from .oomrule files at runtime so the grammar only validates the per-token shape. + */ +class ConfigParseManagedOomRulesOptionValue : SimpleGrammarOptionValues( + "config_parse_managed_oom_rules", + SequenceCombinator( + RULE_NAME, + ZeroOrMore(SequenceCombinator(WhitespaceTerminal(), RULE_NAME)), + EOF() + ) +) { + companion object { + // STRING_FILENAME forbids slashes, NUL, whitespace, and shell metacharacters. The + // regex below is a conservative ASCII printable set excluding those plus the "." / + // ".." filename reservations (rejected via the negative lookahead). + private val RULE_NAME = RegexTerminal( + "(?!\\.{1,2}\\Z)[A-Za-z0-9._-][A-Za-z0-9._+-]*", + "(?!\\.{1,2}\\Z)[A-Za-z0-9._-][A-Za-z0-9._+-]*" + ) + } +} diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParsePassEnvironOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParsePassEnvironOptionValue.kt new file mode 100644 index 0000000..0e5142b --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParsePassEnvironOptionValue.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.* + +/** + * Validator for PassEnvironment=. + * + * C function: config_parse_pass_environ in src/core/load-fragment.c. Whitespace-separated list + * of environment variable names. Each word is first run through unit_env_printf (resolves + * %p / %n / etc.), then env_name_is_valid: must not be empty, must not start with a digit, + * and may contain only characters in VALID_BASH_ENV_NAME_CHARS (alphanumerics and underscore). + * + * The grammar tolerates "%X" specifiers inline by including "%" in the allowed-character set, + * since the C parser resolves them before the validity check. This means a few unresolved + * specifier-heavy inputs that the runtime parser would reject will pass here — preferred over + * false positives for legitimate `PassEnvironment=%n_LOG` style usage. + */ +class ConfigParsePassEnvironOptionValue : SimpleGrammarOptionValues( + "config_parse_pass_environ", + SequenceCombinator( + RegexTerminal("[A-Za-z_%][A-Za-z0-9_%]*", "[A-Za-z_%][A-Za-z0-9_%]*"), + ZeroOrMore(SequenceCombinator( + WhitespaceTerminal(), + RegexTerminal("[A-Za-z_%][A-Za-z0-9_%]*", "[A-Za-z_%][A-Za-z0-9_%]*") + )), + EOF() + ) +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParsePrivateUsersOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParsePrivateUsersOptionValue.kt new file mode 100644 index 0000000..867d0b4 --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParsePrivateUsersOptionValue.kt @@ -0,0 +1,40 @@ +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 the .nspawn PrivateUsers= setting. + * + * C function: config_parse_private_users in src/nspawn/nspawn-settings.c. Accepts (in order + * the C code checks): + * - boolean ("yes" / "no" / "1" / "0" / "true" / "false" / "on" / "off") + * - "pick" (random UID shift) + * - "identity" (UID shift 0, range 64K) + * - `uid` (single uint32, range defaults to 64K) + * - `uid:range` (two uint32 separated by colon) + * + * Alternatives are ordered from most-specific to least-specific so the colon form is tried + * before the bare uid, and BOOLEAN (FlexibleLiteralChoiceTerminal) comes last — its syntactic + * regex would otherwise greedily match tokens like "pick" or "identity" as boolean prefixes + * and short-circuit AlternativeCombinator. + */ +class ConfigParsePrivateUsersOptionValue : SimpleGrammarOptionValues( + "config_parse_private_users", + SequenceCombinator( + AlternativeCombinator( + // uid:range + SequenceCombinator( + IntegerTerminal(0, 4_294_967_296L), + LiteralChoiceTerminal(":"), + IntegerTerminal(0, 4_294_967_296L) + ), + // bare uid + IntegerTerminal(0, 4_294_967_296L), + // string aliases + LiteralChoiceTerminal("pick", "identity"), + BOOLEAN + ), + EOF() + ) +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseRebootParameterOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseRebootParameterOptionValue.kt new file mode 100644 index 0000000..c5e23d4 --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseRebootParameterOptionValue.kt @@ -0,0 +1,23 @@ +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 RebootArgument= / RebootParameter= keys. + * + * C function: config_parse_reboot_parameter in src/core/load-fragment.c → reboot_parameter_is_valid + * in src/shared/reboot-util.c. After unit_full_printf specifier expansion, the result must: + * - pass ascii_is_valid (printable ASCII) + * - have length ≤ NAME_MAX (255) + * + * Grammar allows printable ASCII (0x20..0x7E) including "%" for specifier syntax; length cap + * of 255 is enforced via a regex quantifier. + */ +class ConfigParseRebootParameterOptionValue : SimpleGrammarOptionValues( + "config_parse_reboot_parameter", + SequenceCombinator( + RegexTerminal("[\\x20-\\x7E]{1,255}", "[\\x20-\\x7E]{1,255}"), + EOF() + ) +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseRestrictNetworkInterfacesOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseRestrictNetworkInterfacesOptionValue.kt new file mode 100644 index 0000000..b879a64 --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseRestrictNetworkInterfacesOptionValue.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.* + +/** + * Validator for RestrictNetworkInterfaces=. + * + * C function: config_parse_restrict_network_interfaces in src/core/load-fragment.c. Optional + * leading "~" (invert / denylist mode), followed by a whitespace-separated list of interface + * names that must pass ifname_valid_full(IFNAME_VALID_ALTERNATIVE): + * - 1..127 characters (ALTIFNAMSIZ - 1) + * - no whitespace, no '/', no ':', no '%' (rejected by ifname_valid_char) + * - cannot be "." or ".." + * - cannot be "all" or "default" + * - cannot be a purely-numeric string (interpreted as ifindex) + * + * The regex mirrors the existing config_parse_ifname validator but extends the length cap + * from 15 (IFNAMSIZ) to 127 (ALTIFNAMSIZ). + */ +class ConfigParseRestrictNetworkInterfacesOptionValue : SimpleGrammarOptionValues( + "config_parse_restrict_network_interfaces", + SequenceCombinator( + ZeroOrOne(LiteralChoiceTerminal("~")), + IFNAME, + ZeroOrMore(SequenceCombinator(WhitespaceTerminal(), IFNAME)), + EOF() + ) +) { + companion object { + private val IFNAME = RegexTerminal( + "(?!(?:all|default|\\.{1,2}|0[xX][0-9a-fA-F]+|[0-9]+)\\Z)[^\\s:/%]{1,127}", + "(?!(?:all|default|\\.{1,2}|0[xX][0-9a-fA-F]+|[0-9]+)\\Z)[^\\s:/%]{1,127}" + ) + } +} 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/ConfigParseSyscallErrnoOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseSyscallErrnoOptionValue.kt new file mode 100644 index 0000000..ebde9b3 --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseSyscallErrnoOptionValue.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.* + +/** + * Validator for SystemCallErrorNumber=. + * + * C function: config_parse_syscall_errno in src/core/load-fragment.c → parse_errno in + * src/basic/parse-util.c. Accepts: + * - "kill" (special, resets to SECCOMP_ERROR_NUMBER_KILL) + * - an errno name (uppercase "E"-prefixed, e.g. EPERM, ENOENT) via errno_from_name + * - an integer that maps to a valid errno via errno_is_valid (or 0) + * + * The grammar matches the errno-name pattern loosely (any uppercase E-prefixed token); + * unknown names like "ENOIENT" would slip past the grammar but fail at runtime. Numeric + * range here is 0..4095 — wider than typical valid errnos but enough to catch obvious typos. + */ +class ConfigParseSyscallErrnoOptionValue : SimpleGrammarOptionValues( + "config_parse_syscall_errno", + SequenceCombinator( + AlternativeCombinator( + LiteralChoiceTerminal("kill"), + RegexTerminal("E[A-Z][A-Z0-9]*", "E[A-Z][A-Z0-9]*"), + IntegerTerminal(0, 4096) + ), + EOF() + ) +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseUnitEnvFileOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseUnitEnvFileOptionValue.kt new file mode 100644 index 0000000..0a13f71 --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseUnitEnvFileOptionValue.kt @@ -0,0 +1,21 @@ +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 EnvironmentFile=. + * + * C function: config_parse_unit_env_file in src/core/load-fragment.c. Each line is a single + * environment file path (after unit_path_printf specifier expansion); an optional leading "-" + * marks the file as missing-OK. The resolved path must be absolute (path_simplify_and_warn + * with PATH_CHECK_ABSOLUTE). + */ +class ConfigParseUnitEnvFileOptionValue : SimpleGrammarOptionValues( + "config_parse_unit_env_file", + SequenceCombinator( + ZeroOrOne(LiteralChoiceTerminal("-")), + RegexTerminal("/\\S*", "/\\S*"), + EOF() + ) +) diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseUnitMountsForOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseUnitMountsForOptionValue.kt new file mode 100644 index 0000000..c4450a0 --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseUnitMountsForOptionValue.kt @@ -0,0 +1,27 @@ +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 RequiresMountsFor= / WantsMountsFor=. + * + * C function: config_parse_unit_mounts_for in src/core/load-fragment.c. Tokenizes rvalue with + * extract_first_word (whitespace-separated, EXTRACT_UNQUOTE), expands unit specifiers via + * unit_path_printf, then requires each path to be absolute via path_simplify_and_warn with + * PATH_CHECK_ABSOLUTE. + * + * The grammar allows any non-whitespace path that starts with "/", and accepts "%X" specifiers + * inline since the C parser expands them before the absolute-path check. + */ +class ConfigParseUnitMountsForOptionValue : SimpleGrammarOptionValues( + "config_parse_unit_mounts_for", + SequenceCombinator( + RegexTerminal("/\\S*", "/\\S*"), + ZeroOrMore(SequenceCombinator( + WhitespaceTerminal(), + RegexTerminal("/\\S*", "/\\S*") + )), + EOF() + ) +) 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/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseWorkingDirectoryOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseWorkingDirectoryOptionValue.kt new file mode 100644 index 0000000..13b725b --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseWorkingDirectoryOptionValue.kt @@ -0,0 +1,27 @@ +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 WorkingDirectory=. + * + * C function: config_parse_working_directory in src/core/load-fragment.c. Accepts: + * - optional leading "-" (missing path is non-fatal) + * - then either "~" alone (use the user's home) OR an absolute path + * + * Path values go through unit_path_printf so "%X" specifiers may appear inline. The grammar + * allows any non-whitespace characters in the path; tighter shell-metacharacter checks happen + * in path_simplify_and_warn at runtime. + */ +class ConfigParseWorkingDirectoryOptionValue : SimpleGrammarOptionValues( + "config_parse_working_directory", + SequenceCombinator( + ZeroOrOne(LiteralChoiceTerminal("-")), + AlternativeCombinator( + LiteralChoiceTerminal("~"), + RegexTerminal("/\\S*", "/\\S*") + ), + EOF() + ) +) diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseAddressFamiliesOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseAddressFamiliesOptionValueTest.kt new file mode 100644 index 0000000..8d37381 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseAddressFamiliesOptionValueTest.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 ConfigParseAddressFamiliesOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // language="unit file (systemd)" + val file = """ + [Service] + RestrictAddressFamilies=none + RestrictAddressFamilies=AF_INET + RestrictAddressFamilies=AF_INET AF_INET6 + RestrictAddressFamilies=AF_UNIX AF_NETLINK + RestrictAddressFamilies=~AF_PACKET + RestrictAddressFamilies=~AF_INET AF_INET6 + RestrictAddressFamilies=AF_BRIDGE AF_X25 AF_AX25 + """.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] + RestrictAddressFamilies=inet + RestrictAddressFamilies=AF_inet + RestrictAddressFamilies=AF_INET, AF_INET6 + RestrictAddressFamilies=~ AF_PACKET + RestrictAddressFamilies=NONE + """.trimIndent() + + setupFileInEditor("file.service", 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/ConfigParseBindNetworkInterfaceOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseBindNetworkInterfaceOptionValueTest.kt new file mode 100644 index 0000000..f29206b --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseBindNetworkInterfaceOptionValueTest.kt @@ -0,0 +1,45 @@ +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 ConfigParseBindNetworkInterfaceOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // language="unit file (systemd)" + val file = """ + [Service] + BindNetworkInterface=eth0 + BindNetworkInterface=lo + BindNetworkInterface=wlan0 + BindNetworkInterface=br-1234abcd + """.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] + BindNetworkInterface=all + BindNetworkInterface=default + BindNetworkInterface=eth0 eth1 + BindNetworkInterface=eth0/0 + BindNetworkInterface=123 + """.trimIndent() + + setupFileInEditor("file.service", 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/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/ConfigParseCpuQuotaOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseCpuQuotaOptionValueTest.kt new file mode 100644 index 0000000..fab7c8c --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseCpuQuotaOptionValueTest.kt @@ -0,0 +1,49 @@ +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 ConfigParseCpuQuotaOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // language="unit file (systemd)" + val file = """ + [Service] + CPUQuota=50% + CPUQuota=100% + CPUQuota=200% + CPUQuota=12.34% + CPUQuota=1.5% + CPUQuota=0.01% + CPUQuota=99.99% + CPUQuota=1000% + """.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] + CPUQuota=50 + CPUQuota=abc + CPUQuota=-5% + CPUQuota=12.345% + CPUQuota=50% 60% + """.trimIndent() + + setupFileInEditor("file.service", 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/ConfigParseDelegateOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseDelegateOptionValueTest.kt new file mode 100644 index 0000000..74f18a0 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseDelegateOptionValueTest.kt @@ -0,0 +1,49 @@ +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 ConfigParseDelegateOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // language="unit file (systemd)" + val file = """ + [Service] + Delegate=yes + Delegate=no + Delegate=true + Delegate=false + Delegate=cpu + Delegate=cpu memory io + Delegate=cpu cpuacct cpuset io blkio memory devices pids + Delegate=bpf-firewall bpf-devices bpf-foreign + Delegate=bpf-socket-bind bpf-restrict-network-interfaces bpf-bind-network-interface + """.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] + Delegate=maybe + Delegate=cpu unknown + Delegate=CPU + Delegate=cpu,memory + """.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/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/ConfigParseFqCodelSizeOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseFqCodelSizeOptionValueTest.kt new file mode 100644 index 0000000..30b4a73 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseFqCodelSizeOptionValueTest.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 ConfigParseFqCodelSizeOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // language="unit file (systemd)" + val file = """ + [FairQueueingControlledDelay] + MemoryLimitBytes=32M + QuantumBytes=1500 + MemoryLimit=64M + Quantum=2K + """.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] + MemoryLimitBytes=abc + QuantumBytes=-1 + MemoryLimit=10X + """.trimIndent() + + setupFileInEditor("file.network", 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/ConfigParseHtbClassSizeOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseHtbClassSizeOptionValueTest.kt new file mode 100644 index 0000000..b07c523 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseHtbClassSizeOptionValueTest.kt @@ -0,0 +1,45 @@ +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 ConfigParseHtbClassSizeOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // language="unit file (systemd)" + val file = """ + [HierarchyTokenBucketClass] + QuantumBytes=1500 + MTUBytes=1500 + OverheadBytes=64 + BufferBytes=8K + CeilBufferBytes=16K + BufferBytes=1M + """.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] + QuantumBytes=abc + MTUBytes=-1 + BufferBytes=8X + """.trimIndent() + + setupFileInEditor("file.network", 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/ConfigParseIecSizeOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseIecSizeOptionValueTest.kt new file mode 100644 index 0000000..81e9ac3 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseIecSizeOptionValueTest.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 ConfigParseIecSizeOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // language="unit file (systemd)" + val file = """ + [Socket] + ReceiveBuffer=4096 + SendBuffer=64K + PipeSize=1M + ReceiveBuffer=2G + """.trimIndent() + + setupFileInEditor("file.socket", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // language="unit file (systemd)" + val file = """ + [Socket] + ReceiveBuffer=abc + SendBuffer=-1 + PipeSize=10X + """.trimIndent() + + setupFileInEditor("file.socket", 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/ConfigParseIntOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseIntOptionValueTest.kt new file mode 100644 index 0000000..f94d089 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseIntOptionValueTest.kt @@ -0,0 +1,45 @@ +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 ConfigParseIntOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // language="unit file (systemd)" + val file = """ + [Socket] + Priority=0 + IPTTL=64 + Mark=-1 + Priority=2147483647 + IPTTL=-2147483648 + """.trimIndent() + + setupFileInEditor("file.socket", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // language="unit file (systemd)" + val file = """ + [Socket] + Priority=abc + IPTTL=1.5 + Mark=2147483648 + Priority=10 20 + """.trimIndent() + + setupFileInEditor("file.socket", 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/ConfigParseJobModeOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseJobModeOptionValueTest.kt new file mode 100644 index 0000000..034a58a --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseJobModeOptionValueTest.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 ConfigParseJobModeOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // language="unit file (systemd)" + val file = """ + [Unit] + OnSuccessJobMode=fail + OnFailureJobMode=replace + OnSuccessJobMode=replace-irreversibly + OnFailureJobMode=isolate + OnSuccessJobMode=flush + OnFailureJobMode=ignore-dependencies + OnSuccessJobMode=ignore-requirements + OnFailureJobMode=triggering + OnSuccessJobMode=restart-dependencies + OnFailureJobMode=lenient + """.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 = """ + [Unit] + OnSuccessJobMode=unknown + OnFailureJobMode=Replace + OnSuccessJobMode=fail isolate + OnFailureJobMode=replace_irreversibly + """.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/ConfigParseManagedOomRulesOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseManagedOomRulesOptionValueTest.kt new file mode 100644 index 0000000..0047a92 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseManagedOomRulesOptionValueTest.kt @@ -0,0 +1,45 @@ +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 ConfigParseManagedOomRulesOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // language="unit file (systemd)" + val file = """ + [Service] + OOMRules=default + OOMRules=default critical + OOMRules=rule1 rule2 rule3 + OOMRules=my-rule_42 + OOMRules=rule.with.dots + """.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] + OOMRules=rule/with/slash + OOMRules=. + OOMRules=.. + OOMRules=rule,other + """.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/ConfigParsePassEnvironOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParsePassEnvironOptionValueTest.kt new file mode 100644 index 0000000..823d1c1 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParsePassEnvironOptionValueTest.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 ConfigParsePassEnvironOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // language="unit file (systemd)" + val file = """ + [Service] + PassEnvironment=PATH + PassEnvironment=HOME LANG TERM + PassEnvironment=MY_VAR + PassEnvironment=_LEADING_UNDERSCORE + PassEnvironment=A B C D E + PassEnvironment=%n_LOG_LEVEL + PassEnvironment=PREFIX_%i + """.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] + PassEnvironment=1STARTS_WITH_DIGIT + PassEnvironment=HAS-DASH + PassEnvironment=HAS.DOT + PassEnvironment=NAME=value + PassEnvironment=PATH,HOME + """.trimIndent() + + setupFileInEditor("file.service", 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/ConfigParsePrivateUsersOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParsePrivateUsersOptionValueTest.kt new file mode 100644 index 0000000..d4c30f7 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParsePrivateUsersOptionValueTest.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 ConfigParsePrivateUsersOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // language="unit file (systemd)" + val file = """ + [Exec] + PrivateUsers=yes + PrivateUsers=no + PrivateUsers=true + PrivateUsers=false + PrivateUsers=pick + PrivateUsers=identity + PrivateUsers=1000 + PrivateUsers=0 + PrivateUsers=1000:65536 + PrivateUsers=100000:1000000 + """.trimIndent() + + setupFileInEditor("file.nspawn", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(0, highlights) + } + + @Test + fun testInvalidValues() { + // language="unit file (systemd)" + val file = """ + [Exec] + PrivateUsers=maybe + PrivateUsers=Pick + PrivateUsers=-1 + PrivateUsers=1000: + PrivateUsers=:1000 + PrivateUsers=1000 65536 + """.trimIndent() + + setupFileInEditor("file.nspawn", 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/ConfigParseRebootParameterOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseRebootParameterOptionValueTest.kt new file mode 100644 index 0000000..1532273 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseRebootParameterOptionValueTest.kt @@ -0,0 +1,42 @@ +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 ConfigParseRebootParameterOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // language="unit file (systemd)" + val file = """ + [Unit] + RebootArgument=recovery + JobTimeoutRebootArgument=panic + RebootArgument=bootloader + JobTimeoutRebootArgument=arg with spaces + """.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 = """ + [Unit] + RebootArgument=café + JobTimeoutRebootArgument=日本 + """.trimIndent() + + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(2, highlights) + } +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseRestrictNetworkInterfacesOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseRestrictNetworkInterfacesOptionValueTest.kt new file mode 100644 index 0000000..a853131 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseRestrictNetworkInterfacesOptionValueTest.kt @@ -0,0 +1,47 @@ +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 ConfigParseRestrictNetworkInterfacesOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // language="unit file (systemd)" + val file = """ + [Service] + RestrictNetworkInterfaces=eth0 + RestrictNetworkInterfaces=eth0 eth1 + RestrictNetworkInterfaces=lo eth0 wlan0 + RestrictNetworkInterfaces=~eth0 + RestrictNetworkInterfaces=~lo eth0 + RestrictNetworkInterfaces=br-1234abcd + """.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] + RestrictNetworkInterfaces=all + RestrictNetworkInterfaces=default + RestrictNetworkInterfaces=eth0/0 + RestrictNetworkInterfaces=eth0:0 + RestrictNetworkInterfaces=123 + """.trimIndent() + + setupFileInEditor("file.service", 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/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/ConfigParseSyscallErrnoOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseSyscallErrnoOptionValueTest.kt new file mode 100644 index 0000000..dd93c81 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseSyscallErrnoOptionValueTest.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 ConfigParseSyscallErrnoOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // language="unit file (systemd)" + val file = """ + [Service] + SystemCallErrorNumber=kill + SystemCallErrorNumber=EPERM + SystemCallErrorNumber=ENOENT + SystemCallErrorNumber=EACCES + SystemCallErrorNumber=EAGAIN + SystemCallErrorNumber=1 + SystemCallErrorNumber=13 + SystemCallErrorNumber=0 + """.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] + SystemCallErrorNumber=KILL + SystemCallErrorNumber=eperm + SystemCallErrorNumber=PERM + SystemCallErrorNumber=-1 + SystemCallErrorNumber=99999 + SystemCallErrorNumber=EPERM ENOENT + """.trimIndent() + + setupFileInEditor("file.service", 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/ConfigParseUnitEnvFileOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseUnitEnvFileOptionValueTest.kt new file mode 100644 index 0000000..1a640ac --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseUnitEnvFileOptionValueTest.kt @@ -0,0 +1,45 @@ +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 ConfigParseUnitEnvFileOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // language="unit file (systemd)" + val file = """ + [Service] + EnvironmentFile=/etc/myapp.env + EnvironmentFile=-/etc/myapp/optional.env + EnvironmentFile=/etc/sysconfig/myapp + EnvironmentFile=/var/lib/%n.env + EnvironmentFile=-/run/secrets/myapp.env + """.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] + EnvironmentFile=relative/path.env + EnvironmentFile=myapp.env + EnvironmentFile=~/myapp.env + EnvironmentFile=--/etc/myapp.env + """.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/ConfigParseUnitMountsForOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseUnitMountsForOptionValueTest.kt new file mode 100644 index 0000000..d58eabe --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseUnitMountsForOptionValueTest.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 ConfigParseUnitMountsForOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // language="unit file (systemd)" + val file = """ + [Unit] + RequiresMountsFor=/var/lib/myapp + WantsMountsFor=/tmp /var/cache + RequiresMountsFor=/srv /opt/app /home/user + WantsMountsFor=/var/log/%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 = """ + [Unit] + RequiresMountsFor=relative/path + WantsMountsFor=no-leading-slash + RequiresMountsFor=/valid relative/path + """.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/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) + } +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseWorkingDirectoryOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseWorkingDirectoryOptionValueTest.kt new file mode 100644 index 0000000..8e39b9b --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseWorkingDirectoryOptionValueTest.kt @@ -0,0 +1,47 @@ +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 ConfigParseWorkingDirectoryOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidValues() { + // language="unit file (systemd)" + val file = """ + [Service] + WorkingDirectory=~ + WorkingDirectory=/var/lib/myapp + WorkingDirectory=/tmp + WorkingDirectory=/ + WorkingDirectory=-/var/cache/myapp + WorkingDirectory=-~ + WorkingDirectory=/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] + WorkingDirectory=relative/path + WorkingDirectory=somepath + WorkingDirectory=/path with space + WorkingDirectory=--/path + """.trimIndent() + + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + assertSize(4, highlights) + } +}