valid = [
  { dep = "_/_", eapis = "..", category = "_", package = "_" },
  { dep = "_/_-", eapis = "..", category = "_", package = "_-" },
  { dep = "_.+-/_+-", eapis = "..", category = "_.+-", package = "_+-" },
  { dep = "_--/_--", eapis = "..", category = "_--", package = "_--" },
  { dep = "a/b", eapis = "..", category = "a", package = "b" },
  { dep = "a/b-", eapis = "..", category = "a", package = "b-" },
  { dep = "a/b-r100", eapis = "..", category = "a", package = "b-r100" },
  { dep = "<a/b-r0-1-r2", eapis = "..", category = "a", package = "b-r0", version = "<1-r2", revision = "2" },
  { dep = "<=a/b-1", eapis = "..", category = "a", package = "b", version = "<=1" },
  { dep = "=a/b-1-r1", eapis = "..", category = "a", package = "b", version = "=1-r1", revision = "1"},
  { dep = "=a/b--1", eapis = "..", category = "a", package = "b-", version = "=1" },
  { dep = "=a/b-r1-2", eapis = "..", category = "a", package = "b-r1", version = "=2" },
  { dep = "=a/b-3*", eapis = "..", category = "a", package = "b", version = "=3*" },
  { dep = "=a/b-3-r1*", eapis = "..", category = "a", package = "b", version = "=3-r1*", revision = "1" },
  { dep = "~a/b-0", eapis = "..", category = "a", package = "b", version = "~0" },
  { dep = ">=a/b-2", eapis = "..", category = "a", package = "b", version = ">=2" },
  { dep = ">a/b-3-r0", eapis = "..", category = "a", package = "b", version = ">3-r0", revision = "0" },
  { dep = ">a/b-3-c-4-r3", eapis = "..", category = "a", package = "b-3-c", version = ">4-r3", revision = "3" },
  ## EAPI specific validity
  # slot deps in EAPI >= 1
  { dep = "a/b:0", eapis = "1..", category = "a", package = "b", slot = "0" },
  { dep = "a/b:_", eapis = "1..", category = "a", package = "b", slot = "_" },
  { dep = "a/b:slot", eapis = "1..", category = "a", package = "b", slot = "slot" },
  { dep = "a/b:S-1.2+3", eapis = "1..", category = "a", package = "b", slot = "S-1.2+3" },
  # blockers in EAPI >= 2
  { dep = "!a/b", eapis = "2..", category = "a", package = "b", blocker = "!" },
  { dep = "!!a/b", eapis = "2..", category = "a", package = "b", blocker = "!!" },
  # use deps in EAPI >= 2
  { dep = "a/b[u]", eapis = "2..", category = "a", package = "b", use = ["u"] },
  { dep = "a/b[1,2]", eapis = "2..", category = "a", package = "b", use = ["1", "2"] },
  { dep = "a/b[u,-u]", eapis = "2..", category = "a", package = "b", use = ["u", "-u"] },
  { dep = "a/b[u-,u+]", eapis = "2..", category = "a", package = "b", use = ["u-", "u+"] },
  { dep = "a/b[a,b=,!c=,d?,!e?,-f]", eapis = "2..", category = "a", package = "b", use = ["a", "b=", "!c=", "d?", "!e?", "-f"] },
  # use dep defaults in EAPI >= 4
  { dep = "a/b[u(+)]", eapis = "4..", category = "a", package = "b", use = ["u(+)"] },
  { dep = "a/b[u(-)]", eapis = "4..", category = "a", package = "b", use = ["u(-)"] },
  { dep = "a/b[u(-),u(+)]", eapis = "4..", category = "a", package = "b", use = ["u(-)", "u(+)"] },
  { dep = "a/b[a(-),b(+)=,!c(-)=,d(+)?,!e(-)?,-f(+)]", eapis = "4..", category = "a", package = "b", use = ["a(-)", "b(+)=", "!c(-)=", "d(+)?", "!e(-)?", "-f(+)"] },
  # subslot deps in EAPI >= 5
  { dep = "a/b:0/1", eapis = "5..", category = "a", package = "b", slot = "0", subslot = "1" },
  { dep = "a/b:_/_", eapis = "5..", category = "a", package = "b", slot = "_", subslot = "_" },
  { dep = "a/b:_/slot", eapis = "5..", category = "a", package = "b", slot = "_", subslot = "slot" },
  { dep = "a/b:_/S-1.2+3", eapis = "5..", category = "a", package = "b", slot = "_", subslot = "S-1.2+3" },
  # slot operators in EAPI >= 5
  { dep = "a/b:*", eapis = "5..", category = "a", package = "b", slot_op = "*" },
  { dep = "a/b:=", eapis = "5..", category = "a", package = "b", slot_op = "=" },
  { dep = "a/b:0=", eapis = "5..", category = "a", package = "b", slot = "0", slot_op = "=" },
  # The equals slot operator with explicit subslot is only allowed in installed package
  # metadata and not in ebuilds; however, pkgcraft globally allows it and flags ebuild
  # usage via pkgcruft instead to maintain a simpler parser.
  { dep = "a/b:0/1=", eapis = "5..", category = "a", package = "b", slot = "0", subslot = "1", slot_op = "=" },
  # all official fields
  { dep = "!!=cat/pkg-1-r2:3/4=[a,b,c]", eapis = "5..", category = "cat", package = "pkg", blocker = "!!", version = "=1-r2", revision = "2", slot = "3", subslot = "4", slot_op = "=", use = ["a", "b", "c"] },
  # repo deps in unofficial EAPIs
  { dep="cat/pkg::repo", eapis="U..", category="cat", package = "pkg", repo = "repo" },
  { dep = "!!=cat/pkg-1-r2:3/4=::repo[a,b,c]", eapis = "U..", category = "cat", package = "pkg", blocker = "!!", version = "=1-r2", revision = "2", slot = "3", subslot = "4", slot_op = "=", repo = "repo", use = ["a", "b", "c"] },
]

