text:
function assemble_endpoints(betweenness, S, P, sigma, s)

    betweenness[s] += length(S) - 1
    source_ration = [k => 0.0 for k = S]

    while length(S) > 0

        node = pop!(S)
        coeff = (1.0 + source_ration[node]) / sigma[node]

        for v in P[node]

            source_ration[v] += sigma[v] * coeff

        end

        if node != s

            betweenness[node] += source_ration[node] + 1

        end

    end

    return betweenness

end

max_stars_repo_name: mpuk/GraphAnalysis

max_issues_repo_name: mpuk/GraphAnalysis

max_forks_repo_name: mpuk/GraphAnalysis


text:
# dependencies
using LFAToolkit
using LinearAlgebra
using CSV
using DataFrames

# setup
dimension = 3
numbercomponents = 3
mesh = Mesh3D(1.0, 1.0, 1.0)
convergencefactors = DataFrame()

# test range
for fineP = 1:3
    println("fine_p = ", 2^fineP)
    for coarseP = 0:fineP-1
        println("  coarse_p = ", 2^coarseP)
        # setup
        # -- bases
        coarsep = 2^coarseP
        finep = 2^fineP
        finebasis = TensorH1LagrangeBasis(finep + 1, finep + 1, numbercomponents, dimension)
        coarsebasis =
            TensorH1LagrangeBasis(coarsep + 1, finep + 1, numbercomponents, dimension)
        ctofbasis = TensorH1LagrangeBasis(
            coarsep + 1,
            finep + 1,
            numbercomponents,
            dimension,
            lagrangequadrature = true,
        )

        # constants
        e = 1E6                             # Young's modulus
        ν = 0.3                             # Poisson's ratio
        λ = e * ν / ((1 + ν) * (1 - 2 * ν)) # Lamé parameters
        μ = e / (2 * (1 + ν))

        function linearelasticityweakform(deltadu::Array{Float64}, w::Array{Float64})
            # strain
            dϵ = (deltadu + deltadu') / 2
            # strain energy
            dσ_11 = (λ + 2μ) * dϵ[1, 1] + λ * dϵ[2, 2] + λ * dϵ[3, 3]
            dσ_22 = λ * dϵ[1, 1] + (λ + 2μ) * dϵ[2, 2] + λ * dϵ[3, 3]
            dσ_33 = λ * dϵ[1, 1] + λ * dϵ[2, 2] + (λ + 2μ) * dϵ[3, 3]
            dσ_12 = μ * dϵ[1, 2]
            dσ_13 = μ * dϵ[1, 3]
            dσ_23 = μ * dϵ[2, 3]
            dσ = [dσ_11 dσ_12 dσ_13; dσ_12 dσ_22 dσ_23; dσ_13 dσ_23 dσ_33]

            # delta dv
            deltadv = dσ * w[1]

            return [deltadv']
        end

        # linear elasticity operators
        function makeoperator(basis::TensorBasis)
            inputs = [
                OperatorField(basis, [EvaluationMode.gradient], "gradent of deformation"),
                OperatorField(
                    basis,
                    [EvaluationMode.quadratureweights],
                    "quadrature weights",
                ),
            ]
            outputs = [
                OperatorField(
                    basis,
                    [EvaluationMode.gradient],
                    "test function gradient of deformation",
                ),
            ]
            return Operator(linearelasticityweakform, mesh, inputs, outputs)
        end
        fineoperator = makeoperator(finebasis)
        coarseoperator = makeoperator(coarsebasis)

        # -- smoothers
        identity = IdentityPC(fineoperator)
        chebyshev = Chebyshev(fineoperator)

        # -- p-multigrid preconditioner
        multigrid = PMultigrid(fineoperator, coarseoperator, identity, [ctofbasis])

        # compute smoothing factor
        # -- setup
        numbersteps = 8
        θ_min = -π / 2
        θ_max = 3π / 2
        θ_step = 2π / numbersteps
        θ_range = θ_min:θ_step:(θ_max-θ_step)

        # -- compute
        maxeigenvalue = zeros(4)
        θ_maxeigenvalue = -1 * ones(4, dimension)
        for i = 1:numbersteps, j = 1:numbersteps, k = 1:numbersteps
            θ = [θ_range[i], θ_range[j], θ_range[k]]
            if sqrt(abs(θ[1])^2 + abs(θ[2])^2 + abs(θ[3])^2) > π / 128
                M = computesymbols(multigrid, [0], [0, 0], θ)
                for k = 1:4
                    S = computesymbols(chebyshev, [k], θ)
                    eigenvalues = [abs(val) for val in eigvals(S * M * S)]
                    currentmaxeigenvalue = max(eigenvalues...)
                    if (currentmaxeigenvalue > maxeigenvalue[k])
                        maxeigenvalue[k] = currentmaxeigenvalue
                        θ_maxeigenvalue[k, :] = θ / π
                    end
                end
            end
        end
        for k = 1:4
            append!(
                convergencefactors,
                DataFrame(
                    finep = finep,
                    coarsep = coarsep,
                    k = k,
                    θ = θ_maxeigenvalue[k, :],
                    ρ = maxeigenvalue[k],
                ),
            )
        end
    end
end

CSV.write("two-grid-linear-elasticity.csv", convergencefactors)

ext: jl


text:
function check_op(ir::IRCode, domtree::DomTree, @nospecialize(op), use_bb::Int, use_idx::Int)
    if isa(op, SSAValue)
        def_bb = block_for_inst(ir.cfg, op.id)
        if (def_bb == use_bb)
            @assert op.id < use_idx
        else
            if !dominates(domtree, def_bb, use_bb)
                #@error "Basic Block $def_bb does not dominate block $use_bb"
                error()
            end
        end
    elseif isa(op, Union{SlotNumber, TypedSlot})
        #@error "Left over slot detected in converted IR"
        error()
    end
end

function verify_ir(ir::IRCode)
    # For now require compact IR
    @assert isempty(ir.new_nodes)
    domtree = construct_domtree(ir.cfg)
    for (bb, idx, stmt) in bbidxstmt(ir)
        if isa(stmt, PhiNode)
            @assert length(stmt.edges) == length(stmt.values)
            for i = 1:length(stmt.edges)
                edge = stmt.edges[i]
                if !(edge in ir.cfg.blocks[bb].preds)
                    error()
                end
                isassigned(stmt.values, i) || continue
                val = stmt.values[i]
                phiT = ir.types[idx]
                if isa(val, SSAValue)
                    if !(ir.types[val.id] ⊑ phiT)
                        #@error """
                        #    PhiNode $idx, has operand $(val.id), whose type is not a sub lattice element.
                        #    PhiNode type was $phiT
                        #    Value type was $(ir.types[val.id])
                        #"""
                        #error()
                    end
                end
                check_op(ir, domtree, val, edge, last(ir.cfg.blocks[stmt.edges[i]].stmts)+1)
            end
        else
            for op in userefs(stmt)
                op = op[]
                check_op(ir, domtree, op, bb, idx)
            end
        end
    end
end

max_stars_repo_name: blegat/julia

max_issues_repo_name: blegat/julia

max_forks_repo_name: blegat/julia


text:
using Dates
using JuliaDB

path = "./test/Sample data/PatientOverview_test.xlsx"
sheet = "Sheet1"
startdate = Date("2019-01-01")
enddate = Date("2019-02-01")
mastercalendar = HP.MasterCalendar(startdate,enddate)

columns = Dict(:Consultation => "Consultation" , :Telefon =>"Telephone" , :TTE => "TTE", :AEKG => "AEKG",  :MR => "MR", :Holter=>"Holter")
patients, visits = HP.readPatientTable(path,sheet,columns,mastercalendar)

path_resourceOverview = "./test/Sample data/GUCHamb_Timeslot_test.xlsx"
sheet_amb = "GUCH AMB"
sheet_resources = "External"
GUCHAmb_resources,timeslots,workpattern = Hospitalplanning.readWorkPattern(path_resourceOverview,sheet_amb)
external_resources = Hospitalplanning.readWorkPattern!(GUCHAmb_resources,timeslots,workpattern,path_resourceOverview,sheet_resources,)
GUCHAmb_resources[1]
path_TimeDelta = "./test/Sample data/GUCHamb_timeDelta.csv"
timeDelta = HP.loadTimeDelta(path_TimeDelta)
HP.generateCalendarFromPattern!(timeslots,GUCHAmb_resources,workpattern,mastercalendar,0.5)
timeslots2 = ndsparse(timeslots)

testpath_resources = "./test/Sample data/resourcetest_output.csv"
HP.save(GUCHAmb_resources,testpath_resources)
resources_read = HP.loadresources(testpath_resources)
@test GUCHAmb_resources == resources_read

testpath_patient = "./test/Sample data/patienttest_output.csv"
HP.save(patients,testpath_patient)
patients_read = HP.loadpatients(testpath_patient)
@test patients == patients_read

testpath_visits = "./test/Sample data/visittest_output.csv"
HP.save(visits,testpath_visits)
visits_read = HP.loadvisits(testpath_visits)
@test visits == visits_read

testpath_timeslots = "./test/Sample data/timeslottest_output.csv"
HP.save(timeslots,testpath_timeslots)
timeslots_read = HP.loadtimeslots(testpath_timeslots)
@test timeslots == timeslots_read
timeslots2_read = ndsparse(timeslots_read)
@test timeslots2 == timeslots2_read

testpath_solution_input = "./test/Sample data/solutiontest_input.csv"
testpath_solution_output = "./test/Sample data/solutiontest_output.csv"
solution_read = HP.loadsolution(testpath_solution_input)

HP.save(solution_read,testpath_solution_output)
solution_read2 = HP.loadsolution(testpath_solution_output)

@test solution_read2 == solution_read


text:
"""
    infer_geometry_based_bonds!(crystal, include_bonds_across_periodic_boundaries::Bool)

Infers bonds by first finding which atoms share a Voronoi face, and then bond the atoms if the distance
 between them is less than the sum of the covalent radius of the two atoms (plus a tolerance).

# Arguments
- `crystal::Crystal`: The crystal structure
- `include_bonds_across_periodic_boundaries::Bool`: Whether to check across the periodic boundaries
- `r::Float`: voronoi radius, Å
- `pad::Float`: amount to pad covalent radii, Å
- `covalent_radii::Dict{Symbol,Float64}`: See [`covalent_radii`](@ref)
"""
function infer_geometry_based_bonds!(crystal::Crystal,
        include_bonds_across_periodic_boundaries::Bool;
        r::Float64=6., pad::Float64=0.,
        covalent_radii::Dict{Symbol,Float64}=rc[:covalent_radii])
    @assert ne(crystal.bonds) == 0 @sprintf("The crystal %s already has bonds. Remove them with the `remove_bonds!` function before inferring new ones.", crystal.name)
    dm = Xtals.distance_matrix(crystal, include_bonds_across_periodic_boundaries)
    for i = 1:crystal.atoms.n
        for j in bonded_atoms(crystal, i, dm, r, pad, covalent_radii)
            add_edge!(crystal.bonds, i, j)
        end
    end
    bond_sanity_check(crystal)
end

"""
    ids_bonded = bonded_atoms(crystal, i, dm; r=6., σ=3.)

Returns the ids of atoms that are bonded to atom `i` by determining bonds using a Voronoi method and covalent radius data (see [`covalent_radii`](@ref))

# Arguments
- `crystal::Crystal`: Crystal structure in which the bonded atoms will be determined
- `i::Int`: Index of the atom we want to determine the bonds of
- `dm::Array{Float64, 2}`: The distance matrix, see [`distance_matrix`](@ref)
- `r::Float64`: The maximum distance used to determine the neighborhood of atom `i`
- `covalent_radii::Dict{Symbol, Float64}`: Cordero parameter dictionary. See [`covalent_radii`](@ref)
- `pad::Float64`: The amount to pad the covalent radius in Å

# Returns
- `ids_bonded::Array{Int, 1}`: A list of indices of atoms bonded to atom `i`
"""
function bonded_atoms(crystal::Crystal, i::Int, dm::Array{Float64, 2},
        r::Float64, pad::Float64, covalent_radii::Dict{Symbol, Float64})
    species_i = crystal.atoms.species[i]
    ids_neighbors, xs, _ = neighborhood(crystal, i, r, dm)
    ids_shared_voro_faces = _shared_voronoi_faces(ids_neighbors, xs)
    ids_bonded = Int[]
    for j in ids_shared_voro_faces
        species_j = crystal.atoms.species[j]
        # sum of covalent radii
        radii_sum = covalent_radii[species_j] + covalent_radii[species_i]
        # margin = σ e.s.d.s, unless that's too small
        max_dist = radii_sum + pad
        if dm[i, j] ≤ max_dist
            push!(ids_bonded, j)
        end
    end
    return ids_bonded
end

"""
    ids_shared_voro_face = _shared_voronoi_faces(ids_neighbors, xs)

Of the neighboring atoms, find those that share a Voronoi face.

# Arguments
- `ids_neighbors::Array{Int, 1}`: indices of atoms within the neighborhood of a specific atom.
- `xs::Array{Array{Float64, 1}, 1}`: array of Cartesian position of the atoms within the neighborhood of a specific atom, relative to the specific atom.

# Returns
- `ids_shared_voro_face::Array{Int, 1}`: indices of atoms that share a Voronoi face with a specific atom
"""
function _shared_voronoi_faces(ids_neighbors::Array{Int,1}, xs::Array{Array{Float64,1},1})
    if isnothing(rc[:scipy])
        error("Python dependency scipy not loaded.")
    else
        scipy = rc[:scipy]
    end
    # first element of xs is the point itself, the origin
    @assert length(ids_neighbors) == (length(xs) - 1)
    voro = scipy.Voronoi(xs)
    rps = voro.ridge_points # connection with atom zero are connection with atom i
    ids_shared_voro_face = Int[] # corresponds to xs, not to atoms of crystal
    for k = 1:size(rps)[1]
        if sort(rps[k, :])[1] == 0 # a shared face with atom i!
            push!(ids_shared_voro_face, sort(rps[k, :])[2])
        end
    end
    # zero based indexing in Scipy accounted for since xs[0] is origin, atom i.
    return ids_neighbors[ids_shared_voro_face]
end

"""
    ids_neighbors, xs, rs = neighborhood(crystal, i, r, dm)

Find and characterize the neighborhood of atom `i` in the crystal `crystal`.
A neighborhood is defined as all atoms within a distance `r` from atom `i`.
The distance matrix `dm` is used to find the distances of all other atoms in the crystal from atom `i`.

# Arguments
- `crystal::Crystal`: crystal structure
- `i::Int`: Index of the atom (in `crystal`) which the neighborhood is to be characterized.
- `r::Float64`: The maximum distance the neighborhood will be characterized.
- `dm::Array{Float64, 2}`: The distance matrix, see [`distance_matrix`](@ref)

# Returns
- `ids_neighbors::Array{Int, 1}`: indices of `crystal.atoms` within the neighborhood of atom `i`.
- `xs::Array{Array{Float64, 1}, 1}`: array of Cartesian positions of the atoms surrounding atom `i`.
    The nearest image convention has been applied to find the nearest periodic image. Also, the coordinates of atom `i`
    have been subtracted off from these coordinates so that atom `i` lies at the origin of this new coordinate system.
    The first vector in `xs` is `[0, 0, 0]` corresponding to atom `i`.
    The choice of type is for the Voronoi decomposition in Scipy.
- `rs::Array{Float64, 1}`: list of distances of the neighboring atoms from atom `i`.
"""
function neighborhood(crystal::Crystal, i::Int, r::Float64, dm::Array{Float64, 2})
    # get indices of atoms within a distance r of atom i
    #  the greater than zero part is to not include itself
    ids_neighbors = findall((dm[:, i] .> 0.0) .& (dm[:, i] .< r))
    # rs is the list of distance of these neighbors from atom i
    rs = [dm[i, id_n] for id_n in ids_neighbors]
    @assert all(rs .< r)
    # xs is a list of Cartesian coords of the neighborhood
    #  coords of atom i are subtracted off
    #  first entry is coords of atom i, the center, the zero vector
    #  remaining entries are neighbors
    # this list is useful to pass to Voronoi for getting Voronoi faces
    #  of the neighborhood.
    xs = [[0.0, 0.0, 0.0]] # this way atom zero is itself
    for j in ids_neighbors
        # subtract off atom i, apply nearest image
        xf = crystal.atoms.coords.xf[:, j] - crystal.atoms.coords.xf[:, i]
        nearest_image!(xf)
        x = crystal.box.f_to_c * xf
        push!(xs, x)
    end
    return ids_neighbors, xs , rs
end

max_stars_repo_name: SimonEnsemble/XtalsPyTools

max_issues_repo_name: SimonEnsemble/XtalsPyTools


text:
# Test for Pulse arm

using MAB
import PyPlot

# Create different Sinusoidal arms
a1  = Arms.Pulse( 40, 0, 5 )
a2  = Arms.Pulse( 40, 20, 5 )

# Plot the rewards
noOfTimeSteps   = 100
noOfIterations  = 1000
rAvg1   = zeros( Float64, noOfTimeSteps )
rAvg2   = zeros( Float64, noOfTimeSteps )
for i ∈ 1:noOfIterations
    rAvg1   = rAvg1 + [ Arms.pull!(a1) for i=1:noOfTimeSteps ];
    rAvg2   = rAvg2 + [ Arms.pull!(a2) for i=1:noOfTimeSteps ];
    Arms.reset!( a1 );
    Arms.reset!( a2 );
end
rAvg1 = rAvg1/noOfIterations;
rAvg2 = rAvg2/noOfIterations;

fig     = PyPlot.figure()
PyPlot.plot( 1:noOfTimeSteps, rAvg1, label = "a1" )
PyPlot.plot( 1:noOfTimeSteps, rAvg2, label = "a2" )
ax = PyPlot.gca()
PyPlot.grid()
ax[:set_ylim]( [-0.20,+1.20] )
PyPlot.legend()


text:
# This file was generated by the Julia Swagger Code Generator
# Do not modify this file directly. Modify the swagger specification instead.

mutable struct IoK8sApiRbacV1beta1RoleBinding <: SwaggerModel
    apiVersion::Any # spec type: Union{ Nothing, String } # spec name: apiVersion
    kind::Any # spec type: Union{ Nothing, String } # spec name: kind
    metadata::Any # spec type: Union{ Nothing, IoK8sApimachineryPkgApisMetaV1ObjectMeta } # spec name: metadata
    roleRef::Any # spec type: Union{ Nothing, IoK8sApiRbacV1beta1RoleRef } # spec name: roleRef
    subjects::Any # spec type: Union{ Nothing, Vector{IoK8sApiRbacV1beta1Subject} } # spec name: subjects

    function IoK8sApiRbacV1beta1RoleBinding(;apiVersion=nothing, kind=nothing, metadata=nothing, roleRef=nothing, subjects=nothing)
        o = new()
        validate_property(IoK8sApiRbacV1beta1RoleBinding, Symbol("apiVersion"), apiVersion)
        setfield!(o, Symbol("apiVersion"), apiVersion)
        validate_property(IoK8sApiRbacV1beta1RoleBinding, Symbol("kind"), kind)
        setfield!(o, Symbol("kind"), kind)
        validate_property(IoK8sApiRbacV1beta1RoleBinding, Symbol("metadata"), metadata)
        setfield!(o, Symbol("metadata"), metadata)
        validate_property(IoK8sApiRbacV1beta1RoleBinding, Symbol("roleRef"), roleRef)
        setfield!(o, Symbol("roleRef"), roleRef)
        validate_property(IoK8sApiRbacV1beta1RoleBinding, Symbol("subjects"), subjects)
        setfield!(o, Symbol("subjects"), subjects)
        o
    end
end # type IoK8sApiRbacV1beta1RoleBinding

const _property_map_IoK8sApiRbacV1beta1RoleBinding = Dict{Symbol,Symbol}(Symbol("apiVersion")=>Symbol("apiVersion"), Symbol("kind")=>Symbol("kind"), Symbol("metadata")=>Symbol("metadata"), Symbol("roleRef")=>Symbol("roleRef"), Symbol("subjects")=>Symbol("subjects"))
const _property_types_IoK8sApiRbacV1beta1RoleBinding = Dict{Symbol,String}(Symbol("apiVersion")=>"String", Symbol("kind")=>"String", Symbol("metadata")=>"IoK8sApimachineryPkgApisMetaV1ObjectMeta", Symbol("roleRef")=>"IoK8sApiRbacV1beta1RoleRef", Symbol("subjects")=>"Vector{IoK8sApiRbacV1beta1Subject}")
Base.propertynames(::Type{ IoK8sApiRbacV1beta1RoleBinding }) = collect(keys(_property_map_IoK8sApiRbacV1beta1RoleBinding))
Swagger.property_type(::Type{ IoK8sApiRbacV1beta1RoleBinding }, name::Symbol) = Union{Nothing,eval(Base.Meta.parse(_property_types_IoK8sApiRbacV1beta1RoleBinding[name]))}
Swagger.field_name(::Type{ IoK8sApiRbacV1beta1RoleBinding }, property_name::Symbol) =  _property_map_IoK8sApiRbacV1beta1RoleBinding[property_name]

function check_required(o::IoK8sApiRbacV1beta1RoleBinding)
    (getproperty(o, Symbol("roleRef")) === nothing) && (return false)
    true
end

function validate_property(::Type{ IoK8sApiRbacV1beta1RoleBinding }, name::Symbol, val)
end


text:
"""
`categoricalselector(v::AbstractArray, f=filter)`

Create as many checkboxes as the unique elements of `v` and use them to select `v`. By default it returns
a filtered version of `v`: use `categoricalselector(v, map)` to get the boolean vector of whether each element is
selected.
"""
function categoricalselector(v::AbstractArray, f=filter; values=unique(v), value=values, label=nothing, kwargs...)
    cb = checkboxes(values; value=value, kwargs...)
    func = t -> ismissing(t) ? any(ismissing, cb[]) : t in cb[]
    data = [:checkboxes => cb, :function => func]
    wdg = Widget{:categoricalselector}(data, output = map(x -> f(func, v), cb))
    @layout! wdg :checkboxes
    label!(wdg, label)
end

"""
`rangeselector(v::AbstractArray, f=filter)`

Create a `rangepicker` as wide as the extrema of `v` and uses to select `v`. By default it returns
a filtered version of `v`: use `rangeselector(v, map)` to get the boolean vector of whether each element is
selected. Missing data is excluded from the range automatically.
"""
function rangeselector(v::AbstractArray{<:Union{Real, Missing}}, f=filter;
    digits=6, vskip=1em, min=minimum(skipnan(skipmissing(v))), max=maximum(skipnan(skipmissing(v))), n=50, label=nothing, kwargs...)

    min = floor(min, digits=digits)
    max = ceil(max, digits=digits)
    step = round((max-min)/n, sigdigits=digits)
    range = min:step:(max+step)
    extrema = InteractBase.rangepicker(range; kwargs...)
    changes = extrema[:changes]
    func = t -> !ismissing(t) && ((min, max) = extrema[]; min <= t <= max)
    data = [:extrema => extrema, :changes => changes, :function => func]
    output = map(t -> f(func, v), changes)
    wdg = Widget{:rangeselector}(data, output=output)
    @layout! wdg :extrema
    label!(wdg, label)
end

"""
`selector(v::AbstractArray, f=filter)`

Create a `textbox` where the user can type in an anonymous function that is used to select `v`. `_` can be used
to denote the funcion argument, e.g. `_ > 0`. By default it returns
a filtered version of `v`: use `selector(v, map)` to get the boolean vector of whether each element is
selected
"""
function selector(v::AbstractArray, f=filter; label=nothing, kwargs...)
    tb = textbox("insert condition")
    changes = tb[:changes]
    func = Observable{Function}(x -> true)
    on(x -> update_function!(func, x, parse=parsepredicate), tb)
    data = [:textbox => tb, :changes => changes, :function => func]
    wdg = Widget{:selector}(data; output=map(t->f(func[], v), changes))
    @layout! wdg :textbox
    label!(wdg, label)
end

label!(v, ::Nothing) = v
function label!(v::Widget, l::AbstractString)
    v[:label] = l
    g = Widgets.layout(v)
    Widget(v, layout = x -> Widgets.div(x[:label], g(x)))
end

for s in [:categoricalselector, :rangeselector, :selector]
    @eval $s(t, c::Symbol, args...; kwargs...) = $s(getproperty(t, c), args...; label = string(c), kwargs...)
end

function parsepredicate(s)
    occursin(r"^(\s)*$", s) && return :(t -> true)
    expr = Meta.parse("_ -> " * s)
    sym = gensym()
    flag = Ref(false)
    expr = MacroTools.postwalk(x -> x == :(_) ? (flag[] = true; sym) : x, Meta.parse(s))
    flag[] ? Expr(:->, sym, expr) : expr
end


text:
# Utilities:
function draw_fullscreen(vao_id)
    glBindVertexArray(vao_id)
    glDrawArrays(GL_TRIANGLES, 0, 3)
    glBindVertexArray(0)
    return
end

struct PostprocessPrerender end

function (sp::PostprocessPrerender)()
    glDepthMask(GL_TRUE)
    glDisable(GL_DEPTH_TEST)
    glDisable(GL_BLEND)
    glDisable(GL_CULL_FACE)
    return
end

const PostProcessROBJ = RenderObject{PostprocessPrerender}

rcpframe(x) = 1f0 ./ Vec2f(x[1], x[2])

struct PostProcessor{F}
    robjs::Vector{PostProcessROBJ}
    render::F
end

function empty_postprocessor(args...; kwargs...)
    PostProcessor(PostProcessROBJ[], screen -> nothing)
end

function ssao_postprocessor(framebuffer)
    # Add missing buffers
    if !haskey(framebuffer.buffers, :position)
        glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.id[1])
        position_buffer = Texture(
            Vec4f, size(framebuffer), minfilter = :nearest, x_repeat = :clamp_to_edge
        )
        attach_framebuffer(position_buffer, GL_COLOR_ATTACHMENT2)
        push!(framebuffer.buffers, :position => position_buffer)
    end
    if !haskey(framebuffer.buffers, :normal)
        glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.id[1])
        normal_occlusion_buffer = Texture(
            Vec4f, size(framebuffer), minfilter = :nearest, x_repeat = :clamp_to_edge
        )
        attach_framebuffer(normal_occlusion_buffer, GL_COLOR_ATTACHMENT3)
        push!(framebuffer.buffers, :normal_occlusion => normal_occlusion_buffer)
    end

    # Add buffers written in primary render (before postprocessing)
    if !(GL_COLOR_ATTACHMENT2 in framebuffer.render_buffer_ids)
        push!(framebuffer.render_buffer_ids, GL_COLOR_ATTACHMENT2)
    end
    if !(GL_COLOR_ATTACHMENT3 in framebuffer.render_buffer_ids)
        push!(framebuffer.render_buffer_ids, GL_COLOR_ATTACHMENT3)
    end

    # SSAO setup
    N_samples = 64
    lerp_min = 0.1f0
    lerp_max = 1.0f0
    kernel = map(1:N_samples) do i
        n = normalize([2.0rand() .- 1.0, 2.0rand() .- 1.0, rand()])
        scale = lerp_min + (lerp_max - lerp_min) * (i / N_samples)^2
        v = Vec3f(scale * rand() * n)
    end

    # compute occlusion
    shader1 = LazyShader(
        loadshader("postprocessing/fullscreen.vert"),
        loadshader("postprocessing/SSAO.frag"),
        view = Dict(
            "N_samples" => "$N_samples"
        )
    )
    data1 = Dict{Symbol, Any}(
        :position_buffer => framebuffer.buffers[:position],
        :normal_occlusion_buffer => framebuffer.buffers[:normal_occlusion],
        :kernel => kernel,
        :noise => Texture(
            [normalize(Vec2f(2.0rand(2) .- 1.0)) for _ in 1:4, __ in 1:4],
            minfilter = :nearest, x_repeat = :repeat
        ),
        :noise_scale => map(s -> Vec2f(s ./ 4.0), framebuffer.resolution),
        :projection => Observable(Mat4f(I)),
        :bias => Observable(0.025f0),
        :radius => Observable(0.5f0)
    )
    pass1 = RenderObject(data1, shader1, PostprocessPrerender(), nothing)
    pass1.postrenderfunction = () -> draw_fullscreen(pass1.vertexarray.id)

    # blur occlusion and combine with color
    shader2 = LazyShader(
        loadshader("postprocessing/fullscreen.vert"),
        loadshader("postprocessing/SSAO_blur.frag")
    )
    data2 = Dict{Symbol, Any}(
        :normal_occlusion => framebuffer.buffers[:normal_occlusion],
        :color_texture => framebuffer.buffers[:color],
        :ids => framebuffer.buffers[:objectid],
        :inv_texel_size => lift(rcpframe, framebuffer.resolution),
        :blur_range => Observable(Int32(2))
    )
    pass2 = RenderObject(data2, shader2, PostprocessPrerender(), nothing)
    pass2.postrenderfunction = () -> draw_fullscreen(pass2.vertexarray.id)

    full_render = screen -> begin
        fb = screen.framebuffer
        w, h = size(fb)

        # Setup rendering
        # SSAO - calculate occlusion
        glDrawBuffer(GL_COLOR_ATTACHMENT3)  # occlusion buffer
        glViewport(0, 0, w, h)
        # glClearColor(1, 1, 1, 1)            # 1 means no darkening
        # glClear(GL_COLOR_BUFFER_BIT)
        glDisable(GL_STENCIL_TEST)
        glEnable(GL_SCISSOR_TEST)

        for (screenid, scene) in screen.screens
            # Select the area of one leaf scene
            # This should be per scene because projection may vary between
            # scenes. It should be a leaf scene to avoid repeatedly shading
            # the same region (though this is not guaranteed...)
            isempty(scene.children) || continue
            a = pixelarea(scene)[]
            glScissor(minimum(a)..., widths(a)...)
            # update uniforms
            SSAO = scene.theme.SSAO
            data1[:projection][] = scene.camera.projection[]
            data1[:bias][] = Float32(to_value(get(SSAO, :bias, 0.025)))
            data1[:radius][] = Float32(to_value(get(SSAO, :radius, 0.5)))
            GLAbstraction.render(pass1)
        end

        # SSAO - blur occlusion and apply to color
        glDrawBuffer(GL_COLOR_ATTACHMENT0)  # color buffer
        for (screenid, scene) in screen.screens
            # Select the area of one leaf scene
            isempty(scene.children) || continue
            a = pixelarea(scene)[]
            glScissor(minimum(a)..., widths(a)...)
            # update uniforms
            SSAO = scene.theme.SSAO
            data2[:blur_range][] = Int32(to_value(get(SSAO, :blur, 2)))
            GLAbstraction.render(pass2)
        end
        glDisable(GL_SCISSOR_TEST)
    end

    PostProcessor([pass1, pass2], full_render)
