# [Statistics](#Statistics)
The keyword arguments `alpha` and `beta` correspond to the same parameters in Hyndman and Fan, setting them to different values allows to calculate quantiles with any of the methods 4-9 defined in this paper:
-   Def. 4: `alpha=0`, `beta=1`
-   Def. 5: `alpha=0.5`, `beta=0.5` (MATLAB default)
-   Def. 6: `alpha=0`, `beta=0` (Excel `PERCENTILE.EXC`, Python default, Stata `altdef`)
-   Def. 7: `alpha=1`, `beta=1` (Julia, R and NumPy default, Excel `PERCENTILE` and `PERCENTILE.INC`, Python `'inclusive'`)
-   Def. 8: `alpha=1/3`, `beta=1/3`
-   Def. 9: `alpha=3/8`, `beta=3/8`
An `ArgumentError` is thrown if `v` contains `NaN` or [`missing`](../../manual/missing/#missing) values.
**References**
-   Hyndman, R.J and Fan, Y. (1996) "Sample Quantiles in Statistical Packages", *The American Statistician*, Vol. 50, No. 4, pp. 361-365
-   [Quantile on Wikipedia](https://en.m.wikipedia.org/wiki/Quantile) details the different quantile definitions
**Examples**
```julia-repl
julia> using Statistics

julia> x = [3, 2, 1];

julia> quantile!(x, 0.5)
2.0

julia> x
3-element Vector{Int64}:
 1
 2
 3

julia> y = zeros(3);

julia> quantile!(y, x, [0.1, 0.5, 0.9]) === y
true

julia> y
3-element Vector{Float64}:
 1.2000000000000002
 2.0
 2.8000000000000003
```
```julia
quantile(itr, p; sorted=false, alpha::Real=1.0, beta::Real=alpha)
```
Compute the quantile(s) of a collection `itr` at a specified probability or vector or tuple of probabilities `p` on the interval \[0,1\]. The keyword argument `sorted` indicates whether `itr` can be assumed to be sorted.


# [Statistics](#Statistics)
Samples quantile are defined by `Q(p) = (1-γ)*x[j] + γ*x[j+1]`, where `x[j]` is the j-th order statistic of `itr`, `j = floor(n*p + m)`, `m = alpha + p*(1 - alpha - beta)` and `γ = n*p + m - j`.
By default (`alpha = beta = 1`), quantiles are computed via linear interpolation between the points `((k-1)/(n-1), x[k])`, for `k = 1:n` where `n = length(itr)`. This corresponds to Definition 7 of Hyndman and Fan (1996), and is the same as the R and NumPy default.
The keyword arguments `alpha` and `beta` correspond to the same parameters in Hyndman and Fan, setting them to different values allows to calculate quantiles with any of the methods 4-9 defined in this paper:
-   Def. 4: `alpha=0`, `beta=1`
-   Def. 5: `alpha=0.5`, `beta=0.5` (MATLAB default)
-   Def. 6: `alpha=0`, `beta=0` (Excel `PERCENTILE.EXC`, Python default, Stata `altdef`)
-   Def. 7: `alpha=1`, `beta=1` (Julia, R and NumPy default, Excel `PERCENTILE` and `PERCENTILE.INC`, Python `'inclusive'`)
-   Def. 8: `alpha=1/3`, `beta=1/3`
-   Def. 9: `alpha=3/8`, `beta=3/8`
An `ArgumentError` is thrown if `v` contains `NaN` or [`missing`](../../manual/missing/#missing) values. Use the [`skipmissing`](../../base/base/#Base.skipmissing) function to omit `missing` entries and compute the quantiles of non-missing values.
**References**
-   Hyndman, R.J and Fan, Y. (1996) "Sample Quantiles in Statistical Packages", *The American Statistician*, Vol. 50, No. 4, pp. 361-365
-   [Quantile on Wikipedia](https://en.m.wikipedia.org/wiki/Quantile) details the different quantile definitions
**Examples**


# [Statistics](#Statistics)
```julia-repl
julia> using Statistics

julia> quantile(0:20, 0.5)
10.0

julia> quantile(0:20, [0.1, 0.5, 0.9])
3-element Vector{Float64}:
  2.0
 10.0
 18.000000000000004

julia> quantile(skipmissing([1, 10, missing]), 0.5)
5.5
```
------------------------------------------------------------------------


# StyledStrings · The Julia Language
Source: https://docs.julialang.org/en/v1/stdlib/StyledStrings/


# [StyledStrings](#stdlib-styledstrings)
The API for StyledStrings and AnnotatedStrings is considered experimental and is subject to change between Julia versions.


## [Styling](#stdlib-styledstrings-styling)
When working with strings, formatting and styling often appear as a secondary concern.
For instance, when printing to a terminal you might want to sprinkle [ANSI escape sequences](https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters) in the output, when outputting HTML styling constructs (``, etc.) serve a similar purpose, and so on. It is possible to simply insert the raw styling constructs into the string next to the content itself, but it quickly becomes apparent that this is not well suited for anything but the most basic use cases. Not all terminals support the same ANSI codes, the styling constructs need to be painstakingly removed when calculating the width of already-styled content, and that's before you even get into handling multiple output formats.
Instead of leaving this headache to be widely experienced downstream, it is tackled head-on by the introduction of a special string type ([`AnnotatedString`](../../base/strings/#Base.AnnotatedString)). This string type wraps any other [`AbstractString`](../../base/strings/#Core.AbstractString) type and allows for formatting information to be applied to regions (e.g. characters 1 through to 7 are bold and red).
Regions of a string are styled by applying [`Face`](#StyledStrings.Face)s (think "typeface") to them — a structure that holds styling information. As a convenience, faces in the global faces dictionary (e.g. `shadow`) can just be named instead of giving the [`Face`](#StyledStrings.Face) directly.


## [Styling](#stdlib-styledstrings-styling)
Along with these capabilities, we also provide a convenient way for constructing [`AnnotatedString`](../../base/strings/#Base.AnnotatedString)s, detailed in [Styled String Literals](#stdlib-styledstring-literals).
```julia-repl
julia> using StyledStrings
julia> styled"{yellow:hello} {blue:there}""hello there"
```


## [Annotated Strings](#man-annotated-strings)
It is sometimes useful to be able to hold metadata relating to regions of a string. A [`AnnotatedString`](../../base/strings/#Base.AnnotatedString) wraps another string and allows for regions of it to be annotated with labelled values (`:label => value`). All generic string operations are applied to the underlying string. However, when possible, styling information is preserved. This means you can manipulate a [`AnnotatedString`](../../base/strings/#Base.AnnotatedString) —taking substrings, padding them, concatenating them with other strings— and the metadata annotations will "come along for the ride".
This string type is fundamental to the [StyledStrings stdlib](#stdlib-styledstrings), which uses `:face`-labelled annotations to hold styling information.
When concatenating a [`AnnotatedString`](../../base/strings/#Base.AnnotatedString), take care to use [`annotatedstring`](../../base/strings/#Base.annotatedstring) instead of [`string`](../../base/strings/#Base.string) if you want to keep the string annotations.
```julia-repl
julia> str = AnnotatedString("hello there", [(1:5, :word, :greeting), (7:11, :label, 1)])
"hello there"

julia> length(str)
11

julia> lpad(str, 14)
"   hello there"

julia> typeof(lpad(str, 7))
AnnotatedString{String}

julia> str2 = AnnotatedString(" julia", [(2:6, :face, :magenta)])
" julia"

julia> annotatedstring(str, str2)
"hello there julia"

julia> str * str2 == annotatedstring(str, str2) # *-concatenation works
true
```


## [Annotated Strings](#man-annotated-strings)
The annotations of a [`AnnotatedString`](../../base/strings/#Base.AnnotatedString) can be accessed and modified via the [`annotations`](../../base/strings/#Base.annotations) and [`annotate!`](../../base/strings/#Base.annotate!) functions.


## [Styling via](#Styling-via-%5BAnnotatedString%5D(@ref-Base.AnnotatedString)s) [`AnnotatedString`](../../base/strings/#Base.AnnotatedString)s


## [Faces](#stdlib-styledstrings-faces)


### [The Face type](#The-Face-type)
A [`Face`](#StyledStrings.Face) specifies details of a typeface that text can be set in. It covers a set of basic attributes that generalize well across different formats, namely:
-   `font`
-   `height`
-   `weight`
-   `slant`
-   `foreground`
-   `background`
-   `underline`
-   `strikethrough`
-   `inverse`
-   `inherit`
For details on the particular forms these attributes take, see the [`Face`](#StyledStrings.Face) docstring, but of particular interest is `inherit` as it allows you to *inherit* attributes from other [`Face`](#StyledStrings.Face)s.


### [The global faces dictionary](#The-global-faces-dictionary)
To make referring to particular styles more convenient, there is a global `Dict{Symbol, Face}` that allows for [`Face`](#StyledStrings.Face)s to be referred to simply by name. Packages can add faces to this dictionary via the [`addface!`](#StyledStrings.addface!) function, and the loaded faces can be easily [customized](#stdlib-styledstrings-face-toml).
Any package registering new faces should ensure that they are prefixed by the package name, i.e. follow the format `mypackage_myface`. This is important for predictability, and to prevent name clashes.
Furthermore, packages should take care to use (and introduce) *semantic* faces (like `code`) over direct colours and styles (like `cyan`). This is helpful in a number of ways, from making the intent in usage more obvious, aiding composability, and making user customisation more intuitive.
There are two set of exemptions to the package-prefix rule:
-   the set of basic faces that are part of the default value of the faces dictionary
-   faces introduced by Julia's own standard library, namely `JuliaSyntaxHighlighting`


#### [Basic faces](#stdlib-styledstrings-basic-faces)
Basic faces are intended to represent a general idea that is widely applicable.
For setting some text with a certain attribute, we have the `bold`, `light`, `italic`, `underline`, `strikethrough`, and `inverse` faces.
There are also named faces for the 16 terminal colors: `black`, `red`, `green`, `yellow`, `blue`, `magenta`, `cyan`, `white`, `bright_black`/`grey`/`gray`, `bright_red`, `bright_green`, `bright_blue`, `bright_magenta`, `bright_cyan`, and `bright_white`.
For shadowed text (i.e. dim but there) there is the `shadow` face. To indicate a selected region, there is the `region` face. Similarly for emphasis and highlighting the `emphasis` and `highlight` faces are defined. There is also `code` for code-like text.
For visually indicating the severity of messages, the `error`, `warning`, `success`, `info`, `note`, and `tip` faces are defined.


### [Customisation of faces (Faces.toml)](#stdlib-styledstrings-face-toml)
It is good for the name faces in the global face dictionary to be customizable. Theming and aesthetics are nice, and it is important for accessibility reasons too. A TOML file can be parsed into a list of [`Face`](#StyledStrings.Face) specifications that are merged with the pre-existing entry in the face dictionary.
A [`Face`](#StyledStrings.Face) is represented in TOML like so:
```toml
[facename]
attribute = "value"
...

[package.facename]
attribute = "value"
```
For example, if the `shadow` face is too hard to read it can be made brighter like so:
```toml
[shadow]
foreground = "white"
```
On initialization, the `config/faces.toml` file under the first Julia depot (usually `~/.julia`) is loaded.


### [Applying faces to a AnnotatedString](#Applying-faces-to-a-AnnotatedString)
By convention, the `:face` attributes of a [`AnnotatedString`](../../base/strings/#Base.AnnotatedString) hold information on the [`Face`](#StyledStrings.Face)s that currently apply. This can be given in multiple forms, as a single `Symbol` naming a [`Face`](#StyledStrings.Face)s in the global face dictionary, a [`Face`](#StyledStrings.Face) itself, or a vector of either.
The `show(::IO, ::MIME"text/plain", ::AnnotatedString)` and `show(::IO, ::MIME"text/html", ::AnnotatedString)` methods both look at the `:face` attributes and merge them all together when determining the overall styling.
We can supply `:face` attributes to a `AnnotatedString` during construction, add them to the properties list afterwards, or use the convenient [Styled String literals](#stdlib-styledstring-literals).
```julia-repl
julia> str1 = AnnotatedString("blue text", [(1:9, :face, :blue)])"blue text"
julia> str2 = styled"{blue:blue text}""blue text"
julia> str1 == str2true
julia> sprint(print, str1, context = :color => true)"\e[34mblue text\e[39m"
julia> sprint(show, MIME("text/html"), str1, context = :color => true)"<span style=\"color: #195eb3\">blue text</span>"
```


## [Styled String Literals](#stdlib-styledstring-literals)
To ease construction of [`AnnotatedString`](../../base/strings/#Base.AnnotatedString)s with [`Face`](#StyledStrings.Face)s applied, the [`styled"..."`](#StyledStrings.StyledMarkup.@styled_str) styled string literal allows for the content and attributes to be easily expressed together via a custom grammar.
Within a [`styled"..."`](#StyledStrings.StyledMarkup.@styled_str) literal, curly braces are considered special characters and must be escaped in normal usage (`\{`, `\}`). This allows them to be used to express annotations with (nestable) `{annotations...:text}` constructs.
The `annotations...` component is a comma-separated list of three types of annotations.
-   Face names
-   Inline `Face` expressions `(key=val,...)`
-   `key=value` pairs
Interpolation is possible everywhere except for inline face keys.
For more information on the grammar, see the extended help of the [`styled"..."`](#StyledStrings.StyledMarkup.@styled_str) docstring.
As an example, we can demonstrate the list of built-in faces mentioned above like so:


## [Styled String Literals](#stdlib-styledstring-literals)
```julia-repl
julia> println(styled"
The basic font-style attributes are {bold:bold}, {light:light}, {italic:italic},
{underline:underline}, and {strikethrough:strikethrough}.

In terms of color, we have named faces for the 16 standard terminal colors:
 {black:■} {red:■} {green:■} {yellow:■} {blue:■} {magenta:■} {cyan:■} {white:■}
 {bright_black:■} {bright_red:■} {bright_green:■} {bright_yellow:■} {bright_blue:■} {bright_magenta:■} {bright_cyan:■} {bright_white:■}

Since {code:bright_black} is effectively grey, we define two aliases for it:
{code:grey} and {code:gray} to allow for regional spelling differences.

To flip the foreground and background colors of some text, you can use the
{code:inverse} face, for example: {magenta:some {inverse:inverse} text}.

The intent-based basic faces are {shadow:shadow} (for dim but visible text),
{region:region} for selections, {emphasis:emphasis}, and {highlight:highlight}.
As above, {code:code} is used for code-like text.

Lastly, we have the 'message severity' faces: {error:error}, {warning:warning},
{success:success}, {info:info}, {note:note}, and {tip:tip}.

Remember that all these faces (and any user or package-defined ones) can
arbitrarily nest and overlap, {region,tip:like {bold,italic:so}}.")
```
     The basic font-style attributes are bold, light, italic,
     underline, and strikethrough.
     In terms of color, we have named faces for the 16 standard terminal colors:
      ■ ■ ■ ■ ■ ■ ■ ■
      ■ ■ ■ ■ ■ ■ ■ ■


## [Styled String Literals](#stdlib-styledstring-literals)
     Since bright_black is effectively grey, we define two aliases for it:
     grey and gray to allow for regional spelling differences.
     To flip the foreground and background colors of some text, you can use the
     inverse face, for example: some inverse text.
     The intent-based basic faces are shadow (for dim but visible text),
     region for selections, emphasis, and highlight.
     As above, code is used for code-like text.
     Lastly, we have the 'message severity' faces: error, warning,
     success, info, note, and tip.
     Remember that all these faces (and any user or package-defined ones) can
     arbitrarily nest and overlap, like so.


## [API reference](#stdlib-styledstrings-api)


### [Styling and Faces](#Styling-and-Faces)
```julia
@styled_str -> AnnotatedString
```
Construct a styled string. Within the string, `{<specs>:<content>}` structures apply the formatting to `<content>`, according to the list of comma-separated specifications `<specs>`. Each spec can either take the form of a face name, an inline face specification, or a `key=value` pair. The value must be wrapped by `{...}` should it contain any of the characters `,=:{}`.
String interpolation with `$` functions in the same way as regular strings, except quotes need to be escaped. Faces, keys, and values can also be interpolated with `$`.
**Example**
```julia
styled"The {bold:{italic:quick} {(foreground=#cd853f):brown} fox} jumped over the {link={https://en.wikipedia.org/wiki/Laziness}:lazy} dog"
```
**Extended help**
This macro can be described by the following EBNF grammar:


### [Styling and Faces](#Styling-and-Faces)
```ebnf
styledstring = { styled | interpolated | escaped | plain } ;

specialchar = '{' | '}' | '$' | '\"' ;
anychar = [\u0-\u1fffff] ;
plain = { anychar - specialchar } ;
escaped = '\\', specialchar ;

interpolated = '$', ? expr ? | '$(', ? expr ?, ')' ;

styled = '{', ws, annotations, ':', content, '}' ;
content = { interpolated | plain | escaped | styled } ;
annotations = annotation | annotations, ws, ',', ws, annotation ;
annotation = face | inlineface | keyvalue ;
ws = { ' ' | '\t' | '\n' } ; (* whitespace *)

face = facename | interpolated ;
facename = [A-Za-z0-9_]+ ;

inlineface = '(', ws, [ faceprop ], { ws, ',', faceprop }, ws, ')' ;
faceprop = [a-z]+, ws, '=', ws, ( [^,)]+ | interpolated) ;

keyvalue = key, ws, '=', ws, value ;
key = ( [^\0${}=,:], [^\0=,:]* ) | interpolated ;
value = simplevalue | curlybraced | interpolated ;
curlybraced = '{' { escaped | plain } '}' ;
simplevalue = [^${},:], [^,:]* ;
```
An extra stipulation not encoded in the above grammar is that `plain` should be a valid input to [`unescape_string`](../../base/strings/#Base.unescape_string), with `specialchar` kept.
The above grammar for `inlineface` is simplified, as the actual implementation is a bit more sophisticated. The full behaviour is given below.


### [Styling and Faces](#Styling-and-Faces)
```ebnf
faceprop = ( 'face', ws, '=', ws, ( ? string ? | interpolated ) ) |
           ( 'height', ws, '=', ws, ( ? number ? | interpolated ) ) |
           ( 'weight', ws, '=', ws, ( symbol | interpolated ) ) |
           ( 'slant', ws, '=', ws, ( symbol | interpolated ) ) |
           ( ( 'foreground' | 'fg' | 'background' | 'bg' ),
               ws, '=', ws, ( simplecolor | interpolated ) ) |
           ( 'underline', ws, '=', ws, ( underline | interpolated ) ) |
           ( 'strikethrough', ws, '=', ws, ( bool | interpolated ) ) |
           ( 'inverse', ws, '=', ws, ( bool | interpolated ) ) |
           ( 'inherit', ws, '=', ws, ( inherit | interpolated ) ) ;

nothing = 'nothing' ;
bool = 'true' | 'false' ;
symbol = [^ ,)]+ ;
hexcolor = ('#' | '0x'), [0-9a-f]{6} ;
simplecolor = hexcolor | symbol | nothing ;

underline = nothing | bool | simplecolor | underlinestyled;
underlinestyled = '(', ws, ('' | nothing | simplecolor | interpolated), ws,
                  ',', ws, ( symbol | interpolated ), ws ')' ;

inherit = ( '[', inheritval, { ',', inheritval }, ']' ) | inheritval;
inheritval = ws, ':'?, symbol ;
```
```julia
styled(content::AbstractString) -> AnnotatedString
```


### [Styling and Faces](#Styling-and-Faces)
Construct a styled string. Within the string, `{<specs>:<content>}` structures apply the formatting to `<content>`, according to the list of comma-separated specifications `<specs>`. Each spec can either take the form of a face name, an inline face specification, or a `key=value` pair. The value must be wrapped by `{...}` should it contain any of the characters `,=:{}`.
This is a functional equivalent of the [`@styled_str`](#StyledStrings.StyledMarkup.@styled_str) macro, just without interpolation capabilities.
A [`Face`](#StyledStrings.Face) is a collection of graphical attributes for displaying text. Faces control how text is displayed in the terminal, and possibly other places too.
Most of the time, a [`Face`](#StyledStrings.Face) will be stored in the global faces dicts as a unique association with a *face name* Symbol, and will be most often referred to by this name instead of the [`Face`](#StyledStrings.Face) object itself.
**Attributes**
All attributes can be set via the keyword constructor, and default to `nothing`.
-   `height` (an `Int` or `Float64`): The height in either deci-pt (when an `Int`), or as a factor of the base size (when a `Float64`).
-   `weight` (a `Symbol`): One of the symbols (from faintest to densest) `:thin`, `:extralight`, `:light`, `:semilight`, `:normal`, `:medium`, `:semibold`, `:bold`, `:extrabold`, or `:black`. In terminals any weight greater than `:normal` is displayed as bold, and in terminals that support variable-brightness text, any weight less than `:normal` is displayed as faint.


### [Styling and Faces](#Styling-and-Faces)
-   `slant` (a `Symbol`): One of the symbols `:italic`, `:oblique`, or `:normal`.
-   `foreground` (a `SimpleColor`): The text foreground color.
-   `background` (a `SimpleColor`): The text background color.
-   `underline`, the text underline, which takes one of the following forms:
    -   a `Bool`: Whether the text should be underlined or not.
    -   a `SimpleColor`: The text should be underlined with this color.
    -   a `Tuple{Nothing, Symbol}`: The text should be underlined using the style set by the Symbol, one of `:straight`, `:double`, `:curly`, `:dotted`, or `:dashed`.
    -   a `Tuple{SimpleColor, Symbol}`: The text should be underlined in the specified SimpleColor, and using the style specified by the Symbol, as before.
-   `strikethrough` (a `Bool`): Whether the text should be struck through.
-   `inverse` (a `Bool`): Whether the foreground and background colors should be inverted.
-   `inherit` (a `Vector{Symbol}`): Names of faces to inherit from, with earlier faces taking priority. All faces inherit from the `:default` face.
```julia
addface!(name::Symbol => default::Face)
```
Create a new face by the name `name`. So long as no face already exists by this name, `default` is added to both `FACES``.default` and (a copy of) to `FACES`.`current`, with the current value returned.
Should the face `name` already exist, `nothing` is returned.
**Examples**
```julia-repl
julia> addface!(:mypkg_myface => Face(slant=:italic, underline=true))
Face (sample)
         slant: italic
     underline: true
```


### [Styling and Faces](#Styling-and-Faces)
```julia
withfaces(f, kv::Pair...)
withfaces(f, kvpair_itr)
```
Execute `f` with `FACES``.current` temporarily modified by zero or more `:name => val` arguments `kv`, or `kvpair_itr` which produces `kv`-form values.
`withfaces` is generally used via the `withfaces(kv...) do ... end` syntax. A value of `nothing` can be used to temporarily unset a face (if it has been set). When `withfaces` returns, the original `FACES``.current` has been restored.
**Examples**
```julia-repl
julia> withfaces(:yellow => Face(foreground=:red), :green => :blue) do
           println(styled"{yellow:red} and {green:blue} mixed make {magenta:purple}")
       end
red and blue mixed make purple
```
```julia
struct SimpleColor
```
A basic representation of a color, intended for string styling purposes. It can either contain a named color (like `:red`), or an `RGBTuple` which is a NamedTuple specifying an `r`, `g`, `b` color with a bit-depth of 8.
**Constructors**
```julia
SimpleColor(name::Symbol)  # e.g. :red
SimpleColor(rgb::RGBTuple) # e.g. (r=1, b=2, g=3)
SimpleColor(r::Integer, b::Integer, b::Integer)
SimpleColor(rgb::UInt32)   # e.g. 0x123456
```
Also see `tryparse(SimpleColor, rgb::String)`.
```julia
parse(::Type{SimpleColor}, rgb::String)
```
An analogue of `tryparse(SimpleColor, rgb::String)` (which see), that raises an error instead of returning `nothing`.
```julia
tryparse(::Type{SimpleColor}, rgb::String)
```


### [Styling and Faces](#Styling-and-Faces)
Attempt to parse `rgb` as a `SimpleColor`. If `rgb` starts with `#` and has a length of 7, it is converted into a `RGBTuple`-backed `SimpleColor`. If `rgb` starts with `a`-`z`, `rgb` is interpreted as a color name and converted to a `Symbol`-backed `SimpleColor`.
Otherwise, `nothing` is returned.
**Examples**
```julia-repl
julia> tryparse(SimpleColor, "blue")
SimpleColor(blue)

julia> tryparse(SimpleColor, "#9558b2")
SimpleColor(#9558b2)

julia> tryparse(SimpleColor, "#nocolor")
```
```julia
merge(initial::Face, others::Face...)
```
Merge the properties of the `initial` face and `others`, with later faces taking priority.
------------------------------------------------------------------------


# TOML · The Julia Language
Source: https://docs.julialang.org/en/v1/stdlib/TOML/


# [TOML](#TOML)
TOML.jl is a Julia standard library for parsing and writing [TOML v1.0](https://toml.io/en/) files.


## [Parsing TOML data](#Parsing-TOML-data)
```julia-repl
julia> using TOML

julia> data = """
           [database]
           server = "192.168.1.1"
           ports = [ 8001, 8001, 8002 ]
       """;

julia> TOML.parse(data)
Dict{String, Any} with 1 entry:
  "database" => Dict{String, Any}("server"=>"192.168.1.1", "ports"=>[8001, 8001…
```
To parse a file, use [`TOML.parsefile`](#TOML.parsefile). If the file has a syntax error, an exception is thrown:
```julia-repl
julia> using TOML

julia> TOML.parse("""
           value = 0.0.0
       """)
ERROR: TOML Parser error:
none:1:16 error: failed to parse value
      value = 0.0.0
                 ^
[...]
```
There are other versions of the parse functions ([`TOML.tryparse`](#TOML.tryparse) and [`TOML.tryparsefile`](#TOML.tryparsefile)) that instead of throwing exceptions on parser error returns a [`TOML.ParserError`](#TOML.ParserError) with information:
```julia-repl
julia> using TOML

julia> err = TOML.tryparse("""
           value = 0.0.0
       """);

julia> err.type
ErrGenericValueError::ErrorType = 14

julia> err.line
1

julia> err.column
16
```


## [Exporting data to TOML file](#Exporting-data-to-TOML-file)
The [`TOML.print`](#TOML.print) function is used to print (or serialize) data into TOML format.
```julia-repl
julia> using TOML

julia> data = Dict(
          "names" => ["Julia", "Julio"],
          "age" => [10, 20],
       );

julia> TOML.print(data)
names = ["Julia", "Julio"]
age = [10, 20]

julia> fname = tempname();

julia> open(fname, "w") do io
           TOML.print(io, data)
       end

julia> TOML.parsefile(fname)
Dict{String, Any} with 2 entries:
  "names" => ["Julia", "Julio"]
  "age"   => [10, 20]
```
Keys can be sorted according to some value
```julia-repl
julia> using TOML

julia> TOML.print(Dict(
       "abc"  => 1,
       "ab"   => 2,
       "abcd" => 3,
       ); sorted=true, by=length)
ab = 2
abc = 1
abcd = 3
```
For custom structs, pass a function that converts the struct to a supported type
```julia-repl
julia> using TOML

julia> struct MyStruct
           a::Int
           b::String
       end

julia> TOML.print(Dict("foo" => MyStruct(5, "bar"))) do x
           x isa MyStruct && return [x.a, x.b]
           error("unhandled type $(typeof(x))")
       end
foo = [5, "bar"]
```


## [References](#References)
```julia
parse(x::Union{AbstractString, IO})
parse(p::Parser, x::Union{AbstractString, IO})
```
Parse the string or stream `x`, and return the resulting table (dictionary). Throw a [`ParserError`](#TOML.ParserError) upon failure.
See also [`TOML.tryparse`](#TOML.tryparse).
```julia
parsefile(f::AbstractString)
parsefile(p::Parser, f::AbstractString)
```
Parse file `f` and return the resulting table (dictionary). Throw a [`ParserError`](#TOML.ParserError) upon failure.
See also [`TOML.tryparsefile`](#TOML.tryparsefile).
```julia
tryparse(x::Union{AbstractString, IO})
tryparse(p::Parser, x::Union{AbstractString, IO})
```
Parse the string or stream `x`, and return the resulting table (dictionary). Return a [`ParserError`](#TOML.ParserError) upon failure.
See also [`TOML.parse`](#TOML.parse).
```julia
tryparsefile(f::AbstractString)
tryparsefile(p::Parser, f::AbstractString)
```
Parse file `f` and return the resulting table (dictionary). Return a [`ParserError`](#TOML.ParserError) upon failure.
See also [`TOML.parsefile`](#TOML.parsefile).
```julia
print([to_toml::Function], io::IO [=stdout], data::AbstractDict; sorted=false, by=identity, inline_tables::IdSet{<:AbstractDict})
```
Write `data` as TOML syntax to the stream `io`. If the keyword argument `sorted` is set to `true`, sort tables according to the function given by the keyword argument `by`. If the keyword argument `inline_tables` is given, it should be a set of tables that should be printed "inline".


## [References](#References)
The following data types are supported: `AbstractDict`, `AbstractVector`, `AbstractString`, `Integer`, `AbstractFloat`, `Bool`, `Dates.DateTime`, `Dates.Time`, `Dates.Date`. Note that the integers and floats need to be convertible to `Float64` and `Int64` respectively. For other data types, pass the function `to_toml` that takes the data types and returns a value of a supported type.
```julia
Parser()
```
Constructor for a TOML `Parser`. Note that in most cases one does not need to explicitly create a `Parser` but instead one directly use use [`TOML.parsefile`](#TOML.parsefile) or [`TOML.parse`](#TOML.parse). Using an explicit parser will however reuse some internal data structures which can be beneficial for performance if a larger number of small files are parsed.
```julia
ParserError
```
Type that is returned from [`tryparse`](#TOML.tryparse) and [`tryparsefile`](#TOML.tryparsefile) when parsing fails. It contains (among others) the following fields:
-   `pos`, the position in the string when the error happened
-   `table`, the result that so far was successfully parsed
-   `type`, an error type, different for different types of errors
------------------------------------------------------------------------


# Tar · The Julia Language
Source: https://docs.julialang.org/en/v1/stdlib/Tar/


# [Tar](#Tar)
```julia
create(
    [ predicate, ] dir, [ tarball ];
    [ skeleton, ] [ portable = false ]
) -> tarball

    predicate :: String --> Bool
    dir       :: AbstractString
    tarball   :: Union{AbstractString, AbstractCmd, IO}
    skeleton  :: Union{AbstractString, AbstractCmd, IO}
    portable  :: Bool
```
Create a tar archive ("tarball") of the directory `dir`. The resulting archive is written to the path `tarball` or if no path is specified, a temporary path is created and returned by the function call. If `tarball` is an IO object then the tarball content is written to that handle instead (the handle is left open).
If a `predicate` function is passed, it is called on each system path that is encountered while recursively searching `dir` and `path` is only included in the tarball if `predicate(path)` is true. If `predicate(path)` returns false for a directory, then the directory is excluded entirely: nothing under that directory will be included in the archive.
If the `skeleton` keyword is passed then the file or IO handle given is used as a "skeleton" to generate the tarball. You create a skeleton file by passing the `skeleton` keyword to the `extract` command. If `create` is called with that skeleton file and the extracted files haven't changed, an identical tarball is recreated. The `skeleton` and `predicate` arguments cannot be used together.


# [Tar](#Tar)
If the `portable` flag is true then path names are checked for validity on Windows, which ensures that they don't contain illegal characters or have names that are reserved. See https://stackoverflow.com/a/31976060/659248 for details.
```julia
extract(
    [ predicate, ] tarball, [ dir ];
    [ skeleton = <none>, ]
    [ copy_symlinks = <auto>, ]
    [ set_permissions = true, ]
) -> dir

    predicate       :: Header --> Bool
    tarball         :: Union{AbstractString, AbstractCmd, IO}
    dir             :: AbstractString
    skeleton        :: Union{AbstractString, AbstractCmd, IO}
    copy_symlinks   :: Bool
    set_permissions :: Bool
```
Extract a tar archive ("tarball") located at the path `tarball` into the directory `dir`. If `tarball` is an IO object instead of a path, then the archive contents will be read from that IO stream. The archive is extracted to `dir` which must either be an existing empty directory or a non-existent path which can be created as a new directory. If `dir` is not specified, the archive is extracted into a temporary directory which is returned by `extract`.
If a `predicate` function is passed, it is called on each `Header` object that is encountered while extracting `tarball` and the entry is only extracted if the `predicate(hdr)` is true. This can be used to selectively extract only parts of an archive, to skip entries that cause `extract` to throw an error, or to record what is extracted during the extraction process.


# [Tar](#Tar)
Before it is passed to the predicate function, the `Header` object is somewhat modified from the raw header in the tarball: the `path` field is normalized to remove `.` entries and replace multiple consecutive slashes with a single slash. If the entry has type `:hardlink`, the link target path is normalized the same way so that it will match the path of the target entry; the size field is set to the size of the target path (which must be an already-seen file).
If the `skeleton` keyword is passed then a "skeleton" of the extracted tarball is written to the file or IO handle given. This skeleton file can be used to recreate an identical tarball by passing the `skeleton` keyword to the `create` function. The `skeleton` and `predicate` arguments cannot be used together.
If `copy_symlinks` is `true` then instead of extracting symbolic links as such, they will be extracted as copies of what they link to if they are internal to the tarball and if it is possible to do so. Non-internal symlinks, such as a link to `/etc/passwd` will not be copied. Symlinks which are in any way cyclic will also not be copied and will instead be skipped. By default, `extract` will detect whether symlinks can be created in `dir` or not and will automatically copy symlinks if they cannot be created.
If `set_permissions` is `false`, no permissions are set on the extracted files.


# [Tar](#Tar)
```julia
list(tarball; [ strict = true ]) -> Vector{Header}
list(callback, tarball; [ strict = true ])

    callback  :: Header, [ <data> ] --> Any
    tarball   :: Union{AbstractString, AbstractCmd, IO}
    strict    :: Bool
```
List the contents of a tar archive ("tarball") located at the path `tarball`. If `tarball` is an IO handle, read the tar contents from that stream. Returns a vector of `Header` structs. See [`Header`](#Tar.Header) for details.
If a `callback` is provided then instead of returning a vector of headers, the callback is called on each `Header`. This can be useful if the number of items in the tarball is large or if you want examine items prior to an error in the tarball. If the `callback` function can accept a second argument of either type `Vector{UInt8}` or `Vector{Pair{Symbol, String}}` then it will be called with a representation of the raw header data either as a single byte vector or as a vector of pairs mapping field names to the raw data for that field (if these fields are concatenated together, the result is the raw data of the header).
By default `list` will error if it encounters any tarball contents which the `extract` function would refuse to extract. With `strict=false` it will skip these checks and list all the the contents of the tar file whether `extract` would extract them or not. Beware that malicious tarballs can do all sorts of crafty and unexpected things to try to trick you into doing something bad.


# [Tar](#Tar)
If the `tarball` argument is a skeleton file (see `extract` and `create`) then `list` will detect that from the file header and appropriately list or iterate the headers of the skeleton file.
```julia
rewrite(
    [ predicate, ] old_tarball, [ new_tarball ];
    [ portable = false, ]
) -> new_tarball

    predicate   :: Header --> Bool
    old_tarball :: Union{AbstractString, AbstractCmd, IO}
    new_tarball :: Union{AbstractString, AbstractCmd, IO}
    portable    :: Bool
```
Rewrite `old_tarball` to the standard format that `create` generates, while also checking that it doesn't contain anything that would cause `extract` to raise an error. This is functionally equivalent to doing
```julia
Tar.create(Tar.extract(predicate, old_tarball), new_tarball)
```
However, it never extracts anything to disk and instead uses the `seek` function to navigate the old tarball's data. If no `new_tarball` argument is passed, the new tarball is written to a temporary file whose path is returned.
If a `predicate` function is passed, it is called on each `Header` object that is encountered while extracting `old_tarball` and the entry is skipped unless `predicate(hdr)` is true. This can be used to selectively rewrite only parts of an archive, to skip entries that would cause `extract` to throw an error, or to record what content is encountered during the rewrite process.


# [Tar](#Tar)
Before it is passed to the predicate function, the `Header` object is somewhat modified from the raw header in the tarball: the `path` field is normalized to remove `.` entries and replace multiple consecutive slashes with a single slash. If the entry has type `:hardlink`, the link target path is normalized the same way so that it will match the path of the target entry; the size field is set to the size of the target path (which must be an already-seen file).
If the `portable` flag is true then path names are checked for validity on Windows, which ensures that they don't contain illegal characters or have names that are reserved. See https://stackoverflow.com/a/31976060/659248 for details.
```julia
tree_hash([ predicate, ] tarball;
          [ algorithm = "git-sha1", ]
          [ skip_empty = false ]) -> hash::String

    predicate  :: Header --> Bool
    tarball    :: Union{AbstractString, AbstractCmd, IO}
    algorithm  :: AbstractString
    skip_empty :: Bool
```


# [Tar](#Tar)
Compute a tree hash value for the file tree that the tarball contains. By default, this uses git's tree hashing algorithm with the SHA1 secure hash function (like current versions of git). This means that for any tarball whose file tree git can represent—i.e. one with only files, symlinks and non-empty directories—the hash value computed by this function will be the same as the hash value git would compute for that file tree. Note that tarballs can represent file trees with empty directories, which git cannot store, and this function can generate hashes for those, which will, by default (see `skip_empty` below for how to change this behavior), differ from the hash of a tarball which omits those empty directories. In short, the hash function agrees with git on all trees which git can represent, but extends (in a consistent way) the domain of hashable trees to other trees which git cannot represent.
If a `predicate` function is passed, it is called on each `Header` object that is encountered while processing `tarball` and an entry is only hashed if `predicate(hdr)` is true. This can be used to selectively hash only parts of an archive, to skip entries that cause `extract` to throw an error, or to record what is extracted during the hashing process.


# [Tar](#Tar)
Before it is passed to the predicate function, the `Header` object is somewhat modified from the raw header in the tarball: the `path` field is normalized to remove `.` entries and replace multiple consecutive slashes with a single slash. If the entry has type `:hardlink`, the link target path is normalized the same way so that it will match the path of the target entry; the size field is set to the size of the target path (which must be an already-seen file).
Currently supported values for `algorithm` are `git-sha1` (the default) and `git-sha256`, which uses the same basic algorithm as `git-sha1` but replaces the SHA1 hash function with SHA2-256, the hash function that git will transition to using in the future (due to known attacks on SHA1). Support for other file tree hashing algorithms may be added in the future.


# [Tar](#Tar)
The `skip_empty` option controls whether directories in the tarball which recursively contain no files or symlinks are included in the hash or ignored. In general, if you are hashing the content of a tarball or a file tree, you care about all directories, not just non-empty ones, so including these in the computed hash is the default. So why does this function even provide the option to skip empty directories? Because git refuses to store empty directories and will ignore them if you try to add them to a repo. So if you compute a reference tree hash by by adding files to a git repo and then asking git for the tree hash, the hash value that you get will match the hash value computed by `tree_hash` with `skip_empty=true`. In other words, this option allows `tree_hash` to emulate how git would hash a tree with empty directories. If you are hashing trees that may contain empty directories (i.e. do not come from a git repo), however, it is recommended that you hash them using a tool (such as this one) that does not ignore empty directories.
The `Header` type is a struct representing the essential metadata for a single record in a tar file with this definition:
```julia
struct Header
    path :: String # path relative to the root
    type :: Symbol # type indicator (see below)
    mode :: UInt16 # mode/permissions (best viewed in octal)
    size :: Int64  # size of record data in bytes
    link :: String # target path of a symlink
end
```


# [Tar](#Tar)
Types are represented with the following symbols: `file`, `hardlink`, `symlink`, `chardev`, `blockdev`, `directory`, `fifo`, or for unknown types, the typeflag character as a symbol. Note that [`extract`](#Tar.extract) refuses to extract records types other than `file`, `symlink` and `directory`; [`list`](#Tar.list) will only list other kinds of records if called with `strict=false`.
The tar format includes various other metadata about records, including user and group IDs, user and group names, and timestamps. The `Tar` package, by design, completely ignores these. When creating tar files, these fields are always set to zero/empty. When reading tar files, these fields are ignored aside from verifying header checksums for each header record for all fields.
------------------------------------------------------------------------


# Unit Testing · The Julia Language
Source: https://docs.julialang.org/en/v1/stdlib/Test/


# [Unit Testing](#Unit-Testing)


## [Testing Base Julia](#Testing-Base-Julia)
Julia is under rapid development and has an extensive test suite to verify functionality across multiple platforms. If you build Julia from source, you can run this test suite with `make test`. In a binary install, you can run the test suite using `Base.runtests()`.
```julia
Base.runtests(tests=["all"]; ncores=ceil(Int, Sys.CPU_THREADS / 2),
              exit_on_error=false, revise=false, [seed])
```
Run the Julia unit tests listed in `tests`, which can be either a string or an array of strings, using `ncores` processors. If `exit_on_error` is `false`, when one test fails, all remaining tests in other files will still be run; they are otherwise discarded, when `exit_on_error == true`. If `revise` is `true`, the `Revise` package is used to load any modifications to `Base` or to the standard libraries before running the tests. If a seed is provided via the keyword argument, it is used to seed the global RNG in the context where the tests are run; otherwise the seed is chosen randomly.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/util.jl#L661-L673)


## [Basic Unit Tests](#Basic-Unit-Tests)
The `Test` module provides simple *unit testing* functionality. Unit testing is a way to see if your code is correct by checking that the results are what you expect. It can be helpful to ensure your code still works after you make changes, and can be used when developing as a way of specifying the behaviors your code should have when complete. You may also want to look at the documentation for [adding tests to your Julia Package](https://pkgdocs.julialang.org/dev/creating-packages/#Adding-tests-to-the-package).
Simple unit testing can be performed with the `@test` and `@test_throws` macros:
```julia
@test ex
@test f(args...) key=val ...
@test ex broken=true
@test ex skip=true
```
Test that the expression `ex` evaluates to `true`. If executed inside a `@testset`, return a `Pass` `Result` if it does, a `Fail` `Result` if it is `false`, and an `Error` `Result` if it could not be evaluated. If executed outside a `@testset`, throw an exception instead of returning `Fail` or `Error`.
**Examples**
```julia-repl
julia> @test true
Test Passed

julia> @test [1, 2] + [2, 1] == [3, 3]
Test Passed
```
The `@test f(args...) key=val...` form is equivalent to writing `@test f(args..., key=val...)` which can be useful when the expression is a call using infix syntax such as approximate comparisons:
```julia-repl
julia> @test π ≈ 3.14 atol=0.01
Test Passed
```


## [Basic Unit Tests](#Basic-Unit-Tests)
This is equivalent to the uglier test `@test ≈(π, 3.14, atol=0.01)`. It is an error to supply more than one expression unless the first is a call expression and the rest are assignments (`k=v`).
You can use any key for the `key=val` arguments, except for `broken` and `skip`, which have special meanings in the context of `@test`:
-   `broken=cond` indicates a test that should pass but currently consistently fails when `cond==true`. Tests that the expression `ex` evaluates to `false` or causes an exception. Returns a `Broken` `Result` if it does, or an `Error` `Result` if the expression evaluates to `true`. Regular `@test ex` is evaluated when `cond==false`.
-   `skip=cond` marks a test that should not be executed but should be included in test summary reporting as `Broken`, when `cond==true`. This can be useful for tests that intermittently fail, or tests of not-yet-implemented functionality. Regular `@test ex` is evaluated when `cond==false`.
**Examples**
```julia-repl
julia> @test 2 + 2 ≈ 6 atol=1 broken=true
Test Broken
  Expression: ≈(2 + 2, 6, atol = 1)

julia> @test 2 + 2 ≈ 5 atol=1 broken=false
Test Passed

julia> @test 2 + 2 == 5 skip=true
Test Broken
  Skipped: 2 + 2 == 5

julia> @test 2 + 2 == 4 skip=false
Test Passed
```
The `broken` and `skip` keyword arguments require at least Julia 1.7.
```julia
@test_throws exception expr
```


## [Basic Unit Tests](#Basic-Unit-Tests)
Tests that the expression `expr` throws `exception`. The exception may specify either a type, a string, regular expression, or list of strings occurring in the displayed error message, a matching function, or a value (which will be tested for equality by comparing fields). Note that `@test_throws` does not support a trailing keyword form.
The ability to specify anything other than a type or a value as `exception` requires Julia v1.8 or later.
**Examples**
```julia-repl
julia> @test_throws BoundsError [1, 2, 3][4]
Test Passed
      Thrown: BoundsError

julia> @test_throws DimensionMismatch [1, 2, 3] + [1, 2]
Test Passed
      Thrown: DimensionMismatch

julia> @test_throws "Try sqrt(Complex" sqrt(-1)
Test Passed
     Message: "DomainError with -1.0:\nsqrt was called with a negative real argument but will only return a complex result if called with a complex argument. Try sqrt(Complex(x))."
```
In the final example, instead of matching a single string it could alternatively have been performed with:
-   `["Try", "Complex"]` (a list of strings)
-   `r"Try sqrt\([Cc]omplex"` (a regular expression)
-   `str -> occursin("complex", str)` (a matching function)
For example, suppose we want to check our new function `foo(x)` works as expected:
```julia-repl
julia> using Test

julia> foo(x) = length(x)^2
foo (generic function with 1 method)
```
If the condition is true, a `Pass` is returned:
```julia-repl
julia> @test foo("bar") == 9
Test Passed

julia> @test foo("fizz") >= 10
Test Passed
```


## [Basic Unit Tests](#Basic-Unit-Tests)
If the condition is false, then a `Fail` is returned and an exception is thrown:
```julia-repl
julia> @test foo("f") == 20
Test Failed at none:1
  Expression: foo("f") == 20
   Evaluated: 1 == 20

ERROR: There was an error during testing
```
If the condition could not be evaluated because an exception was thrown, which occurs in this case because `length` is not defined for symbols, an `Error` object is returned and an exception is thrown:
```julia-repl
julia> @test foo(:cat) == 1
Error During Test
  Test threw an exception of type MethodError
  Expression: foo(:cat) == 1
  MethodError: no method matching length(::Symbol)
  The function `length` exists, but no method is defined for this combination of argument types.

  Closest candidates are:
    length(::SimpleVector) at essentials.jl:256
    length(::Base.MethodList) at reflection.jl:521
    length(::MethodTable) at reflection.jl:597
    ...
  Stacktrace:
  [...]
ERROR: There was an error during testing
```
If we expect that evaluating an expression *should* throw an exception, then we can use `@test_throws` to check that this occurs:
```julia-repl
julia> @test_throws MethodError foo(:cat)
Test Passed
      Thrown: MethodError
```


## [Working with Test Sets](#Working-with-Test-Sets)
Typically a large number of tests are used to make sure functions work correctly over a range of inputs. In the event a test fails, the default behavior is to throw an exception immediately. However, it is normally preferable to run the rest of the tests first to get a better picture of how many errors there are in the code being tested.
The `@testset` will create a local scope of its own when running the tests in it.
The `@testset` macro can be used to group tests into *sets*. All the tests in a test set will be run, and at the end of the test set a summary will be printed. If any of the tests failed, or could not be evaluated due to an error, the test set will then throw a `TestSetException`.
```julia
@testset [CustomTestSet] [options...] ["description"] begin test_ex end
@testset [CustomTestSet] [options...] ["description $v"] for v in itr test_ex end
@testset [CustomTestSet] [options...] ["description $v, $w"] for v in itrv, w in itrw test_ex end
@testset [CustomTestSet] [options...] ["description"] test_func()
@testset let v = v, w = w; test_ex; end
```
**With begin/end or function call**
When @testset is used, with begin/end or a single function call, the macro starts a new test set in which to evaluate the given expression.
If no custom testset type is given it defaults to creating a `DefaultTestSet`. `DefaultTestSet` records all the results and, if there are any `Fail`s or `Error`s, throws an exception at the end of the top-level (non-nested) test set, along with a summary of the test results.


## [Working with Test Sets](#Working-with-Test-Sets)
Any custom testset type (subtype of `AbstractTestSet`) can be given and it will also be used for any nested `@testset` invocations. The given options are only applied to the test set where they are given. The default test set type accepts three boolean options:
-   `verbose`: if `true`, the result summary of the nested testsets is shown even when they all pass (the default is `false`).
-   `showtiming`: if `true`, the duration of each displayed testset is shown (the default is `true`).
-   `failfast`: if `true`, any test failure or error will cause the testset and any child testsets to return immediately (the default is `false`). This can also be set globally via the env var `JULIA_TEST_FAILFAST`.
`@testset test_func()` requires at least Julia 1.8.
`failfast` requires at least Julia 1.9.
The description string accepts interpolation from the loop indices. If no description is provided, one is constructed based on the variables. If a function call is provided, its name will be used. Explicit description strings override this behavior.
By default the `@testset` macro will return the testset object itself, though this behavior can be customized in other testset types. If a `for` loop is used then the macro collects and returns a list of the return values of the `finish` method, which by default will return a list of the testset objects used in each iteration.


## [Working with Test Sets](#Working-with-Test-Sets)
Before the execution of the body of a `@testset`, there is an implicit call to `Random.seed!(seed)` where `seed` is the current seed of the global RNG. Moreover, after the execution of the body, the state of the global RNG is restored to what it was before the `@testset`. This is meant to ease reproducibility in case of failure, and to allow seamless re-arrangements of `@testset`s regardless of their side-effect on the global RNG state.
**Examples**
```julia-repl
julia> @testset "trigonometric identities" begin
           θ = 2/3*π
           @test sin(-θ) ≈ -sin(θ)
           @test cos(-θ) ≈ cos(θ)
           @test sin(2θ) ≈ 2*sin(θ)*cos(θ)
           @test cos(2θ) ≈ cos(θ)^2 - sin(θ)^2
       end;
Test Summary:            | Pass  Total  Time
trigonometric identities |    4      4  0.2s
```
**`@testset for`**
When `@testset for` is used, the macro starts a new test for each iteration of the provided loop. The semantics of each test set are otherwise identical to that of that `begin/end` case (as if used for each loop iteration).
**`@testset let`**


## [Working with Test Sets](#Working-with-Test-Sets)
When `@testset let` is used, the macro starts a *transparent* test set with the given object added as a context object to any failing test contained therein. This is useful when performing a set of related tests on one larger object and it is desirable to print this larger object when any of the individual tests fail. Transparent test sets do not introduce additional levels of nesting in the test set hierarchy and are passed through directly to the parent test set (with the context object appended to any failing tests.)
`@testset let` requires at least Julia 1.9.
Multiple `let` assignments are supported since Julia 1.10.
**Examples**
```julia-repl
julia> @testset let logi = log(im)
           @test imag(logi) == π/2
           @test !iszero(real(logi))
       end
Test Failed at none:3
  Expression: !(iszero(real(logi)))
     Context: logi = 0.0 + 1.5707963267948966im

ERROR: There was an error during testing

julia> @testset let logi = log(im), op = !iszero
           @test imag(logi) == π/2
           @test op(real(logi))
       end
Test Failed at none:3
  Expression: op(real(logi))
     Context: logi = 0.0 + 1.5707963267948966im
              op = !iszero

ERROR: There was an error during testing
```
```julia
TestSetException
```
Thrown when a test set finishes and not all tests passed.
We can put our tests for the `foo(x)` function in a test set:


## [Working with Test Sets](#Working-with-Test-Sets)
```julia-repl
julia> @testset "Foo Tests" begin
           @test foo("a")   == 1
           @test foo("ab")  == 4
           @test foo("abc") == 9
       end;
Test Summary: | Pass  Total  Time
Foo Tests     |    3      3  0.0s
```
Test sets can also be nested:
```julia-repl
julia> @testset "Foo Tests" begin
           @testset "Animals" begin
               @test foo("cat") == 9
               @test foo("dog") == foo("cat")
           end
           @testset "Arrays $i" for i in 1:3
               @test foo(zeros(i)) == i^2
               @test foo(fill(1.0, i)) == i^2
           end
       end;
Test Summary: | Pass  Total  Time
Foo Tests     |    8      8  0.0s
```
As well as call functions:
```julia-repl
julia> f(x) = @test isone(x)
f (generic function with 1 method)

julia> @testset f(1);
Test Summary: | Pass  Total  Time
f             |    1      1  0.0s
```
This can be used to allow for factorization of test sets, making it easier to run individual test sets by running the associated functions instead. Note that in the case of functions, the test set will be given the name of the called function. In the event that a nested test set has no failures, as happened here, it will be hidden in the summary, unless the `verbose=true` option is passed:


## [Working with Test Sets](#Working-with-Test-Sets)
```julia-repl
julia> @testset verbose = true "Foo Tests" begin
           @testset "Animals" begin
               @test foo("cat") == 9
               @test foo("dog") == foo("cat")
           end
           @testset "Arrays $i" for i in 1:3
               @test foo(zeros(i)) == i^2
               @test foo(fill(1.0, i)) == i^2
           end
       end;
Test Summary: | Pass  Total  Time
Foo Tests     |    8      8  0.0s
  Animals     |    2      2  0.0s
  Arrays 1    |    2      2  0.0s
  Arrays 2    |    2      2  0.0s
  Arrays 3    |    2      2  0.0s
```
If we do have a test failure, only the details for the failed test sets will be shown:
```julia-repl
julia> @testset "Foo Tests" begin
           @testset "Animals" begin
               @testset "Felines" begin
                   @test foo("cat") == 9
               end
               @testset "Canines" begin
                   @test foo("dog") == 9
               end
           end
           @testset "Arrays" begin
               @test foo(zeros(2)) == 4
               @test foo(fill(1.0, 4)) == 15
           end
       end

Arrays: Test Failed
  Expression: foo(fill(1.0, 4)) == 15
   Evaluated: 16 == 15
[...]
Test Summary: | Pass  Fail  Total  Time
Foo Tests     |    3     1      4  0.0s
  Animals     |    2            2  0.0s
  Arrays      |    1     1      2  0.0s
ERROR: Some tests did not pass: 3 passed, 1 failed, 0 errored, 0 broken.
```


## [Testing Log Statements](#Testing-Log-Statements)
One can use the [`@test_logs`](#Test.@test_logs) macro to test log statements, or use a [`TestLogger`](#Test.TestLogger).
```julia
@test_logs [log_patterns...] [keywords] expression
```
Collect a list of log records generated by `expression` using `collect_test_logs`, check that they match the sequence `log_patterns`, and return the value of `expression`. The `keywords` provide some simple filtering of log records: the `min_level` keyword controls the minimum log level which will be collected for the test, the `match_mode` keyword defines how matching will be performed (the default `:all` checks that all logs and patterns match pairwise; use `:any` to check that the pattern matches at least once somewhere in the sequence.)
The most useful log pattern is a simple tuple of the form `(level,message)`. A different number of tuple elements may be used to match other log metadata, corresponding to the arguments to passed to `AbstractLogger` via the `handle_message` function: `(level,message,module,group,id,file,line)`. Elements which are present will be matched pairwise with the log record fields using `==` by default, with the special cases that `Symbol`s may be used for the standard log levels, and `Regex`s in the pattern will match string or Symbol fields using `occursin`.
**Examples**
Consider a function which logs a warning, and several debug messages:
```julia
function foo(n)
    @info "Doing foo with n=$n"
    for i=1:n
        @debug "Iteration $i"
    end
    42
end
```
We can test the info message using


## [Testing Log Statements](#Testing-Log-Statements)
```julia
@test_logs (:info,"Doing foo with n=2") foo(2)
```
If we also wanted to test the debug messages, these need to be enabled with the `min_level` keyword:
```julia
using Logging
@test_logs (:info,"Doing foo with n=2") (:debug,"Iteration 1") (:debug,"Iteration 2") min_level=Logging.Debug foo(2)
```
If you want to test that some particular messages are generated while ignoring the rest, you can set the keyword `match_mode=:any`:
```julia
using Logging
@test_logs (:info,) (:debug,"Iteration 42") min_level=Logging.Debug match_mode=:any foo(100)
```
The macro may be chained with `@test` to also test the returned value:
```julia
@test (@test_logs (:info,"Doing foo with n=2") foo(2)) == 42
```
If you want to test for the absence of warnings, you can omit specifying log patterns and set the `min_level` accordingly:
```julia
# test that the expression logs no messages when the logger level is warn:
@test_logs min_level=Logging.Warn @info("Some information") # passes
@test_logs min_level=Logging.Warn @warn("Some information") # fails
```
If you want to test the absence of warnings (or error messages) in [`stderr`](../../base/io-network/#Base.stderr) which are not generated by `@warn`, see [`@test_nowarn`](#Test.@test_nowarn).
```julia
TestLogger(; min_level=Info, catch_exceptions=false)
```
Create a `TestLogger` which captures logged messages in its `logs::Vector{LogRecord}` field.


## [Testing Log Statements](#Testing-Log-Statements)
Set `min_level` to control the `LogLevel`, `catch_exceptions` for whether or not exceptions thrown as part of log event generation should be caught, and `respect_maxlog` for whether or not to follow the convention of logging messages with `maxlog=n` for some integer `n` at most `n` times.
See also: [`LogRecord`](#Test.LogRecord).
**Examples**
```julia-repl
julia> using Test, Logging

julia> f() = @info "Hi" number=5;

julia> test_logger = TestLogger();

julia> with_logger(test_logger) do
           f()
           @info "Bye!"
       end

julia> @test test_logger.logs[1].message == "Hi"
Test Passed

julia> @test test_logger.logs[1].kwargs[:number] == 5
Test Passed

julia> @test test_logger.logs[2].message == "Bye!"
Test Passed
```
```julia
LogRecord
```
Stores the results of a single log event. Fields:
-   `level`: the [`LogLevel`](../Logging/#Logging.LogLevel) of the log message
-   `message`: the textual content of the log message
-   `_module`: the module of the log event
-   `group`: the logging group (by default, the name of the file containing the log event)
-   `id`: the ID of the log event
-   `file`: the file containing the log event
-   `line`: the line within the file of the log event
-   `kwargs`: any keyword arguments passed to the log event


## [Other Test Macros](#Other-Test-Macros)
As calculations on floating-point values can be imprecise, you can perform approximate equality checks using either `@test a ≈ b` (where `≈`, typed via tab completion of `\approx`, is the [`isapprox`](../../base/math/#Base.isapprox) function) or use [`isapprox`](../../base/math/#Base.isapprox) directly.
```julia-repl
julia> @test 1 ≈ 0.999999999
Test Passed

julia> @test 1 ≈ 0.999999
Test Failed at none:1
  Expression: 1 ≈ 0.999999
   Evaluated: 1 ≈ 0.999999

ERROR: There was an error during testing
```
You can specify relative and absolute tolerances by setting the `rtol` and `atol` keyword arguments of `isapprox`, respectively, after the `≈` comparison:
```julia-repl
julia> @test 1 ≈ 0.999999  rtol=1e-5
Test Passed
```
Note that this is not a specific feature of the `≈` but rather a general feature of the `@test` macro: `@test a <op> b key=val` is transformed by the macro into `@test op(a, b, key=val)`. It is, however, particularly useful for `≈` tests.
```julia
@inferred [AllowedType] f(x)
```
Tests that the call expression `f(x)` returns a value of the same type inferred by the compiler. It is useful to check for type stability.
`f(x)` can be any call expression. Returns the result of `f(x)` if the types match, and an `Error` `Result` if it finds different types.


## [Other Test Macros](#Other-Test-Macros)
Optionally, `AllowedType` relaxes the test, by making it pass when either the type of `f(x)` matches the inferred type modulo `AllowedType`, or when the return type is a subtype of `AllowedType`. This is useful when testing type stability of functions returning a small union such as `Union{Nothing, T}` or `Union{Missing, T}`.
```julia-repl
julia> f(a) = a > 1 ? 1 : 1.0
f (generic function with 1 method)

julia> typeof(f(2))
Int64

julia> @code_warntype f(2)
MethodInstance for f(::Int64)
  from f(a) @ Main none:1
Arguments
  #self#::Core.Const(f)
  a::Int64
Body::UNION{FLOAT64, INT64}
1 ─ %1 = (a > 1)::Bool
└──      goto #3 if not %1
2 ─      return 1
3 ─      return 1.0

julia> @inferred f(2)
ERROR: return type Int64 does not match inferred return type Union{Float64, Int64}
[...]

julia> @inferred max(1, 2)
2

julia> g(a) = a < 10 ? missing : 1.0
g (generic function with 1 method)

julia> @inferred g(20)
ERROR: return type Float64 does not match inferred return type Union{Missing, Float64}
[...]

julia> @inferred Missing g(20)
1.0

julia> h(a) = a < 10 ? missing : f(a)
h (generic function with 1 method)

julia> @inferred Missing h(20)
ERROR: return type Int64 does not match inferred return type Union{Missing, Float64, Int64}
[...]
```
```julia
@test_deprecated [pattern] expression
```
When `--depwarn=yes`, test that `expression` emits a deprecation warning and return the value of `expression`. The log message string will be matched against `pattern` which defaults to `r"deprecated"i`.


## [Other Test Macros](#Other-Test-Macros)
When `--depwarn=no`, simply return the result of executing `expression`. When `--depwarn=error`, check that an ErrorException is thrown.
**Examples**
```julia
# Deprecated in julia 0.7
@test_deprecated num2hex(1)

# The returned value can be tested by chaining with @test:
@test (@test_deprecated num2hex(1)) == "0000000000000001"
```
```julia
@test_warn msg expr
```
Test whether evaluating `expr` results in [`stderr`](../../base/io-network/#Base.stderr) output that contains the `msg` string or matches the `msg` regular expression. If `msg` is a boolean function, tests whether `msg(output)` returns `true`. If `msg` is a tuple or array, checks that the error output contains/matches each item in `msg`. Returns the result of evaluating `expr`.
See also [`@test_nowarn`](#Test.@test_nowarn) to check for the absence of error output.
Note: Warnings generated by `@warn` cannot be tested with this macro. Use [`@test_logs`](#Test.@test_logs) instead.
```julia
@test_nowarn expr
```
Test whether evaluating `expr` results in empty [`stderr`](../../base/io-network/#Base.stderr) output (no warnings or other messages). Returns the result of evaluating `expr`.
Note: The absence of warnings generated by `@warn` cannot be tested with this macro. Use [`@test_logs`](#Test.@test_logs) instead.


## [Broken Tests](#Broken-Tests)
If a test fails consistently it can be changed to use the `@test_broken` macro. This will denote the test as `Broken` if the test continues to fail and alerts the user via an `Error` if the test succeeds.
```julia
@test_broken ex
@test_broken f(args...) key=val ...
```
Indicates a test that should pass but currently consistently fails. Tests that the expression `ex` evaluates to `false` or causes an exception. Returns a `Broken` `Result` if it does, or an `Error` `Result` if the expression evaluates to `true`. This is equivalent to [`@test ex broken=true`](#Test.@test).
The `@test_broken f(args...) key=val...` form works as for the `@test` macro.
**Examples**
```julia-repl
julia> @test_broken 1 == 2
Test Broken
  Expression: 1 == 2

julia> @test_broken 1 == 2 atol=0.1
Test Broken
  Expression: ==(1, 2, atol = 0.1)
```
`@test_skip` is also available to skip a test without evaluation, but counting the skipped test in the test set reporting. The test will not run but gives a `Broken` `Result`.
```julia
@test_skip ex
@test_skip f(args...) key=val ...
```
Marks a test that should not be executed but should be included in test summary reporting as `Broken`. This can be useful for tests that intermittently fail, or tests of not-yet-implemented functionality. This is equivalent to [`@test ex skip=true`](#Test.@test).
The `@test_skip f(args...) key=val...` form works as for the `@test` macro.
**Examples**


## [Broken Tests](#Broken-Tests)
```julia-repl
julia> @test_skip 1 == 2
Test Broken
  Skipped: 1 == 2

julia> @test_skip 1 == 2 atol=0.1
Test Broken
  Skipped: ==(1, 2, atol = 0.1)
```


## [Test result types](#Test-result-types)
```julia
Test.Result
```
All tests produce a result object. This object may or may not be stored, depending on whether the test is part of a test set.
```julia
Test.Pass <: Test.Result
```
The test condition was true, i.e. the expression evaluated to true or the correct exception was thrown.
```julia
Test.Fail <: Test.Result
```
The test condition was false, i.e. the expression evaluated to false or the correct exception was not thrown.
```julia
Test.Error <: Test.Result
```
The test condition couldn't be evaluated due to an exception, or it evaluated to something other than a [`Bool`](../../base/numbers/#Core.Bool). In the case of `@test_broken` it is used to indicate that an unexpected `Pass` `Result` occurred.
```julia
Test.Broken <: Test.Result
```
The test condition is the expected (failed) result of a broken test, or was explicitly skipped with `@test_skip`.


## [Creating Custom AbstractTestSet Types](#Creating-Custom-AbstractTestSet-Types)
Packages can create their own `AbstractTestSet` subtypes by implementing the `record` and `finish` methods. The subtype should have a one-argument constructor taking a description string, with any options passed in as keyword arguments.
```julia
record(ts::AbstractTestSet, res::Result)
```
Record a result to a testset. This function is called by the `@testset` infrastructure each time a contained `@test` macro completes, and is given the test result (which could be an `Error`). This will also be called with an `Error` if an exception is thrown inside the test block but outside of a `@test` context.
```julia
finish(ts::AbstractTestSet)
```
Do any final processing necessary for the given testset. This is called by the `@testset` infrastructure after a test block executes.
Custom `AbstractTestSet` subtypes should call `record` on their parent (if there is one) to add themselves to the tree of test results. This might be implemented as:
```julia
if get_testset_depth() != 0
    # Attach this test set to the parent test set
    parent_ts = get_testset()
    record(parent_ts, self)
    return self
end
```
`Test` takes responsibility for maintaining a stack of nested testsets as they are executed, but any result accumulation is the responsibility of the `AbstractTestSet` subtype. You can access this stack with the `get_testset` and `get_testset_depth` methods. Note that these functions are not exported.
```julia
get_testset()
```


## [Creating Custom AbstractTestSet Types](#Creating-Custom-AbstractTestSet-Types)
Retrieve the active test set from the task's local storage. If no test set is active, use the fallback default test set.
```julia
get_testset_depth()
```
Return the number of active test sets, not including the default test set
`Test` also makes sure that nested `@testset` invocations use the same `AbstractTestSet` subtype as their parent unless it is set explicitly. It does not propagate any properties of the testset. Option inheritance behavior can be implemented by packages using the stack infrastructure that `Test` provides.
Defining a basic `AbstractTestSet` subtype might look like:
```julia
import Test: Test, record, finish
using Test: AbstractTestSet, Result, Pass, Fail, Error
using Test: get_testset_depth, get_testset
struct CustomTestSet <: Test.AbstractTestSet
    description::AbstractString
    foo::Int
    results::Vector
    # constructor takes a description string and options keyword arguments
    CustomTestSet(desc; foo=1) = new(desc, foo, [])
end

record(ts::CustomTestSet, child::AbstractTestSet) = push!(ts.results, child)
record(ts::CustomTestSet, res::Result) = push!(ts.results, res)
function finish(ts::CustomTestSet)
    # just record if we're not the top-level parent
    if get_testset_depth() > 0
        record(get_testset(), ts)
        return ts
    end

    # so the results are printed if we are at the top level
    Test.print_test_results(ts)
    return ts
end
```
And using that testset looks like:


## [Creating Custom AbstractTestSet Types](#Creating-Custom-AbstractTestSet-Types)
```julia
@testset CustomTestSet foo=4 "custom testset inner 2" begin
    # this testset should inherit the type, but not the argument.
    @testset "custom testset inner" begin
        @test true
    end
end
```
In order to use a custom testset and have the recorded results printed as part of any outer default testset, also define `Test.get_test_counts`. This might look like so:
```julia
using Test: AbstractTestSet, Pass, Fail, Error, Broken, get_test_counts, TestCounts, format_duration

function Test.get_test_counts(ts::CustomTestSet)
    passes, fails, errors, broken = 0, 0, 0, 0
    # cumulative results
    c_passes, c_fails, c_errors, c_broken = 0, 0, 0, 0

    for t in ts.results
        # count up results
        isa(t, Pass)   && (passes += 1)
        isa(t, Fail)   && (fails  += 1)
        isa(t, Error)  && (errors += 1)
        isa(t, Broken) && (broken += 1)
        # handle children
        if isa(t, AbstractTestSet)
            tc = get_test_counts(t)::TestCounts
            c_passes += tc.passes + tc.cumulative_passes
            c_fails  += tc.fails + tc.cumulative_fails
            c_errors += tc.errors + tc.cumulative_errors
            c_broken += tc.broken + tc.cumulative_broken
        end
    end
    # get a duration, if we have one
    duration = format_duration(ts)
    return TestCounts(true, passes, fails, errors, broken, c_passes, c_fails, c_errors, c_broken, duration)
end
```
```julia
TestCounts
```


## [Creating Custom AbstractTestSet Types](#Creating-Custom-AbstractTestSet-Types)
Holds the state for recursively gathering the results of a test set for display purposes.
Fields:
-   `customized`: Whether the function `get_test_counts` was customized for the `AbstractTestSet` this counts object is for. If a custom method was defined, always pass `true` to the constructor.
-   `passes`: The number of passing `@test` invocations.
-   `fails`: The number of failing `@test` invocations.
-   `errors`: The number of erroring `@test` invocations.
-   `broken`: The number of broken `@test` invocations.
-   `passes`: The cumulative number of passing `@test` invocations.
-   `fails`: The cumulative number of failing `@test` invocations.
-   `errors`: The cumulative number of erroring `@test` invocations.
-   `broken`: The cumulative number of broken `@test` invocations.
-   `duration`: The total duration the `AbstractTestSet` in question ran for, as a formatted `String`.
" get*test*counts(::AbstractTestSet) -> TestCounts
Recursive function that counts the number of test results of each type directly in the testset, and totals across the child testsets.
Custom `AbstractTestSet` should implement this function to get their totals counted & displayed with `DefaultTestSet` as well.
If this is not implemented for a custom `TestSet`, the printing falls back to reporting `x` for failures and `?s` for the duration.
```julia
format_duration(::AbstractTestSet)
```
Return a formatted string for printing the duration the testset ran for.
If not defined, falls back to `"?s"`.


## [Creating Custom AbstractTestSet Types](#Creating-Custom-AbstractTestSet-Types)
```julia
print_test_results(ts::AbstractTestSet, depth_pad=0)
```
Print the results of an `AbstractTestSet` as a formatted table.
`depth_pad` refers to how much padding should be added in front of all output.
Called inside of `Test.finish`, if the `finish`ed testset is the topmost testset.


## [Test utilities](#Test-utilities)
The `GenericArray` can be used to test generic array APIs that program to the `AbstractArray` interface, in order to ensure that functions can work with array types besides the standard `Array` type.
The `GenericDict` can be used to test generic dict APIs that program to the `AbstractDict` interface, in order to ensure that functions can work with associative types besides the standard `Dict` type.
The `GenericOrder` can be used to test APIs for their support of generic ordered types.
The `GenericSet` can be used to test generic set APIs that program to the `AbstractSet` interface, in order to ensure that functions can work with set types besides the standard `Set` and `BitSet` types.
The `GenericString` can be used to test generic string APIs that program to the `AbstractString` interface, in order to ensure that functions can work with string types besides the standard `String` type.
```julia
detect_ambiguities(mod1, mod2...; recursive=false,
                                  ambiguous_bottom=false,
                                  allowed_undefineds=nothing)
```
Return a vector of `(Method,Method)` pairs of ambiguous methods defined in the specified modules. Use `recursive=true` to test in all submodules.
`ambiguous_bottom` controls whether ambiguities triggered only by `Union{}` type parameters are included; in most cases you probably want to set this to `false`. See [`Base.isambiguous`](../../base/base/#Base.isambiguous).
See [`Test.detect_unbound_args`](#Test.detect_unbound_args) for an explanation of `allowed_undefineds`.


## [Test utilities](#Test-utilities)
`allowed_undefineds` requires at least Julia 1.8.
```julia
detect_unbound_args(mod1, mod2...; recursive=false, allowed_undefineds=nothing)
```
Return a vector of `Method`s which may have unbound type parameters. Use `recursive=true` to test in all submodules.
By default, any undefined symbols trigger a warning. This warning can be suppressed by supplying a collection of `GlobalRef`s for which the warning can be skipped. For example, setting
```julia
allowed_undefineds = Set([GlobalRef(Base, :active_repl),
                          GlobalRef(Base, :active_repl_backend)])
```
would suppress warnings about `Base.active_repl` and `Base.active_repl_backend`.
`allowed_undefineds` requires at least Julia 1.8.


## [Workflow for Testing Packages](#Workflow-for-Testing-Packages)
Using the tools available to us in the previous sections, here is a potential workflow of creating a package and adding tests to it.


### [Generating an Example Package](#Generating-an-Example-Package)
For this workflow, we will create a package called `Example`:
```julia
pkg> generate Example
shell> cd Example
shell> mkdir test
pkg> activate .
```


### [Creating Sample Functions](#Creating-Sample-Functions)
The number one requirement for testing a package is to have functionality to test. For that, we will add some simple functions to `Example` that we can test. Add the following to `src/Example.jl`:
```julia
module Example

function greet()
    "Hello world!"
end

function simple_add(a, b)
    a + b
end

function type_multiply(a::Float64, b::Float64)
    a * b
end

export greet, simple_add, type_multiply

end
```


### [Creating a Test Environment](#Creating-a-Test-Environment)
From within the root of the `Example` package, navigate to the `test` directory, activate a new environment there, and add the `Test` package to the environment:
```julia
shell> cd test
pkg> activate .
(test) pkg> add Test
```


### [Testing Our Package](#Testing-Our-Package)
Now, we are ready to add tests to `Example`. It is standard practice to create a file within the `test` directory called `runtests.jl` which contains the test sets we want to run. Go ahead and create that file within the `test` directory and add the following code to it:
```julia
using Example
using Test

@testset "Example tests" begin

    @testset "Math tests" begin
        include("math_tests.jl")
    end

    @testset "Greeting tests" begin
        include("greeting_tests.jl")
    end
end
```
We will need to create those two included files, `math_tests.jl` and `greeting_tests.jl`, and add some tests to them.
> **Note:** Notice how we did not have to specify add `Example` into the `test` environment's `Project.toml`. This is a benefit of Julia's testing system that you could [read about more here](https://pkgdocs.julialang.org/dev/creating-packages/).


#### [Writing Tests for math_tests.jl](#Writing-Tests-for-math_tests.jl)
Using our knowledge of `Test.jl`, here are some example tests we could add to `math_tests.jl`:
```julia
@testset "Testset 1" begin
    @test 2 == simple_add(1, 1)
    @test 3.5 == simple_add(1, 2.5)
        @test_throws MethodError simple_add(1, "A")
        @test_throws MethodError simple_add(1, 2, 3)
end

@testset "Testset 2" begin
    @test 1.0 == type_multiply(1.0, 1.0)
        @test isa(type_multiply(2.0, 2.0), Float64)
    @test_throws MethodError type_multiply(1, 2.5)
end
```


#### [Writing Tests for greeting_tests.jl](#Writing-Tests-for-greeting_tests.jl)
Using our knowledge of `Test.jl`, here are some example tests we could add to `greeting_tests.jl`:
```julia
@testset "Testset 3" begin
    @test "Hello world!" == greet()
    @test_throws MethodError greet("Antonia")
end
```


### [Testing Our Package](#Testing-Our-Package-2)
Now that we have added our tests and our `runtests.jl` script in `test`, we can test our `Example` package by going back to the root of the `Example` package environment and reactivating the `Example` environment:
```julia
shell> cd ..
pkg> activate .
```
From there, we can finally run our test suite as follows:
```julia
(Example) pkg> test
     Testing Example
      Status `/tmp/jl_Yngpvy/Project.toml`
  [fa318bd2] Example v0.1.0 `/home/src/Projects/tmp/errata/Example`
  [8dfed614] Test `@stdlib/Test`
      Status `/tmp/jl_Yngpvy/Manifest.toml`
  [fa318bd2] Example v0.1.0 `/home/src/Projects/tmp/errata/Example`
  [2a0f44e3] Base64 `@stdlib/Base64`
  [b77e0a4c] InteractiveUtils `@stdlib/InteractiveUtils`
  [56ddb016] Logging `@stdlib/Logging`
  [d6f4376e] Markdown `@stdlib/Markdown`
  [9a3f8284] Random `@stdlib/Random`
  [ea8e919c] SHA `@stdlib/SHA`
  [9e88b42a] Serialization `@stdlib/Serialization`
  [8dfed614] Test `@stdlib/Test`
     Testing Running tests...
Test Summary: | Pass  Total
Example tests |    9      9
     Testing Example tests passed
```
And if all went correctly, you should see a similar output as above. Using `Test.jl`, more complicated tests can be added for packages but this should ideally point developers in the direction of how to get started with testing their own created packages.


### [Code Coverage](#Code-Coverage)
Code coverage tracking during tests can be enabled using the `pkg> test --coverage` flag (or at a lower level using the [`--code-coverage`](../../manual/command-line-interface/#command-line-interface) julia arg). This is on by default in the [julia-runtest](https://github.com/julia-actions/julia-runtest) GitHub action.
To evaluate coverage either manually inspect the `.cov` files that are generated beside the source files locally, or in CI use the [julia-processcoverage](https://github.com/julia-actions/julia-processcoverage) GitHub action.
Since Julia 1.11, coverage is not collected during the package precompilation phase.
------------------------------------------------------------------------


# UUIDs · The Julia Language
Source: https://docs.julialang.org/en/v1/stdlib/UUIDs/


# [UUIDs](#UUIDs)
```julia
uuid1([rng::AbstractRNG]) -> UUID
```
Generates a version 1 (time-based) universally unique identifier (UUID), as specified by RFC 4122. Note that the Node ID is randomly generated (does not identify the host) according to section 4.5 of the RFC.
The default rng used by `uuid1` is not `Random.default_rng()` and every invocation of `uuid1()` without an argument should be expected to return a unique identifier. Importantly, the outputs of `uuid1` do not repeat even when `Random.seed!(seed)` is called. Currently (as of Julia 1.6), `uuid1` uses `Random.RandomDevice` as the default rng. However, this is an implementation detail that may change in the future.
The output of `uuid1` does not depend on `Random.default_rng()` as of Julia 1.6.
**Examples**
```julia-repl
julia> using Random

julia> rng = MersenneTwister(1234);

julia> uuid1(rng)
UUID("cfc395e8-590f-11e8-1f13-43a2532b2fa8")
```
```julia
uuid4([rng::AbstractRNG]) -> UUID
```
Generates a version 4 (random or pseudo-random) universally unique identifier (UUID), as specified by RFC 4122.
The default rng used by `uuid4` is not `Random.default_rng()` and every invocation of `uuid4()` without an argument should be expected to return a unique identifier. Importantly, the outputs of `uuid4` do not repeat even when `Random.seed!(seed)` is called. Currently (as of Julia 1.6), `uuid4` uses `Random.RandomDevice` as the default rng. However, this is an implementation detail that may change in the future.
The output of `uuid4` does not depend on `Random.default_rng()` as of Julia 1.6.
**Examples**


# [UUIDs](#UUIDs)
```julia-repl
julia> using Random

julia> rng = Xoshiro(123);

julia> uuid4(rng)
UUID("856e446e-0c6a-472a-9638-f7b8557cd282")
```
```julia
uuid5(ns::UUID, name::String) -> UUID
```
Generates a version 5 (namespace and domain-based) universally unique identifier (UUID), as specified by RFC 4122.
This function requires at least Julia 1.1.
**Examples**
```julia-repl
julia> using Random

julia> rng = Xoshiro(123);

julia> u4 = uuid4(rng)
UUID("856e446e-0c6a-472a-9638-f7b8557cd282")

julia> u5 = uuid5(u4, "julia")
UUID("2df91e3f-da06-5362-a6fe-03772f2e14c9")
```
```julia
uuid_version(u::UUID) -> Int
```
Inspects the given UUID and returns its version (see [RFC 4122](https://www.ietf.org/rfc/rfc4122)).
**Examples**
```julia-repl
julia> uuid_version(uuid4())
4
```
------------------------------------------------------------------------


# Unicode · The Julia Language
Source: https://docs.julialang.org/en/v1/stdlib/Unicode/


# [Unicode](#Unicode)
The `Unicode` module provides essential functionality for managing Unicode characters and strings. It includes validation, category determination, normalization, case transformation, and grapheme segmentation, enabling effective Unicode data handling.
The `Unicode` module provides essential functionality for managing Unicode characters and strings. It includes validation, category determination, normalization, case transformation, and grapheme segmentation, enabling effective Unicode data handling.
```julia
Unicode.julia_chartransform(c::Union{Char,Integer})
```
Map the Unicode character (`Char`) or codepoint (`Integer`) `c` to the corresponding "equivalent" character or codepoint, respectively, according to the custom equivalence used within the Julia parser (in addition to NFC normalization).
For example, `'µ'` (U+00B5 micro) is treated as equivalent to `'μ'` (U+03BC mu) by Julia's parser, so `julia_chartransform` performs this transformation while leaving other characters unchanged:
```julia-repl
julia> Unicode.julia_chartransform('µ')
'μ': Unicode U+03BC (category Ll: Letter, lowercase)

julia> Unicode.julia_chartransform('x')
'x': ASCII/Unicode U+0078 (category Ll: Letter, lowercase)
```
`julia_chartransform` is mainly useful for passing to the [`Unicode.normalize`](#Unicode.normalize) function in order to mimic the normalization used by the Julia parser:


# [Unicode](#Unicode)
```julia-repl
julia> s = "µö"
"µö"

julia> s2 = Unicode.normalize(s, compose=true, stable=true, chartransform=Unicode.julia_chartransform)
"μö"

julia> collect(s2)
2-element Vector{Char}:
 'μ': Unicode U+03BC (category Ll: Letter, lowercase)
 'ö': Unicode U+00F6 (category Ll: Letter, lowercase)

julia> s2 == string(Meta.parse(s))
true
```
This function was introduced in Julia 1.8.
```julia
Unicode.isassigned(c) -> Bool
```
Return `true` if the given char or integer is an assigned Unicode code point.
**Examples**
```julia-repl
julia> Unicode.isassigned(101)
true

julia> Unicode.isassigned('\x01')
true
```
```julia
isequal_normalized(s1::AbstractString, s2::AbstractString; casefold=false, stripmark=false, chartransform=identity)
```
Return whether `s1` and `s2` are canonically equivalent Unicode strings. If `casefold=true`, ignores case (performs Unicode case-folding); if `stripmark=true`, strips diacritical marks and other combining characters.
As with [`Unicode.normalize`](#Unicode.normalize), you can also pass an arbitrary function via the `chartransform` keyword (mapping `Integer` codepoints to codepoints) to perform custom normalizations, such as [`Unicode.julia_chartransform`](#Unicode.julia_chartransform).
The `isequal_normalized` function was added in Julia 1.8.
**Examples**
For example, the string `"noël"` can be constructed in two canonically equivalent ways in Unicode, depending on whether `"ë"` is formed from a single codepoint U+00EB or from the ASCII character `'e'` followed by the U+0308 combining-diaeresis character.


# [Unicode](#Unicode)
```julia-repl
julia> s1 = "noël"
"noël"

julia> s2 = "noël"
"noël"

julia> s1 == s2
false

julia> isequal_normalized(s1, s2)
true

julia> isequal_normalized(s1, "noel", stripmark=true)
true

julia> isequal_normalized(s1, "NOËL", casefold=true)
true
```
```julia
Unicode.normalize(s::AbstractString; keywords...)
Unicode.normalize(s::AbstractString, normalform::Symbol)
```
Normalize the string `s`. By default, canonical composition (`compose=true`) is performed without ensuring Unicode versioning stability (`compat=false`), which produces the shortest possible equivalent string but may introduce composition characters not present in earlier Unicode versions.
Alternatively, one of the four "normal forms" of the Unicode standard can be specified: `normalform` can be `:NFC`, `:NFD`, `:NFKC`, or `:NFKD`. Normal forms C (canonical composition) and D (canonical decomposition) convert different visually identical representations of the same abstract string into a single canonical form, with form C being more compact. Normal forms KC and KD additionally canonicalize "compatibility equivalents": they convert characters that are abstractly similar but visually distinct into a single canonical choice (e.g. they expand ligatures into the individual characters), with form KC being more compact.
Alternatively, finer control and additional transformations may be obtained by calling `Unicode.normalize(s; keywords...)`, where any number of the following boolean keywords options (which all default to `false` except for `compose`) are specified:


# [Unicode](#Unicode)
-   `compose=false`: do not perform canonical composition
-   `decompose=true`: do canonical decomposition instead of canonical composition (`compose=true` is ignored if present)
-   `compat=true`: compatibility equivalents are canonicalized
-   `casefold=true`: perform Unicode case folding, e.g. for case-insensitive string comparison
-   `newline2lf=true`, `newline2ls=true`, or `newline2ps=true`: convert various newline sequences (LF, CRLF, CR, NEL) into a linefeed (LF), line-separation (LS), or paragraph-separation (PS) character, respectively
-   `stripmark=true`: strip diacritical marks (e.g. accents)
-   `stripignore=true`: strip Unicode's "default ignorable" characters (e.g. the soft hyphen or the left-to-right marker)
-   `stripcc=true`: strip control characters; horizontal tabs and form feeds are converted to spaces; newlines are also converted to spaces unless a newline-conversion flag was specified
-   `rejectna=true`: throw an error if unassigned code points are found
-   `stable=true`: enforce Unicode versioning stability (never introduce characters missing from earlier Unicode versions)


# [Unicode](#Unicode)
You can also use the `chartransform` keyword (which defaults to `identity`) to pass an arbitrary *function* mapping `Integer` codepoints to codepoints, which is called on each character in `s` as it is processed, in order to perform arbitrary additional normalizations. For example, by passing `chartransform=Unicode.julia_chartransform`, you can apply a few Julia-specific character normalizations that are performed by Julia when parsing identifiers (in addition to NFC normalization: `compose=true, stable=true`).
For example, NFKC corresponds to the options `compose=true, compat=true, stable=true`.
**Examples**
```julia-repl
julia> "é" == Unicode.normalize("é") #LHS: Unicode U+00e9, RHS: U+0065 & U+0301
true

julia> "μ" == Unicode.normalize("µ", compat=true) #LHS: Unicode U+03bc, RHS: Unicode U+00b5
true

julia> Unicode.normalize("JuLiA", casefold=true)
"julia"

julia> Unicode.normalize("JúLiA", stripmark=true)
"JuLiA"
```
The `chartransform` keyword argument requires Julia 1.8.
```julia
graphemes(s::AbstractString) -> GraphemeIterator
```
Return an iterator over substrings of `s` that correspond to the extended graphemes in the string, as defined by Unicode UAX #29. (Roughly, these are what users would perceive as single characters, even though they may contain more than one codepoint; for example a letter combined with an accent mark is a single grapheme.)
```julia
graphemes(s::AbstractString, m:n) -> SubString
```


# [Unicode](#Unicode)
Returns a [`SubString`](../../base/strings/#Base.SubString) of `s` consisting of the `m`-th through `n`-th graphemes of the string `s`, where the second argument `m:n` is an integer-valued [`AbstractUnitRange`](../../base/collections/#Base.AbstractUnitRange).
Loosely speaking, this corresponds to the `m:n`-th user-perceived "characters" in the string. For example:
```julia-repl
julia> s = graphemes("exposé", 3:6)
"posé"

julia> collect(s)
5-element Vector{Char}:
 'p': ASCII/Unicode U+0070 (category Ll: Letter, lowercase)
 'o': ASCII/Unicode U+006F (category Ll: Letter, lowercase)
 's': ASCII/Unicode U+0073 (category Ll: Letter, lowercase)
 'e': ASCII/Unicode U+0065 (category Ll: Letter, lowercase)
 '́': Unicode U+0301 (category Mn: Mark, nonspacing)
```
This consists of the 3rd to *7th* codepoints ([`Char`](../../base/strings/#Core.Char)s) in `"exposé"`, because the grapheme `"é"` is actually *two* Unicode codepoints (an `'e'` followed by an acute-accent combining character U+0301).
Because finding grapheme boundaries requires iteration over the string contents, the `graphemes(s, m:n)` function requires time proportional to the length of the string (number of codepoints) before the end of the substring.
The `m:n` argument of `graphemes` requires Julia 1.9.
------------------------------------------------------------------------


# Initialization of the Julia runtime · The Julia Language
Source: https://docs.julialang.org/en/v1/devdocs/init/


# [Initialization of the Julia runtime](#Initialization-of-the-Julia-runtime)
How does the Julia runtime execute `julia -e 'println("Hello World!")'` ?


## [`main()`](#main())
Execution starts at [`main()` in `cli/loader_exe.c`](https://github.com/JuliaLang/julia/blob/master/cli/loader_exe.c), which calls `jl_load_repl()` in [`cli/loader_lib.c`](https://github.com/JuliaLang/julia/blob/master/cli/loader_lib.c) which loads a few libraries, eventually calling [`jl_repl_entrypoint()` in `src/jlapi.c`](https://github.com/JuliaLang/julia/blob/master/src/jlapi.c).
`jl_repl_entrypoint()` calls [`libsupport_init()`](https://github.com/JuliaLang/julia/blob/master/src/support/libsupportinit.c) to set the C library locale and to initialize the "ios" library (see [`ios_init_stdstreams()`](https://github.com/JuliaLang/julia/blob/master/src/support/ios.c) and [Legacy `ios.c` library](../stdio/#Legacy-ios.c-library)).
Next [`jl_parse_opts()`](https://github.com/JuliaLang/julia/blob/master/src/jloptions.c) is called to process command line options. Note that `jl_parse_opts()` only deals with options that affect code generation or early initialization. Other options are handled later by [`exec_options()` in `base/client.jl`](https://github.com/JuliaLang/julia/blob/master/base/client.jl).
`jl_parse_opts()` stores command line options in the [global `jl_options` struct](https://github.com/JuliaLang/julia/blob/master/src/julia.h).


## [`julia_init()`](#julia_init())
[`julia_init()` in `init.c`](https://github.com/JuliaLang/julia/blob/master/src/init.c) is called by `main()` and calls [`_julia_init()` in `init.c`](https://github.com/JuliaLang/julia/blob/master/src/init.c).
`_julia_init()` begins by calling `libsupport_init()` again (it does nothing the second time).
[`restore_signals()`](https://github.com/JuliaLang/julia/blob/master/src/signals-unix.c) is called to zero the signal handler mask.
[`jl_resolve_sysimg_location()`](https://github.com/JuliaLang/julia/blob/master/src/init.c) searches configured paths for the base system image. See [Building the Julia system image](../sysimg/#Building-the-Julia-system-image).
[`jl_gc_init()`](https://github.com/JuliaLang/julia/blob/master/src/gc.c) sets up allocation pools and lists for weak refs, preserved values and finalization.
[`jl_init_frontend()`](https://github.com/JuliaLang/julia/blob/master/src/ast.c) loads and initializes a pre-compiled femtolisp image containing the scanner/parser.
[`jl_init_types()`](https://github.com/JuliaLang/julia/blob/master/src/jltypes.c) creates `jl_datatype_t` type description objects for the [built-in types defined in `julia.h`](https://github.com/JuliaLang/julia/blob/master/src/julia.h). e.g.


## [`julia_init()`](#julia_init())
```c
jl_any_type = jl_new_abstracttype(jl_symbol("Any"), core, NULL, jl_emptysvec);
jl_any_type->super = jl_any_type;

jl_type_type = jl_new_abstracttype(jl_symbol("Type"), core, jl_any_type, jl_emptysvec);

jl_int32_type = jl_new_primitivetype(jl_symbol("Int32"), core,
                                     jl_any_type, jl_emptysvec, 32);
```
[`jl_init_tasks()`](https://github.com/JuliaLang/julia/blob/master/src/task.c) creates the `jl_datatype_t* jl_task_type` object; initializes the global `jl_root_task` struct; and sets `jl_current_task` to the root task.
[`jl_init_codegen()`](https://github.com/JuliaLang/julia/blob/master/src/codegen.cpp) initializes the [LLVM library](https://llvm.org).
[`jl_init_serializer()`](https://github.com/JuliaLang/julia/blob/master/src/staticdata.c) initializes 8-bit serialization tags for builtin `jl_value_t` values.
If there is no sysimg file (`!jl_options.image_file`) then the `Core` and `Main` modules are created and `boot.jl` is evaluated:
`jl_core_module = jl_new_module(jl_symbol("Core"))` creates the Julia `Core` module.
[`jl_init_intrinsic_functions()`](https://github.com/JuliaLang/julia/blob/master/src/intrinsics.cpp) creates a new Julia module `Intrinsics` containing constant `jl_intrinsic_type` symbols. These define an integer code for each [intrinsic function](https://github.com/JuliaLang/julia/blob/master/src/intrinsics.cpp). [`emit_intrinsic()`](https://github.com/JuliaLang/julia/blob/master/src/intrinsics.cpp) translates these symbols into LLVM instructions during code generation.