invalid = [
  "",
  "a",
  "/b",
  "a/+b",
  ".a/.b",
  # invalid version suffixes
  "=a/b-1_a",
  "=a/b-1_a1",
  # invalid slot deps
  "a/b:",
  "a/b:+",
  "a/b:+0",
  "a/b:.a",
  "a/b:-b",
  "a/b:a@b",
  # invalid blockers
  "!!!a/b",
  "!a/b-0",
  "!!a/b-0-r1",
  # invalid use deps
  "a/b[]",
  "a/b[,]",
  "a/b[u,]",
  "a/b[,u]",
  "a/b[-]",
  "a/b[+u]",
  "a/b[?]",
  "a/b[?u]",
  "a/b[u??]",
  "a/b[-a?]",
  "a/b[!a]",
  # invalid use dep defaults
  "a/b[(-)]",
  "a/b[(-)u]",
  "a/b[u(+)(-)]",
  "a/b[a()]",
  "a/b[a(?)]",
  "a/b[a(b)]",
  "a/b[a(-+)]",
  "a/b[a(++)]",
  "a/b[a((+))]",
  "a/b[a(-)b]",
  # invalid subslot deps
  "a/b:/",
  "a/b:/0",
  "a/b:0/",
  "a/b:0/*",
  "a/b:0/=",
  "a/b:0/+1",
  "a/b:0//1",
  "a/b:0/1/2",
  # invalid slot ops
  "a/b:*0",
  "a/b:0*",
  "a/b:0/1*",
  "a/b:=0",
  "a/b:*=",
  "a/b:==",
  # package names can't end in a hyphen followed by anything matching a version
  "a/b-0",
  "<a/b-1-1",
  "=a/b-1-c-2-3",
  ">a/b-1-r2-3-r4",
  # version operator with missing version
  "~a/b",
  "~a/b-r1",
  "<a/b1a",
  "<=a/b0",
  ">=a/b1-r1",
  ">a/b1.1",
  # '~' operator can't be used with a revision
  "~a/b-1-r1",
  # '*' suffix can only be used for versioned deps with the '=' operator
  ">=a/b-0*",
  "~a/b-0*",
  "a/b-0*",
  "a/b*",
  # '*' suffix can only be used with valid version strings
  "=a/b-0.*",
  "=a/b-0-r*",
  # invalid repo deps
  "a/b::",
  "a/b::-repo",
  "a/b::repo-1",
  "a/b::repo@path",
]

# format: expression that evaluates to true
compares = [
  # duplicate use deps
  "a/b[u] == a/b[u,u]",
  # differently ordered use deps
  "a/b[a,b] == a/b[b,a]",
  # different sets of use deps
  "a/b[u] != a/b[u,u(+)]",
  "a/b[u] != a/b[u,-u]",
]