end

"""
    fxaa_postprocessor(framebuffer)

Returns a PostProcessor that handles fxaa.
"""
function fxaa_postprocessor(framebuffer)
    # Add missing buffers
    if !haskey(framebuffer.buffers, :color_luma)
        glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.id[2])
        color_luma_buffer = Texture(
            RGBA{N0f8}, size(framebuffer), minfilter=:linear, x_repeat=:clamp_to_edge
        )
        attach_framebuffer(color_luma_buffer, GL_COLOR_ATTACHMENT0)
        push!(framebuffer.buffers, :color_luma => color_luma_buffer)
    end

    # calculate luma for FXAA
    shader1 = LazyShader(
        loadshader("postprocessing/fullscreen.vert"),
        loadshader("postprocessing/postprocess.frag")
    )
    data1 = Dict{Symbol, Any}(
        :color_texture => framebuffer.buffers[:color]
    )
    pass1 = RenderObject(data1, shader1, PostprocessPrerender(), nothing)
    pass1.postrenderfunction = () -> draw_fullscreen(pass1.vertexarray.id)

    # perform FXAA
    shader2 = LazyShader(
        loadshader("postprocessing/fullscreen.vert"),
        loadshader("postprocessing/fxaa.frag")
    )
    data2 = Dict{Symbol, Any}(
        :color_texture => framebuffer.buffers[:color_luma],
        :RCPFrame => lift(rcpframe, framebuffer.resolution),
    )
    pass2 = RenderObject(data2, shader2, PostprocessPrerender(), nothing)
    pass2.postrenderfunction = () -> draw_fullscreen(pass2.vertexarray.id)

    full_render = screen -> begin
        fb = screen.framebuffer
        w, h = size(fb)

        # FXAA - calculate LUMA
        glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.id[2])
        glDrawBuffer(GL_COLOR_ATTACHMENT0)  # color_luma buffer
        glViewport(0, 0, w, h)
        # necessary with negative SSAO bias...
        glClearColor(1, 1, 1, 1)
        glClear(GL_COLOR_BUFFER_BIT)
        GLAbstraction.render(pass1)

        # FXAA - perform anti-aliasing
        glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.id[1])
        glDrawBuffer(GL_COLOR_ATTACHMENT0)  # color buffer
        # glViewport(0, 0, w, h) # not necessary
        GLAbstraction.render(pass2)
    end

    PostProcessor([pass1, pass2], full_render)
