Documentation
¶
Overview ¶
Package verifactu provides the VeriFactu client
Index ¶
- Constants
- Variables
- type ChainData
- type Client
- func (c *Client) CancelInvoice(env *gobl.Envelope, prev *ChainData, opts ...GenerateOption) (*InvoiceCancellation, error)
- func (c *Client) CurrentTime() time.Time
- func (c *Client) NewEnvelopeInvoiceRequest(env *gobl.Envelope, prev *ChainData) (*InvoiceRequest, error)
- func (c *Client) NewInvoiceRequest(supplier *org.Party) (*InvoiceRequest, error)
- func (c *Client) RegisterInvoice(env *gobl.Envelope, prev *ChainData, opts ...GenerateOption) (*InvoiceRegistration, error)
- func (c *Client) Sandbox() bool
- func (c *Client) SendInvoiceRequest(ctx context.Context, ir *InvoiceRequest) (*InvoiceResponse, error)
- type Desglose
- type Destinatario
- type DetalleDesglose
- type Encadenamiento
- type Envelope
- type EnvelopeResponse
- type Environment
- type Error
- type FacturaRectificada
- type FacturaSustituida
- type Fault
- type GenerateOption
- type IDFactura
- type IDFacturaAnulada
- type IDOtro
- type ImporteRectificacion
- type InvoiceCancellation
- type InvoiceRegistration
- type InvoiceRequest
- type InvoiceRequestHeader
- type InvoiceRequestLine
- type InvoiceResponse
- type InvoiceResponseIssuer
- type InvoiceResponseLine
- type InvoiceResponseLineDuplicated
- type InvoiceResponseVoluntarySubmission
- type Issuer
- type OpType
- type Option
- type Party
- type RegistroAnterior
- type RemisionVoluntaria
- type Software
Constants ¶
const ( EnvironmentProduction Environment = "production" EnvironmentSandbox Environment = "sandbox" ProductionBaseURL = "https://www1.agenciatributaria.gob.es/wlpl/TIKE-CONT/ws/SistemaFacturacion/VerifactuSOAP" TestingBaseURL = "https://prewww1.aeat.es/wlpl/TIKE-CONT/ws/SistemaFacturacion/VerifactuSOAP" )
Environment to use for connections
const ( SUM = "https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/tike/cont/ws/SuministroLR.xsd" SUM1 = "" /* 130-byte string literal not displayed */ EnvNamespace = "http://schemas.xmlsoap.org/soap/envelope/" )
SUM is the namespace for the main VeriFactu schema
const ( StatusCorrect string = "Correcto" StatusAcceptedWithErrors string = "AceptadoConErrores" StatusCancelled string = "Anulada" StatusIncorrect string = "Incorrecto" )
Default response status
const (
// CurrentVersion is the current version of the VeriFactu document
CurrentVersion = "1.0"
)
const ( // StampKeyHash defines the key used to store the Hash in the envelope // stamps. StampKeyHash cbc.Key = "verifactu-hash" )
const TipoHuella = "01"
TipoHuella is the SHA-256 fingerprint type for Verifactu - L12 Might include support for other encryption types in the future.
Variables ¶
var ( ErrConnection = newError("connection") ErrValidation = newError("validation") ErrDuplicate = newError("duplicate") ErrWarning = newError("warning") )
Standard gateway error responses
var ( ErrNotSpanish = ErrValidation.WithMessage("only spanish invoices are supported") ErrAlreadyProcessed = ErrValidation.WithMessage("already processed") ErrOnlyInvoices = ErrValidation.WithMessage("only invoices are supported") )
Standard error responses.
Functions ¶
This section is empty.
Types ¶
type ChainData ¶ added in v0.12.0
type ChainData struct {
IDIssuer string `json:"issuer"`
NumSeries string `json:"num_series"`
IssueDate string `json:"issue_date"`
Fingerprint string `json:"fingerprint"`
}
ChainData contains the fields of this invoice that will be required for fingerprinting the _next_ invoice. JSON tags are provided to help with serialization.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client provides the main interface to the VeriFactu package.
func New ¶
New creates a new VeriFactu client with shared software and configuration options for creating and sending new documents.
func (*Client) CancelInvoice ¶ added in v0.12.0
func (c *Client) CancelInvoice(env *gobl.Envelope, prev *ChainData, opts ...GenerateOption) (*InvoiceCancellation, error)
CancelInvoice builds a cancellation message from the provided document and previous chain data. Note that the cancellation does not require Hash information of the last, invoice, and instead only requires the previous chain entry.
func (*Client) CurrentTime ¶
CurrentTime returns the current time to use when generating the VeriFactu document.
func (*Client) NewEnvelopeInvoiceRequest ¶ added in v0.12.0
func (c *Client) NewEnvelopeInvoiceRequest(env *gobl.Envelope, prev *ChainData) (*InvoiceRequest, error)
NewEnvelopeInvoiceRequest is a convenience method that prepares a new InvoiceRequest from the GOBL envelope in a single method call.
func (*Client) NewInvoiceRequest ¶ added in v0.12.0
func (c *Client) NewInvoiceRequest(supplier *org.Party) (*InvoiceRequest, error)
NewInvoiceRequest prepares a new invoice request for the provided supplier.
func (*Client) RegisterInvoice ¶ added in v0.12.0
func (c *Client) RegisterInvoice(env *gobl.Envelope, prev *ChainData, opts ...GenerateOption) (*InvoiceRegistration, error)
RegisterInvoice prepares a new registration document from the provided invoice inside the GOBL envelope. It will fingerprint and update the registration with the chaining hash and QR code. The resulting document can be persisted for sending later.
func (*Client) SendInvoiceRequest ¶ added in v0.12.0
func (c *Client) SendInvoiceRequest(ctx context.Context, ir *InvoiceRequest) (*InvoiceResponse, error)
SendInvoiceRequest will prepare the final SOAP envelope with the invoice request data and send it the agency API.
type Desglose ¶ added in v0.12.0
type Desglose struct {
DetalleDesglose []*DetalleDesglose `xml:"sum1:DetalleDesglose"`
}
Desglose contains the breakdown details
type Destinatario ¶ added in v0.12.0
type Destinatario struct {
IDDestinatario *Party `xml:"sum1:IDDestinatario"`
}
Destinatario represents a recipient in the document
type DetalleDesglose ¶ added in v0.12.0
type DetalleDesglose struct {
Impuesto string `xml:"sum1:Impuesto,omitempty"`
ClaveRegimen string `xml:"sum1:ClaveRegimen,omitempty"`
CalificacionOperacion string `xml:"sum1:CalificacionOperacion,omitempty"`
OperacionExenta string `xml:"sum1:OperacionExenta,omitempty"`
TipoImpositivo string `xml:"sum1:TipoImpositivo,omitempty"`
BaseImponibleOImporteNoSujeto string `xml:"sum1:BaseImponibleOimporteNoSujeto"`
BaseImponibleACoste string `xml:"sum1:BaseImponibleACoste,omitempty"`
CuotaRepercutida string `xml:"sum1:CuotaRepercutida,omitempty"`
TipoRecargoEquivalencia string `xml:"sum1:TipoRecargoEquivalencia,omitempty"`
CuotaRecargoEquivalencia string `xml:"sum1:CuotaRecargoEquivalencia,omitempty"`
}
DetalleDesglose contains detailed breakdown information
type Encadenamiento ¶ added in v0.12.0
type Encadenamiento struct {
PrimerRegistro string `xml:"sum1:PrimerRegistro,omitempty"`
RegistroAnterior *RegistroAnterior `xml:"sum1:RegistroAnterior,omitempty"`
}
Encadenamiento contains chaining information between documents
type Envelope ¶ added in v0.12.0
type Envelope struct {
XMLName xml.Name `xml:"soapenv:Envelope"`
XMLNs string `xml:"xmlns:soapenv,attr"`
SUM string `xml:"xmlns:sum,attr,omitempty"`
SUM1 string `xml:"xmlns:sum1,attr,omitempty"`
Body struct {
ID string `xml:"soapenv:Id,attr,omitempty"`
InvoiceRequest *InvoiceRequest `xml:"sum:RegFactuSistemaFacturacion,omitempty"`
} `xml:"soapenv:Body"`
}
Envelope is the SOAP envelope wrapper used for sending messages to the remote service.
func (*Envelope) BytesIndent ¶ added in v0.12.0
BytesIndent returns the indented XML document bytes
type EnvelopeResponse ¶ added in v0.12.0
type EnvelopeResponse struct {
XMLName xml.Name `xml:"Envelope"`
Body struct {
ID string `xml:"Id,attr,omitempty"`
Fault *Fault `xml:"Fault,omitempty"`
InvoiceResponse *InvoiceResponse `xml:"RespuestaRegFactuSistemaFacturacion,omitempty"`
} `xml:"Body"`
}
EnvelopeResponse handles a SOAP response object that will correctly handle the namespaces.
type Environment ¶ added in v0.12.0
type Environment string
Environment defines the environment to use for connections
type Error ¶ added in v0.12.0
type Error struct {
// contains filtered or unexported fields
}
Error allows for structured responses from the gateway to be able to response codes and messages.
func (*Error) Is ¶ added in v0.12.0
Is checks to see if the target error is the same as the current one or forms part of the chain.
func (*Error) WithMessage ¶ added in v0.12.0
WithMessage duplicates and adds the message to the error.
type FacturaRectificada ¶ added in v0.12.0
type FacturaRectificada struct {
IDFactura IDFactura `xml:"sum1:IDFacturaRectificada"`
}
FacturaRectificada represents a rectified invoice
type FacturaSustituida ¶ added in v0.12.0
type FacturaSustituida struct {
IDFactura IDFactura `xml:"sum1:IDFacturaSustituida"`
}
FacturaSustituida represents a substituted invoice
type GenerateOption ¶ added in v0.12.0
type GenerateOption func(*generateOptions)
GenerateOption defines what is expected from an option used in generate methods.
func Amended ¶ added in v0.12.0
func Amended() GenerateOption
Amended indicates that the incoming document is an amendment of a previous document, known in Spanish as "Subsanación". If incorrect data was sent, this will allow the new document to replace the old.
func NoPriorRecord ¶ added in v0.12.0
func NoPriorRecord() GenerateOption
NoPriorRecord is used with cancellation documents when no previous attempt was made to issue an invoice via Verifactu, or if the document to cancel was rejected.
func PreviouslyRejected ¶ added in v0.12.0
func PreviouslyRejected() GenerateOption
PreviouslyRejected indicates that an earlier attempt to process the document was rejected and thus never received by the verifactu system. This option automatically implies the Amended option when supported by the document.
type IDFactura ¶ added in v0.12.0
type IDFactura struct {
IDEmisorFactura string `xml:"sum1:IDEmisorFactura"`
NumSerieFactura string `xml:"sum1:NumSerieFactura"`
FechaExpedicionFactura string `xml:"sum1:FechaExpedicionFactura"`
}
IDFactura contains the identifying information for an invoice
type IDFacturaAnulada ¶ added in v0.12.0
type IDFacturaAnulada struct {
IDEmisorFactura string `xml:"sum1:IDEmisorFacturaAnulada"`
NumSerieFactura string `xml:"sum1:NumSerieFacturaAnulada"`
FechaExpedicionFactura string `xml:"sum1:FechaExpedicionFacturaAnulada"`
}
IDFacturaAnulada contains the identifying information for an invoice
type IDOtro ¶ added in v0.12.0
type IDOtro struct {
CodigoPais string `xml:"sum1:CodigoPais"`
IDType string `xml:"sum1:IDType"`
ID string `xml:"sum1:ID"`
}
IDOtro contains alternative identifying information
type ImporteRectificacion ¶ added in v0.12.0
type ImporteRectificacion struct {
BaseRectificada num.Amount `xml:"sum1:BaseRectificada"`
CuotaRectificada num.Amount `xml:"sum1:CuotaRectificada"`
CuotaRecargoRectificado num.Amount `xml:"sum1:CuotaRecargoRectificado,omitempty"`
}
ImporteRectificacion contains rectification amounts
type InvoiceCancellation ¶ added in v0.12.0
type InvoiceCancellation struct {
IDVersion string `xml:"sum1:IDVersion"`
IDFactura *IDFacturaAnulada `xml:"sum1:IDFactura"`
RefExterna string `xml:"sum1:RefExterna,omitempty"`
SinRegistroPrevio string `xml:"sum1:SinRegistroPrevio,omitempty"`
RechazoPrevio string `xml:"sum1:RechazoPrevio,omitempty"`
GeneradoPor string `xml:"sum1:GeneradoPor,omitempty"`
Generador *Party `xml:"sum1:Generador,omitempty"`
Encadenamiento *Encadenamiento `xml:"sum1:Encadenamiento"`
SistemaInformatico *Software `xml:"sum1:SistemaInformatico"`
FechaHoraHusoGenRegistro string `xml:"sum1:FechaHoraHusoGenRegistro"`
TipoHuella string `xml:"sum1:TipoHuella"`
Huella string `xml:"sum1:Huella"`
}
InvoiceCancellation contains the details of an invoice cancellation
func (*InvoiceCancellation) ChainData ¶ added in v0.12.0
func (c *InvoiceCancellation) ChainData() *ChainData
ChainData provides the details for this cancellation entry.
type InvoiceRegistration ¶ added in v0.12.0
type InvoiceRegistration struct {
XMLName xml.Name `xml:"sum1:RegistroAlta"`
NS string `xml:"xmlns:sum1,attr,omitempty"`
IDVersion string `xml:"sum1:IDVersion"`
IDFactura *IDFactura `xml:"sum1:IDFactura"`
RefExterna string `xml:"sum1:RefExterna,omitempty"`
NombreRazonEmisor string `xml:"sum1:NombreRazonEmisor"`
Subsanacion string `xml:"sum1:Subsanacion,omitempty"`
RechazoPrevio string `xml:"sum1:RechazoPrevio,omitempty"`
TipoFactura string `xml:"sum1:TipoFactura"`
TipoRectificativa string `xml:"sum1:TipoRectificativa,omitempty"`
FacturasRectificadas []*FacturaRectificada `xml:"sum1:FacturasRectificadas,omitempty"`
FacturasSustituidas []*FacturaSustituida `xml:"sum1:FacturasSustituidas,omitempty"`
ImporteRectificacion *ImporteRectificacion `xml:"sum1:ImporteRectificacion,omitempty"`
FechaOperacion string `xml:"sum1:FechaOperacion,omitempty"`
DescripcionOperacion string `xml:"sum1:DescripcionOperacion"`
FacturaSimplificadaArt7273 string `xml:"sum1:FacturaSimplificadaArt7273,omitempty"`
FacturaSinIdentifDestinatarioArt61d string `xml:"sum1:FacturaSinIdentifDestinatarioArt61d,omitempty"`
Macrodato string `xml:"sum1:Macrodato,omitempty"`
EmitidaPorTerceroODestinatario string `xml:"sum1:EmitidaPorTerceroODestinatario,omitempty"`
Tercero *Party `xml:"sum1:Tercero,omitempty"`
Destinatarios []*Destinatario `xml:"sum1:Destinatarios,omitempty"`
Cupon string `xml:"sum1:Cupon,omitempty"`
Desglose *Desglose `xml:"sum1:Desglose"`
CuotaTotal num.Amount `xml:"sum1:CuotaTotal"`
ImporteTotal num.Amount `xml:"sum1:ImporteTotal"`
Encadenamiento *Encadenamiento `xml:"sum1:Encadenamiento"`
SistemaInformatico *Software `xml:"sum1:SistemaInformatico"`
FechaHoraHusoGenRegistro string `xml:"sum1:FechaHoraHusoGenRegistro"`
NumRegistroAcuerdoFacturacion string `xml:"sum1:NumRegistroAcuerdoFacturacion,omitempty"`
IdAcuerdoSistemaInformatico string `xml:"sum1:IdAcuerdoSistemaInformatico,omitempty"` //nolint:revive,staticcheck
TipoHuella string `xml:"sum1:TipoHuella"`
Huella string `xml:"sum1:Huella"`
}
InvoiceRegistration contains the details of an invoice registration
func (*InvoiceRegistration) Bytes ¶ added in v0.12.0
func (r *InvoiceRegistration) Bytes() ([]byte, error)
Bytes prepares an indendented XML document suitable for persistence.
func (*InvoiceRegistration) ChainData ¶ added in v0.12.0
func (r *InvoiceRegistration) ChainData() *ChainData
ChainData provides the details for this registration entry.
type InvoiceRequest ¶ added in v0.12.0
type InvoiceRequest struct {
XMLName xml.Name `xml:"sum:RegFactuSistemaFacturacion"`
Header *InvoiceRequestHeader `xml:"sum:Cabecera"`
Lines []*InvoiceRequestLine `xml:"sum:RegistroFactura,omitempty"`
}
InvoiceRequest represents the root element of a RegFactuSistemaFacturacion document
func (*InvoiceRequest) AddCancellation ¶ added in v0.12.0
func (req *InvoiceRequest) AddCancellation(d *InvoiceCancellation)
AddCancellation adds the requested document to the request body.
func (*InvoiceRequest) AddRegistration ¶ added in v0.12.0
func (req *InvoiceRequest) AddRegistration(d *InvoiceRegistration)
AddRegistration adds the provided document to the list of registrations.
func (*InvoiceRequest) Envelop ¶ added in v0.12.0
func (req *InvoiceRequest) Envelop() *Envelope
Envelop provides a SOAP Envelope around the InvoiceRequest, ready to send off via the API.
type InvoiceRequestHeader ¶ added in v0.12.0
type InvoiceRequestHeader struct {
Obligado Issuer `xml:"sum1:ObligadoEmision"`
Representante *Issuer `xml:"sum1:Representante,omitempty"`
RemisionVoluntaria *RemisionVoluntaria `xml:"sum1:RemisionVoluntaria,omitempty"`
}
InvoiceRequestHeader contains the header information for a VeriFactu document
type InvoiceRequestLine ¶ added in v0.12.0
type InvoiceRequestLine struct {
Registration *InvoiceRegistration `xml:"sum1:RegistroAlta,omitempty"`
Cancellation *InvoiceCancellation `xml:"sum1:RegistroAnulacion,omitempty"`
}
InvoiceRequestLine contains either an invoice registration or cancellation
func (*InvoiceRequestLine) ChainData ¶ added in v0.12.0
func (line *InvoiceRequestLine) ChainData() *ChainData
ChainData provides the chaining data for this line inside the invoice request.
type InvoiceResponse ¶ added in v0.12.0
type InvoiceResponse struct {
XMLName xml.Name `xml:"RespuestaRegFactuSistemaFacturacion"`
Header struct {
Issuer InvoiceResponseIssuer `xml:"ObligadoEmision"`
Representative *InvoiceResponseIssuer `xml:"Representante,omitempty"`
RemisionVoluntaria *InvoiceResponseVoluntarySubmission `xml:"sum1:RemisionVoluntaria,omitempty"`
} `xml:"Cabecera"`
Wait int `xml:"TiempoEsperaEnvio"`
Status string `xml:"EstadoEnvio"`
Lines []*InvoiceResponseLine `xml:"RespuestaLinea"`
}
InvoiceResponse defines the response fields from the VeriFactu gateway.
func (*InvoiceResponse) Bytes ¶ added in v0.12.0
func (ir *InvoiceResponse) Bytes() ([]byte, error)
Bytes prepares an indendented XML document suitable for persistence.
type InvoiceResponseIssuer ¶ added in v0.12.0
InvoiceResponseIssuer maps the response from the invoice request for the issuer.
type InvoiceResponseLine ¶ added in v0.12.0
type InvoiceResponseLine struct {
XMLName xml.Name `xml:"RespuestaLinea"`
ID struct {
Issuer string `xml:"IDEmisorFactura"`
Code string `xml:"NumSerieFactura"`
Date string `xml:"FechaExpedicionFactura"`
} `xml:"IDFactura"`
Operation struct {
Type OpType `xml:"TipoOperacion"`
Correction string `xml:"Subsanacion,omitempty"`
RejectedPrevious string `xml:"RechazoPrevio,omitempty"`
NoPrevious string `xml:"SinRegistroPrevio,omitempty"`
} `xml:"Operacion"`
Ref string `xml:"RefExterna,omitempty"`
Status string `xml:"EstadoRegistro"`
Code string `xml:"CodigoErrorRegistro,omitempty"`
Description string `xml:"DescripcionErrorRegistro,omitempty"`
// Duplicated contains information about possible duplicated requests
// that may need to be handled differently.
Duplicated *InvoiceResponseLineDuplicated `xml:"RegistroDuplicado,omitempty"`
}
InvoiceResponseLine defines the contents of a single line of the request.
func (*InvoiceResponseLine) Error ¶ added in v0.12.0
func (r *InvoiceResponseLine) Error() error
Error provides a specific error repsonse for the individual line so that it can be handled correctly by the consumer.
func (*InvoiceResponseLine) Message ¶ added in v0.12.0
func (r *InvoiceResponseLine) Message() string
Message provides a message body, if any.
type InvoiceResponseLineDuplicated ¶ added in v0.12.0
type InvoiceResponseLineDuplicated struct {
ID string `xml:"IdPeticionRegistroDuplicado"`
Status string `xml:"EstadoRegistroDuplicado"`
Code string `xml:"CodigoErrorRegistro,omitempty"`
Description string `xml:"DescripcionErrorRegistro,omitempty"`
}
InvoiceResponseLineDuplicated describes details about the detected duplicate.
type InvoiceResponseVoluntarySubmission ¶ added in v0.12.0
type InvoiceResponseVoluntarySubmission struct {
Date string `xml:"FechaFinVerifactu,omitempty"`
Incident string `xml:"Incidencia,omitempty"`
}
InvoiceResponseVoluntarySubmission for additional header data.
type OpType ¶ added in v0.12.0
type OpType string
OpType defines the type of operation that was performed.
type Option ¶
type Option func(*Client)
Option is used to configure the client.
func InProduction ¶
func InProduction() Option
InProduction defines the connection to use the production environment.
func InSandbox ¶
func InSandbox() Option
InSandbox defines the connection to use the testing environment.
func WithCertificate ¶
func WithCertificate(cert *xmldsig.Certificate) Option
WithCertificate defines the signing certificate to use when producing the VeriFactu document.
func WithCurrentTime ¶
WithCurrentTime defines the current time to use when generating the VeriFactu document. Only useful for testing.
func WithRepresentative ¶ added in v0.3.0
WithRepresentative can be used to define a legal representative of the entity legally obliged to issue the invoice, usually the supplier. This may be required when the supplier's digital certificate is not available.
type Party ¶ added in v0.12.0
type Party struct {
NombreRazon string `xml:"sum1:NombreRazon"`
NIF string `xml:"sum1:NIF,omitempty"`
IDOtro *IDOtro `xml:"sum1:IDOtro,omitempty"`
}
Party represents a in the document, covering fields Generador, Tercero and IDDestinatario
type RegistroAnterior ¶ added in v0.12.0
type RegistroAnterior struct {
IDEmisorFactura string `xml:"sum1:IDEmisorFactura"`
NumSerieFactura string `xml:"sum1:NumSerieFactura"`
FechaExpedicionFactura string `xml:"sum1:FechaExpedicionFactura"`
Huella string `xml:"sum1:Huella"`
}
RegistroAnterior contains information about the previous registration
type RemisionVoluntaria ¶ added in v0.12.0
type RemisionVoluntaria struct {
FechaFinVerifactu string `xml:"sum1:FechaFinVerifactu,omitempty"`
Incidencia string `xml:"sum1:Incidencia,omitempty"`
}
RemisionVoluntaria contains voluntary submission details
type Software ¶ added in v0.12.0
type Software struct {
NombreRazon string `xml:"sum1:NombreRazon"`
NIF string `xml:"sum1:NIF"`
NombreSistemaInformatico string `xml:"sum1:NombreSistemaInformatico"`
IdSistemaInformatico string `xml:"sum1:IdSistemaInformatico"` //nolint:revive,staticcheck
Version string `xml:"sum1:Version"`
NumeroInstalacion string `xml:"sum1:NumeroInstalacion"`
TipoUsoPosibleSoloVerifactu string `xml:"sum1:TipoUsoPosibleSoloVerifactu,omitempty"`
TipoUsoPosibleMultiOT string `xml:"sum1:TipoUsoPosibleMultiOT,omitempty"`
IndicadorMultiplesOT string `xml:"sum1:IndicadorMultiplesOT,omitempty"`
}
Software contains the details about the software that is using this library to generate VeriFactu documents. These details are included in the final document.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
gobl.verifactu
command
Package main provides the command line interface to the VeriFactu package.
|
Package main provides the command line interface to the VeriFactu package. |
|
Package test provides common functions for testing.
|
Package test provides common functions for testing. |