intersects = [
  # categories
  { vals = ["cat-a/pkg", "cat-b/pkg"], status = false },
  # packages
  { vals = ["cat/pkg-a", "cat/pkg-b"], status = false },
  # slots
  { vals = ["cat/pkg:0", "cat/pkg:1"], status = false },
  { vals = ["cat/pkg:0", "cat/pkg:1="], status = false },
  { vals = ["cat/pkg:0", "cat/pkg:="], status = true },
  { vals = ["cat/pkg:0", "cat/pkg:0="], status = true },
  { vals = ["cat/pkg:0", "cat/pkg:*"], status = true },
  { vals = ["cat/pkg:0", "cat/pkg"], status = true },
  { vals = ["cat/pkg:0=", "cat/pkg"], status = true },
  { vals = ["cat/pkg:*", "cat/pkg:="], status = true },
  { vals = ["cat/pkg:*", "cat/pkg"], status = true },
  { vals = ["cat/pkg:=", "cat/pkg"], status = true },
  # subslots
  { vals = ["cat/pkg:0/1", "cat/pkg:0/2"], status = false },
  { vals = ["cat/pkg:0/1", "cat/pkg:0"], status = true },
  { vals = ["cat/pkg:0/1", "cat/pkg:*"], status = true },
  { vals = ["cat/pkg:0/1", "cat/pkg:="], status = true },
  { vals = ["cat/pkg:0/1", "cat/pkg"], status = true },
  # use deps
  { vals = ["cat/pkg", "cat/pkg[a]"], status = true },
  { vals = ["cat/pkg[a]", "cat/pkg[a,b]"], status = true },
  { vals = ["cat/pkg[a]", "cat/pkg[b]"], status = true },
  { vals = ["cat/pkg[a]", "cat/pkg[a=]"], status = true },
  { vals = ["cat/pkg[a]", "cat/pkg[!a=]"], status = true },
  { vals = ["cat/pkg[a]", "cat/pkg[a?]"], status = true },
  { vals = ["cat/pkg[a]", "cat/pkg[!a?]"], status = true },
  { vals = ["cat/pkg[-a]", "cat/pkg[a]"], status = false },
  { vals = ["cat/pkg[-a]", "cat/pkg[b]"], status = true },
  # repo deps
  { vals = ["cat/pkg::a", "cat/pkg::b"], status = false },
  # unversioned and versioned
  { vals = ["cat/pkg", ">cat/pkg-1"], status = true },
]

sorting = [
  ## Attributes
  # categories
  { sorted = ["a/pkg", "b/pkg", "c/pkg"], equal = false },
  # packages
  { sorted = ["cat/a", "cat/b", "cat/c"], equal = false },
  # blocks
  { sorted = ["a/b", "!!a/b", "!a/b"], equal = false },
  # slots
  { sorted = ["a/b:0", "a/b:1", "a/b:2"], equal = false },
  # subslots
  { sorted = ["a/b:0/0", "a/b:0/1", "a/b:0/2"], equal = false },
  # slot operators
  { sorted = ["a/b", "a/b:=", "a/b:*", "a/b:0", "a/b:0=", "a/b:0/1="], equal = false },
  # use deps
  { sorted = ["a/b[a]", "a/b[b]", "a/b[c]"], equal = false },
  # precedence
  { sorted = [
    # category
    "!>a/b-2-r2:2/2::b[b]", "!!=b/a-1-r1:1/1::a[a]",
    # package
    "!>b/a-2-r2:2/2::b[b]", "!!=b/b-1-r1:1/1::a[a]",
    # version
    "!>b/b-1-r2:2/2::b[b]", "!!=b/b-2-r1:1/1::a[a]",
    # revision
    "!>b/b-2-r1:2/2::b[b]", "!!=b/b-2-r2:1/1::a[a]",
    # operator
    "!=b/b-2-r2:2/2::b[b]", "!!>b/b-2-r2:1/1::a[a]",
    # blocker
    "!!>b/b-2-r2:2/2::b[b]", "!>b/b-2-r2:1/1::a[a]",
    # slot
    "!>b/b-2-r2:1/1::b[b]", "!>b/b-2-r2:2/1::a[a]",
    # subslot
    "!>b/b-2-r2:2/1::b[b]", "!>b/b-2-r2:2/2::a[a]",
    # slot op
    "!>b/b-2-r2:2/2::b[b]", "!>b/b-2-r2:2/2=::a[a]",
    # use deps
    "!>b/b-2-r2:2/2=::b[a]", "!>b/b-2-r2:2/2=::a[b]",
    # repo
    "!>b/b-2-r2:2/2=::a[b]", "!>b/b-2-r2:2/2=::b[b]",
    ], equal = false },

  ## Versions
  # equal versions shouldn't be sorted
  { sorted = ["=a/b-0", "=a/b-00", "=a/b-0-r0"], equal = true },
  { sorted = ["=a/b-1.0.2", "=a/b-1.0.2-r0", "=a/b-1.000.2"], equal = true },
  # simple versions
  { sorted = ["=a/b-0", "=a/b-1", "=a/b-2"], equal = false },
  { sorted = ["=a/b-1.1", "=a/b-1.10", "=a/b-1.100"], equal = false },
  # operators
  { sorted = ["<a/b-1", "<=a/b-1", "=a/b-1", "=a/b-1*", "~a/b-1", ">=a/b-1", ">a/b-1"], equal = false },
  # letter suffixes
  { sorted = ["=a/b-1a", "=a/b-1b", "=a/b-1y", "=a/b-1z"], equal = false },
  # release suffixes
  { sorted = ["=a/b-1_alpha", "=a/b-1_beta", "=a/b-1_pre", "=a/b-1_rc", "=a/b-1_p"], equal = false },
  { sorted = ["=a/b-1_p0", "=a/b-1_p1", "=a/b-1_p2"], equal = false },
  # revisions
  { sorted = ["=a/b-1-r0", "=a/b-1-r1", "=a/b-1-r2"], equal = false },
]