end

"""
    to_screen_postprocessor(framebuffer)

Sets up a Postprocessor which copies the color buffer to the screen. Used as a
final step for displaying the screen.
"""
function to_screen_postprocessor(framebuffer)
    # draw color buffer
    shader = LazyShader(
        loadshader("postprocessing/fullscreen.vert"),
        loadshader("postprocessing/copy.frag")
    )
    data = Dict{Symbol, Any}(
        :color_texture => framebuffer.buffers[:color]
    )
    pass = RenderObject(data, shader, PostprocessPrerender(), nothing)
    pass.postrenderfunction = () -> draw_fullscreen(pass.vertexarray.id)

    full_render = screen -> begin
        fb = screen.framebuffer
        w, h = size(fb)

        # transfer everything to the screen
        glBindFramebuffer(GL_FRAMEBUFFER, 0)
        glViewport(0, 0, w, h)
        glClear(GL_COLOR_BUFFER_BIT)
        GLAbstraction.render(pass) # copy postprocess
    end

    PostProcessor([pass], full_render)
end


text:
#=--- CpuId / test / mockdb.jl --------------------------------------------=#

####################################################################################
#
#   R e c o r d e d    c p u i d    d u m p s

# Fake
push!(_mockdb, (Dict(
    ((0x00000000, 0x00000000) => (0x00000008, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000000, 0x00000000) => (0x80000008, 0x00000000, 0x00000000, 0x00000000)),
  ) => Dict{Symbol,Any}(
    :cpuvendor       => :Unknown,
    :cpuarchitecture => :Unknown,
    :cpucores        => 0,
    :cputhreads      => 0,
    :cachesize       => (),
    :cachelinesize   => 0,
    :simdbits        => sizeof(UInt)*8,
  )))

# Intel(R) Xeon(R) CPU E5-2670 0 @ 2.60GHz, no hypervisor
push!(_mockdb, (Dict(
    ((0x00000000, 0x00000000) => (0x0000000d, 0x756e6547, 0x6c65746e, 0x49656e69)),
    ((0x00000001, 0x00000000) => (0x000206d7, 0x24200800, 0x1fbee3ff, 0xbfebfbff)),
    ((0x00000002, 0x00000000) => (0x76035a01, 0x00f0b2ff, 0x00000000, 0x00ca0000)),
    ((0x00000003, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000004, 0x00000000) => (0x3c004121, 0x01c0003f, 0x0000003f, 0x00000000)),
    ((0x00000004, 0x00000001) => (0x3c004122, 0x01c0003f, 0x0000003f, 0x00000000)),
    ((0x00000004, 0x00000002) => (0x3c004143, 0x01c0003f, 0x000001ff, 0x00000000)),
    ((0x00000004, 0x00000003) => (0x3c07c163, 0x04c0003f, 0x00003fff, 0x00000006)),
    ((0x00000004, 0x00000004) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000005, 0x00000000) => (0x00000040, 0x00000040, 0x00000003, 0x00021120)),
    ((0x00000006, 0x00000000) => (0x00000077, 0x00000002, 0x00000009, 0x00000000)),
    ((0x00000007, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000008, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000009, 0x00000000) => (0x00000001, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000a, 0x00000000) => (0x07300403, 0x00000000, 0x00000000, 0x00000603)),
    ((0x0000000b, 0x00000000) => (0x00000001, 0x00000002, 0x00000100, 0x00000024)),
    ((0x0000000b, 0x00000001) => (0x00000005, 0x00000010, 0x00000201, 0x00000024)),
    ((0x0000000b, 0x00000002) => (0x00000000, 0x00000000, 0x00000002, 0x00000024)),
    ((0x0000000c, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000d, 0x00000000) => (0x00000007, 0x00000340, 0x00000340, 0x00000000)),
    ((0x80000000, 0x00000000) => (0x80000008, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000001, 0x00000000) => (0x00000000, 0x00000000, 0x00000001, 0x2c100800)),
    ((0x80000002, 0x00000000) => (0x20202020, 0x49202020, 0x6c65746e, 0x20295228)),
    ((0x80000003, 0x00000000) => (0x6e6f6558, 0x20295228, 0x20555043, 0x322d3545)),
    ((0x80000004, 0x00000000) => (0x20303736, 0x20402030, 0x30362e32, 0x007a4847)),
    ((0x80000005, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000006, 0x00000000) => (0x00000000, 0x00000000, 0x01006040, 0x00000000)),
    ((0x80000007, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000100)),
    ((0x80000008, 0x00000000) => (0x0000302e, 0x00000000, 0x00000000, 0x00000000)),
  ) => Dict{Symbol,Any}(
    :cpuvendor       => :Intel,
    :cpuarchitecture => :SandyBridge,
    :cpucores        => 8,
    :cputhreads      => 16,
    :cachesize       => (32768, 262144, 20971520),
    :cachelinesize   => 64,
    :simdbits        => 256,
  )))

# Intel(R) Xeon(R) CPU E5-2680 v2 @ 2.80GHz, with Xen hypervisor
push!(_mockdb, (Dict(
    ((0x00000000, 0x00000000) => (0x0000000d, 0x756e6547, 0x6c65746e, 0x49656e69)),
    ((0x00000001, 0x00000000) => (0x000306e4, 0x24200800, 0xffba2203, 0x178bfbff)),
    ((0x00000002, 0x00000000) => (0x76036301, 0x00f0b2ff, 0x00000000, 0x00ca0000)),
    ((0x00000003, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000004, 0x00000000) => (0x3c004121, 0x01c0003f, 0x0000003f, 0x00000000)),
    ((0x00000004, 0x00000001) => (0x3c004122, 0x01c0003f, 0x0000003f, 0x00000000)),
    ((0x00000004, 0x00000002) => (0x3c004143, 0x01c0003f, 0x000001ff, 0x00000000)),
    ((0x00000004, 0x00000003) => (0x3c07c163, 0x04c0003f, 0x00004fff, 0x00000006)),
    ((0x00000004, 0x00000004) => (0x04000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000005, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000006, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000007, 0x00000000) => (0x00000000, 0x00000281, 0x00000000, 0x00000000)),
    ((0x00000008, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000009, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000a, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000b, 0x00000000) => (0x00000001, 0x00000002, 0x00000100, 0x00000024)),
    ((0x0000000b, 0x00000001) => (0x00000005, 0x00000010, 0x00000201, 0x00000024)),
    ((0x0000000b, 0x00000002) => (0x00000000, 0x00000000, 0x00000000, 0x00000024)),
    ((0x0000000c, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000d, 0x00000000) => (0x00000007, 0x00000340, 0x00000340, 0x00000000)),
    ((0x40000000, 0x00000000) => (0x40000004, 0x566e6558, 0x65584d4d, 0x4d4d566e)),
    ((0x40000001, 0x00000000) => (0x00040002, 0x00000000, 0x00000000, 0x00000000)),
    ((0x40000002, 0x00000000) => (0x00000001, 0x40000000, 0x00000000, 0x00000000)),
    ((0x40000003, 0x00000000) => (0x00000006, 0x00000000, 0x002ab9d6, 0x00000001)),
    ((0x40000004, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000000, 0x00000000) => (0x80000008, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000001, 0x00000000) => (0x00000000, 0x00000000, 0x00000001, 0x28100800)),
    ((0x80000002, 0x00000000) => (0x20202020, 0x6e492020, 0x286c6574, 0x58202952)),
    ((0x80000003, 0x00000000) => (0x286e6f65, 0x43202952, 0x45205550, 0x36322d35)),
    ((0x80000004, 0x00000000) => (0x76203038, 0x20402032, 0x30382e32, 0x007a4847)),
    ((0x80000005, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000006, 0x00000000) => (0x00000000, 0x00000000, 0x01006040, 0x00000000)),
    ((0x80000007, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000008, 0x00000000) => (0x0000302e, 0x00000000, 0x00000000, 0x00000000)),
  ) => Dict{Symbol,Any}(
    :cpuvendor       => :Intel,
    :cpuarchitecture => :IvyBridge,
    :cpucores        => 8,
    :cputhreads      => 16,
    :cachesize       => (32768, 262144, 26214400),
    :cachelinesize   => 64,
    :simdbits        => 256,
  )))

# Intel(R) Xeon(R) CPU E5-2680 v3 @ 2.50GHz with Microsoft hypervisor
push!( _mockdb, (Dict(
    ((0x00000000, 0x00000000) => (0x0000000d, 0x756e6547, 0x6c65746e, 0x49656e69)),
    ((0x00000001, 0x00000000) => (0x000306f2, 0x00020800, 0xfed83203, 0x1f8bfbff)),
    ((0x00000002, 0x00000000) => (0x76036301, 0x00f0b5ff, 0x00000000, 0x00c10000)),
    ((0x00000003, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000004, 0x00000000) => (0x04000121, 0x01c0003f, 0x0000003f, 0x00000000)),
    ((0x00000004, 0x00000001) => (0x04000122, 0x01c0003f, 0x0000003f, 0x00000000)),
    ((0x00000004, 0x00000002) => (0x04000143, 0x01c0003f, 0x000001ff, 0x00000000)),
    ((0x00000004, 0x00000003) => (0x04000163, 0x04c0003f, 0x00005fff, 0x00000002)),
    ((0x00000004, 0x00000004) => (0x04000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000005, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000006, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000007, 0x00000000) => (0x00000000, 0x000023a9, 0x00000000, 0x00000000)),
    ((0x00000008, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000009, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000a, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000b, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000b, 0x00000001) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000c, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000d, 0x00000000) => (0x00000007, 0x00000340, 0x00000340, 0x00000000)),
    ((0x40000000, 0x00000000) => (0x40000006, 0x7263694d, 0x666f736f, 0x76482074)),
    ((0x40000001, 0x00000000) => (0x31237648, 0x00000000, 0x00000000, 0x00000000)),
    ((0x40000002, 0x00000000) => (0x00002580, 0x00060003, 0x00000012, 0x00004690)),
    ((0x40000003, 0x00000000) => (0x00000e7f, 0x000008b0, 0x00000002, 0x000017b2)),
    ((0x40000004, 0x00000000) => (0x0000002c, 0x00000fff, 0x00000000, 0x00000000)),
    ((0x40000005, 0x00000000) => (0x00000040, 0x00000200, 0x00002580, 0x00000000)),
    ((0x40000006, 0x00000000) => (0x0000004f, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000000, 0x00000000) => (0x80000008, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000001, 0x00000000) => (0x00000000, 0x00000000, 0x00000021, 0x20100800)),
    ((0x80000002, 0x00000000) => (0x65746e49, 0x2952286c, 0x6f655820, 0x2952286e)),
    ((0x80000003, 0x00000000) => (0x55504320, 0x2d354520, 0x30383632, 0x20337620)),
    ((0x80000004, 0x00000000) => (0x2e322040, 0x48473035, 0x0000007a, 0x00000000)),
    ((0x80000005, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000006, 0x00000000) => (0x00000000, 0x00000000, 0x01006040, 0x00000000)),
    ((0x80000007, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000008, 0x00000000) => (0x0000302a, 0x00000000, 0x00000000, 0x00000000)),
    ) => Dict{Symbol,Any}(
      :cpuvendor       => :Intel,
      :cpuarchitecture => :Haswell,
      :cpucores        => 1,
      :cputhreads      => 2,
      :cachesize       => (32768, 262144, 31457280),
      :cachelinesize   => 64,
      :simdbits        => 256,
    )))

# Intel(R) Xeon(R) CPU E3-1225 v5 @ 3.30GHz
push!(_mockdb, (Dict(
    ((0x00000000, 0x00000000) => (0x0000000d, 0x756e6547, 0x6c65746e, 0x49656e69)),
    ((0x00000001, 0x00000000) => (0x000206d7, 0x24200800, 0x1fbee3ff, 0xbfebfbff)),
    ((0x00000002, 0x00000000) => (0x76035a01, 0x00f0b2ff, 0x00000000, 0x00ca0000)),
    ((0x00000003, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000004, 0x00000000) => (0x3c004121, 0x01c0003f, 0x0000003f, 0x00000000)),
    ((0x00000004, 0x00000001) => (0x3c004122, 0x01c0003f, 0x0000003f, 0x00000000)),
    ((0x00000004, 0x00000002) => (0x3c004143, 0x01c0003f, 0x000001ff, 0x00000000)),
    ((0x00000004, 0x00000003) => (0x3c07c163, 0x04c0003f, 0x00003fff, 0x00000006)),
    ((0x00000004, 0x00000004) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000005, 0x00000000) => (0x00000040, 0x00000040, 0x00000003, 0x00021120)),
    ((0x00000006, 0x00000000) => (0x00000077, 0x00000002, 0x00000009, 0x00000000)),
    ((0x00000007, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000008, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000009, 0x00000000) => (0x00000001, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000a, 0x00000000) => (0x07300403, 0x00000000, 0x00000000, 0x00000603)),
    ((0x0000000b, 0x00000000) => (0x00000001, 0x00000002, 0x00000100, 0x00000024)),
    ((0x0000000b, 0x00000001) => (0x00000005, 0x00000010, 0x00000201, 0x00000024)),
    ((0x0000000b, 0x00000002) => (0x00000000, 0x00000000, 0x00000002, 0x00000024)),
    ((0x0000000c, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000d, 0x00000000) => (0x00000007, 0x00000340, 0x00000340, 0x00000000)),
    ((0x80000000, 0x00000000) => (0x80000008, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000001, 0x00000000) => (0x00000000, 0x00000000, 0x00000001, 0x2c100800)),
    ((0x80000002, 0x00000000) => (0x20202020, 0x49202020, 0x6c65746e, 0x20295228)),
    ((0x80000003, 0x00000000) => (0x6e6f6558, 0x20295228, 0x20555043, 0x322d3545)),
    ((0x80000004, 0x00000000) => (0x20303736, 0x20402030, 0x30362e32, 0x007a4847)),
    ((0x80000005, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000006, 0x00000000) => (0x00000000, 0x00000000, 0x01006040, 0x00000000)),
    ((0x80000007, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000100)),
    ((0x80000008, 0x00000000) => (0x0000302e, 0x00000000, 0x00000000, 0x00000000)),
  ) => Dict{Symbol,Any}(
    :cpuvendor       => :Intel,
    :cpuarchitecture => :SandyBridge,
    :cpucores        => 8,
    :cputhreads      => 16,
    :cachesize       => (32768, 262144, 20971520),
    :cachelinesize   => 64,
    :simdbits        => 256,
  )))

# Intel(R) Xeon(R) CPU X5570 @ 2.93GHz, with VMware hypervisor
push!(_mockdb, (Dict(
    ((0x00000000, 0x00000000) => (0x0000000b, 0x756e6547, 0x6c65746e, 0x49656e69)),
    ((0x00000001, 0x00000000) => (0x000106a5, 0x00010800, 0x81b82209, 0x0fabfbff)),
    ((0x00000002, 0x00000000) => (0x55035a01, 0x00f0b2e4, 0x00000000, 0x09ca212c)),
    ((0x00000003, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000004, 0x00000000) => (0x00000121, 0x01c0003f, 0x0000003f, 0x00000000)),
    ((0x00000004, 0x00000000) => (0x00000121, 0x01c0003f, 0x0000003f, 0x00000000)),
    ((0x00000004, 0x00000001) => (0x00000122, 0x00c0003f, 0x0000007f, 0x00000000)),
    ((0x00000004, 0x00000002) => (0x00000143, 0x01c0003f, 0x000001ff, 0x00000000)),
    ((0x00000004, 0x00000003) => (0x00000163, 0x03c0003f, 0x00001fff, 0x00000002)),
    ((0x00000004, 0x00000004) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000005, 0x00000000) => (0x00001000, 0x00001000, 0x00000003, 0x00001120)),
    ((0x00000006, 0x00000000) => (0x00000003, 0x00000002, 0x00000001, 0x00000000)),
    ((0x00000007, 0x00000000) => (0x00000000, 0x00000002, 0x00000000, 0x00000000)),
    ((0x00000008, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000009, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000a, 0x00000000) => (0x07300401, 0x0000007f, 0x00000000, 0x00000000)),
    ((0x0000000b, 0x00000000) => (0x00000000, 0x00000001, 0x00000100, 0x00000000)),
    ((0x0000000b, 0x00000001) => (0x00000000, 0x00000001, 0x00000201, 0x00000002)),
    ((0x0000000b, 0x00000002) => (0x00000000, 0x00000000, 0x00000002, 0x00000000)),
    ((0x40000000, 0x00000000) => (0x40000010, 0x61774d56, 0x4d566572, 0x65726177)),
    ((0x40000001, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x40000002, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x40000003, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x40000004, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x40000005, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x40000006, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x40000007, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x40000008, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x40000009, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x4000000a, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x4000000b, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x4000000c, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x4000000d, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x4000000e, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x4000000f, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x40000010, 0x00000000) => (0x002ca5b0, 0x000170b3, 0x00000000, 0x00000000)),
    ((0x80000000, 0x00000000) => (0x80000008, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000001, 0x00000000) => (0x00000000, 0x00000000, 0x00000001, 0x28100800)),
    ((0x80000002, 0x00000000) => (0x65746e49, 0x2952286c, 0x6f655820, 0x2952286e)),
    ((0x80000003, 0x00000000) => (0x55504320, 0x20202020, 0x20202020, 0x58202020)),
    ((0x80000004, 0x00000000) => (0x30373535, 0x20402020, 0x33392e32, 0x007a4847)),
    ((0x80000005, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000006, 0x00000000) => (0x00000000, 0x00000000, 0x01006040, 0x00000000)),
    ((0x80000007, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000100)),
    ((0x80000008, 0x00000000) => (0x0000302a, 0x00000000, 0x00000000, 0x00000000)),
  ) => Dict{Symbol,Any}(
    :cpuvendor       => :Intel,
    :cpuarchitecture => :Nehalem,
    :cpucores        => 1,   # physical: 4, but with hypervisor
    :cputhreads      => 1,   # physical: 8, but with hypervisor
    :cachesize       => (32768, 262144, 8388608),
    :cachelinesize   => 64,
    :simdbits        => 128,
  )))

# Intel(R) Core(TM) i5-2520M CPU @ 2.50GHz with VMware hypervisor
push!(_mockdb, (Dict(
    ((0x00000000, 0x00000000) => (0x0000000d, 0x756e6547, 0x6c65746e, 0x49656e69)),
    ((0x00000001, 0x00000000) => (0x000206a7, 0x06010800, 0x9fba2223, 0x0fabfbff)),
    ((0x00000002, 0x00000000) => (0x76035a01, 0x00f0b2ff, 0x00000000, 0x00ca0000)),
    ((0x00000003, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000004, 0x00000000) => (0x00000121, 0x01c0003f, 0x0000003f, 0x00000000)),
    ((0x00000004, 0x00000001) => (0x00000122, 0x01c0003f, 0x0000003f, 0x00000000)),
    ((0x00000004, 0x00000002) => (0x00000143, 0x01c0003f, 0x000001ff, 0x00000000)),
    ((0x00000004, 0x00000003) => (0x00000163, 0x02c0003f, 0x00000fff, 0x00000006)),
    ((0x00000004, 0x00000004) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000005, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000006, 0x00000000) => (0x00000077, 0x00000002, 0x00000009, 0x00000000)),
    ((0x00000007, 0x00000000) => (0x00000000, 0x00000002, 0x00000000, 0x00000000)),
    ((0x00000008, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000009, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000a, 0x00000000) => (0x07300403, 0x00000000, 0x00000000, 0x00000603)),
    ((0x0000000b, 0x00000000) => (0x00000000, 0x00000001, 0x00000100, 0x00000006)),
    ((0x0000000b, 0x00000001) => (0x00000000, 0x00000001, 0x00000201, 0x00000006)),
    ((0x0000000b, 0x00000002) => (0x00000000, 0x00000000, 0x00000002, 0x00000006)),
    ((0x0000000c, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000d, 0x00000000) => (0x00000007, 0x00000340, 0x00000340, 0x00000000)),
    ((0x40000000, 0x00000000) => (0x40000010, 0x61774d56, 0x4d566572, 0x65726177)),
    ((0x40000001, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x40000002, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x40000003, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x40000004, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x40000005, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x40000006, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x40000007, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x40000008, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x40000009, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x4000000a, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x4000000b, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x4000000c, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x4000000d, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x4000000e, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x4000000f, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x40000010, 0x00000000) => (0x00262988, 0x000101d0, 0x00000000, 0x00000000)),
    ((0x80000000, 0x00000000) => (0x80000008, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000001, 0x00000000) => (0x00000000, 0x00000000, 0x00000001, 0x28100800)),
    ((0x80000002, 0x00000000) => (0x20202020, 0x49202020, 0x6c65746e, 0x20295228)),
    ((0x80000003, 0x00000000) => (0x65726f43, 0x294d5428, 0x2d356920, 0x30323532)),
    ((0x80000004, 0x00000000) => (0x5043204d, 0x20402055, 0x30352e32, 0x007a4847)),
    ((0x80000005, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000006, 0x00000000) => (0x00000000, 0x00000000, 0x01006040, 0x00000000)),
    ((0x80000007, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000100)),
    ((0x80000008, 0x00000000) => (0x0000302a, 0x00000000, 0x00000000, 0x00000000)),
  ) => Dict{Symbol,Any}(
    :cpuvendor       => :Intel,
    :cpuarchitecture => :SandyBridge,
    :cpucores        => 1,  # physical: 2, but with hypervisor
    :cputhreads      => 1,  # physical: 4, but with hypervisor
    :cachesize       => (32768, 262144, 3145728),
    :cachelinesize   => 64,
    :simdbits        => 256,
  )))

# Intel(R) Core(TM) i5-2520M CPU @ 2.50GHz without hypervisor
push!(_mockdb, (Dict(
    ((0x00000000, 0x00000000) => (0x0000000d, 0x756e6547, 0x6c65746e, 0x49656e69)),
    ((0x00000001, 0x00000000) => (0x000206a7, 0x00100800, 0x1fbae3ff, 0xbfebfbff)),
    ((0x00000002, 0x00000000) => (0x76035a01, 0x00f0b2ff, 0x00000000, 0x00ca0000)),
    ((0x00000003, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000004, 0x00000000) => (0x1c004121, 0x01c0003f, 0x0000003f, 0x00000000)),
    ((0x00000004, 0x00000001) => (0x1c004122, 0x01c0003f, 0x0000003f, 0x00000000)),
    ((0x00000004, 0x00000002) => (0x1c004143, 0x01c0003f, 0x000001ff, 0x00000000)),
    ((0x00000004, 0x00000003) => (0x1c03c163, 0x02c0003f, 0x00000fff, 0x00000006)),
    ((0x00000004, 0x00000004) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000005, 0x00000000) => (0x00000040, 0x00000040, 0x00000003, 0x00021120)),
    ((0x00000006, 0x00000000) => (0x00000077, 0x00000002, 0x00000009, 0x00000000)),
    ((0x00000007, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000008, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000009, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000a, 0x00000000) => (0x07300403, 0x00000000, 0x00000000, 0x00000603)),
    ((0x0000000b, 0x00000000) => (0x00000001, 0x00000002, 0x00000100, 0x00000000)),
    ((0x0000000b, 0x00000001) => (0x00000004, 0x00000004, 0x00000201, 0x00000003)),
    ((0x0000000b, 0x00000002) => (0x00000000, 0x00000000, 0x00000002, 0x00000003)),
    ((0x0000000c, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000d, 0x00000000) => (0x00000007, 0x00000340, 0x00000340, 0x00000000)),
    ((0x80000000, 0x00000000) => (0x80000008, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000001, 0x00000000) => (0x00000000, 0x00000000, 0x00000001, 0x28100800)),
    ((0x80000002, 0x00000000) => (0x20202020, 0x49202020, 0x6c65746e, 0x20295228)),
    ((0x80000003, 0x00000000) => (0x65726f43, 0x294d5428, 0x2d356920, 0x30323532)),
    ((0x80000004, 0x00000000) => (0x5043204d, 0x20402055, 0x30352e32, 0x007a4847)),
    ((0x80000005, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000006, 0x00000000) => (0x00000000, 0x00000000, 0x01006040, 0x00000000)),
    ((0x80000007, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000100)),
    ((0x80000008, 0x00000000) => (0x00003024, 0x00000000, 0x00000000, 0x00000000)),
  ) => Dict{Symbol,Any}(
    :cpuvendor       => :Intel,
    :cpuarchitecture => :SandyBridge,
    :cpucores        => 2,
    :cputhreads      => 4,
    :cachesize       => (32768, 262144, 3145728),
    :cachelinesize   => 64,
    :simdbits        => 256,
  )))

# Intel(R) Xeon Phi(TM) CPU 7250 @ 1.40GHz without hypervisor
push!( _mockdb, (Dict(
    ((0x00000000, 0x00000000) => (0x0000000d, 0x756e6547, 0x6c65746e, 0x49656e69)),
    ((0x00000001, 0x00000000) => (0x00050671, 0x01ff0800, 0x7ff8f3bf, 0xbfebfbff)),
    ((0x00000002, 0x00000000) => (0x6c6b6a01, 0x00ff616d, 0x00000000, 0x00000000)),
    ((0x00000003, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000004, 0x00000000) => (0xfc00c121, 0x01c0003f, 0x0000003f, 0x00000000)),
    ((0x00000005, 0x00000000) => (0x00000040, 0x00000040, 0x00000003, 0x00000110)),
    ((0x00000006, 0x00000000) => (0x00000077, 0x00000002, 0x00000009, 0x00000000)),
    ((0x00000007, 0x00000000) => (0x00000000, 0x1c0d23ab, 0x00000001, 0x00000000)),
    ((0x00000008, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000009, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000a, 0x00000000) => (0x07280203, 0x00000000, 0x00000000, 0x00000503)),
    ((0x0000000b, 0x00000000) => (0x00000002, 0x00000004, 0x00000100, 0x00000001)),
    ((0x0000000c, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000d, 0x00000000) => (0x000000e7, 0x00000a80, 0x00000a80, 0x00000000)),
    ((0x80000000, 0x00000000) => (0x80000008, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000001, 0x00000000) => (0x00000000, 0x00000000, 0x00000121, 0x2c100800)),
    ((0x80000002, 0x00000000) => (0x65746e49, 0x2952286c, 0x6f655820, 0x6850206e)),
    ((0x80000003, 0x00000000) => (0x4d542869, 0x50432029, 0x32372055, 0x40203035)),
    ((0x80000004, 0x00000000) => (0x342e3120, 0x7a484730, 0x00000000, 0x00000000)),
    ((0x80000005, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000006, 0x00000000) => (0x00000000, 0x00000000, 0x04008040, 0x00000000)),
    ((0x80000007, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000100)),
    ((0x80000008, 0x00000000) => (0x0000302e, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000004, 0x00000001) => (0xfc00c122, 0x01c0003f, 0x0000003f, 0x00000000)),
    ((0x00000004, 0x00000002) => (0xfc01c143, 0x03c0003f, 0x000003ff, 0x00000013)),
    ((0x00000004, 0x00000003) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000b, 0x00000001) => (0x00000009, 0x00000110, 0x00000201, 0x00000001)),
    ((0x0000000b, 0x00000002) => (0x00000000, 0x00000000, 0x00000002, 0x00000001)),
  ) => Dict{Symbol,Any}(
    :cpuvendor       => :Intel,
    :cpuarchitecture => :KnightsLanding,
    :cpucores        => 68,
    :cputhreads      => 272,
    :cachesize       => (32768, 1048576),
    :cachelinesize   => 64,
    :simdbits        => 512,
  )))

# This is used on pkg.julialang.org for testing.
# Intel(R) Xeon(R) CPU E3-1241 v3 @ 3.50GHz without hypervisor
#
# processor         : 0
# vendor_id         : GenuineIntel
# cpu family        : 6
# model             : 60
# model name        : Intel(R) Xeon(R) CPU E3-1241 v3 @ 3.50GHz
# stepping          : 3
# microcode         : 0x19
# cpu MHz           : 3503.064
# cache size        : 6144 KB
# physical id       : 0
# siblings          : 2
# core id           : 0
# cpu cores         : 2
# apicid            : 0
# initial apicid    : 0
# fpu               : yes
# fpu_exception     : yes
# cpuid level       : 5
# wp                : yes
# flags             : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov
#                       pat pse36 clflush mmx fxsr sse sse2 ht syscall nx rdtscp lm
#                       constant_tsc rep_good nopl pni ssse3 lahf_lm
# bogomips          : 7006.12
# clflush size      : 64
# cache_alignment   : 64
# address sizes     : 39 bits physical, 48 bits virtual
# power management:
#
push!( _mockdb, (Dict(
    ((0x00000000,0x00000000) => (0x00000005,0x756e6547,0x6c65746e,0x49656e69)),
    ((0x00000001,0x00000000) => (0x000306c3,0x01020800,0x00000201,0x178bfbff)),
    ((0x00000002,0x00000000) => (0x76036301,0x00f0b5ff,0x00000000,0x00c10000)),
    ((0x00000003,0x00000000) => (0x00000000,0x00000000,0x00000000,0x00000000)),
    ((0x00000004,0x00000000) => (0x04000021,0x01c0003f,0x0000003f,0x00000000)),
    ((0x00000005,0x00000000) => (0x00000000,0x00000000,0x00000000,0x00000000)),
    ((0x80000000,0x00000000) => (0x80000008,0x00000000,0x00000000,0x00000000)),
    ((0x80000001,0x00000000) => (0x00000000,0x00000000,0x00000001,0x28100800)),
    ((0x80000002,0x00000000) => (0x65746e49,0x2952286c,0x6f655820,0x2952286e)),
    ((0x80000003,0x00000000) => (0x55504320,0x2d334520,0x31343231,0x20337620)),
    ((0x80000004,0x00000000) => (0x2e332040,0x48473035,0x0000007a,0x00000000)),
    ((0x80000005,0x00000000) => (0x00000000,0x00000000,0x00000000,0x00000000)),
    ((0x80000006,0x00000000) => (0x00000000,0x00000000,0x01006040,0x00000000)),
    ((0x80000007,0x00000000) => (0x00000000,0x00000000,0x00000000,0x00000000)),
    ((0x80000008,0x00000000) => (0x00003027,0x00000000,0x00000000,0x00000000)),
    ((0x00000004,0x00000001) => (0x04000021,0x01c0003f,0x0000003f,0x00000000)),
    ((0x00000004,0x00000002) => (0x04004041,0x05c0003f,0x00000fff,0x00000000)),
    ((0x00000004,0x00000003) => (0x04000000,0x00000000,0x00000000,0x00000000)),
  ) => Dict{Symbol,Any}(
    :cpuvendor       => :Intel,
    :cpuarchitecture => :Haswell,
    :cpucores        => 0,  # physical: 4, but with hypervisor
    :cputhreads      => 0,  # physical: 8, but with hypervisor
    :cachesize       => (32768, 32768, 6291456), # 8MB ?
    :cachelinesize   => 64,
    :simdbits        => 128,
  )))

# Intel(R) Core(TM) i7-6600U CPU @ 2.60GHz without hypervisor
push!( _mockdb, (Dict(
    ((0x00000000,0x00000000) => (0x00000016,0x756e6547,0x6c65746e,0x49656e69)),
    ((0x00000001,0x00000000) => (0x000406e3,0x00100800,0x7ffafbff,0xbfebfbff)),
    ((0x00000002,0x00000000) => (0x76036301,0x00f0b5ff,0x00000000,0x00c30000)),
    ((0x00000003,0x00000000) => (0x00000000,0x00000000,0x00000000,0x00000000)),
    ((0x00000004,0x00000000) => (0x1c004121,0x01c0003f,0x0000003f,0x00000000)),
    ((0x00000005,0x00000000) => (0x00000040,0x00000040,0x00000003,0x11142120)),
    ((0x00000006,0x00000000) => (0x000027f7,0x00000002,0x00000009,0x00000000)),
    ((0x00000007,0x00000000) => (0x00000000,0x029c6fbf,0x00000000,0x00000000)),
    ((0x00000008,0x00000000) => (0x00000000,0x00000000,0x00000000,0x00000000)),
    ((0x00000009,0x00000000) => (0x00000000,0x00000000,0x00000000,0x00000000)),
    ((0x0000000a,0x00000000) => (0x07300404,0x00000000,0x00000000,0x00000603)),
    ((0x0000000b,0x00000000) => (0x00000001,0x00000002,0x00000100,0x00000003)),
    ((0x0000000c,0x00000000) => (0x00000000,0x00000000,0x00000000,0x00000000)),
    ((0x0000000d,0x00000000) => (0x0000001f,0x00000440,0x00000440,0x00000000)),
    ((0x0000000e,0x00000000) => (0x00000000,0x00000000,0x00000000,0x00000000)),
    ((0x0000000f,0x00000000) => (0x00000000,0x00000000,0x00000000,0x00000000)),
    ((0x00000010,0x00000000) => (0x00000000,0x00000000,0x00000000,0x00000000)),
    ((0x00000011,0x00000000) => (0x00000000,0x00000000,0x00000000,0x00000000)),
    ((0x00000012,0x00000000) => (0x00000000,0x00000000,0x00000000,0x00000000)),
    ((0x00000013,0x00000000) => (0x00000000,0x00000000,0x00000000,0x00000000)),
    ((0x00000014,0x00000000) => (0x00000001,0x0000000f,0x00000007,0x00000000)),
    ((0x00000015,0x00000000) => (0x00000002,0x000000ea,0x00000000,0x00000000)),
    ((0x00000016,0x00000000) => (0x00000af0,0x00000d48,0x00000064,0x00000000)),
    ((0x80000000,0x00000000) => (0x80000008,0x00000000,0x00000000,0x00000000)),
    ((0x80000001,0x00000000) => (0x00000000,0x00000000,0x00000121,0x2c100800)),
    ((0x80000002,0x00000000) => (0x65746e49,0x2952286c,0x726f4320,0x4d542865)),
    ((0x80000003,0x00000000) => (0x37692029,0x3036362d,0x43205530,0x40205550)),
    ((0x80000004,0x00000000) => (0x362e3220,0x7a484730,0x00000000,0x00000000)),
    ((0x80000005,0x00000000) => (0x00000000,0x00000000,0x00000000,0x00000000)),
    ((0x80000006,0x00000000) => (0x00000000,0x00000000,0x01006040,0x00000000)),
    ((0x80000007,0x00000000) => (0x00000000,0x00000000,0x00000000,0x00000100)),
    ((0x80000008,0x00000000) => (0x00003027,0x00000000,0x00000000,0x00000000)),
    ((0x00000004,0x00000001) => (0x1c004122,0x01c0003f,0x0000003f,0x00000000)),
    ((0x00000004,0x00000002) => (0x1c004143,0x00c0003f,0x000003ff,0x00000000)),
    ((0x00000004,0x00000003) => (0x1c03c163,0x03c0003f,0x00000fff,0x00000006)),
    ((0x00000004,0x00000004) => (0x00000000,0x00000000,0x00000000,0x00000000)),
    ((0x0000000b,0x00000001) => (0x00000004,0x00000004,0x00000201,0x00000001)),
    ((0x0000000b,0x00000002) => (0x00000000,0x00000000,0x00000002,0x00000001)),
  ) => Dict{Symbol,Any}(
    :cpuvendor       => :Intel,
    :cpuarchitecture => :Skylake,
    :cpucores        => 2,
    :cputhreads      => 4,
    :cachesize       => (32768, 262144, 4194304),
    :cachelinesize   => 64,
    :simdbits        => 256,
  )))

# AMD A10-8700P Radeon R6, 10 Compute Cores 4C+6G without hypervisor
push!( _mockdb, (Dict(
    ((0x00000000, 0x00000000) => (0x0000000d, 0x68747541, 0x444d4163, 0x69746e65)),
    ((0x00000001, 0x00000000) => (0x00660f01, 0x02040800, 0x3ed8320b, 0x178bfbff)),
    ((0x00000002, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000003, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000004, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000005, 0x00000000) => (0x00000040, 0x00000040, 0x00000003, 0x00000000)),
    ((0x00000006, 0x00000000) => (0x00000004, 0x00000000, 0x00000001, 0x00000000)),
    ((0x00000007, 0x00000000) => (0x00000000, 0x000001a9, 0x00000000, 0x00000000)),
    ((0x00000008, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000009, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000a, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000b, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000c, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000d, 0x00000000) => (0x00000007, 0x00000340, 0x000003c0, 0x40000000)),
    ((0x80000000, 0x00000000) => (0x8000001e, 0x68747541, 0x444d4163, 0x69746e65)),
    ((0x80000001, 0x00000000) => (0x00660f01, 0x00000000, 0x2febbfff, 0x2fd3fbff)),
    ((0x80000002, 0x00000000) => (0x20444d41, 0x2d303141, 0x30303738, 0x61522050)),
    ((0x80000003, 0x00000000) => (0x6e6f6564, 0x2c365220, 0x20303120, 0x706d6f43)),
    ((0x80000004, 0x00000000) => (0x20657475, 0x65726f43, 0x43342073, 0x0047362b)),
    ((0x80000005, 0x00000000) => (0xff40ff18, 0xff40ff30, 0x20080140, 0x60030140)),
    ((0x80000006, 0x00000000) => (0x64006400, 0x64004200, 0x04008140, 0x00000000)),
    ((0x80000007, 0x00000000) => (0x00000000, 0x00000005, 0x00000400, 0x000037d9)),
    ((0x80000008, 0x00000000) => (0x00003030, 0x00000000, 0x00004003, 0x00000000)),
    ((0x80000009, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000000a, 0x00000000) => (0x00000001, 0x00008000, 0x00000000, 0x0001bcff)),
    ((0x8000000b, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000000c, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000000d, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000000e, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000000f, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000010, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000011, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000012, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000013, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000014, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000015, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000016, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000017, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000018, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000019, 0x00000000) => (0xf040f018, 0x64006400, 0x00000000, 0x00000000)),
    ((0x8000001a, 0x00000000) => (0x00000003, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000001b, 0x00000000) => (0x000007ff, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000001c, 0x00000000) => (0x00000000, 0x80032013, 0x00010200, 0xe000000f)),
    ((0x8000001d, 0x00000000) => (0x00000121, 0x01c0003f, 0x0000003f, 0x00000000)),
    ((0x8000001e, 0x00000000) => (0x00000010, 0x00000100, 0x00000000, 0x00000000)),
    ((0x00000004, 0x00000001) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000b, 0x00000001) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
  ) => Dict{Symbol,Any}(
    # http://www.cpu-world.com/CPUs/Bulldozer/AMD-A10-Series%20A10-8700P.html
    :cpuvendor       => :AMD,
    :cpuarchitecture => :Bulldozer, # :Excavator
    :cpucores        => 4,
    :cputhreads      => 4,  # plus 6 GPU cores
    :cachesize       => (32768,), # This is correct since the subleaf 2 is missing of the cpuid dump.
    :cachelinesize   => 64,
    :simdbits        => 256,
  )))

# AMD Ryzen Threadripper 1950X 16-Core Processor
push!( _mockdb, (Dict(
    ((0x00000000, 0x00000000) => (0x0000000D, 0x68747541, 0x444D4163, 0x69746E65)),
    ((0x00000001, 0x00000000) => (0x00800F11, 0x00200800, 0x7ED8320B, 0x178BFBFF)),
    ((0x00000002, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000003, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000005, 0x00000000) => (0x00000040, 0x00000040, 0x00000003, 0x00000000)),
    ((0x00000006, 0x00000000) => (0x00000004, 0x00000000, 0x00000001, 0x00000000)),
    ((0x00000007, 0x00000000) => (0x00000000, 0x209C01A9, 0x00000000, 0x00000000)),
    ((0x00000008, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000009, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000A, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000C, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000D, 0x00000000) => (0x00000007, 0x00000340, 0x00000340, 0x00000000)),
    ((0x0000000D, 0x00000001) => (0x0000000F, 0x00000340, 0x00000000, 0x00000000)),
    ((0x0000000D, 0x00000002) => (0x00000100, 0x00000240, 0x00000000, 0x00000000)),
    ((0x80000000, 0x00000000) => (0x8000001F, 0x68747541, 0x444D4163, 0x69746E65)),
    ((0x80000001, 0x00000000) => (0x00800F11, 0x70000000, 0x35C233FF, 0x2FD3FBFF)),
    ((0x80000002, 0x00000000) => (0x20444D41, 0x657A7952, 0x6854206E, 0x64616572)),
    ((0x80000003, 0x00000000) => (0x70706972, 0x31207265, 0x58303539, 0x2D363120)),
    ((0x80000004, 0x00000000) => (0x65726F43, 0x6F725020, 0x73736563, 0x0020726F)),
    ((0x80000005, 0x00000000) => (0xFF40FF40, 0xFF40FF40, 0x20080140, 0x40040140)),
    ((0x80000006, 0x00000000) => (0x36006400, 0x56006400, 0x02006140, 0x0100A140)),
    ((0x80000007, 0x00000000) => (0x00000000, 0x0000001B, 0x00000000, 0x00006799)),
    ((0x80000008, 0x00000000) => (0x00003030, 0x00000007, 0x0000501F, 0x00000000)),
    ((0x80000009, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000000A, 0x00000000) => (0x00000001, 0x00008000, 0x00000000, 0x0001BCFF)),
    ((0x8000000B, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000000C, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000000D, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000000E, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000000F, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000010, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000011, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000012, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000013, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000014, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000015, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000016, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000017, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000018, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000019, 0x00000000) => (0xF040F040, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000001A, 0x00000000) => (0x00000003, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000001B, 0x00000000) => (0x000003FF, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000001C, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000001D, 0x00000000) => (0x00004121, 0x01C0003F, 0x0000003F, 0x00000000)),
    ((0x8000001D, 0x00000001) => (0x00004122, 0x00C0003F, 0x000000FF, 0x00000000)),
    ((0x8000001D, 0x00000002) => (0x00004143, 0x01C0003F, 0x000003FF, 0x00000002)),
    ((0x8000001D, 0x00000003) => (0x0001C163, 0x03C0003F, 0x00001FFF, 0x00000001)),
    ((0x8000001E, 0x00000000) => (0x00000000, 0x00000100, 0x00000100, 0x00000000)),
    ((0x8000001F, 0x00000000) => (0x00000007, 0x0000016F, 0x0000000F, 0x00000001)),
    ((0x8FFFFFFF, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
  ) => Dict{Symbol,Any}(
    # http://www.cpu-world.com/CPUs/Zen/AMD-Ryzen%20Threadripper%201950X.html
    :cpuvendor       => :AMD,
    :cpuarchitecture => :Zen,
    :cpucores        => (:broken, 16),
    :cputhreads      => 32,
    :cachesize       => (32768, 524288, 8388608),
    :cachelinesize   => 64,
    :simdbits        => 256,
  )))

# AMD A8-6410 APU with AMD Radeon R5 Graphics
push!( _mockdb, (Dict(
    ((0x00000000, 0x00000000) => (0x0000000D, 0x68747541, 0x444D4163, 0x69746E65)),
    ((0x00000001, 0x00000000) => (0x00730F01, 0x00040800, 0x7ED8220B, 0x178BFBFF)),
    ((0x00000002, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000003, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000005, 0x00000000) => (0x00000040, 0x00000040, 0x00000003, 0x00000000)),
    ((0x00000006, 0x00000000) => (0x00000000, 0x00000000, 0x00000001, 0x00000000)),
    ((0x00000007, 0x00000000) => (0x00000000, 0x00000008, 0x00000000, 0x00000000)),
    ((0x00000008, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000009, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000A, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000C, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000D, 0x00000000) => (0x00000007, 0x00000340, 0x00000340, 0x00000000)),
    ((0x0000000D, 0x00000001) => (0x00000001, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000D, 0x00000002) => (0x00000100, 0x00000240, 0x00000000, 0x00000000)),
    ((0x80000000, 0x00000000) => (0x8000001E, 0x68747541, 0x444D4163, 0x69746E65)),
    ((0x80000001, 0x00000000) => (0x00730F01, 0x00000000, 0x1D4037FF, 0x2FD3FBFF)),
    ((0x80000002, 0x00000000) => (0x20444D41, 0x362D3841, 0x20303134, 0x20555041)),
    ((0x80000003, 0x00000000) => (0x68746977, 0x444D4120, 0x64615220, 0x206E6F65)),
    ((0x80000004, 0x00000000) => (0x47203552, 0x68706172, 0x20736369, 0x00202020)),
    ((0x80000005, 0x00000000) => (0xFF08FF08, 0xFF28FF20, 0x20080140, 0x20020140)),
    ((0x80000006, 0x00000000) => (0x21000000, 0x42004200, 0x08008140, 0x00000000)),
    ((0x80000007, 0x00000000) => (0x00000000, 0x00000001, 0x00002800, 0x000033D9)),
    ((0x80000008, 0x00000000) => (0x00003028, 0x00000000, 0x00003003, 0x00000000)),
    ((0x80000009, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000000A, 0x00000000) => (0x00000001, 0x00000008, 0x00000000, 0x00001CDF)),
    ((0x8000000B, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000000C, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000000D, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000000E, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000000F, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000010, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000011, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000012, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000013, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000014, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000015, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000016, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000017, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000018, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000019, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000001A, 0x00000000) => (0x00000003, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000001B, 0x00000000) => (0x000000FF, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000001C, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000001D, 0x00000000) => (0x00000121, 0x01C0003F, 0x0000003F, 0x00000000)),
    ((0x8000001D, 0x00000001) => (0x00000122, 0x0040003F, 0x000000FF, 0x00000000)),
    ((0x8000001D, 0x00000002) => (0x0000C143, 0x03C0003F, 0x000007FF, 0x00000002)),
    ((0x8000001E, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
  ) => Dict{Symbol,Any}(
    # http://www.cpu-world.com/CPUs/Puma/AMD-A8-Series%20A8-6410.html
    :cpuvendor       => :AMD,
    :cpuarchitecture => :Puma,
    :cpucores        => 4,
    :cputhreads      => 4,
    :cachesize       => (32768, 2097152),
    :cachelinesize   => 64,
    :simdbits        => 256,
  )))

# AMD Athlon(tm) 5350 APU with Radeon(tm) R3
push!( _mockdb, (Dict(
    ((0x00000000, 0x00000000) => (0x0000000D, 0x68747541, 0x444D4163, 0x69746E65)),
    ((0x00000001, 0x00000000) => (0x00700F01, 0x00040800, 0x3ED8220B, 0x178BFBFF)),
    ((0x00000002, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000003, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000005, 0x00000000) => (0x00000040, 0x00000040, 0x00000003, 0x00000000)),
    ((0x00000006, 0x00000000) => (0x00000000, 0x00000000, 0x00000001, 0x00000000)),
    ((0x00000007, 0x00000000) => (0x00000000, 0x00000008, 0x00000000, 0x00000000)),
    ((0x00000008, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x00000009, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000A, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000C, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000D, 0x00000000) => (0x00000007, 0x00000340, 0x00000340, 0x00000000)),
    ((0x0000000D, 0x00000001) => (0x00000001, 0x00000000, 0x00000000, 0x00000000)),
    ((0x0000000D, 0x00000002) => (0x00000100, 0x00000240, 0x00000000, 0x00000000)),
    ((0x80000000, 0x00000000) => (0x8000001E, 0x68747541, 0x444D4163, 0x69746E65)),
    ((0x80000001, 0x00000000) => (0x00700F01, 0x10000000, 0x154037FF, 0x2FD3FBFF)),
    ((0x80000002, 0x00000000) => (0x20444D41, 0x6C687441, 0x74286E6F, 0x3520296D)),
    ((0x80000003, 0x00000000) => (0x20303533, 0x20555041, 0x68746977, 0x64615220)),
    ((0x80000004, 0x00000000) => (0x286E6F65, 0x20296D74, 0x20203352, 0x00202020)),
    ((0x80000005, 0x00000000) => (0xFF08FF08, 0xFF28FF20, 0x20080140, 0x20020140)),
    ((0x80000006, 0x00000000) => (0x21000000, 0x42004200, 0x08008140, 0x00000000)),
    ((0x80000007, 0x00000000) => (0x0D6B0101, 0x00000001, 0x00000000, 0x000009D9)),
    ((0x80000008, 0x00000000) => (0x00003028, 0x00000000, 0x00003003, 0x00000000)),
    ((0x80000009, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000000A, 0x00000000) => (0x00000001, 0x00000008, 0x00000000, 0x00001CDF)),
    ((0x8000000B, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000000C, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000000D, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000000E, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000000F, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000010, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000011, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000012, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000013, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000014, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000015, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000016, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000017, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000018, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x80000019, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000001A, 0x00000000) => (0x00000003, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000001B, 0x00000000) => (0x000000FF, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000001C, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8000001D, 0x00000000) => (0x00000121, 0x01C0003F, 0x0000003F, 0x00000000)),
    ((0x8000001D, 0x00000001) => (0x00000122, 0x0040003F, 0x000000FF, 0x00000000)),
    ((0x8000001D, 0x00000002) => (0x0000C143, 0x03C0003F, 0x000007FF, 0x00000002)),
    ((0x8000001E, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
    ((0x8FFFFFFF, 0x00000000) => (0x4C4C4548, 0x494B204F, 0x21595454, 0x5E2D5E20)),
  ) => Dict{Symbol,Any}(
    # http://www.cpu-world.com/CPUs/Puma/AMD-A8-Series%20A8-6410.html
    :cpuvendor       => :AMD,
    :cpuarchitecture => :Jaguar,
    :cpucores        => 4,
    :cputhreads      => 4,
    :cachesize       => (32768, 2097152),
    :cachelinesize   => 64,
    :simdbits        => 256,
  )))

# AMD EPYC 7401P 24-Core Processor without hypervisor
push!( _mockdb, (Dict(
  ((0x00000000, 0x00000000) => (0x0000000d, 0x68747541, 0x444d4163, 0x69746e65)),
  ((0x00000001, 0x00000000) => (0x00800f12, 0x30300800, 0x7ed8320b, 0x178bfbff)),
  ((0x00000002, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
  ((0x00000003, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
  ((0x00000004, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
  ((0x00000005, 0x00000000) => (0x00000040, 0x00000040, 0x00000003, 0x00000011)),
  ((0x00000006, 0x00000000) => (0x00000004, 0x00000000, 0x00000001, 0x00000000)),
  ((0x00000007, 0x00000000) => (0x00000000, 0x209c01a9, 0x00000000, 0x00000000)),
  ((0x00000008, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
  ((0x00000009, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
  ((0x0000000a, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
  ((0x0000000b, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
  ((0x0000000c, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
  ((0x0000000d, 0x00000000) => (0x00000007, 0x00000340, 0x00000340, 0x00000000)),
  ((0x80000000, 0x00000000) => (0x8000001f, 0x68747541, 0x444d4163, 0x69746e65)),
  ((0x80000001, 0x00000000) => (0x00800f12, 0x40000000, 0x35c233ff, 0x2fd3fbff)),
  ((0x80000002, 0x00000000) => (0x20444d41, 0x43595045, 0x30343720, 0x32205031)),
  ((0x80000003, 0x00000000) => (0x6f432d34, 0x50206572, 0x65636f72, 0x726f7373)),
  ((0x80000004, 0x00000000) => (0x20202020, 0x20202020, 0x20202020, 0x00202020)),
  ((0x80000005, 0x00000000) => (0xff40ff40, 0xff40ff40, 0x20080140, 0x40040140)),
  ((0x80000006, 0x00000000) => (0x36006400, 0x56006400, 0x02006140, 0x0200c140)),
  ((0x80000007, 0x00000000) => (0x00000000, 0x0000001b, 0x00000000, 0x00006799)),
  ((0x80000008, 0x00000000) => (0x00003030, 0x00001007, 0x0000602f, 0x00000000)),
  ((0x80000009, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
  ((0x8000000a, 0x00000000) => (0x00000001, 0x00008000, 0x00000000, 0x0001bcff)),
  ((0x8000000b, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
  ((0x8000000c, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
  ((0x8000000d, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
  ((0x8000000e, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
  ((0x8000000f, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
  ((0x80000010, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
  ((0x80000011, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
  ((0x80000012, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
  ((0x80000013, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
  ((0x80000014, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
  ((0x80000015, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
  ((0x80000016, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
  ((0x80000017, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
  ((0x80000018, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
  ((0x80000019, 0x00000000) => (0xf040f040, 0x00000000, 0x00000000, 0x00000000)),
  ((0x8000001a, 0x00000000) => (0x00000003, 0x00000000, 0x00000000, 0x00000000)),
  ((0x8000001b, 0x00000000) => (0x000003ff, 0x00000000, 0x00000000, 0x00000000)),
  ((0x8000001c, 0x00000000) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
  ((0x8000001d, 0x00000000) => (0x00004121, 0x01c0003f, 0x0000003f, 0x00000000)),
  ((0x8000001e, 0x00000000) => (0x00000030, 0x00000118, 0x00000303, 0x00000000)),
  ((0x8000001f, 0x00000000) => (0x0000000f, 0x0000016f, 0x0000000f, 0x00000001)),
  ((0x00000004, 0x00000001) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
  ((0x0000000b, 0x00000001) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
  ((0x8000001d, 0x00000001) => (0x00004122, 0x00c0003f, 0x000000ff, 0x00000000)),
  ((0x8000001d, 0x00000002) => (0x00004143, 0x01c0003f, 0x000003ff, 0x00000002)),
  ((0x8000001d, 0x00000003) => (0x00014163, 0x03c0003f, 0x00001fff, 0x00000001)),
  ((0x8000001d, 0x00000004) => (0x00000000, 0x00000000, 0x00000000, 0x00000000)),
) => Dict{Symbol,Any}(
  # http://www.cpu-world.com/CPUs/Zen/AMD-EPYC%207401P.html
  :cpuvendor       => :AMD,
  :cpuarchitecture => :Zen,
  :cpucores        => (:broken, 24),
  :cputhreads      => 48,
  :cachesize       => (32768, 524288, 8388608),
  :cachelinesize   => 64,
  :simdbits        => 256,
)))

#=--- end of file ---------------------------------------------------------=#


text: # simulate random positions within a small region of interest


text:
module TestSmoke

include("preamble.jl")

using LinearAlgebra
using DataFrames: DataFrame

suite = BenchSweepGroup()
suite.axes[:n] = 2 .^ (4:5)
suite.axes[:m] = 2 .^ (4:5)

@defsweep! for n in suite["matrix-vector"]
    @benchmarkable mul!(y, A, x) setup=begin
        y = zeros($n)
        A = rand($n, $n)
        x = rand($n)
    end
end

@defsweep! for (n, m) in suite["matrix-matrix"]
    @benchmarkable mul!(Y, A, X) setup=begin
        Y = zeros($n, $m)
        A = rand($n, $n)
        X = rand($n, $m)
    end
end

# Passing some options to `tune!` to make runtime short:
tune!(suite; maxevals=1, seconds=0.1, samples=1)
results = run(suite)

for row in BenchSweeps.astable(results)
    @test row isa NamedTuple
end

for row in BenchSweeps.asrawtable(results)
    @test row isa NamedTuple
end

for row in BenchSweeps.asbenchtable(results)
    @test row isa NamedTuple
    @test row.bench isa BenchmarkTools.Trial
end

for row in BenchSweeps.asbenchtable(suite)
    @test row isa NamedTuple
    @test row.bench isa BenchmarkTools.Benchmark
end

@test DataFrame(results) isa DataFrame
@test DataFrame(results, :raw) isa DataFrame
@test DataFrame(results, :bench) isa DataFrame
@test DataFrame(suite, :bench) isa DataFrame

buf = IOBuffer()
@test BenchSweeps.save(buf, results) isa Nothing
seekstart(buf)
@test (global recovered = BenchSweeps.load(buf)) isa BenchSweepGroup

@test mktempdir() do dir
    filename = joinpath(dir, "results.json")
    BenchSweeps.save(filename, results)
    BenchSweeps.load(filename) isa BenchSweepGroup
end

@test DataFrame(recovered) isa DataFrame
@test DataFrame(recovered, :raw) isa DataFrame
@test DataFrame(recovered, :bench) isa DataFrame

end  # module